@optimum-intelligence/opti-ui 0.0.0-stage → 0.3.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 (193) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +244 -2
  3. package/dist/components/accordion/Accordion.d.ts +17 -0
  4. package/dist/components/accordion/Accordion.js +204 -0
  5. package/dist/components/accordion/Accordion.js.map +1 -0
  6. package/dist/components/alert/Alert.d.ts +18 -0
  7. package/dist/components/alert/Alert.js +164 -0
  8. package/dist/components/alert/Alert.js.map +1 -0
  9. package/dist/components/app-shell/AppShell.d.ts +97 -0
  10. package/dist/components/app-shell/AppShell.js +689 -0
  11. package/dist/components/app-shell/AppShell.js.map +1 -0
  12. package/dist/components/avatar/Avatar.d.ts +21 -0
  13. package/dist/components/avatar/Avatar.js +190 -0
  14. package/dist/components/avatar/Avatar.js.map +1 -0
  15. package/dist/components/badge/Badge.d.ts +16 -0
  16. package/dist/components/badge/Badge.js +94 -0
  17. package/dist/components/badge/Badge.js.map +1 -0
  18. package/dist/components/breadcrumbs/Breadcrumbs.d.ts +18 -0
  19. package/dist/components/breadcrumbs/Breadcrumbs.js +154 -0
  20. package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -0
  21. package/dist/components/button/Button.d.ts +23 -0
  22. package/dist/components/button/Button.js +159 -0
  23. package/dist/components/button/Button.js.map +1 -0
  24. package/dist/components/calendar/Calendar.d.ts +59 -0
  25. package/dist/components/calendar/Calendar.js +709 -0
  26. package/dist/components/calendar/Calendar.js.map +1 -0
  27. package/dist/components/calendar/date-utils.d.ts +32 -0
  28. package/dist/components/calendar/date-utils.js +112 -0
  29. package/dist/components/calendar/date-utils.js.map +1 -0
  30. package/dist/components/card/Card.d.ts +42 -0
  31. package/dist/components/card/Card.js +82 -0
  32. package/dist/components/card/Card.js.map +1 -0
  33. package/dist/components/choice/Choice.d.ts +32 -0
  34. package/dist/components/choice/Choice.js +371 -0
  35. package/dist/components/choice/Choice.js.map +1 -0
  36. package/dist/components/collapsible/Collapsible.d.ts +15 -0
  37. package/dist/components/collapsible/Collapsible.js +155 -0
  38. package/dist/components/collapsible/Collapsible.js.map +1 -0
  39. package/dist/components/combobox/Combobox.d.ts +68 -0
  40. package/dist/components/combobox/Combobox.js +752 -0
  41. package/dist/components/combobox/Combobox.js.map +1 -0
  42. package/dist/components/command-palette/CommandPalette.d.ts +52 -0
  43. package/dist/components/command-palette/CommandPalette.js +328 -0
  44. package/dist/components/command-palette/CommandPalette.js.map +1 -0
  45. package/dist/components/data-table/DataTable.d.ts +73 -0
  46. package/dist/components/data-table/DataTable.js +478 -0
  47. package/dist/components/data-table/DataTable.js.map +1 -0
  48. package/dist/components/data-table/DataTableContent.d.ts +35 -0
  49. package/dist/components/data-table/DataTableContent.js +550 -0
  50. package/dist/components/data-table/DataTableContent.js.map +1 -0
  51. package/dist/components/data-table/DataTableFilters.d.ts +15 -0
  52. package/dist/components/data-table/DataTableFilters.js +284 -0
  53. package/dist/components/data-table/DataTableFilters.js.map +1 -0
  54. package/dist/components/data-table/DataTableRow.d.ts +33 -0
  55. package/dist/components/data-table/DataTableRow.js +552 -0
  56. package/dist/components/data-table/DataTableRow.js.map +1 -0
  57. package/dist/components/data-table/context.d.ts +5 -0
  58. package/dist/components/data-table/context.js +14 -0
  59. package/dist/components/data-table/context.js.map +1 -0
  60. package/dist/components/data-table/layout.d.ts +60 -0
  61. package/dist/components/data-table/layout.js +272 -0
  62. package/dist/components/data-table/layout.js.map +1 -0
  63. package/dist/components/data-table/types.d.ts +319 -0
  64. package/dist/components/data-table/useDataTable.d.ts +9 -0
  65. package/dist/components/data-table/useDataTable.js +666 -0
  66. package/dist/components/data-table/useDataTable.js.map +1 -0
  67. package/dist/components/date-picker/DatePicker.d.ts +50 -0
  68. package/dist/components/date-picker/DatePicker.js +485 -0
  69. package/dist/components/date-picker/DatePicker.js.map +1 -0
  70. package/dist/components/date-picker/DateRangePicker.d.ts +39 -0
  71. package/dist/components/date-picker/DateRangePicker.js +339 -0
  72. package/dist/components/date-picker/DateRangePicker.js.map +1 -0
  73. package/dist/components/date-picker/PickerField.d.ts +38 -0
  74. package/dist/components/date-picker/PickerField.js +238 -0
  75. package/dist/components/date-picker/PickerField.js.map +1 -0
  76. package/dist/components/dialog/Dialog.d.ts +70 -0
  77. package/dist/components/dialog/Dialog.js +354 -0
  78. package/dist/components/dialog/Dialog.js.map +1 -0
  79. package/dist/components/drawer/Drawer.d.ts +39 -0
  80. package/dist/components/drawer/Drawer.js +225 -0
  81. package/dist/components/drawer/Drawer.js.map +1 -0
  82. package/dist/components/empty-state/EmptyState.d.ts +12 -0
  83. package/dist/components/empty-state/EmptyState.js +116 -0
  84. package/dist/components/empty-state/EmptyState.js.map +1 -0
  85. package/dist/components/field/Field.d.ts +36 -0
  86. package/dist/components/field/Field.js +337 -0
  87. package/dist/components/field/Field.js.map +1 -0
  88. package/dist/components/file-upload/FileUpload.d.ts +91 -0
  89. package/dist/components/file-upload/FileUpload.js +714 -0
  90. package/dist/components/file-upload/FileUpload.js.map +1 -0
  91. package/dist/components/input/Input.d.ts +49 -0
  92. package/dist/components/input/Input.js +538 -0
  93. package/dist/components/input/Input.js.map +1 -0
  94. package/dist/components/link/Link.d.ts +17 -0
  95. package/dist/components/link/Link.js +91 -0
  96. package/dist/components/link/Link.js.map +1 -0
  97. package/dist/components/menu/Menu.d.ts +79 -0
  98. package/dist/components/menu/Menu.js +615 -0
  99. package/dist/components/menu/Menu.js.map +1 -0
  100. package/dist/components/number-field/NumberField.d.ts +16 -0
  101. package/dist/components/number-field/NumberField.js +188 -0
  102. package/dist/components/number-field/NumberField.js.map +1 -0
  103. package/dist/components/pagination/Pagination.d.ts +34 -0
  104. package/dist/components/pagination/Pagination.js +244 -0
  105. package/dist/components/pagination/Pagination.js.map +1 -0
  106. package/dist/components/popover/Popover.d.ts +22 -0
  107. package/dist/components/popover/Popover.js +186 -0
  108. package/dist/components/popover/Popover.js.map +1 -0
  109. package/dist/components/preview-card/PreviewCard.d.ts +20 -0
  110. package/dist/components/preview-card/PreviewCard.js +114 -0
  111. package/dist/components/preview-card/PreviewCard.js.map +1 -0
  112. package/dist/components/progress/Progress.d.ts +20 -0
  113. package/dist/components/progress/Progress.js +169 -0
  114. package/dist/components/progress/Progress.js.map +1 -0
  115. package/dist/components/scroll-area/ScrollArea.d.ts +8 -0
  116. package/dist/components/scroll-area/ScrollArea.js +112 -0
  117. package/dist/components/scroll-area/ScrollArea.js.map +1 -0
  118. package/dist/components/search-input/SearchInput.d.ts +14 -0
  119. package/dist/components/search-input/SearchInput.js +114 -0
  120. package/dist/components/search-input/SearchInput.js.map +1 -0
  121. package/dist/components/select/Select.d.ts +66 -0
  122. package/dist/components/select/Select.js +601 -0
  123. package/dist/components/select/Select.js.map +1 -0
  124. package/dist/components/separator/Separator.d.ts +4 -0
  125. package/dist/components/separator/Separator.js +46 -0
  126. package/dist/components/separator/Separator.js.map +1 -0
  127. package/dist/components/skeleton/Skeleton.d.ts +16 -0
  128. package/dist/components/skeleton/Skeleton.js +135 -0
  129. package/dist/components/skeleton/Skeleton.js.map +1 -0
  130. package/dist/components/slider/Slider.d.ts +11 -0
  131. package/dist/components/slider/Slider.js +107 -0
  132. package/dist/components/slider/Slider.js.map +1 -0
  133. package/dist/components/spinner/Spinner.d.ts +9 -0
  134. package/dist/components/spinner/Spinner.js +78 -0
  135. package/dist/components/spinner/Spinner.js.map +1 -0
  136. package/dist/components/stack/Stack.d.ts +23 -0
  137. package/dist/components/stack/Stack.js +79 -0
  138. package/dist/components/stack/Stack.js.map +1 -0
  139. package/dist/components/stat-card/StatCard.d.ts +22 -0
  140. package/dist/components/stat-card/StatCard.js +153 -0
  141. package/dist/components/stat-card/StatCard.js.map +1 -0
  142. package/dist/components/stepper/Stepper.d.ts +30 -0
  143. package/dist/components/stepper/Stepper.js +131 -0
  144. package/dist/components/stepper/Stepper.js.map +1 -0
  145. package/dist/components/table/Table.d.ts +53 -0
  146. package/dist/components/table/Table.js +221 -0
  147. package/dist/components/table/Table.js.map +1 -0
  148. package/dist/components/tabs/Tabs.d.ts +19 -0
  149. package/dist/components/tabs/Tabs.js +183 -0
  150. package/dist/components/tabs/Tabs.js.map +1 -0
  151. package/dist/components/tag/Tag.d.ts +22 -0
  152. package/dist/components/tag/Tag.js +121 -0
  153. package/dist/components/tag/Tag.js.map +1 -0
  154. package/dist/components/toast/Toast.d.ts +34 -0
  155. package/dist/components/toast/Toast.js +187 -0
  156. package/dist/components/toast/Toast.js.map +1 -0
  157. package/dist/components/toggle/Toggle.d.ts +31 -0
  158. package/dist/components/toggle/Toggle.js +197 -0
  159. package/dist/components/toggle/Toggle.js.map +1 -0
  160. package/dist/components/toolbar/Toolbar.d.ts +21 -0
  161. package/dist/components/toolbar/Toolbar.js +239 -0
  162. package/dist/components/toolbar/Toolbar.js.map +1 -0
  163. package/dist/components/tooltip/Tooltip.d.ts +33 -0
  164. package/dist/components/tooltip/Tooltip.js +182 -0
  165. package/dist/components/tooltip/Tooltip.js.map +1 -0
  166. package/dist/components/typography/Typography.d.ts +32 -0
  167. package/dist/components/typography/Typography.js +183 -0
  168. package/dist/components/typography/Typography.js.map +1 -0
  169. package/dist/fonts.css +3 -0
  170. package/dist/icons/index.d.ts +133 -0
  171. package/dist/icons/index.js +182 -0
  172. package/dist/icons/index.js.map +1 -0
  173. package/dist/index.d.ts +55 -0
  174. package/dist/index.js +58 -0
  175. package/dist/opti-ui.css +5692 -0
  176. package/dist/theme/ThemeProvider.d.ts +22 -0
  177. package/dist/theme/ThemeProvider.js +115 -0
  178. package/dist/theme/ThemeProvider.js.map +1 -0
  179. package/dist/theme/index.d.ts +2 -0
  180. package/dist/utils/cx.d.ts +10 -0
  181. package/dist/utils/cx.js +18 -0
  182. package/dist/utils/cx.js.map +1 -0
  183. package/dist/utils/index.d.ts +2 -0
  184. package/dist/utils/portal.d.ts +8 -0
  185. package/dist/utils/portal.js +16 -0
  186. package/dist/utils/portal.js.map +1 -0
  187. package/dist/utils/primitive.d.ts +13 -0
  188. package/dist/utils/primitive.js +61 -0
  189. package/dist/utils/primitive.js.map +1 -0
  190. package/dist/utils/search.d.ts +4 -0
  191. package/dist/utils/search.js +15 -0
  192. package/dist/utils/search.js.map +1 -0
  193. package/package.json +71 -4
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2026 Optimum Intelligence. All rights reserved.
2
+
3
+ PROPRIETARY LICENSE
4
+
5
+ This software and associated files (the "Software") are the confidential and
6
+ proprietary property of Optimum Intelligence ("Optimum"). The Software is
7
+ published to a public registry for distribution convenience only; publication
8
+ does not grant any license to the public.
9
+
10
+ Permission to install, use, and modify the Software is granted solely to
11
+ Optimum and to its employees and contractors acting on Optimum's behalf, for
12
+ Optimum's internal business purposes and for products and services operated by
13
+ Optimum.
14
+
15
+ Without Optimum's prior written permission, you may not: (a) use the Software
16
+ for any other purpose; (b) copy, redistribute, sublicense, sell, or publish the
17
+ Software or any derivative of it; or (c) remove or alter this notice.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
+ OPTIMUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE
23
+ USE OF THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,245 @@
1
- # Temporary Holding Version
1
+ # Opti 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
+ Optimum Intelligence's shared React component library. It is built on [Base UI](https://base-ui.com) for
4
+ behaviour and accessibility, with a Poppins/Montserrat look: deep purple `#271645`, accent `#63537d`,
5
+ soft tinted borders and rounded controls. Everything is themeable through CSS variables.
6
+
7
+ ## Showcase
8
+
9
+ ```sh
10
+ npm ci
11
+ npm run dev # http://127.0.0.1:5173
12
+ ```
13
+
14
+ The showcase covers every component with live examples, code snippets and prop tables, plus a dashboard
15
+ example. **Customize** in the top bar re-themes the whole app live (mode, brand/accent colors,
16
+ radius, button shape, typeface) and gives you the CSS to paste into your own app.
17
+
18
+ ```sh
19
+ npm test # typecheck, library build, smoke tests on dist/
20
+ npm run build # library → dist/ (ESM per module, opti-ui.css, .d.ts)
21
+ npm run build:showcase # static showcase → showcase-dist/
22
+ npm pack # tarball for installing in other projects
23
+ ```
24
+
25
+ ## Using the package
26
+
27
+ React 19 is a peer dependency; the build is precompiled with React Compiler. `@base-ui/react` is installed with the package.
28
+
29
+ ```tsx
30
+ import '@optimum-intelligence/opti-ui/styles.css';
31
+ import '@optimum-intelligence/opti-ui/fonts.css'; // optional: loads Poppins + Montserrat from Google Fonts
32
+ import { Button, Card, CardTitle, ToastProvider, Tooltip } from '@optimum-intelligence/opti-ui';
33
+
34
+ export function App() {
35
+ return (
36
+ <Tooltip.Provider>
37
+ <ToastProvider>
38
+ <Card>
39
+ <CardTitle>Monthly energy</CardTitle>
40
+ <Button>Export report</Button>
41
+ </Card>
42
+ </ToastProvider>
43
+ </Tooltip.Provider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ Add `class="oui-root"` to `<body>` for the library font, text color and background. Add `oui-isolate`
49
+ to your app root so portalled popups stack above app content. Every module has a `'use client'` banner,
50
+ so the components work in Next.js App Router.
51
+
52
+ ### Components
53
+
54
+ | Area | Components |
55
+ | --- | --- |
56
+ | Layout | `AppShell`, `Navbar` (+ `NavbarHeader/Brand/Section/SectionLabel/Item/Footer`), `PageHeader`, `Grid`, `Stack`, `Card` (+ parts), `StatCard`, `Separator`, `ScrollArea` |
57
+ | Actions | `Button`, `IconButton`, `Toggle`, `ToggleGroup`, `SegmentedControl`, `Menu.*`, `ContextMenu.*`, `Toolbar.*` |
58
+ | Forms | `Field.*`, `Fieldset.*`, `Form`, `Input`, `TextField`, `PasswordInput`, `PasswordField`, `Textarea`, `TextareaField`, `Select` (+ parts), `Combobox` (+ parts), `Checkbox`, `CheckboxGroup`, `Radio`, `RadioGroup`, `Switch`, `NumberField`, `Slider`, `SearchInput`, `DatePicker`, `DateTimePicker`, `DateRangePicker`, `Calendar`, `RangeCalendar`, `FileUpload`, `Dropzone`, `FileItem` |
59
+ | Overlays | `Dialog.*` (modal, or a sheet with `placement`), `AlertDialog.*`, `Drawer` (detail side panel), `Popover.*`, `PreviewCard.*`, `Tooltip`, `ToastProvider` + `useToast()`, `CommandPalette` |
60
+ | Disclosure & navigation | `Tabs.*`, `Accordion.*`, `Collapsible.*`, `Breadcrumbs` + `Breadcrumb`, `Pagination`, `Stepper` |
61
+ | Feedback & data | `Alert`, `Badge`, `Tag`, `Avatar`, `AvatarGroup`, `Progress`, `Meter`, `Skeleton`, `SkeletonText`, `Spinner`, `Table` (+ parts), `DataTable`, `EmptyState`, `Heading`, `Text`, `Eyebrow`, `Link` |
62
+ | Theme | `ThemeProvider`, `createTheme`, `themeToStyle`, icons (`CheckIcon`, `ChevronDownIcon`, …) |
63
+
64
+ Components with a common one-line form can be called directly, and their parts are attached for full
65
+ control: `<Select items={…} />` or `<Select.Root>…<Select.Trigger/>…</Select.Root>`; the same applies to
66
+ `Combobox` and `Tooltip`. Compound components (`Dialog`, `Menu`, `Tabs`, …) mirror Base UI's part names,
67
+ so the [Base UI docs](https://base-ui.com/react/overview/quick-start) apply to them directly.
68
+
69
+ `DatePicker` and `DateTimePicker` use ISO strings as values (`"2026-03-09"`, `"2026-03-09T14:30"`), the
70
+ same format as native date inputs; `DateRangePicker` uses `{ start, end }` with both days inclusive.
71
+ Dates are displayed the same way in every locale, on a 24-hour clock: `2026-03-09 14:30:00` in fields
72
+ (`formatDate`) and `2026. March 9. 14:30` where they are written out (`formatDateLong`); the locale only
73
+ translates month and weekday names.
74
+
75
+ `DataTable` handles search, filters, sorting, pagination, selection, row actions and inline editing for
76
+ rows held in memory. Columns declare what they take part in:
77
+
78
+ ```tsx
79
+ const columns: DataTableColumn<Driver>[] = [
80
+ { id: 'badge', header: 'Badge', mono: true, searchMode: 'exact' },
81
+ { id: 'name', header: 'Name', edit: 'text' },
82
+ { id: 'depot', header: 'Depot', filter: 'select', edit: { type: 'select', options: depots } },
83
+ { id: 'active', header: 'Active', filter: 'toggle', edit: 'checkbox', cell: (row) => <StatusBadge on={row.active} /> },
84
+ { id: 'hired', header: 'Hired', filter: 'dateRange' },
85
+ { id: 'notes', header: 'Notes', hidden: true }, // searched, not shown
86
+ ];
87
+
88
+ <DataTable
89
+ data={drivers}
90
+ columns={columns}
91
+ locale="hu"
92
+ filters={[{ id: 'new', type: 'toggle', label: 'New this month', match: isNew }]}
93
+ rowActions={(row) => [{ label: 'Locate', icon: <MapPin />, onClick: () => locate(row) }]}
94
+ rowTone={(row) => (row.suspended ? 'danger' : undefined)}
95
+ onRowSave={(row) => api.saveDriver(row)}
96
+ onRowDelete={(row) => confirmDelete(row)}
97
+ />
98
+ ```
99
+
100
+ A `select` filter collects its options from the rows unless you pass `options`; a `toggle` keeps truthy
101
+ values, or the rows passing its `match`; a `dateRange` includes both of its days. `onRowSave` adds the
102
+ edit action and receives the edited row: return a promise to keep the row open while it saves, and reject
103
+ it to leave the row open for another try.
104
+
105
+ Every piece of state (`search`, `filterValues`, `sort`, `page`, `pageSize`, `selection`) works
106
+ uncontrolled, or controlled with its `on…Change` callback. With `mode="server"` the table renders the page
107
+ it is given and reports those changes, so the API does the work; typing in the search box is debounced
108
+ by 300 ms (`searchDebounce`). Pass `total`, `loading` and `error` alongside:
109
+
110
+ ```tsx
111
+ <DataTable
112
+ mode="server"
113
+ data={data?.rows ?? []}
114
+ total={data?.total}
115
+ columns={columns}
116
+ loading={isFetching}
117
+ error={error?.message}
118
+ onRetry={refetch}
119
+ page={page}
120
+ onPageChange={setPage}
121
+ onSortChange={setSort}
122
+ onSearchChange={setSearch}
123
+ onFilterValuesChange={setFilters}
124
+ />
125
+ ```
126
+
127
+ The table measures its columns once, with the longest values of all rows, and then holds their widths:
128
+ paging, sorting, filtering and editing a row move nothing, and a short last page stays as tall as a full
129
+ one. The widths are measured again when the table is resized. A column's `width` is a starting point and
130
+ `minWidth` a floor; `truncate` cuts long text with an ellipsis instead of wrapping it. `layout="auto"`
131
+ hands the widths back to the browser.
132
+
133
+ For thousands of rows, `virtualized` renders only the ones in view inside `maxHeight` (default `32rem`)
134
+ and turns pagination off. Rows are then one line high and every column fits its longest value, so mark
135
+ long-text columns `truncate`. `onEndReached` loads more rows as the end is scrolled into view:
136
+
137
+ ```tsx
138
+ <DataTable data={shipments} columns={columns} virtualized maxHeight={480} />
139
+
140
+ <DataTable
141
+ mode="server"
142
+ data={rows}
143
+ total={total}
144
+ columns={columns}
145
+ loading={isFetchingNextPage}
146
+ paginated={false}
147
+ maxHeight={480}
148
+ onEndReached={fetchNextPage}
149
+ />
150
+ ```
151
+
152
+ Rows of another height take `virtualized={{ rowHeight: 56 }}`. A row scrolled far out of view is
153
+ unmounted, so focus inside it is lost; an edit in progress is kept and shows again when the row returns.
154
+
155
+ For another layout, `useDataTable` takes the same options and returns the state and the processed rows,
156
+ and the parts render it wherever you place them inside `DataTable.Root`:
157
+
158
+ ```tsx
159
+ const table = useDataTable({ data, columns });
160
+
161
+ <DataTable.Root table={table}>
162
+ <DataTable.Toolbar>
163
+ <DataTable.Search />
164
+ <DataTable.Filter id="depot" />
165
+ <DataTable.Actions>
166
+ <DataTable.Summary />
167
+ <Button onClick={() => exportCsv(table.rows.map(({ row }) => row))}>Export</Button>
168
+ </DataTable.Actions>
169
+ </DataTable.Toolbar>
170
+ <DataTable.Content density="compact" maxHeight={480} />
171
+ <DataTable.Pagination />
172
+ </DataTable.Root>
173
+ ```
174
+
175
+ `DataTable.Filters` renders every filter with a clear button, and `useDataTableContext()` gives your own
176
+ components the same table.
177
+
178
+ `FileUpload` collects `File` objects and leaves the upload to you; report its progress per file through
179
+ `fileState`. Components with built-in text (`DataTable`, `Pagination`, `DatePicker`, `DateRangePicker`,
180
+ `Calendar`, `FileUpload`, `Stepper`) take a `labels` prop for translation, and the date components take a
181
+ `locale`.
182
+
183
+ ## Customization
184
+
185
+ Start with the simplest option that does what you need:
186
+
187
+ 1. **Tokens.** Every color, radius, shadow, font, size and duration is a `--oui-*` custom property. Most
188
+ colors are derived from two inputs with `color-mix()`, so a product theme is often just two values:
189
+
190
+ ```css
191
+ :root {
192
+ --oui-color-brand: #0f2a44; /* deep base: primary buttons, headings, navbar, muted text */
193
+ --oui-color-accent: #1f8fd6; /* focus rings, selection, borders, tints */
194
+ }
195
+ ```
196
+
197
+ 2. **Scoped themes.** `<ThemeProvider theme={{ 'color-accent': '#1f8fd6' }} mode="dark">` applies tokens to a
198
+ subtree. Popups opened inside are portalled into the provider, so they inherit the same theme. For
199
+ dark mode across the whole app, set `data-oui-theme="dark"` on `<html>`.
200
+ 3. **Component variables.** Use these per instance or globally, e.g. `--oui-button-radius`,
201
+ `--oui-button-height`, `--oui-input-height`, `--oui-card-padding`, `--oui-card-radius`,
202
+ `--oui-dialog-width`, `--oui-navbar-width`, `--oui-navbar-collapsed-width`, `--oui-switch-width`, `--oui-progress-height`.
203
+ 4. **Classes.** All library CSS is inside cascade layers (`oui.tokens < oui.base < oui.components`).
204
+ Any unlayered CSS in your app overrides it, whatever its specificity, so `!important` is never
205
+ needed. Every part has a stable class (`oui-select__trigger`, `oui-dialog__footer`, …).
206
+ 5. **State attributes.** Style states through Base UI's data attributes (`[data-checked]`,
207
+ `[data-popup-open]`, `[data-highlighted]`, …) and the library's own (`[data-variant]`, `[data-size]`,
208
+ `[data-tone]`). `className` also accepts a function of component state.
209
+ 6. **The render prop.** Swap the rendered element and keep the styles and behaviour:
210
+ `<NavbarItem render={<NavLink to="/fleet" />}>`,
211
+ `<Button render={<a href="…" />} nativeButton={false}>`.
212
+
213
+ **Tailwind v4:** declare the layer order so utilities still win over library styles:
214
+ `@layer theme, base, oui, components, utilities;`
215
+
216
+ ## Project layout
217
+
218
+ ```
219
+ src/
220
+ styles/ tokens, layer order, shared Sass mixins, stylesheet entry
221
+ theme/ ThemeProvider, helpers
222
+ components/ one folder per component: Component.tsx + component.scss
223
+ icons/ small built-in icon set (stroke icons, currentColor)
224
+ utils/ class helpers, render-prop primitive, portal container
225
+ showcase/ documentation app (consumes src/ directly)
226
+ tests/ smoke tests against dist/
227
+ ```
228
+
229
+ Conventions: kebab-case component folders, BEM-style `oui-block__element` classes, and variants as
230
+ `data-*` attributes, never modifier classes. Private custom properties are prefixed `--_`; public
231
+ ones `--oui-`.
232
+
233
+ ## Docker / Dokploy deployment
234
+
235
+ The Docker image builds the static showcase and serves it with Nginx on port 80. It needs no
236
+ environment variables or persistent storage.
237
+
238
+ ```sh
239
+ docker build -t opti-ui-showcase .
240
+ docker run --rm -p 8080:80 opti-ui-showcase # http://localhost:8080
241
+ ```
242
+
243
+ In Dokploy, create an **Application** for this repository, select the **Dockerfile** build type
244
+ (path `Dockerfile`, context `.`), add a domain with container port `80`, and deploy. The image includes
245
+ an HTTP health check.
@@ -0,0 +1,17 @@
1
+ import { Accordion as BaseAccordion } from '@base-ui/react/accordion';
2
+ export interface AccordionRootProps extends BaseAccordion.Root.Props {
3
+ /** `separated` renders each item as its own card; `plain` uses dividers. */
4
+ variant?: 'separated' | 'plain';
5
+ }
6
+ declare function AccordionRoot({ variant, className, ref, ...props }: AccordionRootProps): import("react").JSX.Element;
7
+ declare function AccordionItem({ className, ref, ...props }: BaseAccordion.Item.Props): import("react").JSX.Element;
8
+ /** Header + trigger + chevron in one. */
9
+ declare function AccordionTrigger({ className, children, ref, ...props }: BaseAccordion.Trigger.Props): import("react").JSX.Element;
10
+ declare function AccordionPanel({ className, children, ref, ...props }: BaseAccordion.Panel.Props): import("react").JSX.Element;
11
+ export declare const Accordion: {
12
+ Root: typeof AccordionRoot;
13
+ Item: typeof AccordionItem;
14
+ Trigger: typeof AccordionTrigger;
15
+ Panel: typeof AccordionPanel;
16
+ };
17
+ export {};
@@ -0,0 +1,204 @@
1
+ "use client";
2
+ import { withClass } from "../../utils/cx.js";
3
+ import { ChevronDownIcon } from "../../icons/index.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Accordion } from "@base-ui/react/accordion";
7
+ //#region src/components/accordion/Accordion.tsx
8
+ function AccordionRoot(t0) {
9
+ const $ = c(12);
10
+ let className;
11
+ let props;
12
+ let ref;
13
+ let t1;
14
+ if ($[0] !== t0) {
15
+ ({variant: t1, className, ref, ...props} = t0);
16
+ $[0] = t0;
17
+ $[1] = className;
18
+ $[2] = props;
19
+ $[3] = ref;
20
+ $[4] = t1;
21
+ } else {
22
+ className = $[1];
23
+ props = $[2];
24
+ ref = $[3];
25
+ t1 = $[4];
26
+ }
27
+ const variant = t1 === void 0 ? "plain" : t1;
28
+ let t2;
29
+ if ($[5] !== className) {
30
+ t2 = withClass("oui-accordion", className);
31
+ $[5] = className;
32
+ $[6] = t2;
33
+ } else t2 = $[6];
34
+ let t3;
35
+ if ($[7] !== props || $[8] !== ref || $[9] !== t2 || $[10] !== variant) {
36
+ t3 = /* @__PURE__ */ jsx(Accordion.Root, {
37
+ ref,
38
+ className: t2,
39
+ "data-variant": variant,
40
+ ...props
41
+ });
42
+ $[7] = props;
43
+ $[8] = ref;
44
+ $[9] = t2;
45
+ $[10] = variant;
46
+ $[11] = t3;
47
+ } else t3 = $[11];
48
+ return t3;
49
+ }
50
+ function AccordionItem(t0) {
51
+ const $ = c(10);
52
+ let className;
53
+ let props;
54
+ let ref;
55
+ if ($[0] !== t0) {
56
+ ({className, ref, ...props} = t0);
57
+ $[0] = t0;
58
+ $[1] = className;
59
+ $[2] = props;
60
+ $[3] = ref;
61
+ } else {
62
+ className = $[1];
63
+ props = $[2];
64
+ ref = $[3];
65
+ }
66
+ let t1;
67
+ if ($[4] !== className) {
68
+ t1 = withClass("oui-accordion__item", className);
69
+ $[4] = className;
70
+ $[5] = t1;
71
+ } else t1 = $[5];
72
+ let t2;
73
+ if ($[6] !== props || $[7] !== ref || $[8] !== t1) {
74
+ t2 = /* @__PURE__ */ jsx(Accordion.Item, {
75
+ ref,
76
+ className: t1,
77
+ ...props
78
+ });
79
+ $[6] = props;
80
+ $[7] = ref;
81
+ $[8] = t1;
82
+ $[9] = t2;
83
+ } else t2 = $[9];
84
+ return t2;
85
+ }
86
+ /** Header + trigger + chevron in one. */
87
+ function AccordionTrigger(t0) {
88
+ const $ = c(15);
89
+ let children;
90
+ let className;
91
+ let props;
92
+ let ref;
93
+ if ($[0] !== t0) {
94
+ ({className, children, ref, ...props} = t0);
95
+ $[0] = t0;
96
+ $[1] = children;
97
+ $[2] = className;
98
+ $[3] = props;
99
+ $[4] = ref;
100
+ } else {
101
+ children = $[1];
102
+ className = $[2];
103
+ props = $[3];
104
+ ref = $[4];
105
+ }
106
+ let t1;
107
+ if ($[5] !== className) {
108
+ t1 = withClass("oui-accordion__trigger", className);
109
+ $[5] = className;
110
+ $[6] = t1;
111
+ } else t1 = $[6];
112
+ let t2;
113
+ if ($[7] !== children) {
114
+ t2 = /* @__PURE__ */ jsx("span", {
115
+ className: "oui-accordion__trigger-label",
116
+ children
117
+ });
118
+ $[7] = children;
119
+ $[8] = t2;
120
+ } else t2 = $[8];
121
+ let t3;
122
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
123
+ t3 = /* @__PURE__ */ jsx(ChevronDownIcon, { className: "oui-accordion__chevron" });
124
+ $[9] = t3;
125
+ } else t3 = $[9];
126
+ let t4;
127
+ if ($[10] !== props || $[11] !== ref || $[12] !== t1 || $[13] !== t2) {
128
+ t4 = /* @__PURE__ */ jsx(Accordion.Header, {
129
+ className: "oui-accordion__header",
130
+ children: /* @__PURE__ */ jsxs(Accordion.Trigger, {
131
+ ref,
132
+ className: t1,
133
+ ...props,
134
+ children: [t2, t3]
135
+ })
136
+ });
137
+ $[10] = props;
138
+ $[11] = ref;
139
+ $[12] = t1;
140
+ $[13] = t2;
141
+ $[14] = t4;
142
+ } else t4 = $[14];
143
+ return t4;
144
+ }
145
+ function AccordionPanel(t0) {
146
+ const $ = c(14);
147
+ let children;
148
+ let className;
149
+ let props;
150
+ let ref;
151
+ if ($[0] !== t0) {
152
+ ({className, children, ref, ...props} = t0);
153
+ $[0] = t0;
154
+ $[1] = children;
155
+ $[2] = className;
156
+ $[3] = props;
157
+ $[4] = ref;
158
+ } else {
159
+ children = $[1];
160
+ className = $[2];
161
+ props = $[3];
162
+ ref = $[4];
163
+ }
164
+ let t1;
165
+ if ($[5] !== className) {
166
+ t1 = withClass("oui-accordion__panel", className);
167
+ $[5] = className;
168
+ $[6] = t1;
169
+ } else t1 = $[6];
170
+ let t2;
171
+ if ($[7] !== children) {
172
+ t2 = /* @__PURE__ */ jsx("div", {
173
+ className: "oui-accordion__content",
174
+ children
175
+ });
176
+ $[7] = children;
177
+ $[8] = t2;
178
+ } else t2 = $[8];
179
+ let t3;
180
+ if ($[9] !== props || $[10] !== ref || $[11] !== t1 || $[12] !== t2) {
181
+ t3 = /* @__PURE__ */ jsx(Accordion.Panel, {
182
+ ref,
183
+ className: t1,
184
+ ...props,
185
+ children: t2
186
+ });
187
+ $[9] = props;
188
+ $[10] = ref;
189
+ $[11] = t1;
190
+ $[12] = t2;
191
+ $[13] = t3;
192
+ } else t3 = $[13];
193
+ return t3;
194
+ }
195
+ var Accordion$1 = {
196
+ Root: AccordionRoot,
197
+ Item: AccordionItem,
198
+ Trigger: AccordionTrigger,
199
+ Panel: AccordionPanel
200
+ };
201
+ //#endregion
202
+ export { Accordion$1 as Accordion };
203
+
204
+ //# sourceMappingURL=Accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Accordion.js","names":["Accordion","BaseAccordion","withClass","ChevronDownIcon","AccordionRootProps","Root","Props","variant","AccordionRoot","t0","$","_c","className","props","ref","t1","undefined","t2","t3","AccordionItem","AccordionTrigger","children","Symbol","for","t4","AccordionPanel","Item","Trigger","Panel","_c","BaseAccordion","Accordion"],"sources":["../../../src/components/accordion/Accordion.tsx"],"sourcesContent":["import { Accordion as BaseAccordion } from '@base-ui/react/accordion';\nimport { withClass } from '../../utils/cx';\nimport { ChevronDownIcon } from '../../icons';\n\nexport interface AccordionRootProps extends BaseAccordion.Root.Props {\n /** `separated` renders each item as its own card; `plain` uses dividers. */\n variant?: 'separated' | 'plain';\n}\n\nfunction AccordionRoot({ variant = 'plain', className, ref, ...props }: AccordionRootProps) {\n return (\n <BaseAccordion.Root ref={ref} className={withClass('oui-accordion', className)} data-variant={variant} {...props} />\n );\n}\n\nfunction AccordionItem({ className, ref, ...props }: BaseAccordion.Item.Props) {\n return <BaseAccordion.Item ref={ref} className={withClass('oui-accordion__item', className)} {...props} />;\n}\n\n/** Header + trigger + chevron in one. */\nfunction AccordionTrigger({ className, children, ref, ...props }: BaseAccordion.Trigger.Props) {\n return (\n <BaseAccordion.Header className=\"oui-accordion__header\">\n <BaseAccordion.Trigger ref={ref} className={withClass('oui-accordion__trigger', className)} {...props}>\n <span className=\"oui-accordion__trigger-label\">{children}</span>\n <ChevronDownIcon className=\"oui-accordion__chevron\" />\n </BaseAccordion.Trigger>\n </BaseAccordion.Header>\n );\n}\n\nfunction AccordionPanel({ className, children, ref, ...props }: BaseAccordion.Panel.Props) {\n return (\n <BaseAccordion.Panel ref={ref} className={withClass('oui-accordion__panel', className)} {...props}>\n <div className=\"oui-accordion__content\">{children}</div>\n </BaseAccordion.Panel>\n );\n}\n\nexport const Accordion = {\n Root: AccordionRoot,\n Item: AccordionItem,\n Trigger: AccordionTrigger,\n Panel: AccordionPanel,\n};\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ export type AlertTone = 'info' | 'success' | 'warning' | 'danger' | 'neutral';
3
+ export interface AlertProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
4
+ ref?: React.Ref<HTMLDivElement>;
5
+ tone?: AlertTone;
6
+ /** `soft` (tinted, default) or `outline`. */
7
+ variant?: 'soft' | 'outline';
8
+ title?: React.ReactNode;
9
+ /** Custom icon, or `false` to hide it. */
10
+ icon?: React.ReactNode | false;
11
+ /** Buttons rendered after the message. */
12
+ actions?: React.ReactNode;
13
+ /** Shows a dismiss button. */
14
+ onDismiss?: () => void;
15
+ dismissLabel?: string;
16
+ }
17
+ /** Inline message for page- or section-level feedback. */
18
+ export declare function Alert({ tone, variant, title, icon, actions, onDismiss, dismissLabel, className, children, ref, ...props }: AlertProps): React.JSX.Element;
@@ -0,0 +1,164 @@
1
+ "use client";
2
+ import { cx } from "../../utils/cx.js";
3
+ import { CircleCheckIcon, CircleXIcon, InfoIcon, TriangleAlertIcon, XIcon } from "../../icons/index.js";
4
+ import { IconButton } from "../button/Button.js";
5
+ import { c } from "react/compiler-runtime";
6
+ import "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/alert/Alert.tsx
9
+ var defaultIcons = {
10
+ info: /* @__PURE__ */ jsx(InfoIcon, {}),
11
+ neutral: /* @__PURE__ */ jsx(InfoIcon, {}),
12
+ success: /* @__PURE__ */ jsx(CircleCheckIcon, {}),
13
+ warning: /* @__PURE__ */ jsx(TriangleAlertIcon, {}),
14
+ danger: /* @__PURE__ */ jsx(CircleXIcon, {})
15
+ };
16
+ /** Inline message for page- or section-level feedback. */
17
+ function Alert(t0) {
18
+ const $ = c(39);
19
+ let actions;
20
+ let children;
21
+ let className;
22
+ let icon;
23
+ let onDismiss;
24
+ let props;
25
+ let ref;
26
+ let t1;
27
+ let t2;
28
+ let t3;
29
+ let title;
30
+ if ($[0] !== t0) {
31
+ ({tone: t1, variant: t2, title, icon, actions, onDismiss, dismissLabel: t3, className, children, ref, ...props} = t0);
32
+ $[0] = t0;
33
+ $[1] = actions;
34
+ $[2] = children;
35
+ $[3] = className;
36
+ $[4] = icon;
37
+ $[5] = onDismiss;
38
+ $[6] = props;
39
+ $[7] = ref;
40
+ $[8] = t1;
41
+ $[9] = t2;
42
+ $[10] = t3;
43
+ $[11] = title;
44
+ } else {
45
+ actions = $[1];
46
+ children = $[2];
47
+ className = $[3];
48
+ icon = $[4];
49
+ onDismiss = $[5];
50
+ props = $[6];
51
+ ref = $[7];
52
+ t1 = $[8];
53
+ t2 = $[9];
54
+ t3 = $[10];
55
+ title = $[11];
56
+ }
57
+ const tone = t1 === void 0 ? "info" : t1;
58
+ const variant = t2 === void 0 ? "soft" : t2;
59
+ const dismissLabel = t3 === void 0 ? "Dismiss" : t3;
60
+ const urgent = tone === "danger" || tone === "warning";
61
+ const iconNode = icon === false ? null : icon ?? defaultIcons[tone];
62
+ const t4 = urgent ? "alert" : "status";
63
+ let t5;
64
+ if ($[12] !== className) {
65
+ t5 = cx("oui-alert", className);
66
+ $[12] = className;
67
+ $[13] = t5;
68
+ } else t5 = $[13];
69
+ let t6;
70
+ if ($[14] !== iconNode) {
71
+ t6 = iconNode && /* @__PURE__ */ jsx("span", {
72
+ className: "oui-alert__icon",
73
+ children: iconNode
74
+ });
75
+ $[14] = iconNode;
76
+ $[15] = t6;
77
+ } else t6 = $[15];
78
+ let t7;
79
+ if ($[16] !== title) {
80
+ t7 = title && /* @__PURE__ */ jsx("p", {
81
+ className: "oui-alert__title",
82
+ children: title
83
+ });
84
+ $[16] = title;
85
+ $[17] = t7;
86
+ } else t7 = $[17];
87
+ let t8;
88
+ if ($[18] !== children) {
89
+ t8 = children && /* @__PURE__ */ jsx("div", {
90
+ className: "oui-alert__message",
91
+ children
92
+ });
93
+ $[18] = children;
94
+ $[19] = t8;
95
+ } else t8 = $[19];
96
+ let t9;
97
+ if ($[20] !== actions) {
98
+ t9 = actions && /* @__PURE__ */ jsx("div", {
99
+ className: "oui-alert__actions",
100
+ children: actions
101
+ });
102
+ $[20] = actions;
103
+ $[21] = t9;
104
+ } else t9 = $[21];
105
+ let t10;
106
+ if ($[22] !== t7 || $[23] !== t8 || $[24] !== t9) {
107
+ t10 = /* @__PURE__ */ jsxs("div", {
108
+ className: "oui-alert__body",
109
+ children: [
110
+ t7,
111
+ t8,
112
+ t9
113
+ ]
114
+ });
115
+ $[22] = t7;
116
+ $[23] = t8;
117
+ $[24] = t9;
118
+ $[25] = t10;
119
+ } else t10 = $[25];
120
+ let t11;
121
+ if ($[26] !== dismissLabel || $[27] !== onDismiss) {
122
+ t11 = onDismiss && /* @__PURE__ */ jsx(IconButton, {
123
+ className: "oui-alert__dismiss",
124
+ size: "sm",
125
+ "aria-label": dismissLabel,
126
+ onClick: onDismiss,
127
+ children: /* @__PURE__ */ jsx(XIcon, {})
128
+ });
129
+ $[26] = dismissLabel;
130
+ $[27] = onDismiss;
131
+ $[28] = t11;
132
+ } else t11 = $[28];
133
+ let t12;
134
+ if ($[29] !== props || $[30] !== ref || $[31] !== t10 || $[32] !== t11 || $[33] !== t4 || $[34] !== t5 || $[35] !== t6 || $[36] !== tone || $[37] !== variant) {
135
+ t12 = /* @__PURE__ */ jsxs("div", {
136
+ ref,
137
+ role: t4,
138
+ className: t5,
139
+ "data-tone": tone,
140
+ "data-variant": variant,
141
+ ...props,
142
+ children: [
143
+ t6,
144
+ t10,
145
+ t11
146
+ ]
147
+ });
148
+ $[29] = props;
149
+ $[30] = ref;
150
+ $[31] = t10;
151
+ $[32] = t11;
152
+ $[33] = t4;
153
+ $[34] = t5;
154
+ $[35] = t6;
155
+ $[36] = tone;
156
+ $[37] = variant;
157
+ $[38] = t12;
158
+ } else t12 = $[38];
159
+ return t12;
160
+ }
161
+ //#endregion
162
+ export { Alert };
163
+
164
+ //# sourceMappingURL=Alert.js.map