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.
Files changed (143) hide show
  1. package/README.md +4 -2
  2. package/dist/assets/types/hmr.d.ts +2 -0
  3. package/dist/cli-entry.js +1 -1
  4. package/dist/data-table/cli.d.ts +2 -0
  5. package/dist/data-table/cli.d.ts.map +1 -0
  6. package/dist/{ui/scroll-lock.js → data-table/cli.js} +1 -1
  7. package/dist/node-hmr/runtime.d.ts +2 -0
  8. package/dist/node-hmr/runtime.d.ts.map +1 -0
  9. package/dist/node-hmr/runtime.js +2 -0
  10. package/dist/node-hmr/types.d.ts +2 -0
  11. package/dist/node-hmr.d.ts +2 -0
  12. package/dist/node-hmr.d.ts.map +1 -0
  13. package/dist/{ui/glyph.js → node-hmr.js} +1 -1
  14. package/dist/ui/accordion/primitives.d.ts +2 -0
  15. package/dist/ui/accordion/primitives.d.ts.map +1 -0
  16. package/dist/ui/accordion/primitives.js +2 -0
  17. package/dist/ui/button.d.ts +1 -0
  18. package/dist/ui/button.d.ts.map +1 -1
  19. package/dist/ui/button.js +1 -0
  20. package/dist/ui/checkbox.d.ts +3 -0
  21. package/dist/ui/checkbox.d.ts.map +1 -0
  22. package/dist/ui/checkbox.js +3 -0
  23. package/dist/ui/combobox/primitives.d.ts +2 -0
  24. package/dist/ui/combobox/primitives.d.ts.map +1 -0
  25. package/dist/ui/combobox/primitives.js +2 -0
  26. package/dist/ui/dev/refresh.d.ts +2 -0
  27. package/dist/ui/dev/refresh.d.ts.map +1 -0
  28. package/dist/ui/dev/refresh.js +2 -0
  29. package/dist/ui/input.d.ts +3 -0
  30. package/dist/ui/input.d.ts.map +1 -0
  31. package/dist/ui/input.js +3 -0
  32. package/dist/ui/menu/primitives.d.ts +2 -0
  33. package/dist/ui/menu/primitives.d.ts.map +1 -0
  34. package/dist/ui/menu/primitives.js +2 -0
  35. package/dist/ui/radio.d.ts +3 -0
  36. package/dist/ui/radio.d.ts.map +1 -0
  37. package/dist/ui/radio.js +3 -0
  38. package/dist/ui/select/primitives.d.ts +2 -0
  39. package/dist/ui/select/primitives.d.ts.map +1 -0
  40. package/dist/ui/select/primitives.js +2 -0
  41. package/dist/ui/tabs/primitives.d.ts +2 -0
  42. package/dist/ui/tabs/primitives.d.ts.map +1 -0
  43. package/dist/ui/tabs/primitives.js +2 -0
  44. package/dist/ui/tabs.d.ts +2 -0
  45. package/dist/ui/tabs.d.ts.map +1 -0
  46. package/{src/ui/theme.ts → dist/ui/tabs.js} +1 -1
  47. package/dist/ui/toggle/primitives.d.ts +2 -0
  48. package/dist/ui/toggle/primitives.d.ts.map +1 -0
  49. package/dist/ui/toggle/primitives.js +2 -0
  50. package/dist/ui/toggle.d.ts +3 -0
  51. package/dist/ui/toggle.d.ts.map +1 -0
  52. package/dist/ui/toggle.js +3 -0
  53. package/dist/ui-hmr/assets.d.ts +2 -0
  54. package/dist/ui-hmr/assets.d.ts.map +1 -0
  55. package/dist/ui-hmr/assets.js +2 -0
  56. package/dist/ui-hmr/node.d.ts +3 -0
  57. package/dist/ui-hmr/node.d.ts.map +1 -0
  58. package/dist/ui-hmr/node.js +3 -0
  59. package/dist/ui-hmr/runtime/browser.d.ts +2 -0
  60. package/dist/ui-hmr/runtime/browser.d.ts.map +1 -0
  61. package/dist/ui-hmr/runtime/browser.js +2 -0
  62. package/dist/ui-hmr/runtime/server.d.ts +2 -0
  63. package/dist/ui-hmr/runtime/server.d.ts.map +1 -0
  64. package/dist/ui-hmr/runtime/server.js +2 -0
  65. package/dist/ui-hmr.d.ts +2 -0
  66. package/dist/ui-hmr.d.ts.map +1 -0
  67. package/{src/ui/glyph.ts → dist/ui-hmr.js} +1 -1
  68. package/package.json +122 -142
  69. package/src/assets/README.md +322 -56
  70. package/src/assets/types/hmr.d.ts +2 -0
  71. package/src/cli/README.md +105 -1
  72. package/src/cookie/README.md +4 -4
  73. package/src/data-table/README.md +202 -68
  74. package/src/data-table/cli.ts +2 -0
  75. package/src/data-table-mysql/README.md +46 -17
  76. package/src/data-table-postgres/README.md +39 -13
  77. package/src/data-table-sqlite/README.md +38 -20
  78. package/src/fetch-proxy/README.md +25 -0
  79. package/src/form-data-parser/README.md +4 -4
  80. package/src/mime/README.md +8 -1
  81. package/src/node-fetch-server/README.md +39 -13
  82. package/src/node-hmr/README.md +307 -0
  83. package/src/node-hmr/runtime.ts +2 -0
  84. package/src/node-hmr/types.d.ts +2 -0
  85. package/{dist/ui/theme.js → src/node-hmr.ts} +1 -1
  86. package/src/route-pattern/README.md +141 -13
  87. package/src/session/README.md +1 -1
  88. package/src/session-middleware/README.md +9 -7
  89. package/src/test/README.md +161 -115
  90. package/src/ui/README.md +116 -157
  91. package/src/ui/accordion/README.md +50 -14
  92. package/src/ui/accordion/primitives/README.md +202 -0
  93. package/src/ui/accordion/primitives.ts +2 -0
  94. package/src/ui/anchor/README.md +37 -2
  95. package/src/ui/breadcrumbs/README.md +4 -4
  96. package/src/ui/button/README.md +26 -26
  97. package/src/ui/button.ts +1 -0
  98. package/src/ui/checkbox/README.md +59 -0
  99. package/src/ui/checkbox.ts +3 -0
  100. package/src/ui/combobox/README.md +58 -9
  101. package/src/ui/combobox/primitives/README.md +194 -0
  102. package/src/ui/combobox/primitives.ts +2 -0
  103. package/src/ui/dev/refresh.ts +2 -0
  104. package/src/ui/input/README.md +52 -0
  105. package/src/ui/input.ts +3 -0
  106. package/src/ui/listbox/README.md +9 -41
  107. package/src/ui/menu/README.md +55 -14
  108. package/src/ui/menu/primitives/README.md +161 -0
  109. package/src/ui/menu/primitives.ts +2 -0
  110. package/src/ui/popover/README.md +20 -39
  111. package/src/ui/radio/README.md +53 -0
  112. package/src/ui/radio.ts +3 -0
  113. package/src/ui/select/README.md +29 -19
  114. package/src/ui/select/primitives/README.md +117 -0
  115. package/src/ui/select/primitives.ts +2 -0
  116. package/src/ui/tabs/README.md +141 -0
  117. package/src/ui/tabs/primitives/README.md +141 -0
  118. package/src/ui/tabs/primitives.ts +2 -0
  119. package/src/ui/tabs.ts +2 -0
  120. package/src/ui/test/README.md +151 -60
  121. package/src/ui/toggle/README.md +56 -0
  122. package/src/ui/toggle/primitives/README.md +56 -0
  123. package/src/ui/toggle/primitives.ts +2 -0
  124. package/src/ui/toggle.ts +3 -0
  125. package/src/ui-hmr/README.md +119 -0
  126. package/{dist/ui/separator.js → src/ui-hmr/assets.ts} +1 -1
  127. package/src/ui-hmr/node.ts +3 -0
  128. package/src/ui-hmr/runtime/browser.ts +2 -0
  129. package/src/ui-hmr/runtime/server.ts +2 -0
  130. package/src/ui-hmr.ts +2 -0
  131. package/dist/ui/glyph.d.ts +0 -2
  132. package/dist/ui/glyph.d.ts.map +0 -1
  133. package/dist/ui/scroll-lock.d.ts +0 -2
  134. package/dist/ui/scroll-lock.d.ts.map +0 -1
  135. package/dist/ui/separator.d.ts +0 -2
  136. package/dist/ui/separator.d.ts.map +0 -1
  137. package/dist/ui/theme.d.ts +0 -2
  138. package/dist/ui/theme.d.ts.map +0 -1
  139. package/src/ui/glyph/README.md +0 -72
  140. package/src/ui/scroll-lock/README.md +0 -33
  141. package/src/ui/scroll-lock.ts +0 -2
  142. package/src/ui/separator.ts +0 -2
  143. 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
