@navecss/base-ui 0.0.0-stage → 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.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +417 -2
  3. package/dist/accordion/index.d.ts +2 -0
  4. package/dist/accordion/index.js +2 -0
  5. package/dist/accordion/parts.generated.d.ts +31 -0
  6. package/dist/accordion/parts.generated.js +9 -0
  7. package/dist/alert-dialog/index.d.ts +2 -0
  8. package/dist/alert-dialog/index.js +2 -0
  9. package/dist/alert-dialog/parts.generated.d.ts +55 -0
  10. package/dist/alert-dialog/parts.generated.js +14 -0
  11. package/dist/autocomplete/index.d.ts +2 -0
  12. package/dist/autocomplete/index.js +2 -0
  13. package/dist/autocomplete/parts.generated.d.ts +116 -0
  14. package/dist/autocomplete/parts.generated.js +27 -0
  15. package/dist/avatar/index.d.ts +2 -0
  16. package/dist/avatar/index.js +2 -0
  17. package/dist/avatar/parts.generated.d.ts +18 -0
  18. package/dist/avatar/parts.generated.js +6 -0
  19. package/dist/button/index.d.ts +2 -0
  20. package/dist/button/index.js +3 -0
  21. package/dist/button/parts.generated.d.ts +8 -0
  22. package/dist/button/parts.generated.js +4 -0
  23. package/dist/checkbox/index.d.ts +2 -0
  24. package/dist/checkbox/index.js +2 -0
  25. package/dist/checkbox/parts.generated.d.ts +13 -0
  26. package/dist/checkbox/parts.generated.js +6 -0
  27. package/dist/checkbox-group/index.d.ts +2 -0
  28. package/dist/checkbox-group/index.js +3 -0
  29. package/dist/checkbox-group/parts.generated.d.ts +8 -0
  30. package/dist/checkbox-group/parts.generated.js +5 -0
  31. package/dist/collapsible/index.d.ts +2 -0
  32. package/dist/collapsible/index.js +2 -0
  33. package/dist/collapsible/parts.generated.d.ts +18 -0
  34. package/dist/collapsible/parts.generated.js +7 -0
  35. package/dist/combobox/index.d.ts +2 -0
  36. package/dist/combobox/index.js +2 -0
  37. package/dist/combobox/parts.generated.d.ts +140 -0
  38. package/dist/combobox/parts.generated.js +33 -0
  39. package/dist/context-menu/index.d.ts +2 -0
  40. package/dist/context-menu/index.js +2 -0
  41. package/dist/context-menu/parts.generated.d.ts +104 -0
  42. package/dist/context-menu/parts.generated.js +23 -0
  43. package/dist/dialog/index.d.ts +2 -0
  44. package/dist/dialog/index.js +2 -0
  45. package/dist/dialog/parts.generated.d.ts +55 -0
  46. package/dist/dialog/parts.generated.js +14 -0
  47. package/dist/field/index.d.ts +2 -0
  48. package/dist/field/index.js +2 -0
  49. package/dist/field/parts.generated.d.ts +41 -0
  50. package/dist/field/parts.generated.js +12 -0
  51. package/dist/fieldset/index.d.ts +2 -0
  52. package/dist/fieldset/index.js +2 -0
  53. package/dist/fieldset/parts.generated.d.ts +11 -0
  54. package/dist/fieldset/parts.generated.js +6 -0
  55. package/dist/form/index.d.ts +2 -0
  56. package/dist/form/index.js +3 -0
  57. package/dist/form/parts.generated.d.ts +11 -0
  58. package/dist/form/parts.generated.js +4 -0
  59. package/dist/index.d.ts +36 -0
  60. package/dist/index.js +37 -0
  61. package/dist/input/index.d.ts +2 -0
  62. package/dist/input/index.js +3 -0
  63. package/dist/input/parts.generated.d.ts +8 -0
  64. package/dist/input/parts.generated.js +5 -0
  65. package/dist/menu/index.d.ts +2 -0
  66. package/dist/menu/index.js +2 -0
  67. package/dist/menu/parts.generated.d.ts +117 -0
  68. package/dist/menu/parts.generated.js +25 -0
  69. package/dist/menubar/index.d.ts +2 -0
  70. package/dist/menubar/index.js +3 -0
  71. package/dist/menubar/parts.generated.d.ts +6 -0
  72. package/dist/menubar/parts.generated.js +5 -0
  73. package/dist/meter/index.d.ts +2 -0
  74. package/dist/meter/index.js +2 -0
  75. package/dist/meter/parts.generated.d.ts +26 -0
  76. package/dist/meter/parts.generated.js +9 -0
  77. package/dist/navigation-menu/index.d.ts +2 -0
  78. package/dist/navigation-menu/index.js +2 -0
  79. package/dist/navigation-menu/parts.generated.d.ts +69 -0
  80. package/dist/navigation-menu/parts.generated.js +17 -0
  81. package/dist/number-field/index.d.ts +2 -0
  82. package/dist/number-field/index.js +2 -0
  83. package/dist/number-field/parts.generated.d.ts +40 -0
  84. package/dist/number-field/parts.generated.js +11 -0
  85. package/dist/part.d.ts +39 -0
  86. package/dist/part.js +66 -0
  87. package/dist/popover/index.d.ts +2 -0
  88. package/dist/popover/index.js +2 -0
  89. package/dist/popover/parts.generated.d.ts +65 -0
  90. package/dist/popover/parts.generated.js +16 -0
  91. package/dist/preview-card/index.d.ts +2 -0
  92. package/dist/preview-card/index.js +2 -0
  93. package/dist/preview-card/parts.generated.d.ts +48 -0
  94. package/dist/preview-card/parts.generated.js +14 -0
  95. package/dist/progress/index.d.ts +2 -0
  96. package/dist/progress/index.js +2 -0
  97. package/dist/progress/parts.generated.d.ts +27 -0
  98. package/dist/progress/parts.generated.js +9 -0
  99. package/dist/radio/index.d.ts +2 -0
  100. package/dist/radio/index.js +2 -0
  101. package/dist/radio/parts.generated.d.ts +11 -0
  102. package/dist/radio/parts.generated.js +6 -0
  103. package/dist/radio-group/index.d.ts +2 -0
  104. package/dist/radio-group/index.js +3 -0
  105. package/dist/radio-group/parts.generated.d.ts +8 -0
  106. package/dist/radio-group/parts.generated.js +5 -0
  107. package/dist/scroll-area/index.d.ts +2 -0
  108. package/dist/scroll-area/index.js +2 -0
  109. package/dist/scroll-area/parts.generated.d.ts +31 -0
  110. package/dist/scroll-area/parts.generated.js +10 -0
  111. package/dist/select/index.d.ts +2 -0
  112. package/dist/select/index.js +2 -0
  113. package/dist/select/parts.generated.d.ts +99 -0
  114. package/dist/select/parts.generated.js +23 -0
  115. package/dist/separator/index.d.ts +2 -0
  116. package/dist/separator/index.js +3 -0
  117. package/dist/separator/parts.generated.d.ts +6 -0
  118. package/dist/separator/parts.generated.js +5 -0
  119. package/dist/slider/index.d.ts +2 -0
  120. package/dist/slider/index.js +2 -0
  121. package/dist/slider/parts.generated.d.ts +40 -0
  122. package/dist/slider/parts.generated.js +11 -0
  123. package/dist/styles.css +290 -0
  124. package/dist/switch/index.d.ts +2 -0
  125. package/dist/switch/index.js +2 -0
  126. package/dist/switch/parts.generated.d.ts +13 -0
  127. package/dist/switch/parts.generated.js +6 -0
  128. package/dist/tabs/index.d.ts +2 -0
  129. package/dist/tabs/index.js +2 -0
  130. package/dist/tabs/parts.generated.d.ts +35 -0
  131. package/dist/tabs/parts.generated.js +9 -0
  132. package/dist/toast/index.d.ts +2 -0
  133. package/dist/toast/index.js +2 -0
  134. package/dist/toast/parts.generated.d.ts +61 -0
  135. package/dist/toast/parts.generated.js +16 -0
  136. package/dist/toggle/index.d.ts +2 -0
  137. package/dist/toggle/index.js +3 -0
  138. package/dist/toggle/parts.generated.d.ts +10 -0
  139. package/dist/toggle/parts.generated.js +4 -0
  140. package/dist/toggle-group/index.d.ts +2 -0
  141. package/dist/toggle-group/index.js +3 -0
  142. package/dist/toggle-group/parts.generated.d.ts +8 -0
  143. package/dist/toggle-group/parts.generated.js +5 -0
  144. package/dist/toolbar/index.d.ts +2 -0
  145. package/dist/toolbar/index.js +2 -0
  146. package/dist/toolbar/parts.generated.d.ts +36 -0
  147. package/dist/toolbar/parts.generated.js +9 -0
  148. package/dist/tooltip/index.d.ts +2 -0
  149. package/dist/tooltip/index.js +2 -0
  150. package/dist/tooltip/parts.generated.d.ts +50 -0
  151. package/dist/tooltip/parts.generated.js +13 -0
  152. package/package.json +259 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nave Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,418 @@
