luxen-ui 0.16.2 → 0.17.1
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 +50 -49
- package/cdn/custom-elements.json +237 -1
- package/cdn/elements/avatar/avatar.d.ts.map +1 -1
- package/cdn/elements/avatar/avatar.js +1 -1
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.d.ts +4 -0
- package/cdn/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js +2 -2
- package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
- package/cdn/elements/segmented-control/index.d.ts +2 -0
- package/cdn/elements/segmented-control/index.d.ts.map +1 -0
- package/cdn/elements/segmented-control/index.js +2 -0
- package/cdn/elements/segmented-control/index.js.map +1 -0
- package/cdn/elements/segmented-control/segmented-control.d.ts +80 -0
- package/cdn/elements/segmented-control/segmented-control.d.ts.map +1 -0
- package/cdn/elements/segmented-control/segmented-control.js +2 -0
- package/cdn/elements/segmented-control/segmented-control.js.map +1 -0
- package/cdn/registry.d.ts +1 -1
- package/cdn/registry.d.ts.map +1 -1
- package/cdn/registry.js.map +1 -1
- package/cdn/standalone.css +167 -0
- package/cdn/standalone.js +25 -22
- package/cdn/standalone.js.map +1 -1
- package/cdn/styles/elements/segmented-control.css +165 -0
- package/dist/css/elements/segmented-control.css +165 -0
- package/dist/custom-elements.json +237 -1
- package/dist/elements/avatar/avatar.d.ts.map +1 -1
- package/dist/elements/avatar/avatar.js +27 -7
- package/dist/elements/dropdown-item/dropdown-item.css +18 -0
- package/dist/elements/dropdown-item/dropdown-item.d.ts +4 -0
- package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/dist/elements/dropdown-item/dropdown-item.js +11 -2
- package/dist/elements/segmented-control/index.d.ts +2 -0
- package/dist/elements/segmented-control/index.d.ts.map +1 -0
- package/dist/elements/segmented-control/index.js +4 -0
- package/dist/elements/segmented-control/segmented-control.d.ts +80 -0
- package/dist/elements/segmented-control/segmented-control.d.ts.map +1 -0
- package/dist/elements/segmented-control/segmented-control.js +307 -0
- package/dist/metadata/dropdown-item.json +16 -1
- package/dist/metadata/index.json +122 -2
- package/dist/metadata/segmented-control.json +105 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/templates/elements/dropdown.md +52 -0
- package/dist/templates/elements/segmented-control.md +252 -0
- package/elements.json +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "segmented-control",
|
|
3
|
+
"displayName": "Segmented control",
|
|
4
|
+
"type": "progressive",
|
|
5
|
+
"isCustomElement": true,
|
|
6
|
+
"tag": "l-segmented-control",
|
|
7
|
+
"nativeTag": null,
|
|
8
|
+
"selector": "l-segmented-control",
|
|
9
|
+
"subItemOf": null,
|
|
10
|
+
"summary": "A single-select segmented control: a compact, mutually-exclusive\nswitch between a few options (radio-group semantics with a sliding pill).\nProgressively enhances light-DOM `<button>`s so it works before JS runs.\nForm-associated: give it a `name` and its selected `value` is submitted with\nthe form (and restored on reset), like a native radio group.",
|
|
11
|
+
"status": "stable",
|
|
12
|
+
"appearances": [],
|
|
13
|
+
"import": {
|
|
14
|
+
"css": "luxen-ui/css/segmented-control",
|
|
15
|
+
"js": "luxen-ui/segmented-control"
|
|
16
|
+
},
|
|
17
|
+
"properties": [
|
|
18
|
+
{
|
|
19
|
+
"name": "value",
|
|
20
|
+
"attribute": "value",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"default": "''",
|
|
23
|
+
"reflects": true,
|
|
24
|
+
"description": "Value of the selected segment (its `value` attribute, else its index)."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "size",
|
|
28
|
+
"attribute": "size",
|
|
29
|
+
"type": "SegmentedControlSize",
|
|
30
|
+
"default": "'md'",
|
|
31
|
+
"reflects": true,
|
|
32
|
+
"description": "Control height, aligned with buttons and form controls at the same size."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "label",
|
|
36
|
+
"attribute": "label",
|
|
37
|
+
"type": "string | undefined",
|
|
38
|
+
"default": null,
|
|
39
|
+
"reflects": true,
|
|
40
|
+
"description": "Accessible label announced for the group. Not displayed on screen."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "fullWidth",
|
|
44
|
+
"attribute": "full-width",
|
|
45
|
+
"type": "boolean",
|
|
46
|
+
"default": "false",
|
|
47
|
+
"reflects": true,
|
|
48
|
+
"description": "Stretch segments to fill the container width."
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"attributes": [],
|
|
52
|
+
"events": [
|
|
53
|
+
{
|
|
54
|
+
"name": "change",
|
|
55
|
+
"description": "Fired when the selected segment changes. Not cancelable. Bubbles. Properties: `value: string`, `index: number`.",
|
|
56
|
+
"cancelable": false
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"methods": [
|
|
60
|
+
{
|
|
61
|
+
"name": "formResetCallback",
|
|
62
|
+
"params": [],
|
|
63
|
+
"returns": null,
|
|
64
|
+
"description": ""
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "formStateRestoreCallback",
|
|
68
|
+
"params": [
|
|
69
|
+
{
|
|
70
|
+
"name": "state",
|
|
71
|
+
"type": "string"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "mode",
|
|
75
|
+
"type": "'restore' | 'autocomplete'"
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"returns": null,
|
|
79
|
+
"description": ""
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"slots": [],
|
|
83
|
+
"cssClasses": [],
|
|
84
|
+
"cssParts": [],
|
|
85
|
+
"cssProperties": [
|
|
86
|
+
{
|
|
87
|
+
"name": "--indicator-color",
|
|
88
|
+
"default": "var(--l-color-surface)",
|
|
89
|
+
"description": "Background of the sliding pill behind the selected segment."
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "--border-radius",
|
|
93
|
+
"default": "var(--l-radius-lg)",
|
|
94
|
+
"description": "Corner radius of the track."
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"commands": [],
|
|
98
|
+
"examples": [
|
|
99
|
+
{
|
|
100
|
+
"title": "Mark the initially-selected segment with `aria-checked=\"true\"` (or set",
|
|
101
|
+
"language": "html",
|
|
102
|
+
"code": "`value` to its `value` attribute) so it is styled before the script upgrades\nthe element.\n```html\n<l-segmented-control label=\"Metric\" value=\"cost\">\n <button value=\"volume\">Volume</button>\n <button value=\"cost\" aria-checked=\"true\">Cost</button>\n</l-segmented-control>\n```"
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Every component base name the library ships. */
|
|
2
|
-
export type ElementBaseName = 'alert' | 'alert-dialog' | 'avatar' | 'badge' | 'button-group' | 'carousel' | 'carousel-item' | 'combobox' | 'dialog' | 'divider' | 'drawer' | 'dropdown' | 'dropdown-item' | 'dropdown-label' | 'form-field' | 'icon' | 'input-group' | 'input-otp' | 'input-stepper' | 'popover' | 'prose-editor' | 'skeleton' | 'slider' | 'spinner' | 'rating' | 'select' | 'sticky-bar' | 'stories' | 'story' | 'stories-viewer' | 'tabs' | 'tag' | 'toast' | 'toast-item' | 'tooltip' | 'tree' | 'tree-item';
|
|
2
|
+
export type ElementBaseName = 'alert' | 'alert-dialog' | 'avatar' | 'badge' | 'button-group' | 'carousel' | 'carousel-item' | 'combobox' | 'dialog' | 'divider' | 'drawer' | 'dropdown' | 'dropdown-item' | 'dropdown-label' | 'form-field' | 'icon' | 'input-group' | 'input-otp' | 'input-stepper' | 'popover' | 'prose-editor' | 'skeleton' | 'slider' | 'spinner' | 'rating' | 'segmented-control' | 'select' | 'sticky-bar' | 'stories' | 'story' | 'stories-viewer' | 'tabs' | 'tag' | 'toast' | 'toast-item' | 'tooltip' | 'tree' | 'tree-item';
|
|
3
3
|
/** Set the global prefix. Must be called before defining elements. */
|
|
4
4
|
export declare function setPrefix(prefix: {
|
|
5
5
|
element: string;
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/html/registry.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,cAAc,GACd,QAAQ,GACR,OAAO,GACP,cAAc,GACd,UAAU,GACV,eAAe,GACf,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,YAAY,GACZ,MAAM,GACN,aAAa,GACb,WAAW,GACX,eAAe,GACf,SAAS,GACT,cAAc,GACd,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,OAAO,GACP,gBAAgB,GAChB,MAAM,GACN,KAAK,GACL,OAAO,GACP,YAAY,GACZ,SAAS,GACT,MAAM,GACN,WAAW,CAAC;AAMhB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGxE;AAED,gCAAgC;AAChC,wBAAgB,SAAS,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAE5D;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAEzD;AAED,sEAAsE;AACtE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExC;AAID,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAE/D;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAE9D"}
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/html/registry.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,cAAc,GACd,QAAQ,GACR,OAAO,GACP,cAAc,GACd,UAAU,GACV,eAAe,GACf,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,YAAY,GACZ,MAAM,GACN,aAAa,GACb,WAAW,GACX,eAAe,GACf,SAAS,GACT,cAAc,GACd,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,mBAAmB,GACnB,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,OAAO,GACP,gBAAgB,GAChB,MAAM,GACN,KAAK,GACL,OAAO,GACP,YAAY,GACZ,SAAS,GACT,MAAM,GACN,WAAW,CAAC;AAMhB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGxE;AAED,gCAAgC;AAChC,wBAAgB,SAAS,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAE5D;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAEzD;AAED,sEAAsE;AACtE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExC;AAID,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAE/D;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAE9D"}
|
|
@@ -74,6 +74,57 @@ Set `type="checkbox"` for toggleable items. The dropdown stays open when checkin
|
|
|
74
74
|
</l-dropdown>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
### Destructive items
|
|
78
|
+
|
|
79
|
+
Set `variant="destructive"` to mark a delete-style action in red.
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<l-dropdown>
|
|
83
|
+
<button
|
|
84
|
+
slot="trigger"
|
|
85
|
+
class="l-button"
|
|
86
|
+
>
|
|
87
|
+
Project
|
|
88
|
+
</button>
|
|
89
|
+
|
|
90
|
+
<l-dropdown-item value="share">
|
|
91
|
+
<iconify-icon
|
|
92
|
+
slot="prefix"
|
|
93
|
+
icon="lucide:share"
|
|
94
|
+
></iconify-icon>
|
|
95
|
+
Share
|
|
96
|
+
</l-dropdown-item>
|
|
97
|
+
<l-dropdown-item value="preferences">
|
|
98
|
+
<iconify-icon
|
|
99
|
+
slot="prefix"
|
|
100
|
+
icon="lucide:settings"
|
|
101
|
+
></iconify-icon>
|
|
102
|
+
Preferences
|
|
103
|
+
</l-dropdown-item>
|
|
104
|
+
|
|
105
|
+
<l-divider></l-divider>
|
|
106
|
+
|
|
107
|
+
<l-dropdown-label>Danger zone</l-dropdown-label>
|
|
108
|
+
<l-dropdown-item value="archive">
|
|
109
|
+
<iconify-icon
|
|
110
|
+
slot="prefix"
|
|
111
|
+
icon="lucide:archive"
|
|
112
|
+
></iconify-icon>
|
|
113
|
+
Archive
|
|
114
|
+
</l-dropdown-item>
|
|
115
|
+
<l-dropdown-item
|
|
116
|
+
value="delete"
|
|
117
|
+
variant="destructive"
|
|
118
|
+
>
|
|
119
|
+
<iconify-icon
|
|
120
|
+
slot="prefix"
|
|
121
|
+
icon="lucide:trash-2"
|
|
122
|
+
></iconify-icon>
|
|
123
|
+
Delete
|
|
124
|
+
</l-dropdown-item>
|
|
125
|
+
</l-dropdown>
|
|
126
|
+
```
|
|
127
|
+
|
|
77
128
|
### Section labels
|
|
78
129
|
|
|
79
130
|
Add `<l-dropdown-label>` to caption a group of items. It is non-interactive — keyboard navigation and typeahead skip it. Use `<l-divider>` between sections.
|
|
@@ -433,6 +484,7 @@ while open.
|
|
|
433
484
|
- **value**: `string` — The value associated with this item.
|
|
434
485
|
- **disabled**: `boolean` (default: `false`) — Disables the item.
|
|
435
486
|
- **type**: `'normal' | 'checkbox'` (default: `'normal'`) — The type of item: `normal` or `checkbox`.
|
|
487
|
+
- **variant**: `'destructive' | undefined` (default: `undefined`) — Visual variant. `destructive` marks a delete-style action in red.
|
|
436
488
|
- **checked**: `boolean` (default: `false`) — Whether the checkbox item is checked.
|
|
437
489
|
- **submenu-open**: `boolean` (default: `false`) — Whether this item's submenu is open. Managed by the parent `l-dropdown`.
|
|
438
490
|
- **hasSubmenu**: `boolean` — Whether this item has nested `slot="submenu"` items.
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
outline: deep
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Segmented control
|
|
6
|
+
|
|
7
|
+
A single-select switch between a few mutually-exclusive options, with a sliding pill behind the selected segment.
|
|
8
|
+
|
|
9
|
+
**`<l-segmented-control>`** — Progressive Custom Element
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<l-segmented-control
|
|
13
|
+
label="View"
|
|
14
|
+
value="list"
|
|
15
|
+
>
|
|
16
|
+
<button value="list">List</button>
|
|
17
|
+
<button value="board">Board</button>
|
|
18
|
+
<button value="calendar">Calendar</button>
|
|
19
|
+
</l-segmented-control>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Each segment is a native `<button>`. Set `value` on the control to the `value` of the initially-selected segment; the control emits a `change` event with the new `value` when the selection changes.
|
|
23
|
+
|
|
24
|
+
## Options
|
|
25
|
+
|
|
26
|
+
### Label
|
|
27
|
+
|
|
28
|
+
Add `label` to give the control an accessible name announced by screen readers.
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<l-segmented-control
|
|
32
|
+
label="View"
|
|
33
|
+
value="list"
|
|
34
|
+
>
|
|
35
|
+
<button value="list">List</button>
|
|
36
|
+
<button value="board">Board</button>
|
|
37
|
+
<button value="calendar">Calendar</button>
|
|
38
|
+
</l-segmented-control>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Sizes
|
|
42
|
+
|
|
43
|
+
Add `size` (`sm`, `lg`, `xl`) to align the control with buttons and form controls of the same size. Defaults to `md`.
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<div class="flex flex-col items-start gap-3">
|
|
47
|
+
<l-segmented-control
|
|
48
|
+
label="Size sm"
|
|
49
|
+
size="sm"
|
|
50
|
+
>
|
|
51
|
+
<button value="day">Day</button>
|
|
52
|
+
<button value="week">Week</button>
|
|
53
|
+
<button value="month">Month</button>
|
|
54
|
+
</l-segmented-control>
|
|
55
|
+
<l-segmented-control label="Size md">
|
|
56
|
+
<button value="day">Day</button>
|
|
57
|
+
<button value="week">Week</button>
|
|
58
|
+
<button value="month">Month</button>
|
|
59
|
+
</l-segmented-control>
|
|
60
|
+
<l-segmented-control
|
|
61
|
+
label="Size lg"
|
|
62
|
+
size="lg"
|
|
63
|
+
>
|
|
64
|
+
<button value="day">Day</button>
|
|
65
|
+
<button value="week">Week</button>
|
|
66
|
+
<button value="month">Month</button>
|
|
67
|
+
</l-segmented-control>
|
|
68
|
+
</div>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Full width
|
|
72
|
+
|
|
73
|
+
Add `full-width` to stretch the segments to fill the container.
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<l-segmented-control
|
|
77
|
+
label="Billing period"
|
|
78
|
+
value="yearly"
|
|
79
|
+
full-width
|
|
80
|
+
class="w-full"
|
|
81
|
+
>
|
|
82
|
+
<button value="monthly">Monthly</button>
|
|
83
|
+
<button value="yearly">Yearly</button>
|
|
84
|
+
</l-segmented-control>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Form field
|
|
88
|
+
|
|
89
|
+
It is form-associated: add `name` and the selected `value` is submitted with the form, like a native radio group. Reset restores the initial selection, and `disabled` opts the control out of submission.
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<form class="flex flex-col items-start gap-3">
|
|
93
|
+
<l-segmented-control
|
|
94
|
+
name="billing"
|
|
95
|
+
label="Billing period"
|
|
96
|
+
value="yearly"
|
|
97
|
+
>
|
|
98
|
+
<button value="monthly">Monthly</button>
|
|
99
|
+
<button value="yearly">Yearly</button>
|
|
100
|
+
</l-segmented-control>
|
|
101
|
+
<button
|
|
102
|
+
class="l-button"
|
|
103
|
+
type="reset"
|
|
104
|
+
>
|
|
105
|
+
Reset
|
|
106
|
+
</button>
|
|
107
|
+
</form>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Examples
|
|
111
|
+
|
|
112
|
+
### With icons
|
|
113
|
+
|
|
114
|
+
Place an `<l-icon>` before the label inside a segment.
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<l-segmented-control label="Source">
|
|
118
|
+
<button value="github">
|
|
119
|
+
<l-icon name="lucide:github"></l-icon>
|
|
120
|
+
GitHub
|
|
121
|
+
</button>
|
|
122
|
+
<button value="dribbble">
|
|
123
|
+
<l-icon name="lucide:dribbble"></l-icon>
|
|
124
|
+
Dribbble
|
|
125
|
+
</button>
|
|
126
|
+
<button value="youtube">
|
|
127
|
+
<l-icon name="lucide:youtube"></l-icon>
|
|
128
|
+
YouTube
|
|
129
|
+
</button>
|
|
130
|
+
</l-segmented-control>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Icon-only
|
|
134
|
+
|
|
135
|
+
A segment with no text is squared automatically. Give each one an `aria-label`.
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<l-segmented-control label="Text alignment">
|
|
139
|
+
<button
|
|
140
|
+
value="left"
|
|
141
|
+
aria-label="Align left"
|
|
142
|
+
>
|
|
143
|
+
<l-icon name="lucide:align-left"></l-icon>
|
|
144
|
+
</button>
|
|
145
|
+
<button
|
|
146
|
+
value="center"
|
|
147
|
+
aria-label="Align center"
|
|
148
|
+
>
|
|
149
|
+
<l-icon name="lucide:align-center"></l-icon>
|
|
150
|
+
</button>
|
|
151
|
+
<button
|
|
152
|
+
value="right"
|
|
153
|
+
aria-label="Align right"
|
|
154
|
+
>
|
|
155
|
+
<l-icon name="lucide:align-right"></l-icon>
|
|
156
|
+
</button>
|
|
157
|
+
</l-segmented-control>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Filter toolbar
|
|
161
|
+
|
|
162
|
+
Segmented controls line up with `.l-button` triggers and `l-select` at the same `size`, so a filter bar stays visually consistent. Here the dropdowns take a quiet neutral fill (`bg-fill-neutral-subtle`) so the chrome recedes and the active selections carry the emphasis.
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
166
|
+
<button class="l-button bg-fill-neutral-subtle">
|
|
167
|
+
<l-icon name="lucide:layout-list"></l-icon>
|
|
168
|
+
List view
|
|
169
|
+
<l-icon name="lucide:chevron-down"></l-icon>
|
|
170
|
+
</button>
|
|
171
|
+
<button class="l-button bg-fill-neutral-subtle">
|
|
172
|
+
<l-icon name="lucide:arrow-down-narrow-wide"></l-icon>
|
|
173
|
+
Sort
|
|
174
|
+
<l-icon name="lucide:chevron-down"></l-icon>
|
|
175
|
+
</button>
|
|
176
|
+
<l-segmented-control
|
|
177
|
+
label="Metric"
|
|
178
|
+
value="cost"
|
|
179
|
+
>
|
|
180
|
+
<button value="volume">Volume</button>
|
|
181
|
+
<button value="cost">Cost</button>
|
|
182
|
+
</l-segmented-control>
|
|
183
|
+
<l-segmented-control
|
|
184
|
+
label="Color"
|
|
185
|
+
value="all"
|
|
186
|
+
>
|
|
187
|
+
<button value="all">All</button>
|
|
188
|
+
<button value="color">
|
|
189
|
+
<span class="size-2.5 rounded-[3px] bg-[#ef4444]"></span>
|
|
190
|
+
Color
|
|
191
|
+
</button>
|
|
192
|
+
<button value="black">
|
|
193
|
+
<span class="size-2.5 rounded-[3px] bg-[#64748b]"></span>
|
|
194
|
+
Black
|
|
195
|
+
</button>
|
|
196
|
+
</l-segmented-control>
|
|
197
|
+
</div>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Accessibility
|
|
201
|
+
|
|
202
|
+
### Criteria
|
|
203
|
+
|
|
204
|
+
- **Role** — Host gets `role="radiogroup"`; each segment gets `role="radio"` with `aria-checked`
|
|
205
|
+
- **Accessible name** — `label` sets `aria-label` so assistive tech announces the control purpose
|
|
206
|
+
- **Keyboard** — Arrow keys move selection through the segments; `Home`/`End` jump to the ends
|
|
207
|
+
- **Focus order** — Roving `tabindex`: the group is a single `Tab` stop, arrows move within it
|
|
208
|
+
- **Icon-only segments** — A segment with no visible text needs its own `aria-label`
|
|
209
|
+
|
|
210
|
+
### Rules
|
|
211
|
+
|
|
212
|
+
- Always add a `label` describing the control purpose
|
|
213
|
+
- Segments must be native `<button>` elements with a `value`
|
|
214
|
+
- Give each icon-only segment its own `aria-label`
|
|
215
|
+
|
|
216
|
+
### Keyboard interactions
|
|
217
|
+
|
|
218
|
+
- `Tab` — Moves focus into the control (to the selected segment)
|
|
219
|
+
- `ArrowRight` — Selects and focuses the next segment, wrapping
|
|
220
|
+
- `ArrowLeft` — Selects and focuses the previous segment, wrapping
|
|
221
|
+
- `ArrowDown` — Same as ArrowRight
|
|
222
|
+
- `ArrowUp` — Same as ArrowLeft
|
|
223
|
+
- `Home` — Selects and focuses the first segment
|
|
224
|
+
- `End` — Selects and focuses the last segment
|
|
225
|
+
|
|
226
|
+
## API reference
|
|
227
|
+
|
|
228
|
+
### Importing
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
import 'luxen-ui/segmented-control';
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
```css
|
|
235
|
+
@import 'luxen-ui/css/segmented-control';
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Attributes & Properties
|
|
239
|
+
|
|
240
|
+
- **value**: `string` — Value of the selected segment (its `value` attribute, else its index).
|
|
241
|
+
- **size**: `SegmentedControlSize` (default: `'md'`) — Control height, aligned with buttons and form controls at the same size.
|
|
242
|
+
- **label**: `string | undefined` — Accessible label announced for the group. Not displayed on screen.
|
|
243
|
+
- **full-width**: `boolean` (default: `false`) — Stretch segments to fill the container width.
|
|
244
|
+
|
|
245
|
+
### Events
|
|
246
|
+
|
|
247
|
+
- **change** — Fired when the selected segment changes. Not cancelable. Bubbles. Properties: `value: string`, `index: number`.
|
|
248
|
+
|
|
249
|
+
### CSS custom properties
|
|
250
|
+
|
|
251
|
+
- `--indicator-color` (default: `var(--l-color-surface)`) — Background of the sliding pill behind the selected segment.
|
|
252
|
+
- `--border-radius` (default: `var(--l-radius-lg)`) — Corner radius of the track.
|
package/elements.json
CHANGED
|
@@ -261,6 +261,14 @@
|
|
|
261
261
|
"inSkill": true,
|
|
262
262
|
"inMockups": true
|
|
263
263
|
},
|
|
264
|
+
{
|
|
265
|
+
"name": "segmented-control",
|
|
266
|
+
"displayName": "Segmented control",
|
|
267
|
+
"kind": "element",
|
|
268
|
+
"type": "progressive",
|
|
269
|
+
"inSkill": true,
|
|
270
|
+
"inMockups": true
|
|
271
|
+
},
|
|
264
272
|
{
|
|
265
273
|
"name": "select",
|
|
266
274
|
"displayName": "Select",
|
package/package.json
CHANGED