torch-glare 2.5.3 → 2.5.5

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 (56) hide show
  1. package/apps/lib/components/ActionButton.tsx +39 -6
  2. package/apps/lib/components/Badge.tsx +5 -2
  3. package/apps/lib/components/BadgeField.tsx +71 -67
  4. package/apps/lib/components/Button.tsx +4 -4
  5. package/apps/lib/components/Calendar.tsx +7 -17
  6. package/apps/lib/components/Card.tsx +2 -1
  7. package/apps/lib/components/ColorPicker.tsx +1 -1
  8. package/apps/lib/components/ContextMenu.tsx +65 -22
  9. package/apps/lib/components/DataViews/context.ts +2 -2
  10. package/apps/lib/components/DataViews/data-views.tsx +3 -3
  11. package/apps/lib/components/DataViews/filters/filters.tsx +0 -2
  12. package/apps/lib/components/DataViews/views/table-view.tsx +190 -153
  13. package/apps/lib/components/Drawer.tsx +18 -1
  14. package/apps/lib/components/DropdownMenu.tsx +65 -22
  15. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +19 -5
  16. package/apps/lib/components/FormBuilder/types.ts +16 -0
  17. package/apps/lib/components/FormRenderer/form-renderer.tsx +16 -5
  18. package/apps/lib/components/FormRenderer/stepper.tsx +22 -16
  19. package/apps/lib/components/HeaderBar.tsx +51 -53
  20. package/apps/lib/components/Input.tsx +19 -4
  21. package/apps/lib/components/InputField.tsx +46 -47
  22. package/apps/lib/components/Popover.tsx +108 -56
  23. package/apps/lib/components/SearchableSelect.tsx +22 -17
  24. package/apps/lib/components/SearchableTree.tsx +33 -17
  25. package/apps/lib/components/SearchableTreeDialog.tsx +21 -12
  26. package/apps/lib/components/SectionBlock.tsx +3 -1
  27. package/apps/lib/components/Select.tsx +86 -54
  28. package/apps/lib/components/SimpleSelect.tsx +2 -2
  29. package/apps/lib/components/SlideDatePicker.tsx +15 -4
  30. package/apps/lib/components/Stepper.tsx +329 -180
  31. package/apps/lib/components/Switch.tsx +2 -2
  32. package/apps/lib/components/TabSwitch.tsx +18 -12
  33. package/apps/lib/components/Table.tsx +1 -1
  34. package/apps/lib/components/Textarea.tsx +29 -4
  35. package/apps/lib/components/TreeDropDown.tsx +18 -6
  36. package/apps/lib/layouts/FieldSection.tsx +28 -2
  37. package/apps/lib/registry.json +7 -17
  38. package/apps/lib/tsconfig.tsbuildinfo +1 -1
  39. package/docs/components/action-button.md +3 -1
  40. package/docs/components/badge-field.md +4 -4
  41. package/docs/components/context-menu.md +3 -1
  42. package/docs/components/data-views/examples/filters.md +0 -1
  43. package/docs/components/data-views/index.md +1 -17
  44. package/docs/components/dropdown-menu.md +3 -0
  45. package/docs/components/form-builder.md +27 -1
  46. package/docs/components/header-bar.md +3 -2
  47. package/docs/components/input-field.md +3 -3
  48. package/docs/components/select.md +1 -1
  49. package/docs/components/stepper.md +119 -24
  50. package/docs/migration/changelog.md +13 -0
  51. package/docs/reference/tailwind-plugins.md +42 -0
  52. package/docs/tutorials/getting-started.md +32 -11
  53. package/package.json +1 -1
  54. package/apps/lib/components/DataViews/filters/summary.tsx +0 -65
  55. package/apps/lib/components/FormStepper.tsx +0 -272
  56. package/docs/components/form-stepper.md +0 -250
@@ -378,8 +378,10 @@ Inherits all variants from the Button component:
378
378
  ### Base Styles
379
379
 
380
380
  - **Square dimensions**: Equal width and height for perfect icon centering
381
- - **Rounded corners**: 4px border radius
381
+ - **Rounded corners**: `radius/sm` (4px) at XS and S, `radius/lg` (8px) at M
382
382
  - **Icon-only design**: Optimized padding for icon display
383
+ - **Action colours**: `action-secondary` at rest, `action-hover` on hover and
384
+ `action-disabled` when disabled — applied unless you pass an explicit `variant`
383
385
  - **Inherits Button styles**: All Button component styles and behaviors
384
386
 
385
387
  ### Custom Styling