1
- # Temporary Holding Version
1
+ # @navecss/base-ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ NaveCSS styles Base UI's components with Nave's tokens: the same parts, the same props, pre-styled.
4
+
5
+ This package is not affiliated with, endorsed by or sponsored by MUI or the Base UI project.
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, 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
+
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
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pnpm add @navecss/base-ui @navecss/tokens @base-ui/react react react-dom
15
+ ```
16
+
17
+ ```bash
18
+ npm install @navecss/base-ui @navecss/tokens @base-ui/react react react-dom
19
+ ```
20
+
21
+ It needs `@base-ui/react` 1.3 or later in the 1.x line, React 18 or 19, and `@navecss/tokens`. It does not need `@navecss/core`.
22
+
23
+ ## Use it
24
+
25
+ Change the prefix of an import, and nothing else:
26
+
27
+ ```ts
28
+ import { Dialog } from '@base-ui/react/dialog'
29
+ ```
30
+
31
+ ```tsx
32
+ import { Dialog } from '@navecss/base-ui/dialog'
33
+
34
+ export default function RenameDialog() {
35
+ return (
36
+ <Dialog.Root>
37
+ <Dialog.Trigger>Rename</Dialog.Trigger>
38
+ <Dialog.Portal>
39
+ <Dialog.Backdrop />
40
+ <Dialog.Popup>
41
+ <Dialog.Title>Rename file</Dialog.Title>
42
+ <Dialog.Description>Choose a new name for this file.</Dialog.Description>
43
+ <Dialog.Close>Done</Dialog.Close>
44
+ </Dialog.Popup>
45
+ </Dialog.Portal>
46
+ </Dialog.Root>
47
+ )
48
+ }
49
+ ```
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 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
+
53
+ ## The stylesheet
54
+
55
+ Import Nave's tokens, then this package's stylesheet, before any stylesheet of yours that declares a `@layer`:
56
+
57
+ ```css
58
+ /* app.css */
59
+ @import url('@navecss/tokens/css');
60
+ @import url('@navecss/base-ui/styles.css');
61
+ ```
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` and it declares no custom property. It sets one `z-index`, on the toast area, from `--nave-layer-toast`.
64
+
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
+
67
+ ```text
68
+ build: { cssTarget: ['chrome125', 'edge125', 'firefox128', 'safari18', 'ios18'] },
69
+ ```
70
+
71
+ [Why that floor](https://github.com/navecss/navecss/blob/main/docs/04-adr/0005-browser-floor.md).
72
+
73
+ Tokens are CSS custom properties. If you scope a token yourself, set it on the part's own class or on `:root`, never on an ancestor of a part Base UI portals: a portalled popup renders outside that ancestor, so the token never reaches it.
74
+
75
+ ## Variants
76
+
77
+ The Button family takes two optional props.
78
+
79
+ | Prop | Values | Default |
80
+ | --------- | ------------------------------------- | ------------- |
81
+ | `variant` | `'secondary'`, `'primary'`, `'ghost'` | `'secondary'` |
82
+ | `size` | `'md'`, `'sm'` | `'md'` |
83
+
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'`.
87
+
88
+ ```tsx
89
+ import { Button } from '@navecss/base-ui/button'
90
+
91
+ export default function SaveButton() {
92
+ return (
93
+ <Button variant="primary" size="sm">
94
+ Save
95
+ </Button>
96
+ )
97
+ }
98
+ ```
99
+
100
+ ## Overriding
101
+
102
+ There are three steps, from the lightest:
103
+
104
+ 1. **Tokens.** Re-theme with Nave's tokens and every part follows. Nothing else is needed for a different palette, radius or spacing.
105
+ 2. **`className`.** Pass a class to any part, as a string or as Base UI's function of the part's state. Put its rules in `@layer components.consumer`: that layer comes after Nave's, so your class wins in every state, whatever the specificity of Nave's rule. It also means that restyling a property restyles it in every state: set `background-color` on a Button and your colour replaces the `primary` variant's hover and active colours and a disabled button's too, so write the states you want yourself.
106
+ 3. **The raw Base UI part.** Import the part from `@base-ui/react/<component>` and style it from scratch. It mixes freely with wrapped parts.
107
+
108
+ ```css
109
+ /* menu.module.css */
110
+ @layer components.consumer {
111
+ .popup {
112
+ border-radius: var(--nave-radius-control);
113
+ }
114
+ }
115
+ ```
116
+
117
+ ```tsx
118
+ import { Menu } from '@navecss/base-ui/menu'
119
+
120
+ export default function ActionsMenu() {
121
+ return (
122
+ <Menu.Root>
123
+ <Menu.Trigger>Actions</Menu.Trigger>
124
+ <Menu.Portal>
125
+ <Menu.Positioner>
126
+ <Menu.Popup className="popup">
127
+ <Menu.Item>Rename</Menu.Item>
128
+ <Menu.Item>Delete</Menu.Item>
129
+ </Menu.Popup>
130
+ </Menu.Positioner>
131
+ </Menu.Portal>
132
+ </Menu.Root>
133
+ )
134
+ }
135
+ ```
136
+
137
+ Behaviour is Base UI's. Parts Nave does not style, such as `Portal`, `Positioner`, `Provider` and `Form`, are Base UI's own parts, passed through unchanged.
138
+
139
+ ## What is styled
140
+
141
+ | Group | Subpaths |
142
+ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
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` |
144
+ | Disclosure | `@navecss/base-ui/accordion`, `@navecss/base-ui/collapsible`, `@navecss/base-ui/tabs` |
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.
273
+
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.
366
+
367
+ ## Things to know
368
+
369
+ When a disclosure trigger's last child is an `svg`, that icon turns when the panel opens. A lone icon counts as the last child, so put a decorative leading icon inside an element of its own:
370
+
371
+ ```tsx
372
+ import { Accordion } from '@navecss/base-ui/accordion'
373
+
374
+ export default function ShippingAccordion() {
375
+ return (
376
+ <Accordion.Root>
377
+ <Accordion.Item value="shipping">
378
+ <Accordion.Header>
379
+ <Accordion.Trigger>
380
+ <span>
381
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
382
+ <circle cx="8" cy="8" r="6" />
383
+ </svg>
384
+ </span>
385
+ Shipping
386
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
387
+ <path d="M3 6l5 5 5-5" />
388
+ </svg>
389
+ </Accordion.Trigger>
390
+ </Accordion.Header>
391
+ <Accordion.Panel>Orders ship within two working days.</Accordion.Panel>
392
+ </Accordion.Item>
393
+ </Accordion.Root>
394
+ )
395
+ }
396
+ ```
397
+
398
+ The Accordion and Collapsible panels set `overflow: hidden` so their height can animate, which also clips anything drawn outside the panel's box, focus rings included. Each panel insets its content by enough for Nave's focus ring: at both sides, above its first element and below its last. That inset reaches elements only, so a panel that starts or ends with bare text gets none there, and your own margins on those elements replace it. Keep at least the width plus the offset of your focus ring clear around any focusable element at the panel's edge.
399
+
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.
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
+
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.
413
+
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.
415
+
416
+ ## License
417
+
418
+ MIT. See [LICENSE](https://github.com/navecss/navecss/blob/main/packages/base-ui/LICENSE).
@@ -0,0 +1,2 @@
1
+ export * as Accordion from './parts.generated.ts';
2
+ export type * from '@base-ui/react/accordion';
@@ -0,0 +1,2 @@
1
+ 'use client';
2
+ export * as Accordion from "./parts.generated.js";
@@ -0,0 +1,31 @@
1
+ import { Accordion as Base } from '@base-ui/react/accordion';
2
+ export declare const Root: typeof Base.Root;
3
+ export declare namespace Root {
4
+ type Value<TValue = any> = Base.Root.Value<TValue>;
5
+ type State<TValue = any> = Base.Root.State<TValue>;
6
+ type Props<TValue = any> = Base.Root.Props<TValue>;
7
+ type ChangeEventReason = Base.Root.ChangeEventReason;
8
+ type ChangeEventDetails = Base.Root.ChangeEventDetails;
9
+ }
10
+ export declare const Item: typeof Base.Item;
11
+ export declare namespace Item {
12
+ type State = Base.Item.State;
13
+ type Props = Base.Item.Props;
14
+ type ChangeEventReason = Base.Item.ChangeEventReason;
15
+ type ChangeEventDetails = Base.Item.ChangeEventDetails;
16
+ }
17
+ export declare const Header: typeof Base.Header;
18
+ export declare namespace Header {
19
+ type State = Base.Header.State;
20
+ type Props = Base.Header.Props;
21
+ }
22
+ export declare const Trigger: typeof Base.Trigger;
23
+ export declare namespace Trigger {
24
+ type State = Base.Trigger.State;
25
+ type Props = Base.Trigger.Props;
26
+ }
27
+ export declare const Panel: typeof Base.Panel;
28
+ export declare namespace Panel {
29
+ type State = Base.Panel.State;
30
+ type Props = Base.Panel.Props;
31
+ }
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ // Generated by scripts/generate-wrappers.ts: change the roster or the generator, not this file.
3
+ import { Accordion as Base } from '@base-ui/react/accordion';
4
+ import { wrapPart } from "../part.js";
5
+ export const Root = /*#__PURE__*/ (() => Base.Root)();
6
+ export const Item = /*#__PURE__*/ (() => wrapPart(Base.Item, 'nave-base-ui-accordion-item'))();
7
+ export const Header = /*#__PURE__*/ (() => wrapPart(Base.Header, 'nave-base-ui-accordion-header'))();
8
+ export const Trigger = /*#__PURE__*/ (() => wrapPart(Base.Trigger, 'nave-base-ui-disclosure-trigger nave-base-ui-disclosure-icon'))();
9
+ export const Panel = /*#__PURE__*/ (() => wrapPart(Base.Panel, 'nave-base-ui-accordion-panel'))();
@@ -0,0 +1,2 @@
1
+ export * as AlertDialog from './parts.generated.ts';
2
+ export type * from '@base-ui/react/alert-dialog';
@@ -0,0 +1,2 @@
1
+ 'use client';
2
+ export * as AlertDialog from "./parts.generated.js";
@@ -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,2 @@
1
+ export * as Autocomplete from './parts.generated.ts';
2
+ export type * from '@base-ui/react/autocomplete';
@@ -0,0 +1,2 @@
1
+ 'use client';
2
+ export * as Autocomplete from "./parts.generated.js";