feat(packages): add flip functionality to popovers/tooltips/menus (#1857)

This commit is contained in:
Sam Potts
2026-07-28 16:30:24 +10:00
committed by GitHub
parent 359e56ca49
commit be89470447
34 changed files with 699 additions and 141 deletions
+3 -1
View File
@@ -104,7 +104,7 @@ A submenu is a menu inside another menu. The submenu trigger lives in the parent
## Behavior
Menus open from a trigger and close when you select an item, click outside, move focus away, or press <kbd>Escape</kbd>. Root menus are positioned against their trigger with `side` and `align`.
Menus open from a trigger and close when you select an item, click outside, move focus away, or press <kbd>Escape</kbd>. Root menus use `side` and `align` as their preferred placement. When the preferred side overflows the positioning boundary, the menu uses the opposite side if it has more space.
Create a submenu by putting another menu inside the root menu's content. Its trigger stays in the root list, and its content becomes the next view. In HTML, give the submenu a matching `id` and point the trigger at it with `commandfor`. Wrap the root list in `Menu.View` or `<media-menu-view>` when the root list and submenus share one animated viewport.
@@ -116,6 +116,8 @@ Use data attributes to style open state, highlighted items, selected radio items
`data-highlighted` is added to the current menu item. The highlighted item is the item that keyboard selection will act on. It changes when the menu opens, when the pointer moves over another item, when the user presses arrow keys, or when type-ahead search finds a match.
On root menu content, `data-side` reflects the rendered side and can differ from the preferred `side` prop after collision handling. Submenus do not have `data-side`.
<FrameworkCase frameworks={["react"]}>
```css
.menu[data-open] {
+14 -2
View File
@@ -50,7 +50,7 @@ Displays contextual content anchored to a trigger element. By default, opens on
Set `openOnHover` to open on pointer hover instead of click. Use `delay` and `closeDelay` to control timing for hover interactions.
The `side` and `align` props control popup placement relative to the trigger. The popup repositions automatically to stay within viewport bounds.
The `side` and `align` props control the preferred popup placement relative to the trigger. When the preferred side overflows the positioning boundary, the popup uses the opposite side if it has more space.
<FrameworkCase frameworks={["react"]}>
In React, the component is composed from four parts: `Root` manages state,
@@ -90,7 +90,7 @@ React renders standard DOM elements. Add a `className` to style them:
```
</FrameworkCase>
Style based on open state and transition phases:
Style based on open state, rendered side, and transition phases. `data-side` reflects the rendered side and can differ from the preferred `side` prop after collision handling:
<FrameworkCase frameworks={["html"]}>
```css
@@ -103,6 +103,12 @@ media-popover[data-starting-style] .popup {
media-popover[data-ending-style] .popup {
opacity: 0;
}
media-popover[data-side="top"] {
transform-origin: bottom center;
}
media-popover[data-side="bottom"] {
transform-origin: top center;
}
```
</FrameworkCase>
@@ -117,6 +123,12 @@ media-popover[data-ending-style] .popup {
.popover[data-ending-style] .popup {
opacity: 0;
}
.popover[data-side="top"] {
transform-origin: bottom center;
}
.popover[data-side="bottom"] {
transform-origin: top center;
}
```
</FrameworkCase>
+2 -2
View File
@@ -63,7 +63,7 @@ import groupingHtmlTs from "@/components/docs/demos/tooltip/html/css/Grouping.ts
Displays a short label anchored to a trigger element. Opens after a configurable `delay` (default 600ms) on hover or immediately on focus. Closes when the pointer leaves or focus moves away, with an optional `closeDelay`.
The `side` and `align` props control placement relative to the trigger. Positioning uses CSS Anchor Positioning where supported, with a JavaScript measurement fallback.
The `side` and `align` props control the preferred placement relative to the trigger. When the preferred side overflows the positioning boundary, the tooltip uses the opposite side if it has more space. Positioning uses CSS Anchor Positioning where supported, with a JavaScript measurement fallback.
<FrameworkCase frameworks={["react"]}>
The component is composed from six parts: `Root` manages state and context,
@@ -109,7 +109,7 @@ React renders standard DOM elements. Add a `className` to style them:
```
</FrameworkCase>
Style based on open state and transition phases:
Style based on open state, rendered side, and transition phases. `data-side` reflects the rendered side and can differ from the preferred `side` prop after collision handling:
<FrameworkCase frameworks={["html"]}>
```css