@@ -335,7 +335,7 @@ export function BadgeFieldWithIcon() {
335
335
 
336
336
  ### With Error State
337
337
 
338
- Display validation errors with tooltip.
338
+ Display validation errors. `errorMessage` turns on the field's negative border.
339
339
 
340
340
  ```tsx
341
341
  export function BadgeFieldWithError() {
@@ -467,9 +467,9 @@ Extends all Input element props (except size and variant).
467
467
  | size | `'XS' \| 'S' \| 'M'` | `'M'` | Field size |
468
468
  | variant | `'PresentationStyle'` | `'PresentationStyle'` | Visual variant |
469
469
  | icon | `ReactNode` | - | Leading icon |
470
- | errorMessage | `string` | - | Error message (shows tooltip) |
470
+ | errorMessage | `string` | - | Marks the field invalid — any non-undefined value turns on the negative border |
471
471
  | onTable | `boolean` | `false` | Table-specific styling |
472
- | toolTipSide | `ToolTipSide` | - | Tooltip position |
472
+ | toolTipSide | `ToolTipSide` | - | **Deprecated, ignored.** The error tooltip was removed; an invalid field is shown by its border alone |
473
473
  | label | `string` | - | Field label |
474
474
  | required | `boolean` | `false` | Required indicator |
475
475
  | theme | `Themes` | - | Theme override |
@@ -674,7 +674,7 @@ describe('BadgeField', () => {
674
674
  - **ARIA Labels**: Proper labels for screen readers
675
675
  - **Focus Management**: Clear focus indicators
676
676
  - **Screen Reader**: Announces selected/removed tags
677
- - **Error Messages**: Accessible error tooltips
677
+ - **Error Messages**: Invalid fields are marked with the negative border token
678
678
  - **Tab Order**: Logical tab navigation
679
679
 
680
680
  ## Performance
@@ -230,6 +230,8 @@ function RtlMenu() {
230
230
 
231
231
  Tall menus scroll instead of overflowing off-screen. The surface caps at `maxHeight` (default `320`px) and never exceeds the space available after collision handling. Pass `maxHeight` to change the cap.
232
232
 
233
+ The panel itself does not scroll — it clips, and an inner viewport inside it does the scrolling. That keeps the panel's 4px frosted gutter fixed instead of scrolling away with the rows. Submenus behave identically and take their own `maxHeight` (same `320`px default).
234
+
233
235
  ```typescript
234
236
  import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuLabel } from "@/components/ContextMenu";
235
237
 
@@ -425,7 +427,7 @@ export const ContextMenuRadioItem: React.ForwardRefExoticComponent<ContextMenuRa
425
427
  - **Opens at the pointer**: the menu opens on right-click (`contextmenu`) at the exact cursor position, not anchored to a fixed trigger button.
426
428
  - **Second right-click closes it**: the Root is made controlled and tracks `open` in context. The Trigger listens in the capture phase, and when the menu is already open it `preventDefault()` / `stopPropagation()` and closes — so a second right-click dismisses instead of re-anchoring (which Radix handles unreliably).
427
429
  - **Auto-grouping**: by default (`autoGroup` on `ContextMenuContent`, default `true`) consecutive loose items (`ContextMenuItem`, `ContextMenuCheckboxItem`, `ContextMenuRadioItem`, and `ContextMenuSub`) are automatically wrapped in a `Boxed` `ContextMenuGroup`, so they render inside a boxed container like DropdownMenu even when you do not write a group. Labels and explicit groups act as boundaries and pass through unchanged. Set `autoGroup={false}` to render children verbatim.
428
- - **Max height & scrolling**: the surface caps its height at `min(maxHeight, available-height)` (where `maxHeight` defaults to `320`px and `available-height` is the space Radix has after collision handling). A taller menu scrolls vertically instead of overflowing off-screen — items and groups keep their full height rather than squishing. Pass `maxHeight={N}` to change the cap.
430
+ - **Max height & scrolling**: the surface caps its height at `min(maxHeight, available-height)` (where `maxHeight` defaults to `320`px and `available-height` is the space Radix has after collision handling). A taller menu scrolls vertically instead of overflowing off-screen — items and groups keep their full height rather than squishing. The panel clips and an inner viewport scrolls, so the panel's frosted gutter stays put. Pass `maxHeight={N}` to change the cap; `ContextMenuSubContent` accepts it too.
429
431
  - **Checkbox / radio keep the menu open**: `ContextMenuCheckboxItem` and `ContextMenuRadioItem` call `event.preventDefault()` inside `onSelect`, stopping Radix's default auto-close so users can toggle multiple options in one pass.
430
432
  - **Open-only animation**: only the open (enter) state animates (`fade-in`). There is intentionally no exit animation — holding the old DOM node during close breaks close/reposition on a second right-click, so it is omitted to keep repositioning reliable.
431
433
  - **Submenus and RTL**: nested `ContextMenuSub` / `ContextMenuSubTrigger` / `ContextMenuSubContent` are supported, and `dir="rtl"` on the Root mirrors the layout (including the submenu chevron).
