Skip to content

fix(feed): make widget content inert in customize mode - #7016

Merged
rebelchris merged 1 commit into
mainfrom
fix/feed-widget-edit-inert
Oct 23, 2026
Merged

rebelchris merged 1 commit into
mainfrom
fix/feed-widget-edit-inert

Conversation

@rebelchris

@rebelchris rebelchris commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Problem

In customize mode a click inside a widget could still navigate away:

  • the pinned ad slot was never blocked, so clicking the ad opened it
  • card buttons that opt back in with pointer-events-auto (bookmark, upvote/comment, author/source stack) still took pointer input in the Top story widget
  • links inside widgets stayed in the tab order

Fix

useInertRef (in FeedWidgetFrame.tsx) sets node.inert while editing (React 18 doesn't carry the attribute, same pattern as SidebarDesktopV2). Applied to the widget surface (replacing pointer-events-none) and to the ad slot's content. The remove badge, widget menu and resize corners sit outside that content, so they keep working; inert hit-tests like pointer-events: none, so dragging from the widget body still lands on the cell.

Test plan

  • feedWidgets jest suites (new: content is inert in customize mode, menu isn't)
  • strict typecheck on changed files, eslint, webapp tsc
  • browser: drag still starts from widget content, ad doesn't open in customize mode

🤖 Generated with Claude Code

Preview domain

https://fix-feed-widget-edit-inert.preview.app.daily.dev

pointer-events-none on the widget surface still let card buttons that opt
back in with pointer-events-auto (bookmark, upvote, author stack) take
pointer input, kept links in the tab order, and the pinned ad slot was
never covered at all, so a click in customize mode could navigate away.
inert removes the content from hit-testing and focus; drag, resize, the
remove badge and the widget menu live outside it and keep working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
daily-webapp Ready Ready Preview Oct 23, 2026 8:10am UTC
storybook Ready Ready Preview Oct 23, 2026 8:10am UTC

Request Review

expect(
screen
.getByRole('button', { name: 'Remove Top story' })
.closest('[inert]'),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion always passes. The test env runs jsdom 20.0.3, which doesn't implement HTMLElement.prototype.inert. So node.inert = true only sets a plain JS property and never adds the inert attribute. .closest('[inert]') then returns null for every element, including ones inside the inert surface. I checked this with a standalone jsdom 20.0.3: after a.inert = true, getAttribute('inert') is null and child.closest('[inert]') is null.

The content?.inert checks above it do work, since they read the same property back. Only the claim that the menu isn't inert is untested.

Either of these would fix it:

  • assert the structure directly: expect(content?.contains(screen.getByRole('button', { name: 'Remove Top story' }))).toBe(false), or
  • reuse the reflecting inert polyfill from components/drawers/Drawer.spec.tsx so that [inert] selectors mean something here.

Non-blocking, but right now the test doesn't cover the regression it describes (the controls ending up inside the inert node).

Reviewed by AI.

* does not carry the attribute.
*/
export const useInertRef = <T extends HTMLElement>(
isInert: boolean,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: this is now the fourth hand-written copy of setting inert from an effect. The others are SidebarDesktopV2 (~L1308, the same effect including the false cleanup), ShellCluster and PostOptionsSheet. It's also a general hook exported from a component file, and FeedWidgetAdSlot imports it from there.

Could it move to hooks/ (e.g. hooks/useInertRef.ts), with SidebarDesktopV2 switched over to it in a follow-up? If you'd rather keep this PR small, it's fine to leave it where it is.

Reviewed by AI.

@rebelchris
rebelchris merged commit 1377c9f into main Oct 23, 2026
16 checks passed
@rebelchris
rebelchris deleted the fix/feed-widget-edit-inert branch October 23, 2026 08:17

This branch was successfully deployed

2 active deployments
Preview – daily-webapp — a765e827 Deployed Oct 23, 2026 by vercel[bot]
Preview – storybook — a765e827 Deployed Oct 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant