@slithy/base-ui 0.1.0 → 0.2.0
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/CHANGELOG.md +18 -0
- package/README.md +103 -128
- package/dist/index.d.ts +118 -35
- package/dist/index.js +911 -424
- package/package.json +3 -2
- package/src/Dropdown/Dropdown.test.tsx +361 -186
- package/src/Dropdown/Dropdown.tsx +353 -349
- package/src/Dropdown/DropdownRenderer.tsx +118 -0
- package/src/Dropdown/DropdownStore.ts +147 -0
- package/src/Dropdown/index.ts +1 -0
- package/src/Tooltip/Tooltip.test.tsx +221 -212
- package/src/Tooltip/Tooltip.tsx +274 -201
- package/src/Tooltip/TooltipRenderer.tsx +137 -0
- package/src/Tooltip/TooltipStore.ts +142 -0
- package/src/Tooltip/index.ts +2 -1
- package/src/index.ts +2 -2
- package/src/useCloseCleanup.ts +60 -0
- package/src/useSafePolygon.ts +144 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @slithy/base-ui
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Singleton architecture rewrite for Tooltip and Dropdown.
|
|
8
|
+
|
|
9
|
+
- Tooltip and Dropdown rewritten as singleton implementations (one renderer per app)
|
|
10
|
+
- `TooltipStore` / `DropdownStore` + renderer pattern replaces per-instance components
|
|
11
|
+
- `useSafePolygon` hook for hover bridging between trigger and popup
|
|
12
|
+
- `useCloseCleanup` hook for defensive renderer cleanup on unmount
|
|
13
|
+
- Dropdown: `side`, `sideOffset`, `align`, `alignOffset`, `collisionPadding` positioning props
|
|
14
|
+
- Dropdown: `loopFocus`, `highlightItemOnHover`, `orientation`, `modal`, `openOn` props
|
|
15
|
+
- Dropdown: auto-dismiss when trigger scrolls out of view; controlled `open` / `defaultOpen`
|
|
16
|
+
- Dropdown.Trigger: `tooltip` prop (shows tooltip when dropdown is closed)
|
|
17
|
+
- Tooltip: `hoverable` prop with safe polygon bridging; disabled on touch devices
|
|
18
|
+
- Tooltip: controlled `open` / `defaultOpen`
|
package/README.md
CHANGED
|
@@ -1,47 +1,70 @@
|
|
|
1
1
|
# @slithy/base-ui
|
|
2
2
|
|
|
3
|
-
Compound UI components built on [Base UI](https://base-ui.com/).
|
|
3
|
+
Compound UI components built on [Base UI](https://base-ui.com/). Both Tooltip and Dropdown use a **global singleton architecture**: each trigger is a plain `<button>` with zero Base UI overhead, and a single renderer mounted at the app root owns the positioning and rendering.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Setup
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Mount both renderers once at the app root:
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { DropdownRenderer, TooltipRenderer } from "@slithy/base-ui";
|
|
11
|
+
|
|
12
|
+
function App() {
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
<DropdownRenderer />
|
|
16
|
+
<TooltipRenderer />
|
|
17
|
+
{/* rest of your app */}
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Tooltip
|
|
8
24
|
|
|
9
25
|
```tsx
|
|
10
26
|
import { Tooltip } from "@slithy/base-ui";
|
|
11
27
|
|
|
12
|
-
<Tooltip.
|
|
13
|
-
<Tooltip.
|
|
14
|
-
|
|
15
|
-
<Tooltip.
|
|
16
|
-
<Tooltip.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</Tooltip.Positioner>
|
|
22
|
-
</Tooltip.Portal>
|
|
23
|
-
</Tooltip.Root>
|
|
24
|
-
</Tooltip.Provider>
|
|
28
|
+
<Tooltip.Root>
|
|
29
|
+
<Tooltip.Trigger>Hover me</Tooltip.Trigger>
|
|
30
|
+
<Tooltip.Portal>
|
|
31
|
+
<Tooltip.Popup>
|
|
32
|
+
<Tooltip.Arrow />
|
|
33
|
+
Tooltip content
|
|
34
|
+
</Tooltip.Popup>
|
|
35
|
+
</Tooltip.Portal>
|
|
36
|
+
</Tooltip.Root>
|
|
25
37
|
```
|
|
26
38
|
|
|
27
|
-
**Parts:** `
|
|
39
|
+
**Parts:** `Root`, `Trigger`, `Portal`, `Popup`, `Arrow`
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
### Props
|
|
30
42
|
|
|
31
|
-
**`Root`**
|
|
43
|
+
**`Root`**
|
|
32
44
|
|
|
33
45
|
| Prop | Type | Default | Description |
|
|
34
46
|
|------|------|---------|-------------|
|
|
47
|
+
| `open` | `boolean` | — | Controlled open state. |
|
|
48
|
+
| `defaultOpen` | `boolean` | — | Open on first render (uncontrolled). |
|
|
49
|
+
| `disabled` | `boolean` | `false` | Prevent the tooltip from opening. |
|
|
35
50
|
| `touchDisabled` | `boolean` | `true` | Block activation from touch interactions. Mouse/keyboard still work on hybrid devices. |
|
|
36
|
-
| `
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
| `hoverable` | `boolean` | `false` | Allow hovering into the popup without closing (hover card behavior). |
|
|
52
|
+
| `delay` | `number` | `600` | Delay before opening in ms. |
|
|
53
|
+
| `closeDelay` | `number` | `300` | Delay before closing in ms. |
|
|
54
|
+
| `warmUpDelay` | `number` | `300` | If a tooltip closed within this window (ms), the next one opens instantly. |
|
|
55
|
+
| `side` | `"top" \| "bottom" \| "left" \| "right"` | `"top"` | Which side of the trigger to place the popup. |
|
|
56
|
+
| `sideOffset` | `number` | `6` | Distance between trigger and popup in pixels. |
|
|
57
|
+
| `align` | `"start" \| "center" \| "end"` | `"center"` | Alignment relative to the trigger. |
|
|
58
|
+
| `alignOffset` | `number` | `0` | Offset along the alignment axis in pixels. |
|
|
59
|
+
| `collisionPadding` | `number \| Partial<Record<Side, number>>` | `5` | Padding from viewport edges for collision detection. |
|
|
60
|
+
|
|
61
|
+
**`Trigger`**
|
|
39
62
|
|
|
40
63
|
| Prop | Type | Default | Description |
|
|
41
64
|
|------|------|---------|-------------|
|
|
42
|
-
| `render` | `ReactElement \| (props
|
|
65
|
+
| `render` | `ReactElement \| (props) => ReactElement` | — | Replace the default `<button>` with a custom element. See [Custom trigger element](#custom-trigger-element). |
|
|
43
66
|
|
|
44
|
-
|
|
67
|
+
## Dropdown
|
|
45
68
|
|
|
46
69
|
```tsx
|
|
47
70
|
import { Dropdown } from "@slithy/base-ui";
|
|
@@ -49,74 +72,88 @@ import { Dropdown } from "@slithy/base-ui";
|
|
|
49
72
|
<Dropdown.Root>
|
|
50
73
|
<Dropdown.Trigger>Open menu</Dropdown.Trigger>
|
|
51
74
|
<Dropdown.Portal>
|
|
52
|
-
<Dropdown.
|
|
53
|
-
<Dropdown.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
</Dropdown.Popup>
|
|
59
|
-
</Dropdown.Positioner>
|
|
75
|
+
<Dropdown.Popup>
|
|
76
|
+
<Dropdown.Item onClick={handleEdit}>Edit</Dropdown.Item>
|
|
77
|
+
<Dropdown.Item onClick={handleDuplicate}>Duplicate</Dropdown.Item>
|
|
78
|
+
<Dropdown.Separator />
|
|
79
|
+
<Dropdown.Item onClick={handleDelete}>Delete</Dropdown.Item>
|
|
80
|
+
</Dropdown.Popup>
|
|
60
81
|
</Dropdown.Portal>
|
|
61
82
|
</Dropdown.Root>
|
|
62
83
|
```
|
|
63
84
|
|
|
64
|
-
**Parts:** `Root`, `Trigger`, `Portal`, `
|
|
85
|
+
**Parts:** `Root`, `Trigger`, `Portal`, `Popup`, `Arrow`, `Item`, `Separator`, `Group`, `GroupLabel`, `CheckboxItem`, `CheckboxItemIndicator`, `RadioGroup`, `RadioItem`, `RadioItemIndicator`
|
|
65
86
|
|
|
66
|
-
|
|
87
|
+
### Tooltip on trigger
|
|
67
88
|
|
|
68
|
-
|
|
89
|
+
`Dropdown.Trigger` can show a tooltip on hover/focus that is automatically dismissed when the dropdown opens:
|
|
69
90
|
|
|
70
91
|
```tsx
|
|
71
|
-
|
|
72
|
-
|
|
92
|
+
<Dropdown.Trigger tooltip="Edit, duplicate, or delete">
|
|
93
|
+
Actions
|
|
94
|
+
</Dropdown.Trigger>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Requires `TooltipRenderer` to be mounted. Touch interactions do not trigger tooltips.
|
|
98
|
+
|
|
99
|
+
### Disabling the dropdown
|
|
100
|
+
|
|
101
|
+
Set `disabled` on `Root` to prevent the dropdown from opening while keeping the trigger interactive:
|
|
73
102
|
|
|
103
|
+
```tsx
|
|
74
104
|
<Dropdown.Root disabled={isMobile}>
|
|
75
105
|
<Dropdown.Trigger onClick={isMobile ? () => setModalOpen(true) : undefined}>
|
|
76
106
|
Options
|
|
77
107
|
</Dropdown.Trigger>
|
|
78
108
|
<Dropdown.Portal>
|
|
79
|
-
<Dropdown.
|
|
80
|
-
<Dropdown.
|
|
81
|
-
|
|
82
|
-
<Dropdown.Item onClick={handleDelete}>Delete</Dropdown.Item>
|
|
83
|
-
</Dropdown.Popup>
|
|
84
|
-
</Dropdown.Positioner>
|
|
109
|
+
<Dropdown.Popup>
|
|
110
|
+
<Dropdown.Item onClick={handleEdit}>Edit</Dropdown.Item>
|
|
111
|
+
</Dropdown.Popup>
|
|
85
112
|
</Dropdown.Portal>
|
|
86
113
|
</Dropdown.Root>
|
|
87
114
|
```
|
|
88
115
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
#### Props
|
|
116
|
+
### Props
|
|
92
117
|
|
|
93
|
-
**`Root`**
|
|
118
|
+
**`Root`**
|
|
94
119
|
|
|
95
120
|
| Prop | Type | Default | Description |
|
|
96
121
|
|------|------|---------|-------------|
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
| `open` | `boolean` | — | Controlled open state. |
|
|
123
|
+
| `defaultOpen` | `boolean` | — | Open on first render (uncontrolled). |
|
|
124
|
+
| `disabled` | `boolean` | `false` | Prevent the dropdown from opening. The trigger remains interactive. |
|
|
125
|
+
| `modal` | `boolean` | `true` | Whether the menu is modal (locks scroll, inerts page). When `false`, the popup auto-dismisses when the trigger scrolls out of view. |
|
|
126
|
+
| `openOn` | `"click" \| "pointerdown"` | `"click"` | Open on full click (mouseup) or on pointerdown (mousedown) for snappier response. |
|
|
127
|
+
| `side` | `"top" \| "bottom" \| "left" \| "right"` | `"bottom"` | Which side of the trigger to place the popup. |
|
|
128
|
+
| `sideOffset` | `number` | `4` | Distance between trigger and popup in pixels. |
|
|
129
|
+
| `align` | `"start" \| "center" \| "end"` | `"center"` | Alignment relative to the trigger. |
|
|
130
|
+
| `alignOffset` | `number` | `0` | Offset along the alignment axis in pixels. |
|
|
131
|
+
| `collisionPadding` | `number \| Partial<Record<Side, number>>` | `5` | Padding from viewport edges for collision detection. |
|
|
132
|
+
| `loopFocus` | `boolean` | `true` | Wrap keyboard focus from last item back to first (and vice versa). |
|
|
133
|
+
| `highlightItemOnHover` | `boolean` | `true` | Highlight items on pointer hover. Set to `false` to differentiate CSS `:hover` from keyboard `data-highlighted`. |
|
|
134
|
+
| `orientation` | `"vertical" \| "horizontal"` | `"vertical"` | Arrow key direction for navigation. |
|
|
135
|
+
| `onOpenChange` | `(open: boolean) => void` | — | Called when the menu opens or closes. |
|
|
136
|
+
| `onOpenChangeComplete` | `(open: boolean) => void` | — | Called after open/close animation completes. |
|
|
137
|
+
|
|
138
|
+
**`Trigger`**
|
|
101
139
|
|
|
102
140
|
| Prop | Type | Default | Description |
|
|
103
141
|
|------|------|---------|-------------|
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
|
|
107
|
-
## Deferred rendering
|
|
142
|
+
| `render` | `ReactElement \| (props) => ReactElement` | — | Replace the default `<button>` with a custom element. See [Custom trigger element](#custom-trigger-element). |
|
|
143
|
+
| `tooltip` | `ReactNode` | — | Tooltip content shown on hover/focus. Dismissed when the dropdown opens. Requires `TooltipRenderer`. |
|
|
144
|
+
| `tooltipDelay` | `number` | `600` | Delay before opening the tooltip in ms. |
|
|
108
145
|
|
|
109
|
-
|
|
146
|
+
## Architecture
|
|
110
147
|
|
|
111
|
-
|
|
148
|
+
Both Tooltip and Dropdown use a **global singleton** pattern. Each trigger is a plain `<button>` with ARIA attributes — no Base UI hooks, no floating-ui, no portal. A single renderer (`TooltipRenderer` / `DropdownRenderer`) mounted at the app root subscribes to a global store and renders the active popup anchored to whichever trigger activated it.
|
|
112
149
|
|
|
113
|
-
|
|
150
|
+
Only one tooltip and one dropdown can be open at a time. 200 triggers on a page have the same overhead as 1.
|
|
114
151
|
|
|
115
152
|
## Custom trigger element
|
|
116
153
|
|
|
117
|
-
Both `Tooltip.Trigger` and `Dropdown.Trigger` accept a `render` prop to replace the default `<button>` with a custom element.
|
|
154
|
+
Both `Tooltip.Trigger` and `Dropdown.Trigger` accept a `render` prop to replace the default `<button>` with a custom element.
|
|
118
155
|
|
|
119
|
-
**Element form** — pass a React element
|
|
156
|
+
**Element form** — pass a React element:
|
|
120
157
|
|
|
121
158
|
```tsx
|
|
122
159
|
<Dropdown.Trigger render={<MyButton variant="ghost" />}>
|
|
@@ -124,27 +161,15 @@ Both `Tooltip.Trigger` and `Dropdown.Trigger` accept a `render` prop to replace
|
|
|
124
161
|
</Dropdown.Trigger>
|
|
125
162
|
```
|
|
126
163
|
|
|
127
|
-
**Function form** — receive the full props object
|
|
164
|
+
**Function form** — receive the full props object:
|
|
128
165
|
|
|
129
166
|
```tsx
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
{...props}
|
|
134
|
-
onFocus={(e) => {
|
|
135
|
-
props.onFocus?.(e);
|
|
136
|
-
trackFocusEvent();
|
|
137
|
-
}}
|
|
138
|
-
/>
|
|
139
|
-
)}
|
|
140
|
-
>
|
|
141
|
-
Hover me
|
|
142
|
-
</Tooltip.Trigger>
|
|
167
|
+
<Dropdown.Trigger render={(props) => <MyButton {...props} />}>
|
|
168
|
+
Open menu
|
|
169
|
+
</Dropdown.Trigger>
|
|
143
170
|
```
|
|
144
171
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
Your custom component must forward `ref` to its underlying DOM element so that focus restoration and synthetic event dispatch work correctly after activation.
|
|
172
|
+
Your custom component must forward `ref` to its underlying DOM element.
|
|
148
173
|
|
|
149
174
|
## Styling
|
|
150
175
|
|
|
@@ -175,56 +200,6 @@ Each component applies default class names (`slithy-tooltip-*`, `slithy-dropdown
|
|
|
175
200
|
--slithy-dropdown-group-label-color
|
|
176
201
|
```
|
|
177
202
|
|
|
178
|
-
## Positioning
|
|
179
|
-
|
|
180
|
-
Both components pass all props through to Base UI's Positioner, which wraps floating-ui internally. Common positioning props:
|
|
181
|
-
|
|
182
|
-
```tsx
|
|
183
|
-
<Tooltip.Positioner
|
|
184
|
-
side="bottom" // "top" | "bottom" | "left" | "right"
|
|
185
|
-
sideOffset={8} // distance from trigger (px)
|
|
186
|
-
align="center" // "start" | "center" | "end"
|
|
187
|
-
alignOffset={0} // alignment offset (px)
|
|
188
|
-
collisionPadding={5} // viewport edge padding (px)
|
|
189
|
-
/>
|
|
190
|
-
```
|
|
191
|
-
|
|
192
203
|
## Custom animations
|
|
193
204
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
```tsx
|
|
197
|
-
import { useTransition, animated } from "@react-spring/web";
|
|
198
|
-
|
|
199
|
-
function AnimatedTooltip({ children }: { children: React.ReactNode }) {
|
|
200
|
-
return (
|
|
201
|
-
<Tooltip.Provider>
|
|
202
|
-
<Tooltip.Root>
|
|
203
|
-
<Tooltip.Trigger>Hover me</Tooltip.Trigger>
|
|
204
|
-
<Tooltip.Portal>
|
|
205
|
-
<Tooltip.Positioner sideOffset={8}>
|
|
206
|
-
<Tooltip.Popup
|
|
207
|
-
render={(props) => (
|
|
208
|
-
<animated.div
|
|
209
|
-
{...props}
|
|
210
|
-
style={{
|
|
211
|
-
...props.style,
|
|
212
|
-
opacity: /* your spring value */,
|
|
213
|
-
transform: /* your spring value */,
|
|
214
|
-
}}
|
|
215
|
-
/>
|
|
216
|
-
)}
|
|
217
|
-
>
|
|
218
|
-
{children}
|
|
219
|
-
</Tooltip.Popup>
|
|
220
|
-
</Tooltip.Positioner>
|
|
221
|
-
</Tooltip.Portal>
|
|
222
|
-
</Tooltip.Root>
|
|
223
|
-
</Tooltip.Provider>
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
Base UI exposes `data-open`, `data-starting-style`, and `data-ending-style` attributes on popup elements, and `onOpenChangeComplete` on Root, so you can drive enter/leave animations from open state and signal completion.
|
|
229
|
-
|
|
230
|
-
The deferred rendering layer does not interfere with animations -- by the time they run, the activation latch has flipped and Base UI is fully mounted.
|
|
205
|
+
Base UI exposes `data-open`, `data-starting-style`, and `data-ending-style` attributes on popup elements, so you can drive enter/leave animations from open state. The default styles use CSS transitions with these attributes.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,63 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { Menu } from '@base-ui/react/menu';
|
|
3
|
-
import
|
|
4
|
-
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
5
|
-
import * as _base_ui_react from '@base-ui/react';
|
|
3
|
+
import { ReactNode, ReactElement, ComponentPropsWithoutRef } from 'react';
|
|
6
4
|
import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
|
|
7
5
|
|
|
8
|
-
type
|
|
6
|
+
type DropdownPositionConfig = {
|
|
7
|
+
side?: "top" | "bottom" | "left" | "right" | "inline-end" | "inline-start";
|
|
8
|
+
sideOffset?: number;
|
|
9
|
+
align?: "start" | "center" | "end";
|
|
10
|
+
alignOffset?: number;
|
|
11
|
+
collisionPadding?: number | Partial<Record<"top" | "right" | "bottom" | "left", number>>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type RootProps$1 = {
|
|
9
15
|
children?: ReactNode;
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
/** Controlled open state. */
|
|
17
|
+
open?: boolean;
|
|
18
|
+
/** Open on first render (uncontrolled). */
|
|
19
|
+
defaultOpen?: boolean;
|
|
13
20
|
disabled?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
/** Whether the menu is modal (locks scroll, inerts page). @default true */
|
|
22
|
+
modal?: boolean;
|
|
23
|
+
/** Fire the open/close toggle on `"click"` (mouseup) or `"pointerdown"` (mousedown). @default "click" */
|
|
24
|
+
openOn?: "click" | "pointerdown";
|
|
25
|
+
/** Wrap keyboard focus from last item back to first (and vice versa). @default true */
|
|
26
|
+
loopFocus?: boolean;
|
|
27
|
+
/** Highlight items on pointer hover (`data-highlighted`). @default true */
|
|
28
|
+
highlightItemOnHover?: boolean;
|
|
29
|
+
/** Arrow key direction: `"vertical"` (up/down) or `"horizontal"` (left/right). @default "vertical" */
|
|
30
|
+
orientation?: "vertical" | "horizontal";
|
|
31
|
+
/** Which side of the trigger to place the popup. @default "bottom" */
|
|
32
|
+
side?: DropdownPositionConfig["side"];
|
|
33
|
+
/** Distance between trigger and popup in pixels. @default 4 */
|
|
34
|
+
sideOffset?: number;
|
|
35
|
+
/** Alignment relative to the trigger. @default "center" */
|
|
36
|
+
align?: DropdownPositionConfig["align"];
|
|
37
|
+
/** Offset along the alignment axis in pixels. @default 0 */
|
|
38
|
+
alignOffset?: number;
|
|
39
|
+
/** Padding from viewport edges for collision detection. @default 5 */
|
|
40
|
+
collisionPadding?: DropdownPositionConfig["collisionPadding"];
|
|
41
|
+
onOpenChange?: (open: boolean) => void;
|
|
42
|
+
onOpenChangeComplete?: (open: boolean) => void;
|
|
17
43
|
};
|
|
18
|
-
declare function Root$1({ children, open, defaultOpen, disabled,
|
|
19
|
-
type TriggerProps$1 =
|
|
20
|
-
|
|
44
|
+
declare function Root$1({ children, open, defaultOpen, disabled, modal, openOn, loopFocus, highlightItemOnHover, orientation, side, sideOffset, align, alignOffset, collisionPadding, onOpenChange, onOpenChangeComplete }: RootProps$1): react_jsx_runtime.JSX.Element;
|
|
45
|
+
type TriggerProps$1 = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
46
|
+
children?: ReactNode;
|
|
47
|
+
/** Replace the default `<button>` with a custom element. */
|
|
48
|
+
render?: ReactElement | ((props: Record<string, unknown>) => ReactElement);
|
|
49
|
+
/** Tooltip content shown on hover/focus. Dismissed when the dropdown opens. */
|
|
21
50
|
tooltip?: ReactNode;
|
|
51
|
+
/** Delay before opening the tooltip in ms. @default 600 */
|
|
52
|
+
tooltipDelay?: number;
|
|
53
|
+
};
|
|
54
|
+
declare function Trigger$1({ children, onClick, onPointerDown, onPointerEnter, onPointerLeave, onFocus, onBlur, onKeyDown, render, tooltip, tooltipDelay, ...props }: TriggerProps$1): react_jsx_runtime.JSX.Element;
|
|
55
|
+
type PortalProps$1 = {
|
|
56
|
+
children?: ReactNode;
|
|
22
57
|
};
|
|
23
|
-
declare function
|
|
24
|
-
type
|
|
25
|
-
declare function
|
|
26
|
-
type PositionerProps$1 = ComponentPropsWithoutRef<typeof Menu.Positioner>;
|
|
27
|
-
declare function Positioner$1({ className, ...props }: PositionerProps$1): react_jsx_runtime.JSX.Element;
|
|
58
|
+
declare function Portal$1({ children }: PortalProps$1): null;
|
|
59
|
+
type PositionerProps = ComponentPropsWithoutRef<typeof Menu.Positioner>;
|
|
60
|
+
declare function Positioner({ className, ...props }: PositionerProps): react_jsx_runtime.JSX.Element;
|
|
28
61
|
type PopupProps$1 = ComponentPropsWithoutRef<typeof Menu.Popup>;
|
|
29
62
|
declare function Popup$1({ className, ...props }: PopupProps$1): react_jsx_runtime.JSX.Element;
|
|
30
63
|
type ArrowProps$1 = ComponentPropsWithoutRef<typeof Menu.Arrow>;
|
|
@@ -51,7 +84,7 @@ declare const Dropdown: {
|
|
|
51
84
|
Root: typeof Root$1;
|
|
52
85
|
Trigger: typeof Trigger$1;
|
|
53
86
|
Portal: typeof Portal$1;
|
|
54
|
-
Positioner: typeof Positioner
|
|
87
|
+
Positioner: typeof Positioner;
|
|
55
88
|
Popup: typeof Popup$1;
|
|
56
89
|
Arrow: typeof Arrow$1;
|
|
57
90
|
Item: typeof Item;
|
|
@@ -65,33 +98,83 @@ declare const Dropdown: {
|
|
|
65
98
|
RadioItemIndicator: typeof RadioItemIndicator;
|
|
66
99
|
};
|
|
67
100
|
|
|
68
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Singleton renderer — mount once at the app root.
|
|
103
|
+
* Subscribes to the global DropdownStore and renders the active dropdown
|
|
104
|
+
* using Base UI's Menu.Root + Menu.Positioner.
|
|
105
|
+
*
|
|
106
|
+
* Menu.Root stays mounted so CSS transitions can play on both open and close.
|
|
107
|
+
* Content and anchor are swapped when a new dropdown opens.
|
|
108
|
+
*/
|
|
109
|
+
declare function DropdownRenderer(): react_jsx_runtime.JSX.Element | null;
|
|
110
|
+
|
|
111
|
+
type TooltipPositionConfig = {
|
|
112
|
+
side?: "top" | "bottom" | "left" | "right" | "inline-end" | "inline-start";
|
|
113
|
+
sideOffset?: number;
|
|
114
|
+
align?: "start" | "center" | "end";
|
|
115
|
+
alignOffset?: number;
|
|
116
|
+
collisionPadding?: number | Partial<Record<"top" | "right" | "bottom" | "left", number>>;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
type RootProps = {
|
|
69
120
|
children?: ReactNode;
|
|
70
|
-
/**
|
|
121
|
+
/** Controlled open state. */
|
|
122
|
+
open?: boolean;
|
|
123
|
+
/** Open on first render (uncontrolled). */
|
|
124
|
+
defaultOpen?: boolean;
|
|
125
|
+
disabled?: boolean;
|
|
126
|
+
/** Block activation from touch interactions. @default true */
|
|
71
127
|
touchDisabled?: boolean;
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
|
|
128
|
+
/** Allow hovering into the popup without closing (hover card behavior). @default false */
|
|
129
|
+
hoverable?: boolean;
|
|
130
|
+
/** Delay before opening in ms. @default 600 */
|
|
131
|
+
delay?: number;
|
|
132
|
+
/** Delay before closing in ms. @default 300 */
|
|
133
|
+
closeDelay?: number;
|
|
134
|
+
/** Warm-up window in ms. If a tooltip closed within this window,
|
|
135
|
+
* the next one opens instantly. @default 300 */
|
|
136
|
+
warmUpDelay?: number;
|
|
137
|
+
/** Which side of the trigger to place the popup. @default "top" */
|
|
138
|
+
side?: TooltipPositionConfig["side"];
|
|
139
|
+
/** Distance between trigger and popup in pixels. @default 6 */
|
|
140
|
+
sideOffset?: number;
|
|
141
|
+
/** Alignment relative to the trigger. @default "center" */
|
|
142
|
+
align?: TooltipPositionConfig["align"];
|
|
143
|
+
/** Offset along the alignment axis in pixels. @default 0 */
|
|
144
|
+
alignOffset?: number;
|
|
145
|
+
/** Padding from viewport edges for collision detection. @default 5 */
|
|
146
|
+
collisionPadding?: TooltipPositionConfig["collisionPadding"];
|
|
75
147
|
};
|
|
76
|
-
declare function Root({ children, open, defaultOpen, disabled, touchDisabled,
|
|
77
|
-
type TriggerProps =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
declare function
|
|
148
|
+
declare function Root({ children, open, defaultOpen, disabled, touchDisabled, hoverable, delay, closeDelay, warmUpDelay, side, sideOffset, align, alignOffset, collisionPadding, }: RootProps): react_jsx_runtime.JSX.Element;
|
|
149
|
+
type TriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
150
|
+
children?: ReactNode;
|
|
151
|
+
/** Replace the default `<button>` with a custom element. */
|
|
152
|
+
render?: ReactElement | ((props: Record<string, unknown>) => ReactElement);
|
|
153
|
+
};
|
|
154
|
+
declare function Trigger({ children, render, ...props }: TriggerProps): react_jsx_runtime.JSX.Element;
|
|
155
|
+
type PortalProps = {
|
|
156
|
+
children?: ReactNode;
|
|
157
|
+
};
|
|
158
|
+
declare function Portal({ children }: PortalProps): null;
|
|
83
159
|
type PopupProps = ComponentPropsWithoutRef<typeof Tooltip$1.Popup>;
|
|
84
|
-
declare function Popup({ className, ...props }: PopupProps): react_jsx_runtime.JSX.Element;
|
|
160
|
+
declare function Popup({ className, id, ...props }: PopupProps): react_jsx_runtime.JSX.Element;
|
|
85
161
|
type ArrowProps = ComponentPropsWithoutRef<typeof Tooltip$1.Arrow>;
|
|
86
162
|
declare function Arrow({ className, ...props }: ArrowProps): react_jsx_runtime.JSX.Element;
|
|
87
163
|
declare const Tooltip: {
|
|
88
|
-
Provider: react.FC<_base_ui_react.TooltipProviderProps>;
|
|
89
164
|
Root: typeof Root;
|
|
90
165
|
Trigger: typeof Trigger;
|
|
91
166
|
Portal: typeof Portal;
|
|
92
|
-
Positioner: typeof Positioner;
|
|
93
167
|
Popup: typeof Popup;
|
|
94
168
|
Arrow: typeof Arrow;
|
|
95
169
|
};
|
|
96
170
|
|
|
97
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Singleton renderer — mount once at the app root.
|
|
173
|
+
* Subscribes to the global TooltipStore and renders the active tooltip
|
|
174
|
+
* using Base UI's Tooltip.Root + Tooltip.Positioner.
|
|
175
|
+
*
|
|
176
|
+
* Tooltip.Root stays mounted so CSS transitions can play on both open and close.
|
|
177
|
+
*/
|
|
178
|
+
declare function TooltipRenderer(): react_jsx_runtime.JSX.Element | null;
|
|
179
|
+
|
|
180
|
+
export { Dropdown, DropdownRenderer, Tooltip, TooltipRenderer };
|