- Accordion,
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 wrapper rendered around each trigger. The default level is `3`.
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
- ## `accordion.*`
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 class with `value`, `itemValue`, and `accordionType`.
153
- - `AccordionProps`, `AccordionSingleProps`, `AccordionMultipleProps`, `AccordionItemProps`, `AccordionTriggerProps`, and `AccordionContentProps`: public TypeScript props.
154
- - `rootStyle`, `itemStyle`, `triggerStyle`, `indicatorStyle`, `panelStyle`, and `bodyStyle`: flat style mixins used by the component wrappers.
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`.
@@ -0,0 +1,2 @@
1
+ // IMPORTANT: This file is auto-generated, please do not edit manually.
2
+ export * from '@remix-run/ui/accordion/primitives'
@@ -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
- ## `anchor.*`
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 glyph.
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 the `chevronRight` glyph. Separators render between items and are hidden from assistive technology.
55
+ - The default separator is a chevron icon. Separators render between items and are hidden from assistive technology.
@@ -1,44 +1,44 @@
1
1
  # button
2
2
 
3
- `button` is the shared button styling contract for `remix/ui`. Use `Button` for ordinary action buttons, or compose flat `button.*Style` exports directly when a higher-level control needs button structure without a wrapper.
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 { Button } from 'remix/ui/button'
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
- <Button startIcon={<Glyph name="add" />} tone="primary">
16
- Create project
17
- </Button>
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
- ## `button.*`
21
+ Compose app-owned styles around the primitive when a control needs local layout or state styling:
29
22
 
30
- - `Button`: thin button wrapper for the common `base + tone + label/icon slots` case. Pass `tone`, `startIcon`, and `endIcon` when the default authored structure is enough.
31
- - `button.baseStyle`: base host styling plus the default `type="button"` behavior for button elements.
32
- - `button.primaryStyle`, `button.secondaryStyle`, `button.ghostStyle`, and `button.dangerStyle`: visual button treatments.
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
- ## Behavior Notes
27
+ function ToolbarAction() {
28
+ return () => <button mix={[toolbarButtonStyle, button({ tone: 'ghost' })]}>Archive</button>
29
+ }
30
+ ```
31
+
32
+ ## `remix/ui/button`
37
33
 
