feat(ui): add Radix overlays matched to native VS Code widgets - #1039
Merged
Conversation
EhabY
force-pushed
the
feat/devex-619-radix-overlays
branch
from
July 15, 2026 22:12
87cb194 to
bb96f01
Compare
EhabY
force-pushed
the
feat/devex-624-ui-scaffold
branch
from
July 20, 2026 11:21
b9d3bea to
5a6fe06
Compare
EhabY
force-pushed
the
feat/devex-619-radix-overlays
branch
from
July 20, 2026 11:37
bb96f01 to
88bb435
Compare
EhabY
force-pushed
the
feat/devex-619-radix-overlays
branch
3 times, most recently
from
July 27, 2026 13:57
2559023 to
9289218
Compare
Tooltip, ContextMenu, and DropdownMenu wrap the Radix primitives with flat compound exports (Tooltip takes a content prop) and are styled to match the native menu and hover widgets via --ui-* tokens, including high contrast, forced-colors, and reduced-motion handling. Long menus and tooltips cap to the space Radix reports and scroll like native. The menu entry fade is gated on data-state so an interrupted animation cannot leave a closed overlay mounted. Stories snapshot the four theme families through Pixel and assert focus handling in play functions.
- Menu highlight uses list.hover* and tooltips sit flush left like native - .ui-overlay owns border, radius, shadow, and available-height scrolling - Replace overlaySpace reservations with an afterEach root fit in preview - Trim stories, add JSDoc to menu parts, drop unused Group exports - Inline Radix deps in packages/ui and pin codicons 0.0.46-24
EhabY
force-pushed
the
feat/devex-619-radix-overlays
branch
from
July 28, 2026 13:02
ec5efce to
1db5c9a
Compare
- Shrink #storybook-root to fit-content; the padded layout rendered it as a full-width block, making every Pixel snapshot viewport-wide - Declare react-dom as a peer dependency (the Radix primitives need it) - Extend the README known gaps to cover the whole package, not just the overlays
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1038
Adds
Tooltip,ContextMenu, andDropdownMenuwrapping the Radix primitives, the package's only runtime deps besides codicons. The Radix packages are declared directly inpackages/ui(sole consumer, and portable for a standalone split) at their latest versions; codicons is pinned to0.0.46-24. Menus expose Radix's compound parts as flat named exports with a one-line JSDoc each;Tooltipis a single component with acontentprop and a 500ms delay matchingworkbench.hover.delay.getMenuWidgetCSS()inmenu.ts,hover.css): 24px items, 2em gutters,cornerRadiustokens with pre-token fallbacks, highlight colors fromlist.hover*(what native menus actually use, notmenu.selection*), and native's exactshadow-lgfallback chain..ui-overlaybase owns stacking, border, radius, shadow, and available-height scrolling; each surface maps onto it via--ui-overlay-*properties. Menus fade in like native menus, gated ondata-state; an ungated entry animation interrupted before its first frame left closed overlays mounted, because Radix waits for ananimationendthat never fires.body. High contrast,forced-colors, andprefers-reduced-motionhandled.sideEffectsdeclared so unused components tree-shake out of webview bundles.TooltipProvider, shadow alpha, tooltip height cap) and for the package as a whole (noButton, token-layer coverage,useVscodeThemegranularity, reduced-motion activity cues).Storybook
One stories file per overlay, five stories total;
Openstories snapshot all four themes via the Pixel matrix, with menus and submenus opened by play functions through a sharedopenSubmenuByKeyboardhelper. Portalled overlays stay in frame automatically: a preview-levelafterEachgrows the story root to cover anything portalled tobody, replacing per-storyoverlaySpacereservations (layout switched topaddedso growth never moves an overlay's anchor). The.story-triggerstand-in styles moved into the package next to the constant that names them.Manual checklist for the first real webview consumer:
bodyOut of scope
Checkbox/radio items, groups, labels, keybinding hints, a data-driven
itemswrapper, a shared app-rootTooltipProvider(eachTooltipmounts its own for now), and Tasks' migration off@vscode-elements.🤖 Generated with Claude Code