@@ -231,7 +231,6 @@ export default function FiltersExample() {
231
231
 
232
232
  {/* The active query, as removable chips — including the search term. */}
233
233
  <div className="border-border-presentation-global-primary border-b px-4 py-2 empty:hidden">
234
- <DataViews.Filters.Summary />
235
234
  </div>
236
235
 
237
236
  <DataViews.Table />
@@ -406,21 +406,13 @@ control at its neutral position emits no key at all, is under
406
406
  </DataViews.Filters>
407
407
  ```
408
408
 
409
- `Filters.Summary` paints whatever is active as removable chips. It reads the same context, so it
410
- works anywhere — most usefully **outside** the rail, where it tells the user what is filtering the
411
- rows they are looking at:
412
-
413
- ```tsx
414
- <DataViews.Filters.Summary className="px-4 py-2" />
415
- ```
416
-
417
409
  ### Questions this design gets asked
418
410
 
419
411
  | Question | Answer |
420
412
  | --- | --- |
421
413
  | Is there an in-view filter panel *and* a Filters tab — which is canonical? | **One surface.** `DataViews.Filters` is a single component. Render it inside a `Panel.Tab` or as a standalone bar; author against the component, not against a tab. |
422
414
  | What orders the sections? | **The order you write the children.** There is no `order` prop for filters. |
423
- | Does the applied-count badge count constrained *fields* or selected *values*? | **There is no count badge.** `PanelToggle` carries none. `Filters.Summary` is the equivalent, and it renders **one chip per constrained field** — Status with three values selected is one chip. |
415
+ | Is there an applied-count badge or a chip summary of active filters? | **No.** `PanelToggle` carries no count, and there is no summary component — the controls themselves show what is set. Render your own above the rows if you want one. |
424
416
  | Do `BadgeField` chip colours and `FieldConfig.variants` share a token set? | **They never meet.** Chips come from the field's own `options`; `variants` (`BadgeVariant`) styles `enum-badge` **columns**. Filters and columns are independent. |
425
417
 
426
418
  And the behaviours worth stating because they are easy to assume wrongly:
@@ -771,14 +763,6 @@ A filter no FormBuilder field covers.
771
763
  | `render` | `(args: { value: FilterValue \| undefined; setValue: (v: FilterValue \| undefined) => void }) => ReactNode` | — | **yes** | |
772
764
  | `label` | `ReactNode` | derived from `path` | no | |
773
765
 
774
- ### DataViews.Filters.Summary
775
-
776
- | Prop | Type | Default | Required | Notes |
777
- | --- | --- | --- | --- | --- |
778
- | `className` | `string` | — | no | |
779
-
780
- Active filters — and the search term — as removable chips. Renders `null` when there are none.
781
-
782
766
  ### Cell
783
767
 
784
768
  Paint one field of one row exactly as the views paint it.
@@ -294,6 +294,8 @@ function Example() {
294
294
 
295
295
  Tall menus scroll instead of overflowing off-screen. The surface caps at `maxHeight` (default `320`px) and never exceeds the space available after collision handling. Pass `maxHeight` to change the cap.
296
296
 
297
+ The panel itself does not scroll — it clips, and an inner viewport inside it does the scrolling. That keeps the panel's 4px frosted gutter fixed instead of scrolling away with the rows. Submenus behave identically and take their own `maxHeight`.
298
+
297
299
  ```typescript
298
300
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel } from "@/components/DropdownMenu";
299
301
  import { Button } from "@/components/Button";
