luxen-ui 0.16.2 → 0.17.0
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 +210 -0
- 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/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 +210 -0
- package/dist/elements/avatar/avatar.d.ts.map +1 -1
- package/dist/elements/avatar/avatar.js +27 -7
- 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/index.json +106 -1
- 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/segmented-control.md +252 -0
- package/elements.json +8 -0
- package/package.json +1 -1
package/cdn/standalone.css
CHANGED
|
@@ -4047,6 +4047,173 @@ In dark mode, mixes the base color with black (default 15% black).
|
|
|
4047
4047
|
}
|
|
4048
4048
|
}
|
|
4049
4049
|
|
|
4050
|
+
/* segmented-control.css */
|
|
4051
|
+
@layer components {
|
|
4052
|
+
/*
|
|
4053
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4054
|
+
Segmented control
|
|
4055
|
+
A single-select switch: a muted track with a sliding pill behind the
|
|
4056
|
+
selected segment. Shares its visual language with l-tabs[variant='enclosed']
|
|
4057
|
+
(same neutral-subtle track + surface pill), but carries radio-group
|
|
4058
|
+
semantics instead of tabs.
|
|
4059
|
+
|
|
4060
|
+
Structural selectors (not [role='…']) so the control is styled from plain
|
|
4061
|
+
light DOM — it is progressive, so it must look right before JS adds ARIA.
|
|
4062
|
+
The host is the flex track; its `<button>` children are the segments. JS
|
|
4063
|
+
only enhances (roles, keyboard, and the sliding pill offsets).
|
|
4064
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4065
|
+
*/
|
|
4066
|
+
|
|
4067
|
+
l-segmented-control {
|
|
4068
|
+
--_height: var(--l-size-control-md);
|
|
4069
|
+
--_pad: 0.1875rem;
|
|
4070
|
+
--_duration: 150ms;
|
|
4071
|
+
--_easing: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
4072
|
+
|
|
4073
|
+
display: inline-flex;
|
|
4074
|
+
position: relative;
|
|
4075
|
+
align-items: stretch;
|
|
4076
|
+
height: var(--_height);
|
|
4077
|
+
padding: var(--_pad);
|
|
4078
|
+
gap: calc(var(--spacing) * 0.5);
|
|
4079
|
+
background: var(--l-color-bg-fill-neutral-subtle);
|
|
4080
|
+
border-radius: var(--border-radius, var(--l-radius-lg));
|
|
4081
|
+
/* Match the form-control border (--l-color-border, as used by .l-button,
|
|
4082
|
+
l-select, and l-input) so the track lines up with dropdowns in a toolbar
|
|
4083
|
+
— not the lighter --l-color-divider that enclosed tabs use. */
|
|
4084
|
+
box-shadow: inset 0 0 0 1px var(--l-color-border);
|
|
4085
|
+
|
|
4086
|
+
/* Sliding pill behind the selected segment. Positioned by JS via
|
|
4087
|
+
--_indicator-left / --_indicator-width (button offsetLeft / offsetWidth);
|
|
4088
|
+
width 0 until JS runs, so it stays invisible in the no-JS fallback. */
|
|
4089
|
+
&::before {
|
|
4090
|
+
content: '';
|
|
4091
|
+
position: absolute;
|
|
4092
|
+
top: var(--_pad);
|
|
4093
|
+
bottom: var(--_pad);
|
|
4094
|
+
left: 0;
|
|
4095
|
+
width: var(--_indicator-width, 0);
|
|
4096
|
+
transform: translateX(var(--_indicator-left, 0));
|
|
4097
|
+
background: var(--indicator-color, var(--l-color-surface));
|
|
4098
|
+
border-radius: var(--l-radius-md);
|
|
4099
|
+
box-shadow:
|
|
4100
|
+
0 1px 3px 0 rgb(0 0 0 / 0.08),
|
|
4101
|
+
0 1px 2px -1px rgb(0 0 0 / 0.08);
|
|
4102
|
+
pointer-events: none;
|
|
4103
|
+
will-change: transform, width;
|
|
4104
|
+
transition:
|
|
4105
|
+
transform var(--_duration) var(--_easing),
|
|
4106
|
+
width var(--_duration) var(--_easing);
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4110
|
+
/*
|
|
4111
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4112
|
+
Sizes — align with .l-button and form controls at the same size.
|
|
4113
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4114
|
+
*/
|
|
4115
|
+
|
|
4116
|
+
l-segmented-control[size='sm'] {
|
|
4117
|
+
--_height: var(--l-size-control-sm);
|
|
4118
|
+
}
|
|
4119
|
+
|
|
4120
|
+
l-segmented-control[size='lg'] {
|
|
4121
|
+
--_height: var(--l-size-control-lg);
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
l-segmented-control[size='xl'] {
|
|
4125
|
+
--_height: var(--l-size-control-xl);
|
|
4126
|
+
}
|
|
4127
|
+
|
|
4128
|
+
/* Whole-control disabled (host `disabled` attribute, form-associated). */
|
|
4129
|
+
l-segmented-control[disabled] {
|
|
4130
|
+
opacity: 0.5;
|
|
4131
|
+
pointer-events: none;
|
|
4132
|
+
}
|
|
4133
|
+
|
|
4134
|
+
/*
|
|
4135
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4136
|
+
Segments
|
|
4137
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4138
|
+
*/
|
|
4139
|
+
|
|
4140
|
+
l-segmented-control button {
|
|
4141
|
+
position: relative;
|
|
4142
|
+
z-index: 1;
|
|
4143
|
+
display: inline-flex;
|
|
4144
|
+
align-items: center;
|
|
4145
|
+
justify-content: center;
|
|
4146
|
+
gap: calc(var(--spacing) * 1.5);
|
|
4147
|
+
padding-inline: calc(var(--spacing) * 3);
|
|
4148
|
+
margin: 0;
|
|
4149
|
+
appearance: none;
|
|
4150
|
+
border: none;
|
|
4151
|
+
background: none;
|
|
4152
|
+
border-radius: var(--l-radius-md);
|
|
4153
|
+
color: var(--l-color-text-secondary);
|
|
4154
|
+
font-family: inherit;
|
|
4155
|
+
font-size: var(--l-text-sm);
|
|
4156
|
+
font-weight: 500;
|
|
4157
|
+
line-height: 1;
|
|
4158
|
+
white-space: nowrap;
|
|
4159
|
+
cursor: pointer;
|
|
4160
|
+
-webkit-tap-highlight-color: transparent;
|
|
4161
|
+
transition: color 150ms;
|
|
4162
|
+
|
|
4163
|
+
/* Icon-only segments (JS-detected, no visible text): square them. */
|
|
4164
|
+
&[data-icon-only] {
|
|
4165
|
+
padding-inline: 0;
|
|
4166
|
+
width: calc(var(--_height) - 2 * var(--_pad));
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
&[aria-checked='true'] {
|
|
4170
|
+
color: var(--l-color-text-primary);
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
@media (hover: hover) {
|
|
4174
|
+
&:hover:not([aria-checked='true']):not(:disabled):not([aria-disabled='true']) {
|
|
4175
|
+
color: var(--l-color-text-primary);
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
|
|
4179
|
+
&:disabled,
|
|
4180
|
+
&[aria-disabled='true'] {
|
|
4181
|
+
cursor: not-allowed;
|
|
4182
|
+
opacity: 0.4;
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
&:focus-visible {
|
|
4186
|
+
outline: 2px solid var(--l-focus-ring);
|
|
4187
|
+
outline-offset: -2px;
|
|
4188
|
+
border-radius: var(--l-radius-sm);
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
/*
|
|
4193
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4194
|
+
Full width
|
|
4195
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4196
|
+
*/
|
|
4197
|
+
|
|
4198
|
+
l-segmented-control[full-width] {
|
|
4199
|
+
display: flex;
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
l-segmented-control[full-width] button {
|
|
4203
|
+
flex: 1;
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
@media (prefers-reduced-motion: reduce) {
|
|
4207
|
+
l-segmented-control::before {
|
|
4208
|
+
transition-duration: 0ms;
|
|
4209
|
+
}
|
|
4210
|
+
|
|
4211
|
+
l-segmented-control button {
|
|
4212
|
+
transition-duration: 0ms;
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
|
|
4050
4217
|
/* select.css */
|
|
4051
4218
|
/* Select — `.l-select` on a native <select> using the customizable
|
|
4052
4219
|
`base-select` appearance (the Customizable Select API).
|
package/cdn/standalone.js
CHANGED
|
@@ -1,68 +1,71 @@
|
|
|
1
1
|
//#region src/html/elements/alert/index.ts
|
|
2
|
-
define$
|
|
2
|
+
define$33("alert", Alert);
|
|
3
3
|
//#endregion
|
|
4
4
|
//#region src/html/elements/alert-dialog/index.ts
|
|
5
|
-
define$
|
|
5
|
+
define$32("alert-dialog", AlertDialog);
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/html/elements/avatar/index.ts
|
|
8
|
-
define$
|
|
8
|
+
define$31("avatar", Avatar);
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/html/elements/badge/index.ts
|
|
11
|
-
define$
|
|
11
|
+
define$30("badge", Badge);
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/html/elements/button-group/index.ts
|
|
14
|
-
define$
|
|
14
|
+
define$29("button-group", ButtonGroup);
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/html/elements/carousel/index.ts
|
|
17
|
-
define$
|
|
17
|
+
define$28("carousel", Carousel);
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/html/elements/carousel-item/index.ts
|
|
20
|
-
define$
|
|
20
|
+
define$27("carousel-item", CarouselItem);
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/html/elements/combobox/index.ts
|
|
23
|
-
define$
|
|
23
|
+
define$26("combobox", Combobox);
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region src/html/elements/dialog/index.ts
|
|
26
|
-
define$
|
|
26
|
+
define$25("dialog", Dialog);
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/html/elements/divider/index.ts
|
|
29
|
-
define$
|
|
29
|
+
define$24("divider", Divider);
|
|
30
30
|
//#endregion
|
|
31
31
|
//#region src/html/elements/drawer/index.ts
|
|
32
|
-
define$
|
|
32
|
+
define$23("drawer", Drawer);
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/html/elements/dropdown/index.ts
|
|
35
|
-
define$
|
|
35
|
+
define$22("dropdown", Dropdown);
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/html/elements/dropdown-item/index.ts
|
|
38
|
-
define$
|
|
38
|
+
define$21("dropdown-item", DropdownItem);
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/html/elements/dropdown-label/index.ts
|
|
41
|
-
define$
|
|
41
|
+
define$20("dropdown-label", DropdownLabel);
|
|
42
42
|
//#endregion
|
|
43
43
|
//#region src/html/elements/form-field/index.ts
|
|
44
|
-
define$
|
|
44
|
+
define$19("form-field", FormField);
|
|
45
45
|
//#endregion
|
|
46
46
|
//#region src/html/elements/icon/index.ts
|
|
47
|
-
define$
|
|
47
|
+
define$18("icon", Icon);
|
|
48
48
|
//#endregion
|
|
49
49
|
//#region src/html/elements/input-group/index.ts
|
|
50
|
-
define$
|
|
50
|
+
define$17("input-group", InputGroup);
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/html/elements/input-otp/index.ts
|
|
53
|
-
define$
|
|
53
|
+
define$16("input-otp", InputOtp);
|
|
54
54
|
//#endregion
|
|
55
55
|
//#region src/html/elements/input-stepper/index.ts
|
|
56
|
-
define$
|
|
56
|
+
define$15("input-stepper", InputStepper);
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/html/elements/popover/index.ts
|
|
59
|
-
define$
|
|
59
|
+
define$14("popover", Popover);
|
|
60
60
|
//#endregion
|
|
61
61
|
//#region src/html/elements/prose-editor/index.ts
|
|
62
|
-
define$
|
|
62
|
+
define$13("prose-editor", ProseEditor);
|
|
63
63
|
//#endregion
|
|
64
64
|
//#region src/html/elements/rating/index.ts
|
|
65
|
-
define$
|
|
65
|
+
define$12("rating", Rating);
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/html/elements/segmented-control/index.ts
|
|
68
|
+
define$11("segmented-control", SegmentedControl);
|
|
66
69
|
//#endregion
|
|
67
70
|
//#region src/html/elements/select/index.ts
|
|
68
71
|
define$10("select", Select);
|
package/cdn/standalone.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone.js","names":[],"sources":["../src/html/elements/alert/index.ts","../src/html/elements/alert-dialog/index.ts","../src/html/elements/avatar/index.ts","../src/html/elements/badge/index.ts","../src/html/elements/button-group/index.ts","../src/html/elements/carousel/index.ts","../src/html/elements/carousel-item/index.ts","../src/html/elements/combobox/index.ts","../src/html/elements/dialog/index.ts","../src/html/elements/divider/index.ts","../src/html/elements/drawer/index.ts","../src/html/elements/dropdown/index.ts","../src/html/elements/dropdown-item/index.ts","../src/html/elements/dropdown-label/index.ts","../src/html/elements/form-field/index.ts","../src/html/elements/icon/index.ts","../src/html/elements/input-group/index.ts","../src/html/elements/input-otp/index.ts","../src/html/elements/input-stepper/index.ts","../src/html/elements/popover/index.ts","../src/html/elements/prose-editor/index.ts","../src/html/elements/rating/index.ts","../src/html/elements/select/index.ts","../src/html/elements/skeleton/index.ts","../src/html/elements/slider/index.ts","../src/html/elements/spinner/index.ts","../src/html/elements/sticky-bar/index.ts","../src/html/elements/tabs/index.ts","../src/html/elements/tag/index.ts","../src/html/elements/toast/index.ts","../src/html/elements/tooltip/index.ts","../src/html/elements/tree/index.ts","../src/html/elements/tree-item/index.ts","../src/html/registry.ts"],"sourcesContent":["import { define } from '../../define.js';\nimport { Alert } from './alert.js';\nexport * from './alert.js';\ndefine('alert', Alert);\n","import { define } from '../../define.js';\nimport { AlertDialog } from './alert-dialog.js';\nexport * from './alert-dialog.js';\ndefine('alert-dialog', AlertDialog);\n","import { define } from '../../define.js';\nimport { Avatar } from './avatar.js';\nexport * from './avatar.js';\ndefine('avatar', Avatar);\n","import { define } from '../../define.js';\nimport { Badge } from './badge.js';\nexport * from './badge.js';\ndefine('badge', Badge);\n","import { define } from '../../define.js';\nimport { ButtonGroup } from './button-group.js';\nexport * from './button-group.js';\ndefine('button-group', ButtonGroup);\n","import { define } from '../../define.js';\nimport { Carousel } from './carousel.js';\nexport * from './carousel.js';\ndefine('carousel', Carousel);\n","import { define } from '../../define.js';\nimport { CarouselItem } from './carousel-item.js';\nexport * from './carousel-item.js';\ndefine('carousel-item', CarouselItem);\n","import { define } from '../../define.js';\nimport { Combobox } from './combobox.js';\nexport * from './combobox.js';\ndefine('combobox', Combobox);\n","import { define } from '../../define.js';\nimport { Dialog } from './dialog.js';\nexport * from './dialog.js';\ndefine('dialog', Dialog);\n","import { define } from '../../define.js';\nimport { Divider } from './divider.js';\nexport * from './divider.js';\ndefine('divider', Divider);\n","import { define } from '../../define.js';\nimport { Drawer } from './drawer.js';\nexport * from './drawer.js';\ndefine('drawer', Drawer);\n","import { define } from '../../define.js';\nimport { Dropdown } from './dropdown.js';\nexport * from './dropdown.js';\ndefine('dropdown', Dropdown);\n","import { define } from '../../define.js';\nimport { DropdownItem } from './dropdown-item.js';\nexport * from './dropdown-item.js';\ndefine('dropdown-item', DropdownItem);\n","import { define } from '../../define.js';\nimport { DropdownLabel } from './dropdown-label.js';\nexport * from './dropdown-label.js';\ndefine('dropdown-label', DropdownLabel);\n","import { define } from '../../define.js';\nimport { FormField } from './form-field.js';\nexport * from './form-field.js';\ndefine('form-field', FormField);\n","import { define } from '../../define.js';\nimport { Icon } from './icon.js';\nexport * from './icon.js';\ndefine('icon', Icon);\n","import { define } from '../../define.js';\nimport { InputGroup } from './input-group.js';\nexport * from './input-group.js';\ndefine('input-group', InputGroup);\n","import { define } from '../../define.js';\nimport { InputOtp } from './input-otp.js';\nexport * from './input-otp.js';\ndefine('input-otp', InputOtp);\n","import { define } from '../../define.js';\nimport { InputStepper } from './input-stepper.js';\nexport * from './input-stepper.js';\ndefine('input-stepper', InputStepper);\n","import { define } from '../../define.js';\nimport { Popover } from './popover.js';\nexport * from './popover.js';\ndefine('popover', Popover);\n","import { define } from '../../define.js';\nimport { ProseEditor } from './prose-editor.js';\nexport * from './prose-editor.js';\ndefine('prose-editor', ProseEditor);\n","import { define } from '../../define.js';\nimport { Rating } from './rating.js';\nexport * from './rating.js';\ndefine('rating', Rating);\n","import { define } from '../../define.js';\nimport { Select } from './select.js';\nexport * from './select.js';\ndefine('select', Select);\n","import { define } from '../../define.js';\nimport { Skeleton } from './skeleton.js';\nexport * from './skeleton.js';\ndefine('skeleton', Skeleton);\n","import { define } from '../../define.js';\nimport { Slider } from './slider.js';\nexport * from './slider.js';\ndefine('slider', Slider);\n","import { define } from '../../define.js';\nimport { Spinner } from './spinner.js';\nexport * from './spinner.js';\ndefine('spinner', Spinner);\n","import { define } from '../../define.js';\nimport { StickyBar } from './sticky-bar.js';\nexport * from './sticky-bar.js';\ndefine('sticky-bar', StickyBar);\n","import { define } from '../../define.js';\nimport { Tabs } from './tabs.js';\nexport * from './tabs.js';\ndefine('tabs', Tabs);\n","import { define } from '../../define.js';\nimport { Tag } from './tag.js';\nexport * from './tag.js';\ndefine('tag', Tag);\n","import { define } from '../../define.js';\nimport { Toast, ToastItem } from './toast.js';\nexport * from './toast.js';\ndefine('toast', Toast);\ndefine('toast-item', ToastItem);\n","import { define } from '../../define.js';\nimport { Tooltip } from './tooltip.js';\nexport * from './tooltip.js';\ndefine('tooltip', Tooltip);\n","import { define } from '../../define.js';\nimport { Tree } from './tree.js';\nexport * from './tree.js';\ndefine('tree', Tree);\n","import { define } from '../../define.js';\nimport { TreeItem } from './tree-item.js';\nexport * from './tree-item.js';\ndefine('tree-item', TreeItem);\n","/** Every component base name the library ships. */\nexport type ElementBaseName =\n | 'alert'\n | 'alert-dialog'\n | 'avatar'\n | 'badge'\n | 'button-group'\n | 'carousel'\n | 'carousel-item'\n | 'combobox'\n | 'dialog'\n | 'divider'\n | 'drawer'\n | 'dropdown'\n | 'dropdown-item'\n | 'dropdown-label'\n | 'form-field'\n | 'icon'\n | 'input-group'\n | 'input-otp'\n | 'input-stepper'\n | 'popover'\n | 'prose-editor'\n | 'skeleton'\n | 'slider'\n | 'spinner'\n | 'rating'\n | 'select'\n | 'sticky-bar'\n | 'stories'\n | 'story'\n | 'stories-viewer'\n | 'tabs'\n | 'tag'\n | 'toast'\n | 'toast-item'\n | 'tooltip'\n | 'tree'\n | 'tree-item';\n\nlet _elementPrefix = 'l';\nlet _cssPrefix = 'l';\nconst _registered = new Set<ElementBaseName>();\n\n/** Set the global prefix. Must be called before defining elements. */\nexport function setPrefix(prefix: { element: string; css: string }): void {\n _elementPrefix = prefix.element;\n _cssPrefix = prefix.css;\n}\n\n/** Get the current prefixes. */\nexport function getPrefix(): { element: string; css: string } {\n return { element: _elementPrefix, css: _cssPrefix };\n}\n\n/** Derive the full tag name from element prefix + base name. */\nexport function tagName(baseName: ElementBaseName): string {\n return `${_elementPrefix}-${baseName}`;\n}\n\n/** Prefix a CSS class name. `cls('toast-icon')` → `'l-toast-icon'` */\nexport function cls(name: string): string {\n return `${_cssPrefix}-${name}`;\n}\n\n/** Generate a globally unique prefixed ID. `uniqueId('toast')` → `'l:toast:1'` */\nlet _uid = 0;\nexport function uniqueId(base: string): string {\n return `${_cssPrefix}:${base}:${++_uid}`;\n}\n\n/** Check if a base name is already registered. */\nexport function isRegistered(baseName: ElementBaseName): boolean {\n return _registered.has(baseName);\n}\n\n/** Mark a base name as registered. Called internally by define(). */\nexport function markRegistered(baseName: ElementBaseName): void {\n _registered.add(baseName);\n}\n"],"mappings":";AAGA,UAAO,SAAS,KAAK;;;ACArB,UAAO,gBAAgB,WAAW;;;ACAlC,UAAO,UAAU,MAAM;;;ACAvB,UAAO,SAAS,KAAK;;;ACArB,UAAO,gBAAgB,WAAW;;;ACAlC,UAAO,YAAY,QAAQ;;;ACA3B,UAAO,iBAAiB,YAAY;;;ACApC,UAAO,YAAY,QAAQ;;;ACA3B,UAAO,UAAU,MAAM;;;ACAvB,UAAO,WAAW,OAAO;;;ACAzB,UAAO,UAAU,MAAM;;;ACAvB,UAAO,YAAY,QAAQ;;;ACA3B,UAAO,iBAAiB,YAAY;;;ACApC,UAAO,kBAAkB,aAAa;;;ACAtC,UAAO,cAAc,SAAS;;;ACA9B,UAAO,QAAQ,IAAI;;;ACAnB,UAAO,eAAe,UAAU;;;ACAhC,UAAO,aAAa,QAAQ;;;ACA5B,UAAO,iBAAiB,YAAY;;;ACApC,UAAO,WAAW,OAAO;;;ACAzB,UAAO,gBAAgB,WAAW;;;ACAlC,UAAO,UAAU,MAAM;;;ACAvB,UAAO,UAAU,MAAM;;;ACAvB,SAAO,YAAY,QAAQ;;;ACA3B,SAAO,UAAU,MAAM;;;ACAvB,SAAO,WAAW,OAAO;;;ACAzB,SAAO,cAAc,SAAS;;;ACA9B,SAAO,QAAQ,IAAI;;;ACAnB,SAAO,OAAO,GAAG;;;ACAjB,SAAO,SAAS,KAAK;AACrB,SAAO,cAAc,SAAS;;;ACD9B,SAAO,WAAW,OAAO;;;ACAzB,SAAO,QAAQ,IAAI;;;ACAnB,OAAO,aAAa,QAAQ;;;
|
|
1
|
+
{"version":3,"file":"standalone.js","names":[],"sources":["../src/html/elements/alert/index.ts","../src/html/elements/alert-dialog/index.ts","../src/html/elements/avatar/index.ts","../src/html/elements/badge/index.ts","../src/html/elements/button-group/index.ts","../src/html/elements/carousel/index.ts","../src/html/elements/carousel-item/index.ts","../src/html/elements/combobox/index.ts","../src/html/elements/dialog/index.ts","../src/html/elements/divider/index.ts","../src/html/elements/drawer/index.ts","../src/html/elements/dropdown/index.ts","../src/html/elements/dropdown-item/index.ts","../src/html/elements/dropdown-label/index.ts","../src/html/elements/form-field/index.ts","../src/html/elements/icon/index.ts","../src/html/elements/input-group/index.ts","../src/html/elements/input-otp/index.ts","../src/html/elements/input-stepper/index.ts","../src/html/elements/popover/index.ts","../src/html/elements/prose-editor/index.ts","../src/html/elements/rating/index.ts","../src/html/elements/segmented-control/index.ts","../src/html/elements/select/index.ts","../src/html/elements/skeleton/index.ts","../src/html/elements/slider/index.ts","../src/html/elements/spinner/index.ts","../src/html/elements/sticky-bar/index.ts","../src/html/elements/tabs/index.ts","../src/html/elements/tag/index.ts","../src/html/elements/toast/index.ts","../src/html/elements/tooltip/index.ts","../src/html/elements/tree/index.ts","../src/html/elements/tree-item/index.ts","../src/html/registry.ts"],"sourcesContent":["import { define } from '../../define.js';\nimport { Alert } from './alert.js';\nexport * from './alert.js';\ndefine('alert', Alert);\n","import { define } from '../../define.js';\nimport { AlertDialog } from './alert-dialog.js';\nexport * from './alert-dialog.js';\ndefine('alert-dialog', AlertDialog);\n","import { define } from '../../define.js';\nimport { Avatar } from './avatar.js';\nexport * from './avatar.js';\ndefine('avatar', Avatar);\n","import { define } from '../../define.js';\nimport { Badge } from './badge.js';\nexport * from './badge.js';\ndefine('badge', Badge);\n","import { define } from '../../define.js';\nimport { ButtonGroup } from './button-group.js';\nexport * from './button-group.js';\ndefine('button-group', ButtonGroup);\n","import { define } from '../../define.js';\nimport { Carousel } from './carousel.js';\nexport * from './carousel.js';\ndefine('carousel', Carousel);\n","import { define } from '../../define.js';\nimport { CarouselItem } from './carousel-item.js';\nexport * from './carousel-item.js';\ndefine('carousel-item', CarouselItem);\n","import { define } from '../../define.js';\nimport { Combobox } from './combobox.js';\nexport * from './combobox.js';\ndefine('combobox', Combobox);\n","import { define } from '../../define.js';\nimport { Dialog } from './dialog.js';\nexport * from './dialog.js';\ndefine('dialog', Dialog);\n","import { define } from '../../define.js';\nimport { Divider } from './divider.js';\nexport * from './divider.js';\ndefine('divider', Divider);\n","import { define } from '../../define.js';\nimport { Drawer } from './drawer.js';\nexport * from './drawer.js';\ndefine('drawer', Drawer);\n","import { define } from '../../define.js';\nimport { Dropdown } from './dropdown.js';\nexport * from './dropdown.js';\ndefine('dropdown', Dropdown);\n","import { define } from '../../define.js';\nimport { DropdownItem } from './dropdown-item.js';\nexport * from './dropdown-item.js';\ndefine('dropdown-item', DropdownItem);\n","import { define } from '../../define.js';\nimport { DropdownLabel } from './dropdown-label.js';\nexport * from './dropdown-label.js';\ndefine('dropdown-label', DropdownLabel);\n","import { define } from '../../define.js';\nimport { FormField } from './form-field.js';\nexport * from './form-field.js';\ndefine('form-field', FormField);\n","import { define } from '../../define.js';\nimport { Icon } from './icon.js';\nexport * from './icon.js';\ndefine('icon', Icon);\n","import { define } from '../../define.js';\nimport { InputGroup } from './input-group.js';\nexport * from './input-group.js';\ndefine('input-group', InputGroup);\n","import { define } from '../../define.js';\nimport { InputOtp } from './input-otp.js';\nexport * from './input-otp.js';\ndefine('input-otp', InputOtp);\n","import { define } from '../../define.js';\nimport { InputStepper } from './input-stepper.js';\nexport * from './input-stepper.js';\ndefine('input-stepper', InputStepper);\n","import { define } from '../../define.js';\nimport { Popover } from './popover.js';\nexport * from './popover.js';\ndefine('popover', Popover);\n","import { define } from '../../define.js';\nimport { ProseEditor } from './prose-editor.js';\nexport * from './prose-editor.js';\ndefine('prose-editor', ProseEditor);\n","import { define } from '../../define.js';\nimport { Rating } from './rating.js';\nexport * from './rating.js';\ndefine('rating', Rating);\n","import { define } from '../../define.js';\nimport { SegmentedControl } from './segmented-control.js';\nexport * from './segmented-control.js';\ndefine('segmented-control', SegmentedControl);\n","import { define } from '../../define.js';\nimport { Select } from './select.js';\nexport * from './select.js';\ndefine('select', Select);\n","import { define } from '../../define.js';\nimport { Skeleton } from './skeleton.js';\nexport * from './skeleton.js';\ndefine('skeleton', Skeleton);\n","import { define } from '../../define.js';\nimport { Slider } from './slider.js';\nexport * from './slider.js';\ndefine('slider', Slider);\n","import { define } from '../../define.js';\nimport { Spinner } from './spinner.js';\nexport * from './spinner.js';\ndefine('spinner', Spinner);\n","import { define } from '../../define.js';\nimport { StickyBar } from './sticky-bar.js';\nexport * from './sticky-bar.js';\ndefine('sticky-bar', StickyBar);\n","import { define } from '../../define.js';\nimport { Tabs } from './tabs.js';\nexport * from './tabs.js';\ndefine('tabs', Tabs);\n","import { define } from '../../define.js';\nimport { Tag } from './tag.js';\nexport * from './tag.js';\ndefine('tag', Tag);\n","import { define } from '../../define.js';\nimport { Toast, ToastItem } from './toast.js';\nexport * from './toast.js';\ndefine('toast', Toast);\ndefine('toast-item', ToastItem);\n","import { define } from '../../define.js';\nimport { Tooltip } from './tooltip.js';\nexport * from './tooltip.js';\ndefine('tooltip', Tooltip);\n","import { define } from '../../define.js';\nimport { Tree } from './tree.js';\nexport * from './tree.js';\ndefine('tree', Tree);\n","import { define } from '../../define.js';\nimport { TreeItem } from './tree-item.js';\nexport * from './tree-item.js';\ndefine('tree-item', TreeItem);\n","/** Every component base name the library ships. */\nexport type ElementBaseName =\n | 'alert'\n | 'alert-dialog'\n | 'avatar'\n | 'badge'\n | 'button-group'\n | 'carousel'\n | 'carousel-item'\n | 'combobox'\n | 'dialog'\n | 'divider'\n | 'drawer'\n | 'dropdown'\n | 'dropdown-item'\n | 'dropdown-label'\n | 'form-field'\n | 'icon'\n | 'input-group'\n | 'input-otp'\n | 'input-stepper'\n | 'popover'\n | 'prose-editor'\n | 'skeleton'\n | 'slider'\n | 'spinner'\n | 'rating'\n | 'segmented-control'\n | 'select'\n | 'sticky-bar'\n | 'stories'\n | 'story'\n | 'stories-viewer'\n | 'tabs'\n | 'tag'\n | 'toast'\n | 'toast-item'\n | 'tooltip'\n | 'tree'\n | 'tree-item';\n\nlet _elementPrefix = 'l';\nlet _cssPrefix = 'l';\nconst _registered = new Set<ElementBaseName>();\n\n/** Set the global prefix. Must be called before defining elements. */\nexport function setPrefix(prefix: { element: string; css: string }): void {\n _elementPrefix = prefix.element;\n _cssPrefix = prefix.css;\n}\n\n/** Get the current prefixes. */\nexport function getPrefix(): { element: string; css: string } {\n return { element: _elementPrefix, css: _cssPrefix };\n}\n\n/** Derive the full tag name from element prefix + base name. */\nexport function tagName(baseName: ElementBaseName): string {\n return `${_elementPrefix}-${baseName}`;\n}\n\n/** Prefix a CSS class name. `cls('toast-icon')` → `'l-toast-icon'` */\nexport function cls(name: string): string {\n return `${_cssPrefix}-${name}`;\n}\n\n/** Generate a globally unique prefixed ID. `uniqueId('toast')` → `'l:toast:1'` */\nlet _uid = 0;\nexport function uniqueId(base: string): string {\n return `${_cssPrefix}:${base}:${++_uid}`;\n}\n\n/** Check if a base name is already registered. */\nexport function isRegistered(baseName: ElementBaseName): boolean {\n return _registered.has(baseName);\n}\n\n/** Mark a base name as registered. Called internally by define(). */\nexport function markRegistered(baseName: ElementBaseName): void {\n _registered.add(baseName);\n}\n"],"mappings":";AAGA,UAAO,SAAS,KAAK;;;ACArB,UAAO,gBAAgB,WAAW;;;ACAlC,UAAO,UAAU,MAAM;;;ACAvB,UAAO,SAAS,KAAK;;;ACArB,UAAO,gBAAgB,WAAW;;;ACAlC,UAAO,YAAY,QAAQ;;;ACA3B,UAAO,iBAAiB,YAAY;;;ACApC,UAAO,YAAY,QAAQ;;;ACA3B,UAAO,UAAU,MAAM;;;ACAvB,UAAO,WAAW,OAAO;;;ACAzB,UAAO,UAAU,MAAM;;;ACAvB,UAAO,YAAY,QAAQ;;;ACA3B,UAAO,iBAAiB,YAAY;;;ACApC,UAAO,kBAAkB,aAAa;;;ACAtC,UAAO,cAAc,SAAS;;;ACA9B,UAAO,QAAQ,IAAI;;;ACAnB,UAAO,eAAe,UAAU;;;ACAhC,UAAO,aAAa,QAAQ;;;ACA5B,UAAO,iBAAiB,YAAY;;;ACApC,UAAO,WAAW,OAAO;;;ACAzB,UAAO,gBAAgB,WAAW;;;ACAlC,UAAO,UAAU,MAAM;;;ACAvB,UAAO,qBAAqB,gBAAgB;;;ACA5C,UAAO,UAAU,MAAM;;;ACAvB,SAAO,YAAY,QAAQ;;;ACA3B,SAAO,UAAU,MAAM;;;ACAvB,SAAO,WAAW,OAAO;;;ACAzB,SAAO,cAAc,SAAS;;;ACA9B,SAAO,QAAQ,IAAI;;;ACAnB,SAAO,OAAO,GAAG;;;ACAjB,SAAO,SAAS,KAAK;AACrB,SAAO,cAAc,SAAS;;;ACD9B,SAAO,WAAW,OAAO;;;ACAzB,SAAO,QAAQ,IAAI;;;ACAnB,OAAO,aAAa,QAAQ;;;ACsC5B,IAAI,iBAAiB;AACrB,IAAI,aAAa;;AAIjB,SAAgB,UAAU,QAAgD;CACxE,iBAAiB,OAAO;CACxB,aAAa,OAAO;AACtB;;AAGA,SAAgB,YAA8C;CAC5D,OAAO;EAAE,SAAS;EAAgB,KAAK;CAAW;AACpD"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
/*
|
|
3
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4
|
+
Segmented control
|
|
5
|
+
A single-select switch: a muted track with a sliding pill behind the
|
|
6
|
+
selected segment. Shares its visual language with l-tabs[variant='enclosed']
|
|
7
|
+
(same neutral-subtle track + surface pill), but carries radio-group
|
|
8
|
+
semantics instead of tabs.
|
|
9
|
+
|
|
10
|
+
Structural selectors (not [role='…']) so the control is styled from plain
|
|
11
|
+
light DOM — it is progressive, so it must look right before JS adds ARIA.
|
|
12
|
+
The host is the flex track; its `<button>` children are the segments. JS
|
|
13
|
+
only enhances (roles, keyboard, and the sliding pill offsets).
|
|
14
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
l-segmented-control {
|
|
18
|
+
--_height: var(--l-size-control-md);
|
|
19
|
+
--_pad: 0.1875rem;
|
|
20
|
+
--_duration: 150ms;
|
|
21
|
+
--_easing: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
22
|
+
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
position: relative;
|
|
25
|
+
align-items: stretch;
|
|
26
|
+
height: var(--_height);
|
|
27
|
+
padding: var(--_pad);
|
|
28
|
+
gap: calc(var(--spacing) * 0.5);
|
|
29
|
+
background: var(--l-color-bg-fill-neutral-subtle);
|
|
30
|
+
border-radius: var(--border-radius, var(--l-radius-lg));
|
|
31
|
+
/* Match the form-control border (--l-color-border, as used by .l-button,
|
|
32
|
+
l-select, and l-input) so the track lines up with dropdowns in a toolbar
|
|
33
|
+
— not the lighter --l-color-divider that enclosed tabs use. */
|
|
34
|
+
box-shadow: inset 0 0 0 1px var(--l-color-border);
|
|
35
|
+
|
|
36
|
+
/* Sliding pill behind the selected segment. Positioned by JS via
|
|
37
|
+
--_indicator-left / --_indicator-width (button offsetLeft / offsetWidth);
|
|
38
|
+
width 0 until JS runs, so it stays invisible in the no-JS fallback. */
|
|
39
|
+
&::before {
|
|
40
|
+
content: '';
|
|
41
|
+
position: absolute;
|
|
42
|
+
top: var(--_pad);
|
|
43
|
+
bottom: var(--_pad);
|
|
44
|
+
left: 0;
|
|
45
|
+
width: var(--_indicator-width, 0);
|
|
46
|
+
transform: translateX(var(--_indicator-left, 0));
|
|
47
|
+
background: var(--indicator-color, var(--l-color-surface));
|
|
48
|
+
border-radius: var(--l-radius-md);
|
|
49
|
+
box-shadow:
|
|
50
|
+
0 1px 3px 0 rgb(0 0 0 / 0.08),
|
|
51
|
+
0 1px 2px -1px rgb(0 0 0 / 0.08);
|
|
52
|
+
pointer-events: none;
|
|
53
|
+
will-change: transform, width;
|
|
54
|
+
transition:
|
|
55
|
+
transform var(--_duration) var(--_easing),
|
|
56
|
+
width var(--_duration) var(--_easing);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
62
|
+
Sizes — align with .l-button and form controls at the same size.
|
|
63
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
l-segmented-control[size='sm'] {
|
|
67
|
+
--_height: var(--l-size-control-sm);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
l-segmented-control[size='lg'] {
|
|
71
|
+
--_height: var(--l-size-control-lg);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
l-segmented-control[size='xl'] {
|
|
75
|
+
--_height: var(--l-size-control-xl);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Whole-control disabled (host `disabled` attribute, form-associated). */
|
|
79
|
+
l-segmented-control[disabled] {
|
|
80
|
+
opacity: 0.5;
|
|
81
|
+
pointer-events: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
86
|
+
Segments
|
|
87
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
l-segmented-control button {
|
|
91
|
+
position: relative;
|
|
92
|
+
z-index: 1;
|
|
93
|
+
display: inline-flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
gap: calc(var(--spacing) * 1.5);
|
|
97
|
+
padding-inline: calc(var(--spacing) * 3);
|
|
98
|
+
margin: 0;
|
|
99
|
+
appearance: none;
|
|
100
|
+
border: none;
|
|
101
|
+
background: none;
|
|
102
|
+
border-radius: var(--l-radius-md);
|
|
103
|
+
color: var(--l-color-text-secondary);
|
|
104
|
+
font-family: inherit;
|
|
105
|
+
font-size: var(--l-text-sm);
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
line-height: 1;
|
|
108
|
+
white-space: nowrap;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
-webkit-tap-highlight-color: transparent;
|
|
111
|
+
transition: color 150ms;
|
|
112
|
+
|
|
113
|
+
/* Icon-only segments (JS-detected, no visible text): square them. */
|
|
114
|
+
&[data-icon-only] {
|
|
115
|
+
padding-inline: 0;
|
|
116
|
+
width: calc(var(--_height) - 2 * var(--_pad));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&[aria-checked='true'] {
|
|
120
|
+
color: var(--l-color-text-primary);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@media (hover: hover) {
|
|
124
|
+
&:hover:not([aria-checked='true']):not(:disabled):not([aria-disabled='true']) {
|
|
125
|
+
color: var(--l-color-text-primary);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
&:disabled,
|
|
130
|
+
&[aria-disabled='true'] {
|
|
131
|
+
cursor: not-allowed;
|
|
132
|
+
opacity: 0.4;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&:focus-visible {
|
|
136
|
+
outline: 2px solid var(--l-focus-ring);
|
|
137
|
+
outline-offset: -2px;
|
|
138
|
+
border-radius: var(--l-radius-sm);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
144
|
+
Full width
|
|
145
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
146
|
+
*/
|
|
147
|
+
|
|
148
|
+
l-segmented-control[full-width] {
|
|
149
|
+
display: flex;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
l-segmented-control[full-width] button {
|
|
153
|
+
flex: 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@media (prefers-reduced-motion: reduce) {
|
|
157
|
+
l-segmented-control::before {
|
|
158
|
+
transition-duration: 0ms;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
l-segmented-control button {
|
|
162
|
+
transition-duration: 0ms;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
/*
|
|
3
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
4
|
+
Segmented control
|
|
5
|
+
A single-select switch: a muted track with a sliding pill behind the
|
|
6
|
+
selected segment. Shares its visual language with l-tabs[variant='enclosed']
|
|
7
|
+
(same neutral-subtle track + surface pill), but carries radio-group
|
|
8
|
+
semantics instead of tabs.
|
|
9
|
+
|
|
10
|
+
Structural selectors (not [role='…']) so the control is styled from plain
|
|
11
|
+
light DOM — it is progressive, so it must look right before JS adds ARIA.
|
|
12
|
+
The host is the flex track; its `<button>` children are the segments. JS
|
|
13
|
+
only enhances (roles, keyboard, and the sliding pill offsets).
|
|
14
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
l-segmented-control {
|
|
18
|
+
--_height: var(--l-size-control-md);
|
|
19
|
+
--_pad: 0.1875rem;
|
|
20
|
+
--_duration: 150ms;
|
|
21
|
+
--_easing: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
22
|
+
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
position: relative;
|
|
25
|
+
align-items: stretch;
|
|
26
|
+
height: var(--_height);
|
|
27
|
+
padding: var(--_pad);
|
|
28
|
+
gap: calc(var(--spacing) * 0.5);
|
|
29
|
+
background: var(--l-color-bg-fill-neutral-subtle);
|
|
30
|
+
border-radius: var(--border-radius, var(--l-radius-lg));
|
|
31
|
+
/* Match the form-control border (--l-color-border, as used by .l-button,
|
|
32
|
+
l-select, and l-input) so the track lines up with dropdowns in a toolbar
|
|
33
|
+
— not the lighter --l-color-divider that enclosed tabs use. */
|
|
34
|
+
box-shadow: inset 0 0 0 1px var(--l-color-border);
|
|
35
|
+
|
|
36
|
+
/* Sliding pill behind the selected segment. Positioned by JS via
|
|
37
|
+
--_indicator-left / --_indicator-width (button offsetLeft / offsetWidth);
|
|
38
|
+
width 0 until JS runs, so it stays invisible in the no-JS fallback. */
|
|
39
|
+
&::before {
|
|
40
|
+
content: '';
|
|
41
|
+
position: absolute;
|
|
42
|
+
top: var(--_pad);
|
|
43
|
+
bottom: var(--_pad);
|
|
44
|
+
left: 0;
|
|
45
|
+
width: var(--_indicator-width, 0);
|
|
46
|
+
transform: translateX(var(--_indicator-left, 0));
|
|
47
|
+
background: var(--indicator-color, var(--l-color-surface));
|
|
48
|
+
border-radius: var(--l-radius-md);
|
|
49
|
+
box-shadow:
|
|
50
|
+
0 1px 3px 0 rgb(0 0 0 / 0.08),
|
|
51
|
+
0 1px 2px -1px rgb(0 0 0 / 0.08);
|
|
52
|
+
pointer-events: none;
|
|
53
|
+
will-change: transform, width;
|
|
54
|
+
transition:
|
|
55
|
+
transform var(--_duration) var(--_easing),
|
|
56
|
+
width var(--_duration) var(--_easing);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
62
|
+
Sizes — align with .l-button and form controls at the same size.
|
|
63
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
l-segmented-control[size='sm'] {
|
|
67
|
+
--_height: var(--l-size-control-sm);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
l-segmented-control[size='lg'] {
|
|
71
|
+
--_height: var(--l-size-control-lg);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
l-segmented-control[size='xl'] {
|
|
75
|
+
--_height: var(--l-size-control-xl);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Whole-control disabled (host `disabled` attribute, form-associated). */
|
|
79
|
+
l-segmented-control[disabled] {
|
|
80
|
+
opacity: 0.5;
|
|
81
|
+
pointer-events: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
86
|
+
Segments
|
|
87
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
l-segmented-control button {
|
|
91
|
+
position: relative;
|
|
92
|
+
z-index: 1;
|
|
93
|
+
display: inline-flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
gap: calc(var(--spacing) * 1.5);
|
|
97
|
+
padding-inline: calc(var(--spacing) * 3);
|
|
98
|
+
margin: 0;
|
|
99
|
+
appearance: none;
|
|
100
|
+
border: none;
|
|
101
|
+
background: none;
|
|
102
|
+
border-radius: var(--l-radius-md);
|
|
103
|
+
color: var(--l-color-text-secondary);
|
|
104
|
+
font-family: inherit;
|
|
105
|
+
font-size: var(--l-text-sm);
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
line-height: 1;
|
|
108
|
+
white-space: nowrap;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
-webkit-tap-highlight-color: transparent;
|
|
111
|
+
transition: color 150ms;
|
|
112
|
+
|
|
113
|
+
/* Icon-only segments (JS-detected, no visible text): square them. */
|
|
114
|
+
&[data-icon-only] {
|
|
115
|
+
padding-inline: 0;
|
|
116
|
+
width: calc(var(--_height) - 2 * var(--_pad));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&[aria-checked='true'] {
|
|
120
|
+
color: var(--l-color-text-primary);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@media (hover: hover) {
|
|
124
|
+
&:hover:not([aria-checked='true']):not(:disabled):not([aria-disabled='true']) {
|
|
125
|
+
color: var(--l-color-text-primary);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
&:disabled,
|
|
130
|
+
&[aria-disabled='true'] {
|
|
131
|
+
cursor: not-allowed;
|
|
132
|
+
opacity: 0.4;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&:focus-visible {
|
|
136
|
+
outline: 2px solid var(--l-focus-ring);
|
|
137
|
+
outline-offset: -2px;
|
|
138
|
+
border-radius: var(--l-radius-sm);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
144
|
+
Full width
|
|
145
|
+
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
|
|
146
|
+
*/
|
|
147
|
+
|
|
148
|
+
l-segmented-control[full-width] {
|
|
149
|
+
display: flex;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
l-segmented-control[full-width] button {
|
|
153
|
+
flex: 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@media (prefers-reduced-motion: reduce) {
|
|
157
|
+
l-segmented-control::before {
|
|
158
|
+
transition-duration: 0ms;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
l-segmented-control button {
|
|
162
|
+
transition-duration: 0ms;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|