38
- - `button.baseStyle` only adds `type="button"` when the host element is a `<button>` and no explicit `type` was provided.
39
- - `Button` renders `children` inside `button.labelStyle` and renders `startIcon` and `endIcon` inside `button.iconStyle`.
40
- - Use an explicit accessible name when you render an icon-only button.
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
- ## When To Use Something Else
39
+ ## Behavior Notes
43
40
 
44
- Use `button.*Style` exports directly when a control needs button structure plus extra behavior or layout, like `select`, `menu`, or `tabs`. Those controls own their own interaction mixins and should not hide that behavior behind `Button`.
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
@@ -1,2 +1,3 @@
1
1
  // IMPORTANT: This file is auto-generated, please do not edit manually.
2
2
  export * from '@remix-run/ui/button'
3
+ export { default } from '@remix-run/ui/button'
@@ -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"`.
@@ -0,0 +1,3 @@
1
+ // IMPORTANT: This file is auto-generated, please do not edit manually.
2
+ export * from '@remix-run/ui/checkbox'
3
+ export { default } from '@remix-run/ui/checkbox'
@@ -1,14 +1,15 @@
1
- # Combobox
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, onComboboxChange } from 'remix/ui/combobox'
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
- ## Public API
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 `placeholder`.
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 `combobox.popoverStyle`.
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.