remix 3.0.0-beta.4 → 3.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/assets/types/hmr.d.ts +2 -0
- package/dist/cli-entry.js +1 -1
- package/dist/data-table/cli.d.ts +2 -0
- package/dist/data-table/cli.d.ts.map +1 -0
- package/dist/{ui/scroll-lock.js → data-table/cli.js} +1 -1
- package/dist/node-hmr/runtime.d.ts +2 -0
- package/dist/node-hmr/runtime.d.ts.map +1 -0
- package/dist/node-hmr/runtime.js +2 -0
- package/dist/node-hmr/types.d.ts +2 -0
- package/dist/node-hmr.d.ts +2 -0
- package/dist/node-hmr.d.ts.map +1 -0
- package/dist/{ui/glyph.js → node-hmr.js} +1 -1
- package/dist/ui/accordion/primitives.d.ts +2 -0
- package/dist/ui/accordion/primitives.d.ts.map +1 -0
- package/dist/ui/accordion/primitives.js +2 -0
- package/dist/ui/button.d.ts +1 -0
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +1 -0
- package/dist/ui/checkbox.d.ts +3 -0
- package/dist/ui/checkbox.d.ts.map +1 -0
- package/dist/ui/checkbox.js +3 -0
- package/dist/ui/combobox/primitives.d.ts +2 -0
- package/dist/ui/combobox/primitives.d.ts.map +1 -0
- package/dist/ui/combobox/primitives.js +2 -0
- package/dist/ui/dev/refresh.d.ts +2 -0
- package/dist/ui/dev/refresh.d.ts.map +1 -0
- package/dist/ui/dev/refresh.js +2 -0
- package/dist/ui/input.d.ts +3 -0
- package/dist/ui/input.d.ts.map +1 -0
- package/dist/ui/input.js +3 -0
- package/dist/ui/menu/primitives.d.ts +2 -0
- package/dist/ui/menu/primitives.d.ts.map +1 -0
- package/dist/ui/menu/primitives.js +2 -0
- package/dist/ui/radio.d.ts +3 -0
- package/dist/ui/radio.d.ts.map +1 -0
- package/dist/ui/radio.js +3 -0
- package/dist/ui/select/primitives.d.ts +2 -0
- package/dist/ui/select/primitives.d.ts.map +1 -0
- package/dist/ui/select/primitives.js +2 -0
- package/dist/ui/tabs/primitives.d.ts +2 -0
- package/dist/ui/tabs/primitives.d.ts.map +1 -0
- package/dist/ui/tabs/primitives.js +2 -0
- package/dist/ui/tabs.d.ts +2 -0
- package/dist/ui/tabs.d.ts.map +1 -0
- package/{src/ui/theme.ts → dist/ui/tabs.js} +1 -1
- package/dist/ui/toggle/primitives.d.ts +2 -0
- package/dist/ui/toggle/primitives.d.ts.map +1 -0
- package/dist/ui/toggle/primitives.js +2 -0
- package/dist/ui/toggle.d.ts +3 -0
- package/dist/ui/toggle.d.ts.map +1 -0
- package/dist/ui/toggle.js +3 -0
- package/dist/ui-hmr/assets.d.ts +2 -0
- package/dist/ui-hmr/assets.d.ts.map +1 -0
- package/dist/ui-hmr/assets.js +2 -0
- package/dist/ui-hmr/node.d.ts +3 -0
- package/dist/ui-hmr/node.d.ts.map +1 -0
- package/dist/ui-hmr/node.js +3 -0
- package/dist/ui-hmr/runtime/browser.d.ts +2 -0
- package/dist/ui-hmr/runtime/browser.d.ts.map +1 -0
- package/dist/ui-hmr/runtime/browser.js +2 -0
- package/dist/ui-hmr/runtime/server.d.ts +2 -0
- package/dist/ui-hmr/runtime/server.d.ts.map +1 -0
- package/dist/ui-hmr/runtime/server.js +2 -0
- package/dist/ui-hmr.d.ts +2 -0
- package/dist/ui-hmr.d.ts.map +1 -0
- package/{src/ui/glyph.ts → dist/ui-hmr.js} +1 -1
- package/package.json +122 -142
- package/src/assets/README.md +322 -56
- package/src/assets/types/hmr.d.ts +2 -0
- package/src/cli/README.md +105 -1
- package/src/cookie/README.md +4 -4
- package/src/data-table/README.md +202 -68
- package/src/data-table/cli.ts +2 -0
- package/src/data-table-mysql/README.md +46 -17
- package/src/data-table-postgres/README.md +39 -13
- package/src/data-table-sqlite/README.md +38 -20
- package/src/fetch-proxy/README.md +25 -0
- package/src/form-data-parser/README.md +4 -4
- package/src/mime/README.md +8 -1
- package/src/node-fetch-server/README.md +39 -13
- package/src/node-hmr/README.md +307 -0
- package/src/node-hmr/runtime.ts +2 -0
- package/src/node-hmr/types.d.ts +2 -0
- package/{dist/ui/theme.js → src/node-hmr.ts} +1 -1
- package/src/route-pattern/README.md +141 -13
- package/src/session/README.md +1 -1
- package/src/session-middleware/README.md +9 -7
- package/src/test/README.md +161 -115
- package/src/ui/README.md +116 -157
- package/src/ui/accordion/README.md +50 -14
- package/src/ui/accordion/primitives/README.md +202 -0
- package/src/ui/accordion/primitives.ts +2 -0
- package/src/ui/anchor/README.md +37 -2
- package/src/ui/breadcrumbs/README.md +4 -4
- package/src/ui/button/README.md +26 -26
- package/src/ui/button.ts +1 -0
- package/src/ui/checkbox/README.md +59 -0
- package/src/ui/checkbox.ts +3 -0
- package/src/ui/combobox/README.md +58 -9
- package/src/ui/combobox/primitives/README.md +194 -0
- package/src/ui/combobox/primitives.ts +2 -0
- package/src/ui/dev/refresh.ts +2 -0
- package/src/ui/input/README.md +52 -0
- package/src/ui/input.ts +3 -0
- package/src/ui/listbox/README.md +9 -41
- package/src/ui/menu/README.md +55 -14
- package/src/ui/menu/primitives/README.md +161 -0
- package/src/ui/menu/primitives.ts +2 -0
- package/src/ui/popover/README.md +20 -39
- package/src/ui/radio/README.md +53 -0
- package/src/ui/radio.ts +3 -0
- package/src/ui/select/README.md +29 -19
- package/src/ui/select/primitives/README.md +117 -0
- package/src/ui/select/primitives.ts +2 -0
- package/src/ui/tabs/README.md +141 -0
- package/src/ui/tabs/primitives/README.md +141 -0
- package/src/ui/tabs/primitives.ts +2 -0
- package/src/ui/tabs.ts +2 -0
- package/src/ui/test/README.md +151 -60
- package/src/ui/toggle/README.md +56 -0
- package/src/ui/toggle/primitives/README.md +56 -0
- package/src/ui/toggle/primitives.ts +2 -0
- package/src/ui/toggle.ts +3 -0
- package/src/ui-hmr/README.md +119 -0
- package/{dist/ui/separator.js → src/ui-hmr/assets.ts} +1 -1
- package/src/ui-hmr/node.ts +3 -0
- package/src/ui-hmr/runtime/browser.ts +2 -0
- package/src/ui-hmr/runtime/server.ts +2 -0
- package/src/ui-hmr.ts +2 -0
- package/dist/ui/glyph.d.ts +0 -2
- package/dist/ui/glyph.d.ts.map +0 -1
- package/dist/ui/scroll-lock.d.ts +0 -2
- package/dist/ui/scroll-lock.d.ts.map +0 -1
- package/dist/ui/separator.d.ts +0 -2
- package/dist/ui/separator.d.ts.map +0 -1
- package/dist/ui/theme.d.ts +0 -2
- package/dist/ui/theme.d.ts.map +0 -1
- package/src/ui/glyph/README.md +0 -72
- package/src/ui/scroll-lock/README.md +0 -33
- package/src/ui/scroll-lock.ts +0 -2
- package/src/ui/separator.ts +0 -2
- package/src/ui/theme/README.md +0 -103
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`Accordion` renders a disclosure set with one or more expandable items. Use it for grouped settings, FAQ sections, and dense panels where each item owns a trigger and content region.
|
|
4
4
|
|
|
5
|
-
## Usage
|
|
5
|
+
## Component Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from 'remix/ui/accordion'
|
|
@@ -82,16 +82,11 @@ export function ControlledAccordion(handle: Handle) {
|
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
Listen for bubbling `AccordionChangeEvent` events with `onAccordionChange`.
|
|
85
|
+
Listen for bubbling `AccordionChangeEvent` events with `onAccordionChange` from `remix/ui/accordion/primitives`.
|
|
86
86
|
|
|
87
87
|
```tsx
|
|
88
|
-
import {
|
|
89
|
-
|
|
90
|
-
AccordionContent,
|
|
91
|
-
AccordionItem,
|
|
92
|
-
AccordionTrigger,
|
|
93
|
-
onAccordionChange,
|
|
94
|
-
} from 'remix/ui/accordion'
|
|
88
|
+
import { onAccordionChange } from 'remix/ui/accordion/primitives'
|
|
89
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from 'remix/ui/accordion'
|
|
95
90
|
|
|
96
91
|
export function TrackedAccordion() {
|
|
97
92
|
return (
|
|
@@ -124,7 +119,7 @@ Set `collapsible={false}` in single mode when the open item must stay open. The
|
|
|
124
119
|
</Accordion>
|
|
125
120
|
```
|
|
126
121
|
|
|
127
|
-
Use `headingLevel` to choose the heading
|
|
122
|
+
Use `headingLevel` to choose the heading element rendered around each trigger. The default level is `3`.
|
|
128
123
|
|
|
129
124
|
```tsx
|
|
130
125
|
<Accordion defaultValue="shipping" headingLevel={2}>
|
|
@@ -142,16 +137,57 @@ Pass `indicator={null}` to remove the default chevron, or pass a custom node to
|
|
|
142
137
|
<AccordionTrigger indicator={<span aria-hidden>+</span>}>Custom indicator</AccordionTrigger>
|
|
143
138
|
```
|
|
144
139
|
|
|
145
|
-
##
|
|
140
|
+
## Primitive Usage
|
|
141
|
+
|
|
142
|
+
Use the lower-level primitives when app code owns the accordion markup and styles:
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import * as accordion from 'remix/ui/accordion/primitives'
|
|
146
|
+
import { contentStyle, headingStyle, itemStyle, rootStyle, triggerStyle } from './accordion.styles'
|
|
147
|
+
|
|
148
|
+
export function PrimitiveAccordion() {
|
|
149
|
+
return (
|
|
150
|
+
<accordion.Context defaultValue="shipping">
|
|
151
|
+
<div mix={[rootStyle, accordion.root()]}>
|
|
152
|
+
<accordion.ItemContext value="shipping">
|
|
153
|
+
<div mix={[itemStyle, accordion.item()]}>
|
|
154
|
+
<h3 mix={headingStyle}>
|
|
155
|
+
<button mix={[triggerStyle, accordion.trigger()]} type="button">
|
|
156
|
+
Shipping
|
|
157
|
+
</button>
|
|
158
|
+
</h3>
|
|
159
|
+
<div mix={[contentStyle, accordion.content()]}>
|
|
160
|
+
Delivery windows and carrier defaults.
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</accordion.ItemContext>
|
|
164
|
+
</div>
|
|
165
|
+
</accordion.Context>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## `remix/ui/accordion`
|
|
146
171
|
|
|
147
172
|
- `Accordion`: root component. Defaults to single-item mode and supports controlled `value`, uncontrolled `defaultValue`, `onValueChange`, `disabled`, `headingLevel`, `collapsible`, and `type="multiple"`.
|
|
148
173
|
- `AccordionItem`: registers one accordion item by `value`. Pass `disabled` to prevent that item from opening or receiving keyboard focus.
|
|
149
174
|
- `AccordionTrigger`: heading-wrapped button for an item. It wires `aria-expanded`, `aria-controls`, keyboard navigation, and the default chevron indicator.
|
|
150
175
|
- `AccordionContent`: panel for an item. It wires the panel id, `aria-labelledby`, `aria-hidden`, inert state, and open/closed state attributes.
|
|
176
|
+
- `rootStyle`, `itemStyle`, `headingStyle`, `triggerStyle`, `indicatorStyle`, `panelStyle`, and `bodyStyle`: flat style mixins used by the component markup.
|
|
177
|
+
- `AccordionProps`, `AccordionSingleProps`, `AccordionMultipleProps`, `AccordionItemProps`, `AccordionTriggerProps`, and `AccordionContentProps`: public TypeScript props for the composed APIs.
|
|
178
|
+
|
|
179
|
+
## `remix/ui/accordion/primitives`
|
|
180
|
+
|
|
181
|
+
- `Context`: lower-level provider for custom accordion composition.
|
|
182
|
+
- `ItemContext`: lower-level provider for one item value.
|
|
183
|
+
- `root()`: wires the root element and bubbling change events.
|
|
184
|
+
- `item()`: wires one item wrapper.
|
|
185
|
+
- `trigger()`: wires the item trigger, keyboard navigation, and trigger ARIA attributes.
|
|
186
|
+
- `content()`: wires the item panel id, hidden state, inert state, and open/closed state attributes.
|
|
151
187
|
- `onAccordionChange(...)`: event mixin for the bubbling `AccordionChangeEvent`.
|
|
152
|
-
- `AccordionChangeEvent`: bubbling event
|
|
153
|
-
- `
|
|
154
|
-
- `
|
|
188
|
+
- `AccordionChangeEvent`: bubbling event with `value`, `itemValue`, and `accordionType`.
|
|
189
|
+
- `AccordionType`, `AccordionValue`, `AccordionSingleValue`, `AccordionMultipleValue`, and `AccordionHeadingLevel`: public TypeScript state and configuration types.
|
|
190
|
+
- `AccordionBaseContextProps`, `AccordionSingleContextProps`, `AccordionMultipleContextProps`, `AccordionContextProps`, `AccordionRootOptions`, `AccordionItemOptions`, `AccordionTriggerOptions`, and `AccordionContentOptions`: primitive prop and option types for custom composition.
|
|
155
191
|
|
|
156
192
|
## Behavior Notes
|
|
157
193
|
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# accordion
|
|
2
|
+
|
|
3
|
+
`Accordion` renders a disclosure set with one or more expandable items. Use it for grouped settings, FAQ sections, and dense panels where each item owns a trigger and content region.
|
|
4
|
+
|
|
5
|
+
## Component Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from 'remix/ui/accordion'
|
|
9
|
+
|
|
10
|
+
export function SettingsAccordion() {
|
|
11
|
+
return (
|
|
12
|
+
<Accordion defaultValue="account">
|
|
13
|
+
<AccordionItem value="account">
|
|
14
|
+
<AccordionTrigger>Account</AccordionTrigger>
|
|
15
|
+
<AccordionContent>Manage account preferences.</AccordionContent>
|
|
16
|
+
</AccordionItem>
|
|
17
|
+
|
|
18
|
+
<AccordionItem value="billing">
|
|
19
|
+
<AccordionTrigger>Billing</AccordionTrigger>
|
|
20
|
+
<AccordionContent>Review billing details.</AccordionContent>
|
|
21
|
+
</AccordionItem>
|
|
22
|
+
</Accordion>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use `type="multiple"` when more than one panel may stay open. `defaultValue` and `value` are arrays in multiple mode.
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from 'remix/ui/accordion'
|
|
31
|
+
|
|
32
|
+
export function StatusAccordion() {
|
|
33
|
+
return (
|
|
34
|
+
<Accordion defaultValue={['api', 'alerts']} type="multiple">
|
|
35
|
+
<AccordionItem value="api">
|
|
36
|
+
<AccordionTrigger>API status checks</AccordionTrigger>
|
|
37
|
+
<AccordionContent>Review uptime checks and response time alerts.</AccordionContent>
|
|
38
|
+
</AccordionItem>
|
|
39
|
+
|
|
40
|
+
<AccordionItem disabled value="access">
|
|
41
|
+
<AccordionTrigger>Access control sync</AccordionTrigger>
|
|
42
|
+
<AccordionContent>This disabled item cannot be opened or focused.</AccordionContent>
|
|
43
|
+
</AccordionItem>
|
|
44
|
+
|
|
45
|
+
<AccordionItem value="alerts">
|
|
46
|
+
<AccordionTrigger>Alert routing</AccordionTrigger>
|
|
47
|
+
<AccordionContent>Confirm escalation rules and notification channels.</AccordionContent>
|
|
48
|
+
</AccordionItem>
|
|
49
|
+
</Accordion>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Control the open value when state should live in the owning component. Single mode uses `string | null`; multiple mode uses `string[]`.
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import type { Handle } from 'remix/ui'
|
|
58
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from 'remix/ui/accordion'
|
|
59
|
+
|
|
60
|
+
export function ControlledAccordion(handle: Handle) {
|
|
61
|
+
let value: string | null = 'account'
|
|
62
|
+
|
|
63
|
+
return () => (
|
|
64
|
+
<Accordion
|
|
65
|
+
value={value}
|
|
66
|
+
onValueChange={(nextValue) => {
|
|
67
|
+
value = nextValue
|
|
68
|
+
void handle.update()
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
<AccordionItem value="account">
|
|
72
|
+
<AccordionTrigger>Account</AccordionTrigger>
|
|
73
|
+
<AccordionContent>Manage account preferences.</AccordionContent>
|
|
74
|
+
</AccordionItem>
|
|
75
|
+
|
|
76
|
+
<AccordionItem value="billing">
|
|
77
|
+
<AccordionTrigger>Billing</AccordionTrigger>
|
|
78
|
+
<AccordionContent>Review billing details.</AccordionContent>
|
|
79
|
+
</AccordionItem>
|
|
80
|
+
</Accordion>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Listen for bubbling `AccordionChangeEvent` events with `onAccordionChange` from `remix/ui/accordion/primitives`.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { onAccordionChange } from 'remix/ui/accordion/primitives'
|
|
89
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from 'remix/ui/accordion'
|
|
90
|
+
|
|
91
|
+
export function TrackedAccordion() {
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
mix={[
|
|
95
|
+
onAccordionChange((event) => {
|
|
96
|
+
console.log(event.accordionType, event.itemValue, event.value)
|
|
97
|
+
}),
|
|
98
|
+
]}
|
|
99
|
+
>
|
|
100
|
+
<Accordion>
|
|
101
|
+
<AccordionItem value="account">
|
|
102
|
+
<AccordionTrigger>Account</AccordionTrigger>
|
|
103
|
+
<AccordionContent>Manage account preferences.</AccordionContent>
|
|
104
|
+
</AccordionItem>
|
|
105
|
+
</Accordion>
|
|
106
|
+
</div>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Set `collapsible={false}` in single mode when the open item must stay open. The locked-open trigger receives `aria-disabled`.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<Accordion collapsible={false} defaultValue="account">
|
|
115
|
+
<AccordionItem value="account">
|
|
116
|
+
<AccordionTrigger>Account</AccordionTrigger>
|
|
117
|
+
<AccordionContent>Manage account preferences.</AccordionContent>
|
|
118
|
+
</AccordionItem>
|
|
119
|
+
</Accordion>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use `headingLevel` to choose the heading element rendered around each trigger. The default level is `3`.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<Accordion defaultValue="shipping" headingLevel={2}>
|
|
126
|
+
<AccordionItem value="shipping">
|
|
127
|
+
<AccordionTrigger>Shipping</AccordionTrigger>
|
|
128
|
+
<AccordionContent>Review shipping preferences.</AccordionContent>
|
|
129
|
+
</AccordionItem>
|
|
130
|
+
</Accordion>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Pass `indicator={null}` to remove the default chevron, or pass a custom node to replace it.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<AccordionTrigger indicator={null}>No indicator</AccordionTrigger>
|
|
137
|
+
<AccordionTrigger indicator={<span aria-hidden>+</span>}>Custom indicator</AccordionTrigger>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Primitive Usage
|
|
141
|
+
|
|
142
|
+
Use the lower-level primitives when app code owns the accordion markup and styles:
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import * as accordion from 'remix/ui/accordion/primitives'
|
|
146
|
+
import { contentStyle, headingStyle, itemStyle, rootStyle, triggerStyle } from './accordion.styles'
|
|
147
|
+
|
|
148
|
+
export function PrimitiveAccordion() {
|
|
149
|
+
return (
|
|
150
|
+
<accordion.Context defaultValue="shipping">
|
|
151
|
+
<div mix={[rootStyle, accordion.root()]}>
|
|
152
|
+
<accordion.ItemContext value="shipping">
|
|
153
|
+
<div mix={[itemStyle, accordion.item()]}>
|
|
154
|
+
<h3 mix={headingStyle}>
|
|
155
|
+
<button mix={[triggerStyle, accordion.trigger()]} type="button">
|
|
156
|
+
Shipping
|
|
157
|
+
</button>
|
|
158
|
+
</h3>
|
|
159
|
+
<div mix={[contentStyle, accordion.content()]}>
|
|
160
|
+
Delivery windows and carrier defaults.
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</accordion.ItemContext>
|
|
164
|
+
</div>
|
|
165
|
+
</accordion.Context>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## `remix/ui/accordion`
|
|
171
|
+
|
|
172
|
+
- `Accordion`: root component. Defaults to single-item mode and supports controlled `value`, uncontrolled `defaultValue`, `onValueChange`, `disabled`, `headingLevel`, `collapsible`, and `type="multiple"`.
|
|
173
|
+
- `AccordionItem`: registers one accordion item by `value`. Pass `disabled` to prevent that item from opening or receiving keyboard focus.
|
|
174
|
+
- `AccordionTrigger`: heading-wrapped button for an item. It wires `aria-expanded`, `aria-controls`, keyboard navigation, and the default chevron indicator.
|
|
175
|
+
- `AccordionContent`: panel for an item. It wires the panel id, `aria-labelledby`, `aria-hidden`, inert state, and open/closed state attributes.
|
|
176
|
+
- `rootStyle`, `itemStyle`, `headingStyle`, `triggerStyle`, `indicatorStyle`, `panelStyle`, and `bodyStyle`: flat style mixins used by the component markup.
|
|
177
|
+
- `AccordionProps`, `AccordionSingleProps`, `AccordionMultipleProps`, `AccordionItemProps`, `AccordionTriggerProps`, and `AccordionContentProps`: public TypeScript props for the composed APIs.
|
|
178
|
+
|
|
179
|
+
## `remix/ui/accordion/primitives`
|
|
180
|
+
|
|
181
|
+
- `Context`: lower-level provider for custom accordion composition.
|
|
182
|
+
- `ItemContext`: lower-level provider for one item value.
|
|
183
|
+
- `root()`: wires the root element and bubbling change events.
|
|
184
|
+
- `item()`: wires one item wrapper.
|
|
185
|
+
- `trigger()`: wires the item trigger, keyboard navigation, and trigger ARIA attributes.
|
|
186
|
+
- `content()`: wires the item panel id, hidden state, inert state, and open/closed state attributes.
|
|
187
|
+
- `onAccordionChange(...)`: event mixin for the bubbling `AccordionChangeEvent`.
|
|
188
|
+
- `AccordionChangeEvent`: bubbling event with `value`, `itemValue`, and `accordionType`.
|
|
189
|
+
- `AccordionType`, `AccordionValue`, `AccordionSingleValue`, `AccordionMultipleValue`, and `AccordionHeadingLevel`: public TypeScript state and configuration types.
|
|
190
|
+
- `AccordionBaseContextProps`, `AccordionSingleContextProps`, `AccordionMultipleContextProps`, `AccordionContextProps`, `AccordionRootOptions`, `AccordionItemOptions`, `AccordionTriggerOptions`, and `AccordionContentOptions`: primitive prop and option types for custom composition.
|
|
191
|
+
|
|
192
|
+
## Behavior Notes
|
|
193
|
+
|
|
194
|
+
- Single mode stores one open value or `null`; multiple mode stores an array of open values.
|
|
195
|
+
- Single accordions are collapsible by default. Set `collapsible={false}` to keep the open item locked open.
|
|
196
|
+
- Root `disabled` disables every item. Item `disabled` only disables that item.
|
|
197
|
+
- Arrow keys move between enabled triggers. `Home` and `End` move to the first and last enabled triggers.
|
|
198
|
+
- Disabled items are skipped by keyboard navigation.
|
|
199
|
+
- Trigger and panel ids are generated and linked with `aria-controls`, `aria-labelledby`, and `aria-expanded`; closed panels receive `aria-hidden` and `inert`.
|
|
200
|
+
- `AccordionTrigger` renders inside an `h1`-`h6` element based on `headingLevel`.
|
|
201
|
+
- Each item and trigger receives `data-state="open"` or `data-state="closed"` for styling.
|
|
202
|
+
- `AccordionChangeEvent` bubbles from the root and includes `value`, `itemValue`, and `accordionType`.
|
package/src/ui/anchor/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`anchor` positions a floating element against an anchor element or viewport coordinates and keeps it constrained to the viewport. Use it for custom floating surfaces that need placement, flipping, offsets, and optional relative alignment.
|
|
4
4
|
|
|
5
|
-
## Usage
|
|
5
|
+
## Primitive Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
import { anchor } from 'remix/ui/anchor'
|
|
@@ -55,7 +55,42 @@ Anchor to coordinates when the surface should open at a pointer location.
|
|
|
55
55
|
let cleanup = anchor(popover, { x: event.clientX, y: event.clientY }, { placement: 'bottom-start' })
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Keep presentation app-owned when the anchored element is rendered by your component:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { anchor } from 'remix/ui/anchor'
|
|
62
|
+
import { on, ref, type Handle } from 'remix/ui'
|
|
63
|
+
import { panelStyle } from './floating.styles'
|
|
64
|
+
|
|
65
|
+
export function AnchoredPanel(handle: Handle) {
|
|
66
|
+
let cleanup = () => {}
|
|
67
|
+
let trigger: HTMLElement | null = null
|
|
68
|
+
let panel: HTMLElement | null = null
|
|
69
|
+
|
|
70
|
+
function position() {
|
|
71
|
+
cleanup()
|
|
72
|
+
if (trigger && panel) {
|
|
73
|
+
cleanup = anchor(panel, trigger, { placement: 'bottom-start', offset: 8 })
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return () => (
|
|
78
|
+
<>
|
|
79
|
+
<button
|
|
80
|
+
mix={[ref((node) => (trigger = node as HTMLElement)), on('click', position)]}
|
|
81
|
+
type="button"
|
|
82
|
+
>
|
|
83
|
+
Open
|
|
84
|
+
</button>
|
|
85
|
+
<div data-panel mix={[panelStyle, ref((node) => (panel = node as HTMLElement))]}>
|
|
86
|
+
Panel
|
|
87
|
+
</div>
|
|
88
|
+
</>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## `remix/ui/anchor`
|
|
59
94
|
|
|
60
95
|
- `anchor(floatingElement, anchorTarget, options)`: positions `floatingElement` against an element or coordinate target, starts animation-frame polling for geometry changes, and returns a cleanup function.
|
|
61
96
|
- `AnchorOptions`: placement, inset, relative alignment, and offset options.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`Breadcrumbs` renders semantic breadcrumb navigation from a list of items. Use it when the page needs a compact path back through parent sections.
|
|
4
4
|
|
|
5
|
-
## Usage
|
|
5
|
+
## Component Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
import { Breadcrumbs } from 'remix/ui/breadcrumbs'
|
|
@@ -32,13 +32,13 @@ Mark an earlier item as current when the page belongs to a parent section but th
|
|
|
32
32
|
/>
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Pass `separator` to replace the default chevron
|
|
35
|
+
Pass `separator` to replace the default chevron icon.
|
|
36
36
|
|
|
37
37
|
```tsx
|
|
38
38
|
<Breadcrumbs items={[{ href: '/', label: 'Home' }, { label: 'Breadcrumbs' }]} separator="/" />
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
## `breadcrumbs
|
|
41
|
+
## `remix/ui/breadcrumbs`
|
|
42
42
|
|
|
43
43
|
- `Breadcrumbs`: component that renders a `<nav>` with an ordered list of breadcrumb items.
|
|
44
44
|
- `BreadcrumbItem`: item shape with `label`, optional `href`, and optional `current`.
|
|
@@ -52,4 +52,4 @@ Pass `separator` to replace the default chevron glyph.
|
|
|
52
52
|
- An explicit current item wins over the last-item default.
|
|
53
53
|
- Current items render as text with `aria-current="page"`, even when they include `href`.
|
|
54
54
|
- Non-current items with `href` render as links; non-current items without `href` render as text.
|
|
55
|
-
- The default separator is
|
|
55
|
+
- The default separator is a chevron icon. Separators render between items and are hidden from assistive technology.
|
package/src/ui/button/README.md
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
# button
|
|
2
2
|
|
|
3
|
-
`button` is
|
|
3
|
+
`button` is a style mixin for pill-shaped action controls. It owns only button-like visual styling and the default `type="button"` behavior for native `<button>` hosts.
|
|
4
4
|
|
|
5
|
-
## Usage
|
|
5
|
+
## Primitive Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
|
-
import
|
|
9
|
-
import * as button from 'remix/ui/button'
|
|
10
|
-
import { Glyph } from 'remix/ui/glyph'
|
|
8
|
+
import button from 'remix/ui/button'
|
|
11
9
|
|
|
12
10
|
function Actions() {
|
|
13
|
-
return (
|
|
11
|
+
return () => (
|
|
14
12
|
<div>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
</
|
|
18
|
-
|
|
19
|
-
<a href="/projects" mix={[button.baseStyle, button.secondaryStyle]}>
|
|
20
|
-
<span mix={button.labelStyle}>View projects</span>
|
|
21
|
-
<Glyph mix={button.iconStyle} name="chevronRight" />
|
|
22
|
-
</a>
|
|
13
|
+
<button mix={button()}>Edit order</button>
|
|
14
|
+
<button mix={button({ size: 'lg', tone: 'primary' })}>Add product</button>
|
|
15
|
+
<button mix={button({ tone: 'ghost' })}>Cancel</button>
|
|
23
16
|
</div>
|
|
24
17
|
)
|
|
25
18
|
}
|
|
26
19
|
```
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
Compose app-owned styles around the primitive when a control needs local layout or state styling:
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- `button.labelStyle`: inline label slot with the standard button spacing.
|
|
34
|
-
- `button.iconStyle`: icon slot sizing and `aria-hidden` defaults for decorative icons.
|
|
23
|
+
```tsx
|
|
24
|
+
import button from 'remix/ui/button'
|
|
25
|
+
import { toolbarButtonStyle } from './toolbar.styles'
|
|
35
26
|
|
|
36
|
-
|
|
27
|
+
function ToolbarAction() {
|
|
28
|
+
return () => <button mix={[toolbarButtonStyle, button({ tone: 'ghost' })]}>Archive</button>
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## `remix/ui/button`
|
|
37
33
|
|
|
38
|
-
- `button
|
|
39
|
-
- `
|
|
40
|
-
-
|
|
34
|
+
- `button(options)`: style mixin for native buttons or button-like hosts.
|
|
35
|
+
- `ButtonOptions`: accepts `size` and `tone`.
|
|
36
|
+
- `ButtonSize`: `'md'` or `'lg'`. Defaults to `'md'`.
|
|
37
|
+
- `ButtonTone`: `'neutral'`, `'primary'`, or `'ghost'`. Defaults to `'neutral'`.
|
|
41
38
|
|
|
42
|
-
##
|
|
39
|
+
## Behavior Notes
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
- `button()` returns a mixin descriptor, so it composes with other mixins in the host element's `mix` prop.
|
|
42
|
+
- Native `<button>` hosts receive `type="button"` unless an explicit `type` is provided.
|
|
43
|
+
- Non-button hosts receive styling only.
|
|
44
|
+
- Disabled hosts use the shared disabled treatment through `disabled` or `aria-disabled="true"`.
|
package/src/ui/button.ts
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# checkbox
|
|
2
|
+
|
|
3
|
+
`checkbox` is a style mixin for native checkbox inputs. It only owns checkbox visuals, an optional visual state, and the default `type="checkbox"` behavior for native `<input>` hosts.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import checkbox from 'remix/ui/checkbox'
|
|
9
|
+
|
|
10
|
+
function VisibilityToggle() {
|
|
11
|
+
return () => (
|
|
12
|
+
<label>
|
|
13
|
+
<input defaultChecked mix={checkbox()} name="visibility" value="archived" />
|
|
14
|
+
Show archived items
|
|
15
|
+
</label>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Use `size: 'lg'` when the surrounding UI needs a larger visual control:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<input mix={checkbox({ size: 'lg' })} />
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For mixed state, app code owns the checkbox state and the native `indeterminate` property:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import checkbox from 'remix/ui/checkbox'
|
|
30
|
+
|
|
31
|
+
function PermissionParent() {
|
|
32
|
+
let state: 'checked' | 'mixed' | 'unchecked' = 'mixed'
|
|
33
|
+
|
|
34
|
+
return () => (
|
|
35
|
+
<input
|
|
36
|
+
checked={state === 'checked'}
|
|
37
|
+
indeterminate={state === 'mixed'}
|
|
38
|
+
mix={checkbox({ state })}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## `remix/ui/checkbox`
|
|
45
|
+
|
|
46
|
+
- `checkbox(options)`: style mixin for native checkbox inputs or checkbox-like hosts.
|
|
47
|
+
- `CheckboxOptions`: accepts `size` and `state`.
|
|
48
|
+
- `CheckboxSize`: `'md'` or `'lg'`. Defaults to `'md'`.
|
|
49
|
+
- `CheckboxState`: `'checked'`, `'mixed'`, or `'unchecked'`.
|
|
50
|
+
|
|
51
|
+
## Behavior Notes
|
|
52
|
+
|
|
53
|
+
- `checkbox()` returns a mixin descriptor, so it composes with other mixins in the host element's `mix` prop.
|
|
54
|
+
- Native `<input>` hosts receive `type="checkbox"` unless an explicit `type` is provided.
|
|
55
|
+
- Native input state is browser-owned through `checked`, `defaultChecked`, and user interaction.
|
|
56
|
+
- The optional `state` option adds `aria-checked` and `data-state` for app-owned mixed state or custom hosts.
|
|
57
|
+
- Checked styles apply through `:checked`, `aria-checked="true"`, or `data-state="checked"`.
|
|
58
|
+
- Mixed styles apply through `:indeterminate`, `indeterminate`, `aria-checked="mixed"`, or `data-state="mixed"`.
|
|
59
|
+
- Disabled hosts use the shared disabled treatment through `disabled` or `aria-disabled="true"`.
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# combobox
|
|
2
2
|
|
|
3
|
-
`Combobox` is the input-first popup value picker for `remix/ui`.
|
|
3
|
+
`Combobox` is the input-first popup value picker for `remix/ui/combobox`.
|
|
4
4
|
|
|
5
5
|
Use it when the user should type draft text, filter a popup list, and still commit one stable form value. If you just need a button-triggered picker, use `Select` instead.
|
|
6
6
|
|
|
7
|
-
## Usage
|
|
7
|
+
## Component Usage
|
|
8
8
|
|
|
9
9
|
```tsx
|
|
10
10
|
import { css, type Handle } from 'remix/ui'
|
|
11
|
-
import { Combobox, ComboboxOption
|
|
11
|
+
import { Combobox, ComboboxOption } from 'remix/ui/combobox'
|
|
12
|
+
import { onComboboxChange } from 'remix/ui/combobox/primitives'
|
|
12
13
|
|
|
13
14
|
let airports = [
|
|
14
15
|
{
|
|
@@ -58,7 +59,39 @@ let root = css({
|
|
|
58
59
|
})
|
|
59
60
|
```
|
|
60
61
|
|
|
61
|
-
##
|
|
62
|
+
## Primitive Usage
|
|
63
|
+
|
|
64
|
+
Use the lower-level primitives when app code owns the input, popover, list, and option markup:
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import * as combobox from 'remix/ui/combobox/primitives'
|
|
68
|
+
import { inputStyle, listStyle, optionStyle, popoverStyle } from './combobox.styles'
|
|
69
|
+
|
|
70
|
+
let frameworks = [
|
|
71
|
+
{ label: 'Remix', searchValue: ['remix', 'rmx'], value: 'remix' },
|
|
72
|
+
{ label: 'React Router', value: 'react-router' },
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
export function PrimitiveCombobox() {
|
|
76
|
+
return (
|
|
77
|
+
<combobox.Context name="framework">
|
|
78
|
+
<input mix={[inputStyle, combobox.input()]} placeholder="Search frameworks" />
|
|
79
|
+
<div mix={[popoverStyle, combobox.popover()]}>
|
|
80
|
+
<div mix={[listStyle, combobox.list()]}>
|
|
81
|
+
{frameworks.map((option) => (
|
|
82
|
+
<div key={option.value} mix={[optionStyle, combobox.option(option)]}>
|
|
83
|
+
{option.label}
|
|
84
|
+
</div>
|
|
85
|
+
))}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
<input mix={combobox.hiddenInput()} />
|
|
89
|
+
</combobox.Context>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## `remix/ui/combobox`
|
|
62
95
|
|
|
63
96
|
### `Combobox`
|
|
64
97
|
|
|
@@ -66,7 +99,7 @@ The convenience component.
|
|
|
66
99
|
|
|
67
100
|
- Renders the text input, popover surface, listbox root, and hidden form input.
|
|
68
101
|
- Dispatches a bubbled custom event that `onComboboxChange(...)` listens for when the committed value changes.
|
|
69
|
-
- Accepts `defaultValue`, `disabled`, `inputId`, `name`, and `
|
|
102
|
+
- Accepts `children`, `defaultValue`, `disabled`, `inputId`, `name`, `placeholder`, and root `div` props.
|
|
70
103
|
|
|
71
104
|
### `ComboboxOption`
|
|
72
105
|
|
|
@@ -74,21 +107,31 @@ The default option row for `Combobox`.
|
|
|
74
107
|
|
|
75
108
|
- Uses the shared listbox option visuals.
|
|
76
109
|
- Accepts `label`, `value`, optional `searchValue`, and optional `disabled`.
|
|
110
|
+
- Renders `children` when provided, otherwise renders `label`.
|
|
77
111
|
- `searchValue` can be a string or string array for aliases like airport codes, abbreviations, or alternate labels.
|
|
78
112
|
|
|
113
|
+
### Style and Prop Exports
|
|
114
|
+
|
|
115
|
+
- `inputStyle`: default combobox input style.
|
|
116
|
+
- `popoverStyle`: default combobox popover behavior style.
|
|
117
|
+
- `ComboboxProps` and `ComboboxOptionProps`: public TypeScript props for the composed APIs.
|
|
118
|
+
|
|
119
|
+
## `remix/ui/combobox/primitives`
|
|
120
|
+
|
|
79
121
|
### `onComboboxChange(...)`
|
|
80
122
|
|
|
81
|
-
The listener mixin for bubbled committed-value changes.
|
|
123
|
+
The listener mixin from `remix/ui/combobox/primitives` for bubbled committed-value changes.
|
|
82
124
|
|
|
83
125
|
The event object includes:
|
|
84
126
|
|
|
85
127
|
- `event.value`: the committed value or `null`
|
|
86
128
|
- `event.label`: the committed option label or `null`
|
|
87
129
|
- `event.optionId`: the generated option id or `null`
|
|
130
|
+
- `ComboboxChangeEvent`: the event class dispatched for committed value changes.
|
|
88
131
|
|
|
89
132
|
### `combobox.Context`
|
|
90
133
|
|
|
91
|
-
The lower-level coordinator for custom combobox composition.
|
|
134
|
+
The lower-level coordinator from `remix/ui/combobox/primitives` for custom combobox composition.
|
|
92
135
|
|
|
93
136
|
It wraps the shared `popover` and `listbox` contexts and owns the draft text, committed value, popup state, and selection timing.
|
|
94
137
|
|
|
@@ -106,7 +149,7 @@ Turns the host into the combobox popover surface.
|
|
|
106
149
|
|
|
107
150
|
- Uses the shared popover primitive.
|
|
108
151
|
- Keeps anchor clicks inside the session so the input stays interactive while open.
|
|
109
|
-
- Applies the combobox open/close reason contract used by `
|
|
152
|
+
- Applies the combobox open/close reason contract used by `popoverStyle`.
|
|
110
153
|
|
|
111
154
|
### `combobox.list()`
|
|
112
155
|
|
|
@@ -126,6 +169,12 @@ Mirrors the committed value into a hidden input for forms.
|
|
|
126
169
|
|
|
127
170
|
Apply it to an `<input type="hidden" />` inside the same `combobox.Context`.
|
|
128
171
|
|
|
172
|
+
### Primitive Types
|
|
173
|
+
|
|
174
|
+
- `ComboboxOpenStrategy`: initial active-option strategy when the popup opens.
|
|
175
|
+
- `ComboboxHandle`: imperative ref for reading or updating the combobox value and draft label.
|
|
176
|
+
- `ComboboxContextProps`, `ComboboxProps`, `ComboboxOptionOptions`, and `ComboboxOptionProps`: primitive prop and option types for custom composition.
|
|
177
|
+
|
|
129
178
|
## Behavior Notes
|
|
130
179
|
|
|
131
180
|
- Typing opens the popup in hint mode when there are matches.
|