@@ -396,6 +398,7 @@ function LongMenu() {
396
398
  |------|------|---------|-------------|
397
399
  | `variant` | `'PresentationStyle'` | `'PresentationStyle'` | Visual style variant |
398
400
  | `autoGroup` | `boolean` | `true` | Auto-wrap loose items in boxed groups |
401
+ | `maxHeight` | `number` | `320` | Max height (px) before the submenu scrolls. Same `min(maxHeight, available-height)` cap as `DropdownMenuContent` |
399
402
  | `className` | `string` | - | Additional CSS classes |
400
403
 
401
404
  ### DropdownMenuLabel
@@ -96,7 +96,33 @@ panel beside the form is `FormRenderer`'s `summary`.
96
96
  ## Field components
97
97
 
98
98
  Each is a JSX child taking at least `name`, plus `label`, `placeholder`,
99
- `description`, `required`, `disabled`, `hidden`, `fullWidth`.
99
+ `description`, `required`, `disabled`, `hidden`, `fullWidth`, `hints`.
100
+
101
+ ### Hints
102
+
103
+ `hints` stacks alerts under a field — helper text, a caveat, a confirmation. Each entry mirrors
104
+ `FieldHint`: `label`, an optional `state` of `info` (default) / `warning` / `error` / `success`, and
105
+ an optional `icon`.
106
+
107
+ ```tsx
108
+ <FormBuilder.Text
109
+ name="sku"
110
+ label="SKU"
111
+ required
112
+ hints={[
113
+ { state: "info", label: "Must be unique across the catalogue." },
114
+ { state: "warning", label: "Changing this breaks existing links." },
115
+ ]}
116
+ />
117
+ ```
118
+
119
+ The validation error is not one of these — it is rendered automatically and always comes **first**,
120
+ because it is the actionable message; your hints follow in the order given. A field with no `hints`
121
+ renders exactly as before.
122
+
123
+ Hints are ignored inside a `FormBuilder.Table` cell (and any other `bare` context): there errors
124
+ surface as a tooltip on the control so a row stays one line tall, and stacking alerts would defeat
125
+ that.
100
126
 
101
127
  | Component | Input | Value |
102
128
  | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
@@ -146,13 +146,14 @@ All standard `HTMLAttributes<HTMLDivElement>` (for example `id`, `aria-*`, `data
146
146
  |---------|-----------|-----------|------------------------|
147
147
  | `new` | `bg-blue-sparkle-alpha-50` | `text-blue-sparkle-200` | pill (`label`) → title |
148
148
  | `edit` | `bg-orange-alpha-50` | `text-orange-200` | pill (`label`) → title |
149
- | `detail` | `bg-white-alpha-30` | `text-white-00` | title → pill (`label`) — positions swapped |
149
+ | `detail` | `bg-white-alpha-15` | `text-white-00` | title → pill (`label`) — positions swapped |
150
150
 
151
151
  ## Styling
152
152
 
153
153
  - **Fixed dark container**: `rounded-[14px]`, `border-black-600`, `bg-black-1000`, `p-1.5`, with a double soft shadow. The surface is always dark regardless of theme.
154
154
  - **Layout**: the root is `inline-flex`, so the chip hugs its content rather than stretching to fill its parent.
155
- - **Typography**: 28px, weight 510, uppercase, SF Pro with the `cv05` stylistic set. Both `label` and `title` render uppercase.
155
+ - **Typography**: `typography-display-medium-medium` (28px, weight 510) with the `cv05` stylistic set. Both `label` and `title` render uppercase.
156
+ - **Ordering**: `detail` swaps the two children in the DOM rather than reversing the row, so the pair stays correct under `dir="rtl"` and reads in order to assistive tech.
156
157
  - **Emphasis pill**: the colored badge background and text color are driven entirely by `variant` (see the Variants table). For `detail`, the pill also moves to the right side.
157
158
 
158
159
  ## TypeScript Types
@@ -15,7 +15,7 @@ dependencies:
15
15
 
16
16
  # InputField
17
17
 
18
- > An enhanced input component that combines Input with integrated popover dropdowns, error tooltips, icons, and trailing actions. Perfect for complex form fields requiring additional UI elements.
18
+ > An enhanced input component that combines Input with integrated popover dropdowns, error styling, icons, and trailing actions. Perfect for complex form fields requiring additional UI elements.
19
19
 
20
20
  ## Installation
21
21
 
@@ -206,9 +206,9 @@ function PasswordField() {
206
206
  | `icon` | `ReactNode` | - | Icon to display on the left side |
207
207
  | `childrenSide` | `ReactNode` | - | Content to display on the right side |
208
208
  | `popoverChildren` | `ReactNode` | - | Content for the dropdown popover |
209
- | `errorMessage` | `string` | - | Error message to display in tooltip |
209
+ | `errorMessage` | `string` | - | Marks the field invalid — any non-undefined value turns on the negative border |
210
210
  | `onTable` | `boolean` | `false` | Optimized styling for table context |
211
- | `toolTipSide` | `'top' \| 'right' \| 'bottom' \| 'left'` | - | Tooltip position |
211
+ | `toolTipSide` | `'top' \| 'right' \| 'bottom' \| 'left'` | - | **Deprecated, ignored.** The error tooltip was removed; an invalid field is shown by its border alone |
212
212
  | `theme` | `'dark' \| 'light' \| 'default'` | - | Theme variant |
213
213
  | `className` | `string` | - | Additional CSS classes |
214
214
  | `disabled` | `boolean` | `false` | Disables the input |
@@ -241,7 +241,7 @@ function Uncontrolled() {
241
241
  |------|------|---------|-------------|
242
242
  | `size` | `'S' \| 'M' \| 'L' \| 'XL'` | `'M'` | Size of the trigger |
243
243
  | `variant` | `'PresentationStyle' \| 'SystemStyle'` | `'PresentationStyle'` | Visual variant |
244
- | `errors` | `string` | - | Error message (shows tooltip) |
244
+ | `errors` | `string` | - | Marks the trigger invalid — any non-undefined value turns on the negative border |
245
245
  | `theme` | `Themes` | - | Theme override |
246
246
  | `icon` | `string` | - | Custom icon class |
247
247
  | `className` | `string` | - | Additional CSS classes |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Stepper
3
- description: Generic horizontal/vertical stepper with pending, active, completed, and error states. Composed of Stepper, Step, StepIndicator, StepConnector, StepLabel, and StepDescription.
3
+ description: The pill-shaped multi-step indicator — three semantic types (default, success, negative), horizontal or vertical, three sizes. Composed of Stepper, Step, StepIndicator, StepConnector and StepLabel.
4
4
  component: true
5
5
  group: Forms
6
6
  keywords: [stepper, steps, wizard, progress, multi-step, vertical, horizontal]
@@ -8,9 +8,11 @@ keywords: [stepper, steps, wizard, progress, multi-step, vertical, horizontal]
8
8
 
9
9
  # Stepper
10
10
 
11
- A generic step-progress component for wizards, onboarding flows, and multi-section forms. Each step has four states — `pending`, `active`, `completed`, `error` — derived automatically from `activeStep` or set explicitly per `Step`.
11
+ The step-progress component for wizards, onboarding flows, and multi-section forms, drawn as the Figma `FormStepper-1.0` pill. Each step has a semantic `type` — `default`, `success`, `negative` — and a selected state derived from `activeStep` or set explicitly per `Step`.
12
12
 
13
- The component is composed of `Stepper`, `Step`, `StepIndicator`, `StepConnector`, `StepLabel`, and `StepDescription`. Compare to [`FormStepper`](./form-stepper.md), which is a pill-shaped variant with no connector line.
13
+ Not to be confused with `FormRenderer.Stepper`, which is the wizard *behaviour* (step state, validation, Back/Next) and renders this component as its rail.
14
+
15
+ The component is composed of `Stepper`, `Step`, `StepIndicator`, `StepConnector` and `StepLabel`. It is the single stepper in the library — the former `FormStepper` merged into it, so its types, states and badge live here alongside the orientation, sizes and connector.
14
16
 
15
17
  ## Installation
16
18
 
@@ -33,7 +35,6 @@ import {
33
35
  StepIndicator,
34
36
  StepConnector,
35
37
  StepLabel,
36
- StepDescription,
37
38
  } from '@/components/Stepper'
38
39
  ```
39
40
 
@@ -73,7 +74,7 @@ export function BasicStepper() {
73
74
  }
74
75
  ```
75
76
 
76
- State derivation: `index < activeStep` → `completed`, `index === activeStep` → `active`, otherwise `pending`. Pass `isCompleted`, `isActive`, or `isError` on a `Step` to override.
77
+ State derivation: `index === activeStep` → selected. Pass `selected` on a `Step` to override it, and `type` to mark a step as `success` or `negative`.
77
78
 
78
79
  ## Examples
79
80
 
@@ -85,7 +86,6 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
85
86
  <StepIndicator />
86
87
  <div>
87
88
  <StepLabel>Create account</StepLabel>
88
- <StepDescription>Email and password.</StepDescription>
89
89
  </div>
90
90
  </Step>
91
91
  <StepConnector />
@@ -93,7 +93,6 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
93
93
  <StepIndicator />
94
94
  <div>
95
95
  <StepLabel>Verify email</StepLabel>
96
- <StepDescription>Check your inbox for a code.</StepDescription>
97
96
  </div>
98
97
  </Step>
99
98
  <StepConnector />
@@ -101,7 +100,6 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
101
100
  <StepIndicator />
102
101
  <div>
103
102
  <StepLabel>Done</StepLabel>
104
- <StepDescription>You're all set.</StepDescription>
105
103
  </div>
106
104
  </Step>
107
105
  </Stepper>
@@ -116,7 +114,7 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
116
114
  <StepLabel>Account</StepLabel>
117
115
  </Step>
118
116
  <StepConnector />
119
- <Step index={1} isError>
117
+ <Step index={1} type="negative">
120
118
  <StepIndicator />
121
119
  <StepLabel>Payment</StepLabel>
122
120
  </Step>
@@ -133,7 +131,7 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
133
131
  ### Custom indicators
134
132
 
135
133
  ```tsx
136
- <Step index={0} isCompleted>
134
+ <Step index={0} type="success">
137
135
  <StepIndicator
138
136
  completedIcon={<i className="ri-shield-check-line" />}
139
137
  errorIcon={<i className="ri-shield-cross-line" />}
@@ -145,9 +143,108 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
145
143
  ### Sizes
146
144
 
147
145
  ```tsx
148
- <Stepper size="S" activeStep={1}> {/* 22px indicators */} </Stepper>
149
- <Stepper size="M" activeStep={1}> {/* 28px — default */} </Stepper>
150
- <Stepper size="L" activeStep={1}> {/* 34px */} </Stepper>
146
+ <Stepper size="S" activeStep={1}> {/* 24px pill, 20px indicator */} </Stepper>
147
+ <Stepper size="M" activeStep={1}> {/* 28px pill, 24px indicator — default, the size Figma draws */} </Stepper>
148
+ <Stepper size="L" activeStep={1}> {/* 34px pill, 30px indicator */} </Stepper>
149
+ ```
150
+
151
+ ### Step Types
152
+
153
+ Three semantic types. `success` and `negative` add a small status badge on the indicator (check / info icon) and use filled colors when selected. `default` uses a gray ring at rest, blue ring on hover, and a solid blue fill when selected.
154
+
155
+ ```tsx
156
+ export function StepTypes() {
157
+ return (
158
+ <Stepper>
159
+ <Step index={0} type="default" selected={false}>
160
+ <StepIndicator />
161
+ <StepLabel>Default</StepLabel>
162
+ </Step>
163
+ <Step index={1} type="success" selected={false}>
164
+ <StepIndicator />
165
+ <StepLabel>Success</StepLabel>
166
+ </Step>
167
+ <Step index={2} type="negative" selected={false}>
168
+ <StepIndicator />
169
+ <StepLabel>Negative</StepLabel>
170
+ </Step>
171
+ </Stepper>
172
+ )
173
+ }
174
+ ```
175
+
176
+ ### Selected state
177
+
178
+ ```tsx
179
+ export function SelectedSteps() {
180
+ return (
181
+ <Stepper>
182
+ <Step index={0} type="default" selected>
183
+ <StepIndicator />
184
+ <StepLabel>Default</StepLabel>
185
+ </Step>
186
+ <Step index={1} type="success" selected>
187
+ <StepIndicator />
188
+ <StepLabel>Success</StepLabel>
189
+ </Step>
190
+ <Step index={2} type="negative" selected>
191
+ <StepIndicator />
192
+ <StepLabel>Negative</StepLabel>
193
+ </Step>
194
+ </Stepper>
195
+ )
196
+ }
197
+ ```
198
+
199
+ ### RTL direction
200
+
201
+ The pill, label spacing, and indicator badge all flip under `dir="rtl"`.
202
+
203
+ ```tsx
204
+ export function RTLStepper() {
205
+ return (
206
+ <div dir="rtl">
207
+ <Stepper>
208
+ <Step index={0} type="default" selected>
209
+ <StepIndicator />
210
+ <StepLabel>افتراضي</StepLabel>
211
+ </Step>
212
+ <Step index={1} type="success">
213
+ <StepIndicator />
214
+ <StepLabel>نجاح</StepLabel>
215
+ </Step>
216
+ <Step index={2} type="negative">
217
+ <StepIndicator />
218
+ <StepLabel>خطأ</StepLabel>
219
+ </Step>
220
+ </Stepper>
221
+ </div>
222
+ )
223
+ }
224
+ ```
225
+
226
+ ### Custom badge icon
227
+
228
+ `StepIndicator.badgeIcon` overrides the default check / info icon for `success` / `negative` types.
229
+
230
+ ```tsx
231
+ <Step index={0} type="success" selected>
232
+ <StepIndicator badgeIcon={<i className="ri-shield-check-line" />} />
233
+ <StepLabel>Verified</StepLabel>
234
+ </Step>
235
+ ```
236
+
237
+ ### Custom indicator content
238
+
239
+ Children of `StepIndicator` replace the auto-rendered step number.
240
+
241
+ ```tsx
242
+ <Step index={0} type="default" selected>
243
+ <StepIndicator>
244
+ <i className="ri-user-line" />
245
+ </StepIndicator>
246
+ <StepLabel>Account</StepLabel>
247
+ </Step>
151
248
  ```
152
249
 
153
250
  ## API Reference
@@ -166,15 +263,14 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
166
263
  | Prop | Type | Default | Description |
167
264
  | ------------- | --------- | ------- | ------------------------------------------------------------ |
168
265
  | `index` | `number` | `0` | Zero-based step index. Compared with `Stepper.activeStep`. |
169
- | `isActive` | `boolean` | — | Force the active state. |
170
- | `isCompleted` | `boolean` | — | Force the completed state. |
171
- | `isError` | `boolean` | — | Force the error state. Overrides active and completed. |
266
+ | `type` | `'default' \| 'success' \| 'negative'` | `'default'` | Semantic state. `success`/`negative` fill the indicator and add a corner badge. |
267
+ | `selected` | `boolean` | `index === activeStep` | Force the selected state. |
172
268
 
173
269
  ### StepIndicator
174
270
 
175
271
  | Prop | Type | Default | Description |
176
272
  | --------------- | ----------- | ------- | ------------------------------------------------- |
177
- | `icon` | `ReactNode` | — | Replaces the step number for the pending state. |
273
+ | `icon` | `ReactNode` | — | Replaces the step number. |
178
274
  | `completedIcon` | `ReactNode` | — | Replaces the default check icon when completed. |
179
275
  | `errorIcon` | `ReactNode` | — | Replaces the default close icon on error. |
180
276
 
@@ -182,7 +278,7 @@ State derivation: `index < activeStep` → `completed`, `index === activeStep`
182
278
 
183
279
  The line between steps. No props beyond standard HTML attributes — orientation comes from the parent `Stepper`.
184
280
 
185
- ### StepLabel / StepDescription
281
+ ### StepLabel
186
282
 
187
283
  Forward `HTMLAttributes<HTMLDivElement>`. Their colors follow the parent `Step` state automatically.
188
284
 
@@ -192,7 +288,7 @@ Forward `HTMLAttributes<HTMLDivElement>`. Their colors follow the parent `Step`
192
288
  - Active: blue informational background + focus ring.
193
289
  - Completed: green success background and ring; check icon.
194
290
  - Error: red negative background and ring; close icon.
195
- - Connectors: `2px` line, gray when pending, focus-blue when the preceding step is completed.
291
+ - Connectors: `3px` rounded bar, `border-presentation-stepper-default` by default and focus-blue when `completed` is set. Vertically it centres itself under the indicator, tracking the stepper's size.
196
292
 
197
293
  ## TypeScript Types
198
294
 
@@ -204,18 +300,17 @@ type StepperVariants = VariantProps<typeof stepperStyles>
204
300
  // { orientation?: 'horizontal' | 'vertical' }
205
301
 
206
302
  type IndicatorVariants = VariantProps<typeof stepIndicatorStyles>
207
- // { state?: 'pending' | 'active' | 'completed' | 'error'; size?: 'S' | 'M' | 'L' }
303
+ // { type?: 'default' | 'success' | 'negative'; selected?: boolean; size?: 'S' | 'M' | 'L' }
208
304
  ```
209
305
 
210
306
  ## Accessibility
211
307
 
212
308
  - Wrap the stepper in a `<nav aria-label="Progress">` when it represents real navigation.
213
309
  - Use `aria-current="step"` on the active step's container when steps are interactive.
214
- - Don't rely on color alone for error — pair with `StepDescription` or an off-screen message.
310
+ - Don't rely on colour alone for the negative type — pair it with an off-screen message.
215
311
 
216
312
  ## Best Practices
217
313
 
218
- 1. Use `Stepper` when you need a connector line + numbered/iconified steps. Use `FormStepper` when you want pill-shaped buttons without a line.
314
+ 1. Add `StepConnector` between steps when you want the run of progress drawn; leave it out for a bare row of pills.
219
315
  2. Keep `Step` count to 3–5 horizontal, 3–7 vertical. Beyond that, switch to a checklist or summary.
220
- 3. Drive state from `activeStep` in the parent — only fall back to `isActive`/`isCompleted` for non-linear flows.
221
- 4. Provide a `StepDescription` only on vertical steppers — descriptions wrap horizontal layouts awkwardly.
316
+ 3. Drive selection from `activeStep` in the parent — only fall back to `selected` for non-linear flows.
@@ -26,6 +26,19 @@ npx torch-glare@latest add Button
26
26
 
27
27
  ## Release notes
28
28
 
29
+ - **v2.5.5** — **breaking**: `DataViews.Filters.Summary` is removed with no shim; delete any
30
+ `<DataViews.Filters.Summary />` (render your own from `useDataViewsFilters()` if you want one).
31
+ Also, every `FormBuilder.*` field takes a `hints` array, so one field can
32
+ carry several alerts. The validation error renders first, your hints follow. See
33
+ [FormBuilder](../components/form-builder.md#hints). Dropdown panels (`Select`,
34
+ `SearchableSelect`, `SearchableTree`, `Popover`, `DropdownMenu`, `ContextMenu`) now cap to the
35
+ space actually on screen and scroll their list in an inner viewport instead of being clipped —
36
+ note `SearchableTree`'s `maxBodyHeight` default drops 320 → 200, and menu submenus gained a
37
+ `maxHeight` (they were previously uncapped). `InputField`, `BadgeField` and `Select` no longer
38
+ pop an error tooltip — an invalid control is shown by its negative border alone, and
39
+ `toolTipSide` is deprecated and ignored. Plus fixes to `TabSwitch` dividers,
40
+ `FieldSection` hint placement, the
41
+ `FormRenderer` stepper grid, `SlideDatePicker` theming and `PopoverItem`'s disabled state.
29
42
  - **v2.5.2** — **breaking**: `FormBuilder` now holds only the fields; the section cards, title
30
43
  header and stepper moved to `FormRenderer`. See
31
44
  [FormBuilder 2.5.2](./form-builder-2.5.2.md) for the rename table.
@@ -273,6 +273,8 @@ The TORCH mode plugin provides the actual color values and theme-specific styles
273
273
  - 500+ CSS custom properties
274
274
  - Gradient and alpha channel support
275
275
  - Comprehensive color palette
276
+ - The shared **radius**, **container** and **breakpoint** scales (exported as
277
+ `borderRadius`, `containers` and `screens`)
276
278
 
277
279
  ### Installation
278
280
 
@@ -280,6 +282,46 @@ The TORCH mode plugin provides the actual color values and theme-specific styles
280
282
  npm install glare-torch-mode
281
283
  ```
282
284
 
285
+ ### The radius scale
286
+
287
+ `borderRadius` produces the `rounded-radius-*` classes the components are built on — Button, Badge,
288
+ the shared `Input` field root, ActionButton, Select and TextArea all use them. The keys mirror the
289
+ Figma `radius/*` collection:
290
+
291
+ | class | value | | class | value |
292
+ |---|---|---|---|---|
293
+ | `rounded-radius-none` | 0px | | `rounded-radius-2xl` | 16px |
294
+ | `rounded-radius-xs` | 2px | | `rounded-radius-3xl` | 24px |
295
+ | `rounded-radius-sm` | 4px | | `rounded-radius-4xl` | 32px |
296
+ | `rounded-radius-md` | 6px | | `rounded-radius-5xl` | 40px |
297
+ | `rounded-radius-lg` | 8px | | `rounded-radius-6xl` | 48px |
298
+ | `rounded-radius-xl` | 12px | | `rounded-radius-round` | 9999px |
299
+
300
+ Deliberately **not** reusing Tailwind's own `sm`/`md`/`lg` keys: that would override the built-in
301
+ scale, where Glare's `sm` is 4px and Tailwind's is 2px, silently restyling every existing
302
+ `rounded-sm`.
303
+
304
+ Note that `tailwind-merge` does not dedupe these classes — they are custom scale keys, not values it
305
+ recognises. Never put a `rounded-radius-*` on a `cva` base *and* on one of its variants: both survive
306
+ and CSS source order decides the winner. Put it only on the variants.
307
+
308
+ ### Tailwind v4
309
+
310
+ The plugin is a plain `addBase` function, so under v4 `@plugin` registers the colour variables but
311
+ **not** the scales — those reach Tailwind through `theme.extend` in a JS config, which v4 does not
312
+ have. Import the theme file as well (requires **1.4.0 or newer**):
313
+
314
+ ```css
315
+ @import "tailwindcss";
316
+ @import "glare-torch-mode/theme.css"; /* must precede the @plugin rules */
317
+ @plugin "glare-torch-mode";
318
+ ```
319
+
320
+ Without it `rounded-radius-*` is never generated and `sm:` / `@md:` fall back to Tailwind's values.
321
+ Two v4-only caveats: the container scale is shared with `max-w-*`, so `--container-md` also sets
322
+ `max-w-md` to 650px; and the plugin's `--radius-*` variables land in v4's own border-radius
323
+ namespace — matching values, but `px` where Tailwind uses `rem`.
324
+
283
325
  ### Setup (Required with mapping-color-system)
284
326
 
285
327
  ```ts
@@ -104,6 +104,13 @@ Add the following to your `global.css` file:
104
104
  (e.g. Badge renders with no background). Keep it directly under
105
105
  @import "tailwindcss". */
106
106
  @import "mapping-color-system-v4/tailwindVars.css";
107
+ /* Required, and needs glare-torch-mode >= 1.4.0. The plugin only registers the colour
108
+ variables; the radius scale, container sizes and breakpoints reach Tailwind through
109
+ `theme.extend` in a JS config, which v4 does not have. Without this the
110
+ `rounded-radius-*` classes are never generated (square corners on Button, Badge,
111
+ Input, ActionButton, Select, TextArea) and `sm:` / `@md:` fall back to Tailwind's
112
+ own values. Same @import-ordering rule as above applies. */
113
+ @import "glare-torch-mode/theme.css";
107
114
  @plugin "glare-torch-mode";
108
115
  @plugin "tailwind-scrollbar-hide";
109
116
  @plugin "tailwindcss-animate";
@@ -111,6 +118,14 @@ Add the following to your `global.css` file:
111
118
  @plugin "mapping-color-system-v4";
112
119
  ```
113
120
 
121
+ Two version-4-only caveats:
122
+
123
+ - Tailwind 4 shares the container scale with `max-w-*`, so `--container-md` also sets `max-w-md`
124
+ to 650px.
125
+ - The plugin sets `--radius-*` on `:root`, which is Tailwind 4's own border-radius namespace. The
126
+ values match its defaults (2/4/6/8/12/16/24/32px) but are declared in `px` where Tailwind uses
127
+ `rem`, so they diverge if you change the root font size.
128
+
114
129
  > ⚠️ **Common failure:** if your Badge (or any component using
115
130
  > `bg-background-presentation-*` colors) renders with no background, the
116
131
  > `tailwindVars.css` `@import` is almost certainly positioned **after** the
@@ -130,6 +145,8 @@ Then configure your `tailwind.config.js`:
130
145
 
131
146
  ```js
132
147
  const { plugin, mappingVars } = require('mapping-color-system')
148
+ // Design tokens plus the shared radius / container / screen scales.
149
+ const torchMode = require('glare-torch-mode')
133
150
 
134
151
  module.exports = {
135
152
  content: [
@@ -139,26 +156,22 @@ module.exports = {
139
156
  theme: {
140
157
  extend: {
141
158
  colors: mappingVars,
142
- containers: {
143
- xs: "320px",
144
- sm: "600px",
145
- md: "768px",
146
- lg: "1024px",
147
- xl: "1280px",
148
- "2xl": "1536px",
149
- },
159
+ borderRadius: torchMode.borderRadius,
160
+ containers: torchMode.containers,
150
161
  },
151
162
  },
163
+ // Top level, not inside extend — this replaces Tailwind's breakpoints.
164
+ screens: torchMode.screens,
152
165
  plugins: [
153
166
  plugin,
154
167
  require('@tailwindcss/container-queries'),
155
168
  require('tailwindcss-animate'),
156
169
  require('tailwind-scrollbar-hide'),
157
170
  require('glare-typography'),
158
- require('glare-torch-mode'),
171
+ torchMode,
159
172
  function ({ addVariant }) {
160
- addVariant("rtl", '&[dir="rtl"]');
161
- addVariant("ltr", '&[dir="ltr"]');
173
+ addVariant("rtl", ['&[dir="rtl"]', '[dir="rtl"] &']);
174
+ addVariant("ltr", ['&[dir="ltr"]', '[dir="ltr"] &']);
162
175
  },
163
176
  ],
164
177
  };
@@ -168,6 +181,14 @@ Important:
168
181
  - Specify the component path in the `content` array matching your `glare.json` path
169
182
  - Add all plugins to the `plugins` array
170
183
  - Add `mappingVars` to the `extend.colors` object
184
+ - Take `borderRadius`, `containers` and `screens` from `glare-torch-mode` rather than hardcoding
185
+ them. `borderRadius` is what produces the `rounded-radius-*` classes the components are built on;
186
+ without it Button, Badge, Input, ActionButton, Select and TextArea render with square corners.
187
+ - Put `screens` at the **top level**, not inside `extend`, so Glare's breakpoints replace
188
+ Tailwind's rather than being added alongside them (`sm` is 600px, not 640px).
189
+ - Register `rtl` / `ltr` with **both** selectors. `&[dir="rtl"]` alone only matches an element that
190
+ carries the attribute itself, so an `rtl:` class on a component nested inside an RTL wrapper never
191
+ applies.
171
192
 
172
193
  ---
173
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torch-glare",
3
- "version": "2.5.3",
3
+ "version": "2.5.5",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "A copy-in React component library (TypeScript + Radix UI + Tailwind CSS). Its CLI copies component source directly into your project — you own the code.",