@navecss/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/README.md +242 -12
- package/dist/alert-dialog/index.d.ts +2 -0
- package/dist/alert-dialog/index.js +2 -0
- package/dist/alert-dialog/parts.generated.d.ts +55 -0
- package/dist/alert-dialog/parts.generated.js +14 -0
- package/dist/autocomplete/index.d.ts +2 -0
- package/dist/autocomplete/index.js +2 -0
- package/dist/autocomplete/parts.generated.d.ts +116 -0
- package/dist/autocomplete/parts.generated.js +27 -0
- package/dist/avatar/index.d.ts +2 -0
- package/dist/avatar/index.js +2 -0
- package/dist/avatar/parts.generated.d.ts +18 -0
- package/dist/avatar/parts.generated.js +6 -0
- package/dist/combobox/index.d.ts +2 -0
- package/dist/combobox/index.js +2 -0
- package/dist/combobox/parts.generated.d.ts +140 -0
- package/dist/combobox/parts.generated.js +33 -0
- package/dist/context-menu/index.d.ts +2 -0
- package/dist/context-menu/index.js +2 -0
- package/dist/context-menu/parts.generated.d.ts +104 -0
- package/dist/context-menu/parts.generated.js +23 -0
- package/dist/dialog/parts.generated.d.ts +1 -0
- package/dist/dialog/parts.generated.js +1 -1
- package/dist/field/parts.generated.d.ts +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/menu/parts.generated.d.ts +1 -0
- package/dist/menu/parts.generated.js +7 -7
- package/dist/menubar/index.d.ts +2 -0
- package/dist/menubar/index.js +3 -0
- package/dist/menubar/parts.generated.d.ts +6 -0
- package/dist/menubar/parts.generated.js +5 -0
- package/dist/meter/index.d.ts +2 -0
- package/dist/meter/index.js +2 -0
- package/dist/meter/parts.generated.d.ts +26 -0
- package/dist/meter/parts.generated.js +9 -0
- package/dist/navigation-menu/index.d.ts +2 -0
- package/dist/navigation-menu/index.js +2 -0
- package/dist/navigation-menu/parts.generated.d.ts +69 -0
- package/dist/navigation-menu/parts.generated.js +17 -0
- package/dist/part.d.ts +17 -1
- package/dist/part.js +12 -5
- package/dist/popover/parts.generated.d.ts +1 -0
- package/dist/popover/parts.generated.js +2 -2
- package/dist/preview-card/index.d.ts +2 -0
- package/dist/preview-card/index.js +2 -0
- package/dist/preview-card/parts.generated.d.ts +48 -0
- package/dist/preview-card/parts.generated.js +14 -0
- package/dist/progress/index.d.ts +2 -0
- package/dist/progress/index.js +2 -0
- package/dist/progress/parts.generated.d.ts +27 -0
- package/dist/progress/parts.generated.js +9 -0
- package/dist/scroll-area/index.d.ts +2 -0
- package/dist/scroll-area/index.js +2 -0
- package/dist/scroll-area/parts.generated.d.ts +31 -0
- package/dist/scroll-area/parts.generated.js +10 -0
- package/dist/select/parts.generated.js +3 -3
- package/dist/separator/index.d.ts +2 -0
- package/dist/separator/index.js +3 -0
- package/dist/separator/parts.generated.d.ts +6 -0
- package/dist/separator/parts.generated.js +5 -0
- package/dist/styles.css +129 -0
- package/dist/tabs/parts.generated.js +1 -1
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +2 -0
- package/dist/toast/parts.generated.d.ts +61 -0
- package/dist/toast/parts.generated.js +16 -0
- package/dist/toolbar/parts.generated.d.ts +1 -0
- package/dist/tooltip/parts.generated.d.ts +1 -0
- package/dist/tooltip/parts.generated.js +2 -2
- package/package.json +71 -4
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ NaveCSS styles Base UI's components with Nave's tokens: the same parts, the same
|
|
|
4
4
|
|
|
5
5
|
This package is not affiliated with, endorsed by or sponsored by MUI or the Base UI project.
|
|
6
6
|
|
|
7
|
-
`@base-ui/react` is a separately installed peer, built and maintained by its own maintainers; this package does not include it. You change `@base-ui/react/<component>` to `@navecss/base-ui/<component>` in your imports, add one stylesheet, and every part keeps Base UI's props,
|
|
7
|
+
`@base-ui/react` is a separately installed peer, built and maintained by its own maintainers; this package does not include it. You change `@base-ui/react/<component>` to `@navecss/base-ui/<component>` in your imports, add one stylesheet, and every part keeps Base UI's props, refs and behaviour while gaining Nave's styling. The styling is zero-runtime styling: static classes and one static stylesheet, with all behaviour still Base UI's.
|
|
8
8
|
|
|
9
|
-
On this page: [Install](#install) · [Use it](#use-it) · [The stylesheet](#the-stylesheet) · [Variants](#variants) · [Overriding](#overriding) · [What is styled](#what-is-styled) · [Things to know](#things-to-know) · [License](#license)
|
|
9
|
+
On this page: [Install](#install) · [Use it](#use-it) · [The stylesheet](#the-stylesheet) · [Variants](#variants) · [Overriding](#overriding) · [What is styled](#what-is-styled) · [Feedback and navigation](#feedback-and-navigation) · [Things to know](#things-to-know) · [License](#license)
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -48,7 +48,7 @@ export default function RenameDialog() {
|
|
|
48
48
|
}
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
Every subpath of Base UI that this package wraps is listed under [What is styled](#what-is-styled). Each one also re-exports every type Base UI exports there, so
|
|
51
|
+
Every subpath of Base UI that this package wraps is listed under [What is styled](#what-is-styled). Each one also re-exports every flat type name Base UI exports there, such as `DialogRootProps`, so those imports change the same way. Base UI's dotted type names, such as `Dialog.Root.Props`, come through as well, but not all of them: where one does not compile through this package, import Base UI's flat name for the same type from the same subpath. The end of [What is styled](#what-is-styled) names the ones left out by design. The package root, `@navecss/base-ui`, re-exports the same components.
|
|
52
52
|
|
|
53
53
|
## The stylesheet
|
|
54
54
|
|
|
@@ -60,7 +60,7 @@ Import Nave's tokens, then this package's stylesheet, before any stylesheet of y
|
|
|
60
60
|
@import url('@navecss/base-ui/styles.css');
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Both files begin with Nave's `@layer` order statement, and the order holds only if that statement is the first `@layer` declaration your page sees. The stylesheet is already built: nothing in your build needs to know about Nave, so it takes no plugin and no directive. Every rule in it sits in `@layer components.nave
|
|
63
|
+
Both files begin with Nave's `@layer` order statement, and the order holds only if that statement is the first `@layer` declaration your page sees. The stylesheet is already built: nothing in your build needs to know about Nave, so it takes no plugin and no directive. Every rule in it sits in `@layer components.nave` and it declares no custom property. It sets one `z-index`, on the toast area, from `--nave-layer-toast`.
|
|
64
64
|
|
|
65
65
|
Nave's colours need Chrome or Edge 125, Firefox 128 or Safari 18, and your CSS build has to target the same floor, or it rewrites the colours into a form that does not follow the page's colour scheme. In Vite:
|
|
66
66
|
|
|
@@ -76,12 +76,14 @@ Tokens are CSS custom properties. If you scope a token yourself, set it on the p
|
|
|
76
76
|
|
|
77
77
|
The Button family takes two optional props.
|
|
78
78
|
|
|
79
|
-
| Prop | Values
|
|
80
|
-
| --------- |
|
|
81
|
-
| `variant` | `'secondary'`, `'primary'` | `'secondary'` |
|
|
82
|
-
| `size` | `'md'`, `'sm'`
|
|
79
|
+
| Prop | Values | Default |
|
|
80
|
+
| --------- | ------------------------------------- | ------------- |
|
|
81
|
+
| `variant` | `'secondary'`, `'primary'`, `'ghost'` | `'secondary'` |
|
|
82
|
+
| `size` | `'md'`, `'sm'` | `'md'` |
|
|
83
83
|
|
|
84
|
-
They are accepted by `Button`, `Toolbar.Button`, and the trigger and close parts of Dialog and Popover, `Menu.Trigger` and `Tooltip.Trigger`. `Toggle` takes `size` only. Both are typed as those unions and neither reaches the DOM as a prop.
|
|
84
|
+
They are accepted by `Button`, `Toolbar.Button`, and the trigger and close parts of Dialog, Alert Dialog and Popover, `Menu.Trigger` and `Tooltip.Trigger`. `ghost` is a button with no fill or border at rest that fills under the pointer and while the menu it opens is showing: it is the look of a Menubar's triggers. `Toggle` takes `size` only. Both are typed as those unions and neither reaches the DOM as a prop.
|
|
85
|
+
|
|
86
|
+
`Toast.Action` and `Toast.Close` take both props too. `NavigationMenu.Trigger` has a quieter look of its own and takes neither. `Avatar.Root` takes a `size` of its own: `'sm'`, `'md'` (the default) or `'lg'`.
|
|
85
87
|
|
|
86
88
|
```tsx
|
|
87
89
|
import { Button } from '@navecss/base-ui/button'
|
|
@@ -138,11 +140,229 @@ Behaviour is Base UI's. Parts Nave does not style, such as `Portal`, `Positioner
|
|
|
138
140
|
|
|
139
141
|
| Group | Subpaths |
|
|
140
142
|
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
141
|
-
| Overlays | `@navecss/base-ui/dialog`, `@navecss/base-ui/popover`, `@navecss/base-ui/menu`, `@navecss/base-ui/select`, `@navecss/base-ui/tooltip`
|
|
143
|
+
| Overlays | `@navecss/base-ui/dialog`, `@navecss/base-ui/popover`, `@navecss/base-ui/menu`, `@navecss/base-ui/select`, `@navecss/base-ui/tooltip`, `@navecss/base-ui/alert-dialog`, `@navecss/base-ui/context-menu`, `@navecss/base-ui/menubar`, `@navecss/base-ui/preview-card`, `@navecss/base-ui/combobox`, `@navecss/base-ui/autocomplete` |
|
|
142
144
|
| Disclosure | `@navecss/base-ui/accordion`, `@navecss/base-ui/collapsible`, `@navecss/base-ui/tabs` |
|
|
143
145
|
| Controls | `@navecss/base-ui/button`, `@navecss/base-ui/input`, `@navecss/base-ui/number-field`, `@navecss/base-ui/field`, `@navecss/base-ui/fieldset`, `@navecss/base-ui/form`, `@navecss/base-ui/checkbox`, `@navecss/base-ui/checkbox-group`, `@navecss/base-ui/radio`, `@navecss/base-ui/radio-group`, `@navecss/base-ui/switch`, `@navecss/base-ui/slider`, `@navecss/base-ui/toggle`, `@navecss/base-ui/toggle-group`, `@navecss/base-ui/toolbar` |
|
|
146
|
+
| Feedback | `@navecss/base-ui/toast`, `@navecss/base-ui/progress`, `@navecss/base-ui/meter` |
|
|
147
|
+
| Navigation | `@navecss/base-ui/navigation-menu`, `@navecss/base-ui/scroll-area` |
|
|
148
|
+
| Display | `@navecss/base-ui/avatar`, `@navecss/base-ui/separator` |
|
|
149
|
+
|
|
150
|
+
What this package does not paint: no backdrop colour behind a Dialog, no fill on the Slider's range, and Button sizes `md` and `sm` only. Toasts form a plain list, not a stack of cards that fans out, and there is no motion when the Navigation Menu panel closes. It paints an Alert Dialog's backdrop as a scrim and recommends no other scrim value. What it leaves out you can add with a class of your own, as above.
|
|
151
|
+
|
|
152
|
+
Menubar's menus come from `@navecss/base-ui/menu`: the same `Menu` as anywhere else, and the triggers take `variant="ghost"`.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { Menu } from '@navecss/base-ui/menu'
|
|
156
|
+
import { Menubar } from '@navecss/base-ui/menubar'
|
|
157
|
+
|
|
158
|
+
export default function AppMenubar() {
|
|
159
|
+
return (
|
|
160
|
+
<Menubar>
|
|
161
|
+
<Menu.Root>
|
|
162
|
+
<Menu.Trigger variant="ghost">File</Menu.Trigger>
|
|
163
|
+
<Menu.Portal>
|
|
164
|
+
<Menu.Positioner>
|
|
165
|
+
<Menu.Popup>
|
|
166
|
+
<Menu.Item>New</Menu.Item>
|
|
167
|
+
</Menu.Popup>
|
|
168
|
+
</Menu.Positioner>
|
|
169
|
+
</Menu.Portal>
|
|
170
|
+
</Menu.Root>
|
|
171
|
+
<Menu.Root>
|
|
172
|
+
<Menu.Trigger variant="ghost">Edit</Menu.Trigger>
|
|
173
|
+
<Menu.Portal>
|
|
174
|
+
<Menu.Positioner>
|
|
175
|
+
<Menu.Popup>
|
|
176
|
+
<Menu.Item>Undo</Menu.Item>
|
|
177
|
+
</Menu.Popup>
|
|
178
|
+
</Menu.Positioner>
|
|
179
|
+
</Menu.Portal>
|
|
180
|
+
</Menu.Root>
|
|
181
|
+
</Menubar>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
A Combobox puts its input inside an `InputGroup`:
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
import { Combobox } from '@navecss/base-ui/combobox'
|
|
190
|
+
|
|
191
|
+
export default function FruitCombobox() {
|
|
192
|
+
return (
|
|
193
|
+
<Combobox.Root items={['apple', 'banana']}>
|
|
194
|
+
<Combobox.InputGroup>
|
|
195
|
+
<Combobox.Input />
|
|
196
|
+
<Combobox.Trigger>
|
|
197
|
+
<Combobox.Icon />
|
|
198
|
+
</Combobox.Trigger>
|
|
199
|
+
</Combobox.InputGroup>
|
|
200
|
+
<Combobox.Portal>
|
|
201
|
+
<Combobox.Positioner>
|
|
202
|
+
<Combobox.Popup>
|
|
203
|
+
<Combobox.List>
|
|
204
|
+
{(item: string) => (
|
|
205
|
+
<Combobox.Item key={item} value={item}>
|
|
206
|
+
{item}
|
|
207
|
+
</Combobox.Item>
|
|
208
|
+
)}
|
|
209
|
+
</Combobox.List>
|
|
210
|
+
</Combobox.Popup>
|
|
211
|
+
</Combobox.Positioner>
|
|
212
|
+
</Combobox.Portal>
|
|
213
|
+
</Combobox.Root>
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
A right-to-left app needs both `dir="rtl"` on `<html>` (or on the element you pass as a Portal's `container`) and Base UI's `DirectionProvider`, imported from `@base-ui/react/direction-provider`, with the same direction. With only one of them, a popup that opens on the `inline-start` or `inline-end` side shows its arrow pointing away from what opened it.
|
|
219
|
+
|
|
220
|
+
Context Menu's trigger area is your own element, and Nave paints nothing on it.
|
|
221
|
+
|
|
222
|
+
Parts that Base UI added after 1.3 are exported as whatever your installed version provides. In this release the only such part is Combobox's `createItems`, added in Base UI 1.8.0. On 1.3 to 1.7 it is `undefined`, as it is in Base UI itself, and building an app that imports `@navecss/base-ui` or `@navecss/base-ui/combobox` may print a bundler warning that `createItems` has no matching export in Base UI's combobox module, even if the app never uses it. Vite prints it as `IMPORT_IS_UNDEFINED`. The warning is harmless and stops on Base UI 1.8.0. The package keeps it because avoiding it would make every app that uses `createItems` bundle all of Combobox.
|
|
223
|
+
|
|
224
|
+
The types under a part, such as `Menu.Item.Props`, take their names and type parameters from Base UI 1.3, so four that Base UI added up to 1.8.0 do not come through: `ContextMenu.Root.Actions`, the third type parameter of `Combobox.Root.Props` (`Item`), the type parameter of `NavigationMenu.Root.Props`, and `NavigationMenu.Root.Value`. Import `ContextMenuRootActions` from `@navecss/base-ui/context-menu`, `ComboboxRootProps<Value, Multiple, Item>` from `@navecss/base-ui/combobox`, and `NavigationMenuRootProps<Value>` and `NavigationMenuRoot.Value<Value>` from `@navecss/base-ui/navigation-menu` instead.
|
|
225
|
+
|
|
226
|
+
## Feedback and navigation
|
|
227
|
+
|
|
228
|
+
Toast, Navigation Menu, Scroll Area, Meter, Progress, Avatar and Separator are imported with the same prefix swap as the rest: `@navecss/base-ui/toast`, `@navecss/base-ui/navigation-menu`, `@navecss/base-ui/scroll-area`, `@navecss/base-ui/meter`, `@navecss/base-ui/progress`, `@navecss/base-ui/avatar` and `@navecss/base-ui/separator`. `Separator` is the separator the Toolbar already uses and needs nothing more.
|
|
229
|
+
|
|
230
|
+
### Toast
|
|
231
|
+
|
|
232
|
+
Toast needs one `Toast.Provider` around both the code that raises toasts and the place they appear, and you render the toasts yourself: map the `toasts` from `Toast.useToastManager()` to one `Toast.Root` each, inside `Toast.Viewport`, inside `Toast.Portal`. To raise a toast from outside React, create a manager with `Toast.createToastManager()`, pass it to the provider's `toastManager` prop and call its `add` method.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
'use client'
|
|
236
|
+
import type { ReactNode } from 'react'
|
|
237
|
+
import { Toast } from '@navecss/base-ui/toast'
|
|
238
|
+
|
|
239
|
+
export const toastManager = Toast.createToastManager()
|
|
240
|
+
|
|
241
|
+
function Toasts() {
|
|
242
|
+
const { toasts } = Toast.useToastManager()
|
|
243
|
+
return (
|
|
244
|
+
<>
|
|
245
|
+
{toasts.map((toast) => (
|
|
246
|
+
<Toast.Root key={toast.id} toast={toast}>
|
|
247
|
+
<Toast.Title />
|
|
248
|
+
<Toast.Description />
|
|
249
|
+
<Toast.Close>Dismiss</Toast.Close>
|
|
250
|
+
</Toast.Root>
|
|
251
|
+
))}
|
|
252
|
+
</>
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export default function ToastArea({ children }: { children: ReactNode }) {
|
|
257
|
+
return (
|
|
258
|
+
<Toast.Provider toastManager={toastManager}>
|
|
259
|
+
{children}
|
|
260
|
+
<Toast.Portal>
|
|
261
|
+
<Toast.Viewport>
|
|
262
|
+
<Toasts />
|
|
263
|
+
</Toast.Viewport>
|
|
264
|
+
</Toast.Portal>
|
|
265
|
+
</Toast.Provider>
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
`toastManager.add({ title: 'Saved', description: 'Your changes were saved.' })` then raises a toast from anywhere in your app.
|
|
271
|
+
|
|
272
|
+
Call `Toast.createToastManager()` in a module that starts with `'use client'`, as in the example, and import the manager from that module: every subpath of this package is a client module.
|
|
144
273
|
|
|
145
|
-
|
|
274
|
+
`Toast.Title` renders an `<h2>`. Pass `render` to use another element.
|
|
275
|
+
|
|
276
|
+
While a toast is open, pressing F6 moves keyboard focus to the region that holds the toasts, and Tab moves on into them. This is Base UI's behaviour; Nave's styles add none.
|
|
277
|
+
|
|
278
|
+
A toast closes on its own after its `timeout`, 5000 milliseconds unless you set another on the toast or on the provider. Base UI pauses that timer while the pointer is over the toasts, while keyboard focus is in them and while the window is in the background. A toast whose `timeout` is `0` stays until it is closed, which suits a toast that carries an action the reader needs.
|
|
279
|
+
|
|
280
|
+
If a toast holds a control that opens a popover, menu or other popup, give that toast a `timeout` of `0`. When keyboard focus moves into a popup rendered outside the toast area, Base UI resumes the toast's timer, so the toast can close while the popup is open, and keyboard focus is then lost.
|
|
281
|
+
|
|
282
|
+
When more toasts are open than the provider's `limit` (three unless you set it), Base UI keeps the oldest ones on the page but makes them inert, and Nave hides them. Each one comes back when a newer toast closes, unless its own timer runs out first, because a hidden toast's timer keeps running.
|
|
283
|
+
|
|
284
|
+
Nave fixes the toasts to a bottom corner of the window, above Nave's dialogs and other popups, and an anchored toast, which Base UI places beside its anchor, sits at that same level. So a toast can cover part of your page, a popup or an open dialog, including the control that has keyboard focus. If your page, popups or dialogs can put controls where toasts appear, move the toasts with your own CSS, or move an anchored toast with the `side`, `align` and `sideOffset` of its `Toast.Positioner`.
|
|
285
|
+
|
|
286
|
+
A popover, menu or tooltip opened from a toast opens under the other toasts where they overlap, unless you pass the toast viewport to its `Portal` as `container`. It then renders inside the region Base UI uses to announce toasts.
|
|
287
|
+
|
|
288
|
+
Nave paints every toast alike, whatever its `type`. Say what kind of message it is in its title or description.
|
|
289
|
+
|
|
290
|
+
Base UI moves a toast under the pointer while it is being swiped away, whatever Nave's styles and the reduced-motion setting say; `swipeDirection={[]}` on `Toast.Root` turns swiping off.
|
|
291
|
+
|
|
292
|
+
### Navigation Menu
|
|
293
|
+
|
|
294
|
+
A Navigation Menu is a `NavigationMenu.List` of `NavigationMenu.Item`s, each holding either a `NavigationMenu.Trigger` with its `NavigationMenu.Content`, or a single `NavigationMenu.Link`. The open item's content appears in one `NavigationMenu.Popup`, which you render once, after the list, through `NavigationMenu.Portal` and `NavigationMenu.Positioner`, with a `NavigationMenu.Viewport` inside it.
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { NavigationMenu } from '@navecss/base-ui/navigation-menu'
|
|
298
|
+
|
|
299
|
+
export default function SiteNav() {
|
|
300
|
+
return (
|
|
301
|
+
<NavigationMenu.Root>
|
|
302
|
+
<NavigationMenu.List>
|
|
303
|
+
<NavigationMenu.Item>
|
|
304
|
+
<NavigationMenu.Trigger>
|
|
305
|
+
Guides
|
|
306
|
+
<NavigationMenu.Icon>
|
|
307
|
+
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
|
308
|
+
<path d="M3 6l5 5 5-5" />
|
|
309
|
+
</svg>
|
|
310
|
+
</NavigationMenu.Icon>
|
|
311
|
+
</NavigationMenu.Trigger>
|
|
312
|
+
<NavigationMenu.Content>
|
|
313
|
+
<NavigationMenu.Link href="/guides/start" active>
|
|
314
|
+
Quick start
|
|
315
|
+
</NavigationMenu.Link>
|
|
316
|
+
<NavigationMenu.Link href="/guides/theming">Theming</NavigationMenu.Link>
|
|
317
|
+
</NavigationMenu.Content>
|
|
318
|
+
</NavigationMenu.Item>
|
|
319
|
+
<NavigationMenu.Item>
|
|
320
|
+
<NavigationMenu.Link href="/blog">Blog</NavigationMenu.Link>
|
|
321
|
+
</NavigationMenu.Item>
|
|
322
|
+
</NavigationMenu.List>
|
|
323
|
+
<NavigationMenu.Portal>
|
|
324
|
+
<NavigationMenu.Positioner>
|
|
325
|
+
<NavigationMenu.Popup>
|
|
326
|
+
<NavigationMenu.Viewport />
|
|
327
|
+
</NavigationMenu.Popup>
|
|
328
|
+
</NavigationMenu.Positioner>
|
|
329
|
+
</NavigationMenu.Portal>
|
|
330
|
+
</NavigationMenu.Root>
|
|
331
|
+
)
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
`NavigationMenu.Icon` turns half a turn while its item is open, so put the arrow you want turned inside it.
|
|
336
|
+
|
|
337
|
+
The panel takes the size of the open item's content, and changes size at once when you move to another item: Nave does not animate it.
|
|
338
|
+
|
|
339
|
+
Pass `active` to the `NavigationMenu.Link` for the page the reader is on. Base UI then gives it `aria-current="page"`, which marks it as the current page for assistive technology, and Nave gives it a thicker underline than the other links.
|
|
340
|
+
|
|
341
|
+
Nave removes the bullets from `NavigationMenu.List`. Safari still treats it as a list for screen readers because Base UI renders it inside a `nav` element; if you give the menu's root or popup another element through `render`, add `role="list"` to the list.
|
|
342
|
+
|
|
343
|
+
Nave does not dim a disabled `NavigationMenu.Trigger` and only withholds its hover fill, because before Base UI 1.6 a disabled trigger still opens its menu on hover. If you disable one, style it yourself.
|
|
344
|
+
|
|
345
|
+
### Scroll Area
|
|
346
|
+
|
|
347
|
+
Give `ScrollArea.Root` a height in a class of your own, with `block-size` or `max-block-size`, and its viewport fills it. Render one `ScrollArea.Scrollbar` with a `ScrollArea.Thumb` for each direction that can scroll, and a `ScrollArea.Corner` when both can: Base UI hides the browser's own scrollbars, so a direction without them shows none. Base UI does that with a `<style>` element it renders, so under a Content Security Policy pass your nonce through Base UI's `CSPProvider`. Nave gives the scrollbar and the corner the page's base surface; on a raised panel, set the panel's `background-color` on both with a class of your own.
|
|
348
|
+
|
|
349
|
+
While its content overflows, a Scroll Area's viewport is a Tab stop, so a keyboard can reach and scroll it. Nave leaves its focus ring to the browser and paints the scrollbars whenever there is something to scroll.
|
|
350
|
+
|
|
351
|
+
If you pass `keepMounted` to a `ScrollArea.Scrollbar`, it stays on screen over the edge of the content even when there is nothing to scroll in its direction, but Nave makes room for a scrollbar only while its direction can scroll. Give the viewport that room yourself on that edge, as both `padding` and `scroll-padding`: `calc(var(--nave-size-control-xs) + var(--nave-spacing-control-xs))`.
|
|
352
|
+
|
|
353
|
+
### Meter and Progress
|
|
354
|
+
|
|
355
|
+
Meter and Progress draw their value as a bar inside an outlined track, in the text colour: set `color` on the `Indicator` to change it. Making the `Track` taller leaves the bar as thick as Nave draws it, centred in the track. To draw it thicker, set the `Indicator`'s `border-block-width` to half the thickness you want and its `max-block-size` to the whole of it, in a class of your own.
|
|
356
|
+
|
|
357
|
+
Meter and Progress look alike in Nave, but Base UI gives Meter the `meter` role and Progress the `progressbar` role, so choose by meaning: Meter for a measurement within a known range, such as storage used, and Progress for how far a task has got.
|
|
358
|
+
|
|
359
|
+
An indeterminate Progress (`value={null}`) shows only its empty track: Nave hides the bar, because a full bar would look like a finished task. If you restyle Progress, give the track its height, not the indicator, or an indeterminate bar will fill the track.
|
|
360
|
+
|
|
361
|
+
### Avatar
|
|
362
|
+
|
|
363
|
+
`Avatar.Fallback` takes Base UI's `delay` prop, which holds the fallback back for that many milliseconds, so an image that loads quickly does not flash it.
|
|
364
|
+
|
|
365
|
+
Give `Avatar.Image` an `alt` that names the person, or `alt=""` when their name is written next to it. Until the image loads, or if it fails to load, Base UI shows the fallback in its place, and a screen reader reads the fallback's text instead.
|
|
146
366
|
|
|
147
367
|
## Things to know
|
|
148
368
|
|
|
@@ -179,9 +399,19 @@ The Accordion and Collapsible panels set `overflow: hidden` so their height can
|
|
|
179
399
|
|
|
180
400
|
When nothing inside a popup can take focus, Base UI focuses the popup itself and the browser draws its focus ring around the panel. This package leaves that ring alone. Removing it with `outline: 0`, as Base UI's own demos do, leaves a keyboard user with no visible sign of where focus is.
|
|
181
401
|
|
|
402
|
+
In Combobox and Autocomplete, keyboard focus stays in the text field while the arrow keys move through the list, so Nave marks the option that Enter will choose with the same ring it draws around a focused control. Hovering an option makes it the one Enter chooses, so the ring follows the pointer too. The ring is drawn on the option's `::before`; a rule of yours that sets `::before` on options replaces it.
|
|
403
|
+
|
|
404
|
+
Nave draws the Combobox and Autocomplete field's border on `InputGroup`, not on the input. If you place the input outside an `InputGroup`, wrap it in an element with a visible border of your own, or the field has no visible edge until it is focused.
|
|
405
|
+
|
|
406
|
+
In Chromium, opening a Context Menu with a right-click shows focus rings: the browser's own ring around the menu, then a focus ring on whichever item the pointer is over. Chromium decides when a focus ring shows; Nave does not hide it, and other browsers may show it differently.
|
|
407
|
+
|
|
408
|
+
A Preview Card opens when its link is hovered or focused, but its contents are not reachable with Tab: the next Tab moves past the card and closes it. Keep anything a reader must act on, such as a link or a button, out of the card, or offer it on the page as well.
|
|
409
|
+
|
|
410
|
+
In a Menubar, moving to the next menu with the arrow keys puts focus on that menu's panel before any item, so the browser's ring around the panel shows where you are until the next arrow key reaches an item.
|
|
411
|
+
|
|
182
412
|
In Base UI 1.8.0, `Menu.LinkItem` has no disabled state: a `disabled` prop reaches the `<a>` as a plain attribute, the link still activates, and it does not take the disabled colour Nave gives the other menu items.
|
|
183
413
|
|
|
184
|
-
When the reader's system asks for reduced motion, this package turns off the motion of Accordion and Collapsible panels opening and closing, the turn of the icon in their triggers and the switch's slide, even if you have changed Nave's motion tokens. Motion you add or restyle yourself is yours to switch off.
|
|
414
|
+
When the reader's system asks for reduced motion, this package turns off the popups' fade, the tooltip's fade, the backdrop's fade, the toasts' fade, the turn of the icon in Navigation Menu triggers, the tab indicator's slide, the motion of Accordion and Collapsible panels opening and closing, the turn of the icon in their triggers and the switch's slide, even if you have changed Nave's motion tokens. Motion you add or restyle yourself is yours to switch off.
|
|
185
415
|
|
|
186
416
|
## License
|
|
187
417
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ReactElement, RefAttributes } from 'react';
|
|
2
|
+
import { AlertDialog as Base } from '@base-ui/react/alert-dialog';
|
|
3
|
+
import { type VariantProps } from '../part.ts';
|
|
4
|
+
export declare const Root: typeof Base.Root;
|
|
5
|
+
export declare namespace Root {
|
|
6
|
+
type State = Base.Root.State;
|
|
7
|
+
type Props<Payload = unknown> = Base.Root.Props<Payload>;
|
|
8
|
+
type Actions = Base.Root.Actions;
|
|
9
|
+
type ChangeEventReason = Base.Root.ChangeEventReason;
|
|
10
|
+
type ChangeEventDetails = Base.Root.ChangeEventDetails;
|
|
11
|
+
}
|
|
12
|
+
export declare const Backdrop: typeof Base.Backdrop;
|
|
13
|
+
export declare namespace Backdrop {
|
|
14
|
+
type Props = Base.Backdrop.Props;
|
|
15
|
+
type State = Base.Backdrop.State;
|
|
16
|
+
}
|
|
17
|
+
export declare const Close: (props: Omit<Base.Close.Props, 'ref'> & RefAttributes<HTMLButtonElement> & VariantProps) => ReactElement;
|
|
18
|
+
export declare namespace Close {
|
|
19
|
+
type Props = Base.Close.Props & VariantProps;
|
|
20
|
+
type State = Base.Close.State;
|
|
21
|
+
}
|
|
22
|
+
export declare const Description: typeof Base.Description;
|
|
23
|
+
export declare namespace Description {
|
|
24
|
+
type Props = Base.Description.Props;
|
|
25
|
+
type State = Base.Description.State;
|
|
26
|
+
}
|
|
27
|
+
export declare const Popup: typeof Base.Popup;
|
|
28
|
+
export declare namespace Popup {
|
|
29
|
+
type Props = Base.Popup.Props;
|
|
30
|
+
type State = Base.Popup.State;
|
|
31
|
+
}
|
|
32
|
+
export declare const Portal: typeof Base.Portal;
|
|
33
|
+
export declare namespace Portal {
|
|
34
|
+
type State = Base.Portal.State;
|
|
35
|
+
type Props = Base.Portal.Props;
|
|
36
|
+
}
|
|
37
|
+
export declare const Title: typeof Base.Title;
|
|
38
|
+
export declare namespace Title {
|
|
39
|
+
type Props = Base.Title.Props;
|
|
40
|
+
type State = Base.Title.State;
|
|
41
|
+
}
|
|
42
|
+
export declare const Trigger: <Payload>(props: Omit<Base.Trigger.Props<Payload>, 'ref'> & RefAttributes<HTMLElement> & VariantProps) => ReactElement;
|
|
43
|
+
export type Trigger = typeof Trigger;
|
|
44
|
+
export declare namespace Trigger {
|
|
45
|
+
type Props<Payload = unknown> = Base.Trigger.Props<Payload> & VariantProps;
|
|
46
|
+
type State = Base.Trigger.State;
|
|
47
|
+
}
|
|
48
|
+
export declare const Viewport: typeof Base.Viewport;
|
|
49
|
+
export declare namespace Viewport {
|
|
50
|
+
type State = Base.Viewport.State;
|
|
51
|
+
type Props = Base.Viewport.Props;
|
|
52
|
+
}
|
|
53
|
+
export declare const Handle: typeof Base.Handle;
|
|
54
|
+
export type Handle<Payload> = Base.Handle<Payload>;
|
|
55
|
+
export declare const createHandle: typeof Base.createHandle;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { AlertDialog as Base } from '@base-ui/react/alert-dialog';
|
|
3
|
+
import { wrapPart, wrapVariantPart } from "../part.js";
|
|
4
|
+
export const Root = /*#__PURE__*/ (() => Base.Root)();
|
|
5
|
+
export const Backdrop = /*#__PURE__*/ (() => wrapPart(Base.Backdrop, 'nave-base-ui-backdrop'))();
|
|
6
|
+
export const Close = /*#__PURE__*/ (() => wrapVariantPart(Base.Close, 'nave-base-ui-button'))();
|
|
7
|
+
export const Description = /*#__PURE__*/ (() => wrapPart(Base.Description, 'nave-base-ui-description'))();
|
|
8
|
+
export const Popup = /*#__PURE__*/ (() => wrapPart(Base.Popup, 'nave-base-ui-dialog-popup nave-base-ui-popup-fade'))();
|
|
9
|
+
export const Portal = /*#__PURE__*/ (() => Base.Portal)();
|
|
10
|
+
export const Title = /*#__PURE__*/ (() => wrapPart(Base.Title, 'nave-base-ui-title'))();
|
|
11
|
+
export const Trigger = /*#__PURE__*/ (() => wrapVariantPart(Base.Trigger, 'nave-base-ui-button'))();
|
|
12
|
+
export const Viewport = /*#__PURE__*/ (() => Base.Viewport)();
|
|
13
|
+
export const Handle = /*#__PURE__*/ (() => Base.Handle)();
|
|
14
|
+
export const createHandle = /*#__PURE__*/ (() => Base.createHandle)();
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Autocomplete as Base } from '@base-ui/react/autocomplete';
|
|
2
|
+
export declare const Root: typeof Base.Root;
|
|
3
|
+
export declare namespace Root {
|
|
4
|
+
type Props<ItemValue> = Base.Root.Props<ItemValue>;
|
|
5
|
+
type State = Base.Root.State;
|
|
6
|
+
type Actions = Base.Root.Actions;
|
|
7
|
+
type ChangeEventReason = Base.Root.ChangeEventReason;
|
|
8
|
+
type ChangeEventDetails = Base.Root.ChangeEventDetails;
|
|
9
|
+
type HighlightEventReason = Base.Root.HighlightEventReason;
|
|
10
|
+
type HighlightEventDetails = Base.Root.HighlightEventDetails;
|
|
11
|
+
}
|
|
12
|
+
export declare const Value: typeof Base.Value;
|
|
13
|
+
export declare namespace Value {
|
|
14
|
+
type State = Base.Value.State;
|
|
15
|
+
type Props = Base.Value.Props;
|
|
16
|
+
}
|
|
17
|
+
export declare const Trigger: typeof Base.Trigger;
|
|
18
|
+
export type Trigger = typeof Trigger;
|
|
19
|
+
export declare namespace Trigger {
|
|
20
|
+
type State = Base.Trigger.State;
|
|
21
|
+
type Props = Base.Trigger.Props;
|
|
22
|
+
}
|
|
23
|
+
export declare const Input: typeof Base.Input;
|
|
24
|
+
export declare namespace Input {
|
|
25
|
+
type State = Base.Input.State;
|
|
26
|
+
type Props = Base.Input.Props;
|
|
27
|
+
}
|
|
28
|
+
export declare const InputGroup: typeof Base.InputGroup;
|
|
29
|
+
export type InputGroup = typeof InputGroup;
|
|
30
|
+
export declare namespace InputGroup {
|
|
31
|
+
type State = Base.InputGroup.State;
|
|
32
|
+
type Props = Base.InputGroup.Props;
|
|
33
|
+
}
|
|
34
|
+
export declare const Icon: typeof Base.Icon;
|
|
35
|
+
export declare namespace Icon {
|
|
36
|
+
type State = Base.Icon.State;
|
|
37
|
+
type Props = Base.Icon.Props;
|
|
38
|
+
}
|
|
39
|
+
export declare const Clear: typeof Base.Clear;
|
|
40
|
+
export declare namespace Clear {
|
|
41
|
+
type State = Base.Clear.State;
|
|
42
|
+
type Props = Base.Clear.Props;
|
|
43
|
+
}
|
|
44
|
+
export declare const List: typeof Base.List;
|
|
45
|
+
export declare namespace List {
|
|
46
|
+
type State = Base.List.State;
|
|
47
|
+
type Props = Base.List.Props;
|
|
48
|
+
}
|
|
49
|
+
export declare const Status: typeof Base.Status;
|
|
50
|
+
export declare namespace Status {
|
|
51
|
+
type State = Base.Status.State;
|
|
52
|
+
type Props = Base.Status.Props;
|
|
53
|
+
}
|
|
54
|
+
export declare const Portal: typeof Base.Portal;
|
|
55
|
+
export declare namespace Portal {
|
|
56
|
+
type State = Base.Portal.State;
|
|
57
|
+
type Props = Base.Portal.Props;
|
|
58
|
+
}
|
|
59
|
+
export declare const Backdrop: typeof Base.Backdrop;
|
|
60
|
+
export declare namespace Backdrop {
|
|
61
|
+
type Props = Base.Backdrop.Props;
|
|
62
|
+
type State = Base.Backdrop.State;
|
|
63
|
+
}
|
|
64
|
+
export declare const Positioner: typeof Base.Positioner;
|
|
65
|
+
export declare namespace Positioner {
|
|
66
|
+
type State = Base.Positioner.State;
|
|
67
|
+
type Props = Base.Positioner.Props;
|
|
68
|
+
}
|
|
69
|
+
export declare const Popup: typeof Base.Popup;
|
|
70
|
+
export declare namespace Popup {
|
|
71
|
+
type State = Base.Popup.State;
|
|
72
|
+
type Props = Base.Popup.Props;
|
|
73
|
+
}
|
|
74
|
+
export declare const Arrow: typeof Base.Arrow;
|
|
75
|
+
export declare namespace Arrow {
|
|
76
|
+
type State = Base.Arrow.State;
|
|
77
|
+
type Props = Base.Arrow.Props;
|
|
78
|
+
}
|
|
79
|
+
export declare const Group: typeof Base.Group;
|
|
80
|
+
export declare namespace Group {
|
|
81
|
+
type State = Base.Group.State;
|
|
82
|
+
type Props = Base.Group.Props;
|
|
83
|
+
}
|
|
84
|
+
export declare const GroupLabel: typeof Base.GroupLabel;
|
|
85
|
+
export declare namespace GroupLabel {
|
|
86
|
+
type State = Base.GroupLabel.State;
|
|
87
|
+
type Props = Base.GroupLabel.Props;
|
|
88
|
+
}
|
|
89
|
+
export declare const Item: typeof Base.Item;
|
|
90
|
+
export type Item = typeof Item;
|
|
91
|
+
export declare namespace Item {
|
|
92
|
+
type State = Base.Item.State;
|
|
93
|
+
type Props = Base.Item.Props;
|
|
94
|
+
}
|
|
95
|
+
export declare const Row: typeof Base.Row;
|
|
96
|
+
export declare namespace Row {
|
|
97
|
+
type State = Base.Row.State;
|
|
98
|
+
type Props = Base.Row.Props;
|
|
99
|
+
}
|
|
100
|
+
export declare const Collection: typeof Base.Collection;
|
|
101
|
+
export declare namespace Collection {
|
|
102
|
+
type State = Base.Collection.State;
|
|
103
|
+
type Props = Base.Collection.Props;
|
|
104
|
+
}
|
|
105
|
+
export declare const Empty: typeof Base.Empty;
|
|
106
|
+
export declare namespace Empty {
|
|
107
|
+
type State = Base.Empty.State;
|
|
108
|
+
type Props = Base.Empty.Props;
|
|
109
|
+
}
|
|
110
|
+
export declare const Separator: typeof Base.Separator;
|
|
111
|
+
export declare namespace Separator {
|
|
112
|
+
type Props = Base.Separator.Props;
|
|
113
|
+
type State = Base.Separator.State;
|
|
114
|
+
}
|
|
115
|
+
export declare const useFilter: typeof Base.useFilter;
|
|
116
|
+
export declare const useFilteredItems: typeof Base.useFilteredItems;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
// Generated by scripts/generate-wrappers.ts: change the roster or the generator, not this file.
|
|
3
|
+
import { Autocomplete as Base } from '@base-ui/react/autocomplete';
|
|
4
|
+
import { wrapPart } from "../part.js";
|
|
5
|
+
export const Root = /*#__PURE__*/ (() => Base.Root)();
|
|
6
|
+
export const Value = /*#__PURE__*/ (() => Base.Value)();
|
|
7
|
+
export const Trigger = /*#__PURE__*/ (() => wrapPart(Base.Trigger, 'nave-base-ui-combobox-trigger'))();
|
|
8
|
+
export const Input = /*#__PURE__*/ (() => wrapPart(Base.Input, 'nave-base-ui-number-field-input'))();
|
|
9
|
+
export const InputGroup = /*#__PURE__*/ (() => wrapPart(Base.InputGroup, 'nave-base-ui-input-group'))();
|
|
10
|
+
export const Icon = /*#__PURE__*/ (() => wrapPart(Base.Icon, 'nave-base-ui-select-icon'))();
|
|
11
|
+
export const Clear = /*#__PURE__*/ (() => wrapPart(Base.Clear, 'nave-base-ui-number-field-stepper'))();
|
|
12
|
+
export const List = /*#__PURE__*/ (() => Base.List)();
|
|
13
|
+
export const Status = /*#__PURE__*/ (() => Base.Status)();
|
|
14
|
+
export const Portal = /*#__PURE__*/ (() => Base.Portal)();
|
|
15
|
+
export const Backdrop = /*#__PURE__*/ (() => Base.Backdrop)();
|
|
16
|
+
export const Positioner = /*#__PURE__*/ (() => Base.Positioner)();
|
|
17
|
+
export const Popup = /*#__PURE__*/ (() => wrapPart(Base.Popup, 'nave-base-ui-list-popup nave-base-ui-popup-fade'))();
|
|
18
|
+
export const Arrow = /*#__PURE__*/ (() => wrapPart(Base.Arrow, 'nave-base-ui-arrow nave-base-ui-arrow-inline'))();
|
|
19
|
+
export const Group = /*#__PURE__*/ (() => Base.Group)();
|
|
20
|
+
export const GroupLabel = /*#__PURE__*/ (() => wrapPart(Base.GroupLabel, 'nave-base-ui-group-label'))();
|
|
21
|
+
export const Item = /*#__PURE__*/ (() => wrapPart(Base.Item, 'nave-base-ui-item nave-base-ui-item-highlight nave-base-ui-active-option'))();
|
|
22
|
+
export const Row = /*#__PURE__*/ (() => Base.Row)();
|
|
23
|
+
export const Collection = /*#__PURE__*/ (() => Base.Collection)();
|
|
24
|
+
export const Empty = /*#__PURE__*/ (() => wrapPart(Base.Empty, 'nave-base-ui-list-empty'))();
|
|
25
|
+
export const Separator = /*#__PURE__*/ (() => wrapPart(Base.Separator, 'nave-base-ui-separator'))();
|
|
26
|
+
export const useFilter = /*#__PURE__*/ (() => Base.useFilter)();
|
|
27
|
+
export const useFilteredItems = /*#__PURE__*/ (() => Base.useFilteredItems)();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactElement, RefAttributes } from 'react';
|
|
2
|
+
import { Avatar as Base } from '@base-ui/react/avatar';
|
|
3
|
+
import { type AvatarProps } from '../part.ts';
|
|
4
|
+
export declare const Root: (props: Omit<Base.Root.Props, 'ref'> & RefAttributes<HTMLSpanElement> & AvatarProps) => ReactElement;
|
|
5
|
+
export declare namespace Root {
|
|
6
|
+
type State = Base.Root.State;
|
|
7
|
+
type Props = Base.Root.Props & AvatarProps;
|
|
8
|
+
}
|
|
9
|
+
export declare const Image: typeof Base.Image;
|
|
10
|
+
export declare namespace Image {
|
|
11
|
+
type State = Base.Image.State;
|
|
12
|
+
type Props = Base.Image.Props;
|
|
13
|
+
}
|
|
14
|
+
export declare const Fallback: typeof Base.Fallback;
|
|
15
|
+
export declare namespace Fallback {
|
|
16
|
+
type State = Base.Fallback.State;
|
|
17
|
+
type Props = Base.Fallback.Props;
|
|
18
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Avatar as Base } from '@base-ui/react/avatar';
|
|
3
|
+
import { wrapAvatarPart, wrapPart } from "../part.js";
|
|
4
|
+
export const Root = /*#__PURE__*/ (() => wrapAvatarPart(Base.Root, 'nave-base-ui-avatar'))();
|
|
5
|
+
export const Image = /*#__PURE__*/ (() => wrapPart(Base.Image, 'nave-base-ui-avatar-image'))();
|
|
6
|
+
export const Fallback = /*#__PURE__*/ (() => wrapPart(Base.Fallback, 'nave-base-ui-avatar-fallback'))();
|