aidos-ui 4.0.0 → 4.0.2

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 (99) hide show
  1. package/.claude/settings.local.json +14 -1
  2. package/CLAUDE.md +72 -0
  3. package/dist/BaseButton.js.map +1 -1
  4. package/dist/BaseLink.js.map +1 -1
  5. package/dist/BaseListItem.d.ts +1 -1
  6. package/dist/Calendar.d.ts +2 -2
  7. package/dist/Card.js +1 -1
  8. package/dist/Card.js.map +1 -1
  9. package/dist/DarkMode.js.map +1 -1
  10. package/dist/DatePicker.js.map +1 -1
  11. package/dist/Dialog.d.ts +3 -3
  12. package/dist/Dialog.js +7 -1
  13. package/dist/Dialog.js.map +1 -1
  14. package/dist/Dropdown.js.map +1 -1
  15. package/dist/Icon.d.ts +3 -3
  16. package/dist/Icon.js +2 -21
  17. package/dist/Icon.js.map +1 -1
  18. package/dist/Interactable.js.map +1 -1
  19. package/dist/NextJSRouterState.js.map +1 -1
  20. package/dist/OnVisible.d.ts +1 -1
  21. package/dist/OnVisible.js.map +1 -1
  22. package/dist/Popover.d.ts +3 -3
  23. package/dist/Popover.js +3 -1
  24. package/dist/Popover.js.map +1 -1
  25. package/dist/Providers.d.ts +2 -2
  26. package/dist/RangeInput.d.ts +1 -1
  27. package/dist/RootView.js.map +1 -1
  28. package/dist/Select.d.ts +0 -1
  29. package/dist/Storage.d.ts +2 -1
  30. package/dist/Storage.js.map +1 -1
  31. package/dist/Stream.js.map +1 -1
  32. package/dist/Text.js.map +1 -1
  33. package/dist/TextInput.d.ts +3 -2
  34. package/dist/TextInput.js +13 -4
  35. package/dist/TextInput.js.map +1 -1
  36. package/dist/TextPairing.js.map +1 -1
  37. package/dist/Tooltip.d.ts +2 -2
  38. package/dist/Tooltip.js +3 -2
  39. package/dist/Tooltip.js.map +1 -1
  40. package/dist/aria.js.map +1 -1
  41. package/dist/hash.js.map +1 -1
  42. package/dist/jss.d.ts +11 -6
  43. package/dist/jss.js +47 -2
  44. package/dist/jss.js.map +1 -1
  45. package/dist/numberToBase.js.map +1 -1
  46. package/dist/stateMachineContextFactory.js.map +1 -1
  47. package/dist/useCookie.js.map +1 -1
  48. package/dist/useKeyboard.js.map +1 -1
  49. package/dist/useNavigation.js.map +1 -1
  50. package/dist/useRefEffect.js.map +1 -1
  51. package/next-env.d.ts +2 -1
  52. package/next.config.js +2 -1
  53. package/package.json +27 -20
  54. package/src/BaseListItem.tsx +1 -1
  55. package/src/Calendar.tsx +2 -2
  56. package/src/Card.tsx +1 -1
  57. package/src/Dialog.tsx +10 -4
  58. package/src/Icon.tsx +4 -30
  59. package/src/Popover.tsx +6 -4
  60. package/src/Providers.tsx +1 -1
  61. package/src/RangeInput.tsx +1 -1
  62. package/src/Storage.tsx +1 -1
  63. package/src/TextInput.tsx +17 -5
  64. package/src/Tooltip.tsx +5 -4
  65. package/src/docs/mdx.tsx +40 -0
  66. package/src/docs/searchIndex.ts +1 -1
  67. package/src/jss.tsx +55 -3
  68. package/src/pages/Badge.mdx +136 -14
  69. package/src/pages/Button.mdx +121 -63
  70. package/src/pages/Calendar.mdx +196 -2
  71. package/src/pages/Card.mdx +123 -47
  72. package/src/pages/Checkbox.mdx +103 -28
  73. package/src/pages/Dialog.mdx +172 -7
  74. package/src/pages/FlexLayout.mdx +185 -51
  75. package/src/pages/Hashing.mdx +199 -8
  76. package/src/pages/Icon.mdx +150 -42
  77. package/src/pages/IconButton.mdx +127 -116
  78. package/src/pages/Link.mdx +118 -47
  79. package/src/pages/List.mdx +167 -283
  80. package/src/pages/ListHeader.mdx +157 -27
  81. package/src/pages/Popover.mdx +177 -55
  82. package/src/pages/ProgressBar.mdx +186 -6
  83. package/src/pages/ProgressCircle.mdx +196 -13
  84. package/src/pages/RangeInput.mdx +189 -61
  85. package/src/pages/Tabs.mdx +202 -346
  86. package/src/pages/Text.mdx +102 -81
  87. package/src/pages/TextInput.mdx +169 -44
  88. package/src/pages/TextPairing.mdx +164 -115
  89. package/src/pages/TimeInput.mdx +142 -37
  90. package/src/pages/Tooltip.mdx +99 -12
  91. package/src/pages/_app.tsx +13 -3
  92. package/src/pages/css-in-js.mdx +196 -83
  93. package/src/pages/navigation.mdx +122 -20
  94. package/src/pages/useCookie.mdx +168 -7
  95. package/src/pages/useKeyboard.mdx +242 -5
  96. package/src/pages/useNavigation.mdx +244 -16
  97. package/src/pages/usePromise.mdx +271 -6
  98. package/src/pages/useRefEffect.mdx +230 -28
  99. package/tsconfig.json +13 -4
