@ahrowe/ui 0.16.8 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/common/buttonGroup/buttonGroup.module.mjs.map +1 -1
- package/dist/esm/common/checkbox/checkbox.module.mjs.map +1 -1
- package/dist/esm/common/colorPicker/colorPicker.module.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs.map +1 -1
- package/dist/esm/common/input/input.module.mjs.map +1 -1
- package/dist/esm/common/progressBar/progressBar.module.mjs.map +1 -1
- package/dist/esm/common/sticky/sticky.mjs +1 -1
- package/dist/esm/common/sticky/sticky.mjs.map +1 -1
- package/dist/esm/common/sticky/stickyStack.mjs +1 -1
- package/dist/esm/common/sticky/stickyStack.mjs.map +1 -1
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/package/common/floatingMenu/useFloatingPosition.d.ts +4 -0
- package/dist/types/package/common/sticky/sticky.d.ts +1 -1
- package/dist/types/package/common/sticky/sticky.types.d.ts +5 -1
- package/dist/types/package/common/sticky/stickyStack.d.ts +5 -0
- package/docs/ButtonGroup.md +6 -12
- package/docs/Dropdown.md +1 -1
- package/docs/FloatingMenu.md +1 -1
- package/docs/InputDropdown.md +1 -1
- package/docs/Sticky.md +24 -3
- package/package.json +1 -1
package/docs/FloatingMenu.md
CHANGED
|
@@ -54,7 +54,7 @@ import { FloatingMenu, Align } from '@ahrowe/ui';
|
|
|
54
54
|
|
|
55
55
|
**Slots:** `root` `trigger` `menu` `menuContainer`
|
|
56
56
|
|
|
57
|
-
**Positioning:** the menu is portaled and tracks the trigger across scroll and resize, flipping above it when there's no room below. It re-measures whenever `content` changes size while open, so a menu holding a list that grows or shrinks (filtering, async loading) stays anchored to the trigger and re-evaluates whether it still needs to open upward.
|
|
57
|
+
**Positioning:** the menu is portaled and tracks the trigger across scroll and resize, flipping above it when there's no room below. It re-measures whenever `content` changes size while open, so a menu holding a list that grows or shrinks (filtering, async loading) stays anchored to the trigger and re-evaluates whether it still needs to open upward. It's also shifted horizontally to stay within the viewport — a trigger near the left or right edge of the screen no longer lets the menu overflow off-screen, regardless of `align`.
|
|
58
58
|
|
|
59
59
|
**Closing behaviour:** by default, clicking anywhere in `content` closes the menu — including inside a nested overlay that renders through its own portal (e.g. a `Dropdown` or another `FloatingMenu` used inside `content`), even though that overlay's DOM lives outside `content`'s own subtree. Re-clicking the trigger while open is a clean toggle: it closes the menu (unless `dontCloseOnChildClick` is set, in which case it's a no-op — the trigger owns its own open/close entirely, so it never fights with an outside-click check). Set `dontCloseOnChildClick` when `content` needs several interactions before the user is done (a multi-checkbox toggle, a color picker's slider, a calendar) — the consumer is then responsible for closing explicitly, e.g. calling `onOpenChange(false)` from the handler that reacts to a final selection.
|
|
60
60
|
|
package/docs/InputDropdown.md
CHANGED
|
@@ -68,4 +68,4 @@ interface InputDropdownItem {
|
|
|
68
68
|
|
|
69
69
|
**Slots:** `root` `dropdown` `item`
|
|
70
70
|
|
|
71
|
-
The list is rendered through a portal and tracks the trigger across scroll, so it always escapes clipping ancestors (cards, scroll containers, virtualized lists). It flips to open upward automatically when there's no room below, and hides (without closing) if the trigger itself scrolls behind a clipping ancestor, reappearing once it's back in view. It also re-measures when its own content changes size while open, so a list that shrinks (e.g. filtered down to fewer entries) stays anchored to the trigger instead of hanging above it.
|
|
71
|
+
The list is rendered through a portal and tracks the trigger across scroll, so it always escapes clipping ancestors (cards, scroll containers, virtualized lists). It flips to open upward automatically when there's no room below, and shifts horizontally to stay within the viewport when the trigger sits near the left or right edge of the screen. It hides (without closing) if the trigger itself scrolls behind a clipping ancestor, reappearing once it's back in view. It also re-measures when its own content changes size while open, so a list that shrinks (e.g. filtered down to fewer entries) stays anchored to the trigger instead of hanging above it.
|
package/docs/Sticky.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**When to use:** Pin a piece of content to the top of the viewport once the page scrolls past it — section headers, toolbars, filter bars, table headers. The content sticks while its original position is above the fold and releases the moment that position scrolls back into view. A placeholder preserves the original space, so nothing below jumps when it detaches.
|
|
4
4
|
|
|
5
|
-
**Keywords:** sticky header, pinned toolbar
|
|
5
|
+
**Keywords:** sticky header, pinned toolbar, scroll container, app shell, scrollable panel
|
|
6
6
|
|
|
7
7
|
**Import:** `import { Sticky } from '@ahrowe/ui'`
|
|
8
8
|
|
|
@@ -19,6 +19,23 @@ import { Sticky } from '@ahrowe/ui';
|
|
|
19
19
|
<FilterBar />
|
|
20
20
|
</Sticky>
|
|
21
21
|
|
|
22
|
+
// Stick below a header that isn't a Sticky itself — offset tracks its live height
|
|
23
|
+
const headerRef = useRef<HTMLElement>(null);
|
|
24
|
+
<header ref={headerRef}>...</header>
|
|
25
|
+
<Sticky offsetElement={headerRef}>
|
|
26
|
+
<FilterBar />
|
|
27
|
+
</Sticky>
|
|
28
|
+
|
|
29
|
+
// App-shell layout: a separately-scrollable content pane below a header that's
|
|
30
|
+
// outside that scroll container. Stick to the pane's own top edge instead of the
|
|
31
|
+
// browser viewport's, so it naturally stops below the header with no offset needed
|
|
32
|
+
<div style={{ height: '100vh', overflowY: 'auto' }}>
|
|
33
|
+
<Sticky stickToScrollParent offsetTop={0}>
|
|
34
|
+
<FilterBar />
|
|
35
|
+
</Sticky>
|
|
36
|
+
<Content />
|
|
37
|
+
</div>
|
|
38
|
+
|
|
22
39
|
// React to the stuck state (e.g. add a shadow)
|
|
23
40
|
<Sticky onStuckChange={(stuck) => setElevated(stuck)}>
|
|
24
41
|
<Toolbar />
|
|
@@ -39,7 +56,9 @@ import { Sticky } from '@ahrowe/ui';
|
|
|
39
56
|
</Sticky>
|
|
40
57
|
```
|
|
41
58
|
|
|
42
|
-
**How it works:** while stuck, the content switches to `position: fixed` (measured to keep the same width and horizontal position) and a placeholder of the same height takes its place in the flow. It tracks scroll on the window *and* any ancestor scroll container, so it works inside scrollable panels too
|
|
59
|
+
**How it works:** while stuck, the content switches to `position: fixed` (measured to keep the same width and horizontal position) and a placeholder of the same height takes its place in the flow. It tracks scroll on the window *and* any ancestor scroll container, so it works inside scrollable panels too. By default it pins to the top of the browser viewport (offset by `offsetTop`), regardless of any scroll container it's nested in — set `stickToScrollParent` to pin to that container's own top edge instead (see below).
|
|
60
|
+
|
|
61
|
+
**`stickToScrollParent`:** by default `Sticky` always pins relative to the browser viewport, which can overlap other fixed/pinned chrome (e.g. an app header) that sits outside the element's own scroll container. Set `stickToScrollParent` to pin relative to the nearest ancestor with its own scrollbar (`overflow-y: auto`/`scroll`/`overlay`) instead — found once on mount by walking up from the root. Falls back to the viewport if no scrollable ancestor is found. Combine with `offsetTop` for extra spacing from that container's top (e.g. its own internal header).
|
|
43
62
|
|
|
44
63
|
**Stacking:** every mounted `Sticky` coordinates automatically, no extra markup needed. When more than one is stuck at the same time, a later one (in DOM order) that horizontally overlaps an earlier stuck one pins below it — `offsetTop` plus the overlapping ones' heights — instead of both landing on the same spot. Stickies that don't overlap horizontally (e.g. two half-width ones side by side under a full-width one) land at the same `top`, next to each other, rather than pushing each other down.
|
|
45
64
|
|
|
@@ -48,7 +67,9 @@ import { Sticky } from '@ahrowe/ui';
|
|
|
48
67
|
| Prop | Type | Description |
|
|
49
68
|
|------|------|-------------|
|
|
50
69
|
| `children` | `ReactNode` | The content to make sticky |
|
|
51
|
-
| `offsetTop` | `number` | Distance in px from the top of the viewport the content sticks to (default `0`) |
|
|
70
|
+
| `offsetTop` | `number` | Distance in px from the top of the viewport the content sticks to (default `0`). Ignored if `offsetElement` is set |
|
|
71
|
+
| `offsetElement` | `RefObject<HTMLElement \| null>` | Element to stick below (e.g. a fixed/pinned header outside this library) — its live height is used as the offset instead of a fixed `offsetTop` |
|
|
72
|
+
| `stickToScrollParent` | `boolean` | Stick to the top of the nearest scrollable ancestor instead of the browser viewport (default `false`). Falls back to the viewport if no scrollable ancestor is found |
|
|
52
73
|
| `zIndex` | `number` | z-index applied while stuck (default `20`) |
|
|
53
74
|
| `disabled` | `boolean` | Disable sticking — content stays in normal flow |
|
|
54
75
|
| `onStuckChange` | `(isStuck: boolean) => void` | Fired whenever the stuck state flips |
|