@@ -33,14 +33,22 @@ import { Column } from "../Column";
33
33
  import { Icon } from "../Icon";
34
34
  import { BaseLinkComponentOverrideContext } from "../BaseLink";
35
35
  import { DocsMDXProvider, labelToID } from "../docs/mdx";
36
- import { Pipeline, dot, pipeline } from "@xenova/transformers";
36
+ import type { Pipeline } from "@xenova/transformers";
37
37
  import { pages } from "../docs/pages";
38
38
 
39
39
  import { Inter } from "next/font/google";
40
40
 
41
41
  const inter = Inter({ subsets: ["latin"] });
42
42
 
43
- const transformers = import("@xenova/transformers");
43
+ let transformersPromise: Promise<typeof import("@xenova/transformers")> | null =
44
+ null;
45
+ const getTransformers = () => {
46
+ if (!transformersPromise) {
47
+ transformersPromise = import("@xenova/transformers");
48
+ }
49
+ return transformersPromise;
50
+ };
51
+
44
52
  const searchIndex = import("../docs/searchIndex").then(
45
53
  (module) => module.index
46
54
  );
@@ -170,6 +178,8 @@ export default function App({ Component, pageProps }: AppProps) {
170
178
  return;
171
179
  }
172
180
 
181
+ const { dot } = await getTransformers();
182
+
173
183
  const queryEmbeddings = await generateEmbeddings(query, {
174
184
  normalize: true,
175
185
  pooling: "mean",
@@ -446,7 +456,7 @@ export default function App({ Component, pageProps }: AppProps) {
446
456
  let modelPromise: Promise<Pipeline> | null = null;
447
457
 
448
458
  const loadModel: () => Promise<Pipeline> = async () => {
449
- const { pipeline } = await transformers;
459
+ const { pipeline } = await getTransformers();
450
460
  if (modelPromise == null) {
451
461
  modelPromise = pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
452
462
  }
@@ -1,127 +1,240 @@
1
1
  import { Button } from "../Button";
2
2
  import { Row } from "../Row";
3
- import { cssVar } from "../jss";
3
+ import { Column } from "../Column";
4
+ import { BaseView } from "../BaseView";
5
+ import { Span } from "../Text";
6
+ import { cssVar, mobile, tablet } from "../jss";
4
7
 
5
8
  # CSS in JS
6
9
 
7
- Aidos UI has a mechanism to do css in js, which, for lack of a better name, is called `jss`, which is the name of the only function that is needed. The idea is similar to other css in js frameworks: colocation is nice, adding javascrip features to CSS solves many of the problems CSS has.
10
+ Aidos UI uses a custom CSS-in-JS system called `jss`. Every component accepts a `jss` prop for styling, and the library includes utilities for theming, responsive design, and type-safe CSS variables.
8
11
 
9
- ## How it works
12
+ ---
13
+
14
+ ## The jss prop
10
15
 
11
- The way the library works looks similar to inline styles:
16
+ All components accept a `jss` prop that works like inline styles but with additional capabilities:
12
17
 
13
18
  ```js
14
- <div className={jss({ background: "red", padding: 12 })} />
19
+ <BaseView jss={{ backgroundColor: "red", padding: 12 }} />
15
20
  ```
16
21
 
17
- Internally what is happening is that each property gets atomized into a single CSS classname with a unique hash that gets re-used.
22
+ Internally, each property becomes an atomic CSS class with a deterministic hash, enabling server-side rendering and hydration:
18
23
 
19
24
  ```html
20
25
  <style>
21
- .x1uc1pme {
22
- background: red;
23
- }
24
-
25
- .x1kbdebd {
26
- padding: 12;
27
- }
26
+ .x1uc1pme { background: red; }
27
+ .x1kbdebd { padding: 12px; }
28
28
  </style>
29
29
  <div class="x1uc1pme x1kbdebd" />
30
30
  ```
31
31
 
32
- The CSS class name is a hash based on each key-pair. This makes it deterministic, which enables for this system to work with server rendered hydrated react.
32
+ ---
33
33
 
34
- ## Selectors
34
+ ## Arrays and conditionals
35
35
 
36
- Because of how this system works not all selectors can be written, but this is a good thing because arguably CSS selectors are so powerful that it is very easy to make something too hard to understand. These are some examples of how selectors are generated:
36
+ The `jss` prop accepts arrays and falsy values for conditional styling:
37
37
 
38
38
  ```js
39
- jss({[':hover']: { background: 'blue' }})
40
- .x1uc1pme:hover {
41
- background: blue;
42
- }
39
+ <BaseView
40
+ jss={[
41
+ { padding: 16 },
42
+ isActive && { backgroundColor: "blue" },
43
+ isDisabled && { opacity: 0.5 },
44
+ ]}
45
+ />
43
46
  ```
44
47
 
48
+ ---
49
+
50
+ ## Automatic pixel conversion
51
+
52
+ Numeric values are automatically converted to pixels for dimensional properties:
53
+
45
54
  ```js
46
- jss({[':first-child']: { background: 'blue' }})
47
- .x1uc1pme:first-child {
48
- background: blue;
49
- }
55
+ <BaseView jss={{ padding: 16, fontSize: 14, opacity: 0.5 }} />
56
+ // Results in: padding: 16px; font-size: 14px; opacity: 0.5;
50
57
  ```
51
58
 
59
+ ---
60
+
61
+ ## Pseudo-selectors
62
+
63
+ Use string keys for pseudo-classes and pseudo-elements:
64
+
52
65
  ```js
53
- jss({[' div']: { background: 'blue' }})
54
- .x1uc1pme div {
55
- background: blue;
56
- }
66
+ // Hover state
67
+ jss({ ":hover": { backgroundColor: "blue" } })
68
+
69
+ // Focus state
70
+ jss({ ":focus": { outline: "2px solid blue" } })
71
+
72
+ // First child
73
+ jss({ ":first-child": { marginTop: 0 } })
57
74
  ```
58
75
 
76
+ ---
77
+
78
+ ## Descendant selectors
79
+
80
+ Target child elements with space-prefixed selectors:
81
+
59
82
  ```js
60
- jss({['@media (min-width: 750px)']: { maxWidth: 750 }})
61
- @media (min-width: 750px) .x1uc1pme {
62
- maxWidth: 750
63
- }
83
+ // All child divs
84
+ jss({ " div": { padding: 8 } })
85
+
86
+ // Direct children
87
+ jss({ " > span": { color: "red" } })
64
88
  ```
65
89
 
90
+ ---
91
+
92
+ ## Media queries
93
+
94
+ Use media query strings as keys:
95
+
96
+ ```js
97
+ jss({
98
+ padding: 8,
99
+ "@media (min-width: 750px)": {
100
+ padding: 16,
101
+ },
102
+ })
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Responsive helpers
108
+
109
+ The library provides helper functions for common breakpoints:
110
+
111
+ ```js
112
+ import { mobile, tablet, laptop, desktop } from "aidos-ui";
113
+
114
+ <BaseView
115
+ jss={[
116
+ { padding: 8 },
117
+ tablet({ padding: 16 }),
118
+ desktop({ padding: 24 }),
119
+ ]}
120
+ />
121
+ ```
122
+
123
+ | Helper | Breakpoint |
124
+ |--------|------------|
125
+ | `mobile()` | max-width: 479px |
126
+ | `tablet()` | min-width: 480px |
127
+ | `laptop()` | min-width: 1024px |
128
+ | `desktop()` | min-width: 1280px |
129
+
130
+ ---
131
+
66
132
  ## CSS variables
67
133
 
68
- Aidos UI comes with two default themes that can be overridden. These come with the following css variables that can be safely used (in typescript) with the `cssVar` utility:
69
-
70
- - `--overlay-background`
71
- - `--primary-background`
72
- - `--secondary-background`
73
- - `--divider`
74
- - `--strong-divider`
75
- - `--pressed-background`
76
- - `--hovered-background`
77
- - `--selected-background`
78
- - `--nav-bar`
79
- - `--warning`
80
- - `--highlight`
81
- - `--outline`
82
- - `--light-highlight`
83
- - `--primary-text`
84
- - `--secondary-text`
85
- - `--subtle-text`
86
- - `--highlight-text`
87
- - `--negative-text`
88
- - `--light-text`
89
- - `--background-button-positive`
90
- - `--background-button-secondary`
91
- - `--background-button-negative`
92
- - `--background-button-disabled`
93
- - `--spacing-xs`
94
- - `--spacing-s`
95
- - `--spacing-m`
96
- - `--spacing-l`
97
- - `--spacing-xl`
98
- - `--spacing-xxl`
99
- - `--spacing-xxxl`
100
- - `--border-radius-s`
101
- - `--border-radius-m`
102
- - `--border-radius-l`
103
- - `--nav-bar-height`
104
-
105
- For example:
106
-
107
- <Row justify="center">
134
+ Use the `cssVar()` helper for type-safe access to theme variables:
135
+
136
+ <Row justify="center" padding="medium">
108
137
  <Button
109
- jss={{ border: `10px solid ${cssVar("--warning")}` }}
110
- label="Hello"
138
+ jss={{ border: `4px solid ${cssVar("--warning")}` }}
111
139
  color="positive"
112
140
  onClick={() => {}}
113
- />
141
+ >
142
+ Styled button
143
+ </Button>
114
144
  </Row>
115
145
 
116
146
  ```js
117
- <Row justify="center">
118
- <Button
119
- jss={{ border: `10px solid ${cssVar("--warning")}` }}
120
- label="Hello"
121
- color="positive"
122
- onClick={() => {}}
123
- />
124
- </Row>
147
+ import { cssVar } from "aidos-ui";
148
+
149
+ <BaseView jss={{
150
+ backgroundColor: cssVar("--primary-background"),
151
+ color: cssVar("--primary-text"),
152
+ padding: cssVar("--spacing-m"),
153
+ }} />
125
154
  ```
126
155
 
127
156
  ---
157
+
158
+ ## Available CSS variables
159
+
160
+ ### Colors
161
+
162
+ | Variable | Purpose |
163
+ |----------|---------|
164
+ | `--primary-background` | Main background |
165
+ | `--secondary-background` | Alternate background |
166
+ | `--overlay-background` | Modal/popover background |
167
+ | `--divider` | Border/divider color |
168
+ | `--highlight` | Accent/brand color |
169
+ | `--warning` | Warning indicator |
170
+
171
+ ### Text colors
172
+
173
+ | Variable | Purpose |
174
+ |----------|---------|
175
+ | `--primary-text` | Main text |
176
+ | `--secondary-text` | Supporting text |
177
+ | `--subtle-text` | Muted/disabled text |
178
+ | `--highlight-text` | Accent text |
179
+ | `--negative-text` | Error/destructive text |
180
+ | `--light-text` | Text on dark backgrounds |
181
+
182
+ ### Interactive states
183
+
184
+ | Variable | Purpose |
185
+ |----------|---------|
186
+ | `--hovered-background` | Hover state |
187
+ | `--pressed-background` | Active/pressed state |
188
+ | `--selected-background` | Selected item |
189
+
190
+ ### Button backgrounds
191
+
192
+ | Variable | Purpose |
193
+ |----------|---------|
194
+ | `--background-button-positive` | Positive action buttons |
195
+ | `--background-button-secondary` | Secondary buttons |
196
+ | `--background-button-negative` | Destructive buttons |
197
+ | `--background-button-disabled` | Disabled buttons |
198
+
199
+ ### Spacing
200
+
201
+ | Variable | Size |
202
+ |----------|------|
203
+ | `--spacing-xs` | 4px |
204
+ | `--spacing-s` | 8px |
205
+ | `--spacing-m` | 12px |
206
+ | `--spacing-l` | 16px |
207
+ | `--spacing-xl` | 24px |
208
+ | `--spacing-xxl` | 32px |
209
+ | `--spacing-xxxl` | 48px |
210
+
211
+ ### Border radius
212
+
213
+ | Variable | Size |
214
+ |----------|------|
215
+ | `--border-radius-s` | 4px |
216
+ | `--border-radius-m` | 8px |
217
+ | `--border-radius-l` | 12px |
218
+
219
+ ---
220
+
221
+ ## Using toClassnames directly
222
+
223
+ For custom components, use `toClassnames()` to convert style objects to class names:
224
+
225
+ ```js
226
+ import { toClassnames } from "aidos-ui";
227
+
228
+ function CustomComponent({ active }) {
229
+ return (
230
+ <div
231
+ className={toClassnames([
232
+ { padding: 16, borderRadius: 8 },
233
+ active && { backgroundColor: "blue" },
234
+ ])}
235
+ >
236
+ Content
237
+ </div>
238
+ );
239
+ }
240
+ ```
@@ -1,9 +1,15 @@
1
1
  import { List } from "../List";
2
2
  import { ListButtonItem } from "../ListButtonItem";
3
3
 
4
- ## List navigation
4
+ # List Navigation
5
5
 
6
- Lists support keyboard navigation by default via the `useNavigation` hook. It can be disabled by passing the prop `navigation` and tries to emulate the [grid layout spec](https://www.w3.org/WAI/ARIA/apg/patterns/grid/examples/layout-grids/):
6
+ Lists support built-in keyboard navigation using the `useNavigation` hook. This creates an accessible, keyboard-friendly experience following WAI-ARIA patterns.
7
+
8
+ ---
9
+
10
+ ## Enabling navigation
11
+
12
+ Use the `navigation` prop to enable or disable keyboard navigation:
7
13
 
8
14
  <List ariaLabel="example" navigation={true}>
9
15
  <ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
@@ -16,8 +22,20 @@ Lists support keyboard navigation by default via the `useNavigation` hook. It ca
16
22
  />
17
23
  </List>
18
24
 
25
+ ```js
26
+ <List ariaLabel="example" navigation={true}>
27
+ <ListButtonItem headline="Headline 1" onClick={() => {}} />
28
+ <ListButtonItem headline="Headline 2" onClick={() => {}} />
29
+ <ListButtonItem headline="Headline 3" onClick={() => {}} />
30
+ </List>
31
+ ```
32
+
19
33
  ---
20
34
 
35
+ ## Without navigation
36
+
37
+ When `navigation` is `false`, each item is a separate tab stop:
38
+
21
39
  <List ariaLabel="example" navigation={false}>
22
40
  <ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
23
41
  <ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
@@ -30,27 +48,111 @@ Lists support keyboard navigation by default via the `useNavigation` hook. It ca
30
48
  </List>
31
49
 
32
50
  ```js
33
- <List ariaLabel="example" navigation={true}>
34
- <ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
35
- <ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
36
- <ListButtonItem
37
- withDivider={false}
38
- color="secondary"
39
- headline="Headline 3"
40
- onClick={() => {}}
41
- />
51
+ <List ariaLabel="example" navigation={false}>
52
+ <ListButtonItem headline="Headline 1" onClick={() => {}} />
53
+ <ListButtonItem headline="Headline 2" onClick={() => {}} />
54
+ <ListButtonItem headline="Headline 3" onClick={() => {}} />
42
55
  </List>
56
+ ```
43
57
 
44
- <List ariaLabel="example" navigation={false}>
45
- <ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
46
- <ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
47
- <ListButtonItem
48
- withDivider={false}
49
- color="secondary"
50
- headline="Headline 3"
51
- onClick={() => {}}
52
- />
58
+ ---
59
+
60
+ ## Keyboard controls
61
+
62
+ When navigation is enabled:
63
+
64
+ | Key | Action |
65
+ |-----|--------|
66
+ | **Arrow Down** | Move to next item |
67
+ | **Arrow Up** | Move to previous item |
68
+ | **Arrow Right** | Move to next item |
69
+ | **Arrow Left** | Move to previous item |
70
+ | **Enter / Space** | Activate the focused item |
71
+ | **Tab** | Move focus out of the list |
72
+
73
+ Navigation wraps around - pressing down on the last item moves to the first.
74
+
75
+ ---
76
+
77
+ ## How it works
78
+
79
+ The navigation system uses `tabIndex` management:
80
+
81
+ 1. **Single tab stop**: The entire list is one tab stop
82
+ 2. **Active item**: Gets `tabIndex="0"` (focusable)
83
+ 3. **Other items**: Get `tabIndex="-1"` (not in tab order)
84
+ 4. **Arrow keys**: Move the active state between items
85
+
86
+ This follows the [WAI-ARIA grid layout pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/examples/layout-grids/).
87
+
88
+ ---
89
+
90
+ ## Benefits
91
+
92
+ **With navigation enabled:**
93
+ - Faster keyboard navigation (single Tab to enter list)
94
+ - Arrow keys to move between items
95
+ - Better for long lists
96
+ - More efficient for power users
97
+
98
+ **With navigation disabled:**
99
+ - Standard Tab behavior between items
100
+ - Simpler mental model
101
+ - Better for short lists (2-3 items)
102
+ - Each item is independently focusable
103
+
104
+ ---
105
+
106
+ ## Accessibility considerations
107
+
108
+ Always provide an `ariaLabel` for the list:
109
+
110
+ ```js
111
+ <List ariaLabel="Search results" navigation={true}>
112
+ {/* items */}
113
+ </List>
114
+
115
+ <List ariaLabel="User menu options" navigation={true}>
116
+ {/* items */}
53
117
  </List>
54
118
  ```
55
119
 
120
+ This helps screen reader users understand the list's purpose.
121
+
56
122
  ---
123
+
124
+ ## When to use navigation
125
+
126
+ **Enable navigation for:**
127
+ - Long lists (5+ items)
128
+ - Menu-like interfaces
129
+ - Search results
130
+ - Option lists
131
+ - File browsers
132
+
133
+ **Disable navigation for:**
134
+ - Short action lists (2-3 items)
135
+ - Form field groups
136
+ - Simple button groups
137
+ - When each item needs independent focus
138
+
139
+ ---
140
+
141
+ ## Implementation
142
+
143
+ Lists use the `useNavigation` hook internally:
144
+
145
+ ```js
146
+ // Simplified internal implementation
147
+ function List({ navigation = true, children, ariaLabel }) {
148
+ const rootRef = useNavigation({ enabled: navigation });
149
+
150
+ return (
151
+ <ul ref={rootRef} aria-label={ariaLabel}>
152
+ {children}
153
+ </ul>
154
+ );
155
+ }
156
+ ```
157
+
158
+ See the [useNavigation documentation](/useNavigation) for more details on the underlying hook.