@inglorious/ui 9.0.0 → 9.1.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/package.json +2 -2
- package/src/controls/button/button.stories.js +7 -1
- package/src/controls/button/style.css +11 -0
- package/src/controls/checkbox/checkbox.stories.js +12 -0
- package/src/controls/checkbox/style.css +11 -0
- package/src/controls/checkbox/template.js +9 -1
- package/src/controls/radio-group/radio-group.stories.js +21 -1
- package/src/controls/radio-group/style.css +11 -0
- package/src/controls/radio-group/template.js +11 -1
- package/src/controls/rating/rating.stories.js +8 -0
- package/src/controls/slider/slider.stories.js +28 -1
- package/src/controls/slider/style.css +102 -0
- package/src/controls/slider/template.js +114 -15
- package/src/controls/switch/style.css +11 -0
- package/src/controls/switch/switch.stories.js +10 -0
- package/src/controls/switch/template.js +11 -1
- package/src/data-display/chip/chip.stories.js +17 -0
- package/src/data-display/chip/style.css +5 -0
- package/src/data-display/chip/template.js +3 -1
- package/src/data-display/divider/divider.stories.js +9 -0
- package/src/data-display/divider/template.js +12 -4
- package/src/feedback/alert/alert.stories.js +9 -1
- package/src/feedback/alert/style.css +5 -0
- package/src/feedback/alert/template.js +2 -1
- package/src/feedback/dialog/dialog.stories.js +22 -0
- package/src/feedback/dialog/style.css +15 -2
- package/src/feedback/dialog/template.js +6 -1
- package/src/feedback/progress/progress.stories.js +5 -0
- package/src/layout/flex/flex.stories.js +1 -1
- package/src/layout/flex/style.css +8 -0
- package/src/surfaces/accordion/accordion.stories.js +9 -0
- package/src/surfaces/accordion/template.js +5 -1
- package/src/surfaces/card/card.stories.js +24 -0
- package/src/surfaces/card/style.css +15 -0
- package/src/surfaces/card/template.js +2 -0
- package/types/controls/button.d.ts +1 -1
- package/types/controls/checkbox.d.ts +2 -0
- package/types/controls/radio-group.d.ts +2 -0
- package/types/controls/slider.d.ts +6 -2
- package/types/controls/switch.d.ts +2 -0
- package/types/data-display/chip.d.ts +2 -0
- package/types/data-display/divider.d.ts +2 -0
- package/types/feedback/alert.d.ts +1 -1
- package/types/feedback/dialog.d.ts +2 -0
- package/types/layout/flex.d.ts +1 -1
- package/types/surfaces/card.d.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/ui",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "A design system for Inglorious Web with render-function components and customizable themes",
|
|
5
5
|
"author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -315,7 +315,7 @@
|
|
|
315
315
|
"@iconify-icons/fa7-regular": "^2.0.0",
|
|
316
316
|
"@iconify-icons/fa7-solid": "^2.0.0",
|
|
317
317
|
"@iconify-icons/material-symbols": "^2.0.6",
|
|
318
|
-
"@inglorious/charts": "
|
|
318
|
+
"@inglorious/charts": "12.0.0",
|
|
319
319
|
"@inglorious/eslint-config": "1.2.0",
|
|
320
320
|
"@inglorious/store": "12.0.0",
|
|
321
321
|
"@inglorious/vite-plugin-jsx": "2.0.5",
|
|
@@ -32,7 +32,7 @@ export default {
|
|
|
32
32
|
},
|
|
33
33
|
size: {
|
|
34
34
|
control: "select",
|
|
35
|
-
options: ["sm", "md", "lg"],
|
|
35
|
+
options: ["xs", "sm", "md", "lg"],
|
|
36
36
|
description: "Size scale for paddings and font-size.",
|
|
37
37
|
},
|
|
38
38
|
shape: {
|
|
@@ -106,6 +106,12 @@ Ghost.args = {
|
|
|
106
106
|
variant: "ghost",
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
export const ExtraSmall = {}
|
|
110
|
+
ExtraSmall.args = {
|
|
111
|
+
...Default.args,
|
|
112
|
+
size: "xs",
|
|
113
|
+
}
|
|
114
|
+
|
|
109
115
|
export const Small = {}
|
|
110
116
|
Small.args = {
|
|
111
117
|
...Default.args,
|
|
@@ -153,6 +153,11 @@
|
|
|
153
153
|
cursor: not-allowed;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
&.iw-button-xs {
|
|
157
|
+
padding: var(--iw-space-0) var(--iw-space-2);
|
|
158
|
+
font-size: var(--iw-font-size-xs);
|
|
159
|
+
}
|
|
160
|
+
|
|
156
161
|
&.iw-button-sm {
|
|
157
162
|
padding: var(--iw-space-1) var(--iw-space-3);
|
|
158
163
|
font-size: var(--iw-font-size-sm);
|
|
@@ -179,6 +184,12 @@
|
|
|
179
184
|
border-radius: var(--iw-radius-sm);
|
|
180
185
|
}
|
|
181
186
|
|
|
187
|
+
&.iw-button-xs.iw-button-shape-round,
|
|
188
|
+
&.iw-button-xs.iw-button-shape-square {
|
|
189
|
+
width: 1.5rem;
|
|
190
|
+
height: 1.5rem;
|
|
191
|
+
}
|
|
192
|
+
|
|
182
193
|
&.iw-button-sm.iw-button-shape-round,
|
|
183
194
|
&.iw-button-sm.iw-button-shape-square {
|
|
184
195
|
width: 2rem;
|
|
@@ -7,6 +7,10 @@ export default {
|
|
|
7
7
|
render: createRender(Checkbox),
|
|
8
8
|
argTypes: {
|
|
9
9
|
label: { control: "text", description: "Label text." },
|
|
10
|
+
description: {
|
|
11
|
+
control: "text",
|
|
12
|
+
description: "A line of detail under the label.",
|
|
13
|
+
},
|
|
10
14
|
name: { control: "text", description: "Native HTML name attribute." },
|
|
11
15
|
isChecked: { control: "boolean", description: "Current checked state." },
|
|
12
16
|
isDisabled: { control: "boolean", description: "Disables interaction." },
|
|
@@ -48,3 +52,11 @@ Checked.args = {
|
|
|
48
52
|
...Default.args,
|
|
49
53
|
isChecked: true,
|
|
50
54
|
}
|
|
55
|
+
|
|
56
|
+
export const WithDescription = {}
|
|
57
|
+
WithDescription.args = {
|
|
58
|
+
...Default.args,
|
|
59
|
+
label: "Weekly summary",
|
|
60
|
+
name: "summary",
|
|
61
|
+
description: "An email every Monday with last week's totals.",
|
|
62
|
+
}
|
|
@@ -14,6 +14,17 @@
|
|
|
14
14
|
accent-color: var(--iw-checkbox-accent);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/* With a description, the label and it stack beside the box. */
|
|
18
|
+
.iw-checkbox-text {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.iw-checkbox-description {
|
|
24
|
+
font-size: var(--iw-font-size-sm);
|
|
25
|
+
color: var(--iw-color-text-secondary);
|
|
26
|
+
}
|
|
27
|
+
|
|
17
28
|
.iw-checkbox-label {
|
|
18
29
|
font-size: var(--iw-font-size-base);
|
|
19
30
|
line-height: var(--iw-line-height-normal);
|
|
@@ -21,6 +21,7 @@ export function render(props) {
|
|
|
21
21
|
type, // eslint-disable-line no-unused-vars
|
|
22
22
|
name = "",
|
|
23
23
|
label = "",
|
|
24
|
+
description,
|
|
24
25
|
isChecked = false,
|
|
25
26
|
isDisabled = false,
|
|
26
27
|
isRequired = false,
|
|
@@ -54,7 +55,14 @@ export function render(props) {
|
|
|
54
55
|
@change=${(event) => onChange?.(event.target.checked)}
|
|
55
56
|
${ref((element) => applyElementProps(element, rest))}
|
|
56
57
|
/>
|
|
57
|
-
|
|
58
|
+
${
|
|
59
|
+
description
|
|
60
|
+
? html`<span class="iw-checkbox-text">
|
|
61
|
+
<span class="iw-checkbox-label">${label}</span>
|
|
62
|
+
<span class="iw-checkbox-description">${description}</span>
|
|
63
|
+
</span>`
|
|
64
|
+
: html`<span class="iw-checkbox-label">${label}</span>`
|
|
65
|
+
}
|
|
58
66
|
</label>
|
|
59
67
|
`
|
|
60
68
|
}
|
|
@@ -20,7 +20,11 @@ export default {
|
|
|
20
20
|
description: "Semantic accent color.",
|
|
21
21
|
},
|
|
22
22
|
isDisabled: { control: "boolean", description: "Disables all options." },
|
|
23
|
-
options: {
|
|
23
|
+
options: {
|
|
24
|
+
control: "object",
|
|
25
|
+
description:
|
|
26
|
+
"List of radio options: `label`, `value`, and an optional `description` under the label.",
|
|
27
|
+
},
|
|
24
28
|
onChange: { action: "onChange" },
|
|
25
29
|
},
|
|
26
30
|
parameters: {
|
|
@@ -52,3 +56,19 @@ Row.args = {
|
|
|
52
56
|
...Default.args,
|
|
53
57
|
direction: "row",
|
|
54
58
|
}
|
|
59
|
+
|
|
60
|
+
export const WithDescriptions = {}
|
|
61
|
+
WithDescriptions.args = {
|
|
62
|
+
...Default.args,
|
|
63
|
+
label: "Shipping",
|
|
64
|
+
name: "shipping",
|
|
65
|
+
value: "standard",
|
|
66
|
+
options: [
|
|
67
|
+
{
|
|
68
|
+
label: "Standard",
|
|
69
|
+
value: "standard",
|
|
70
|
+
description: "3 to 5 working days, free",
|
|
71
|
+
},
|
|
72
|
+
{ label: "Express", value: "express", description: "Next day, €9" },
|
|
73
|
+
],
|
|
74
|
+
}
|
|
@@ -19,6 +19,17 @@
|
|
|
19
19
|
cursor: pointer;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/* With a description, the label and it stack beside the circle. */
|
|
23
|
+
.iw-radio-text {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.iw-radio-description {
|
|
29
|
+
font-size: var(--iw-font-size-sm);
|
|
30
|
+
color: var(--iw-color-text-secondary);
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
.iw-radio {
|
|
23
34
|
margin: 0;
|
|
24
35
|
accent-color: var(--iw-radio-accent);
|
|
@@ -55,6 +55,7 @@ export function render(props) {
|
|
|
55
55
|
${options.map((option, index) => {
|
|
56
56
|
const {
|
|
57
57
|
label: optionLabel,
|
|
58
|
+
description: optionDescription,
|
|
58
59
|
value: optionValue,
|
|
59
60
|
isDisabled: optionDisabled = false,
|
|
60
61
|
...optionRest
|
|
@@ -73,7 +74,16 @@ export function render(props) {
|
|
|
73
74
|
@change=${(event) => onChange?.(event.target.value)}
|
|
74
75
|
${ref((element) => applyElementProps(element, optionRest))}
|
|
75
76
|
/>
|
|
76
|
-
|
|
77
|
+
${
|
|
78
|
+
optionDescription
|
|
79
|
+
? html`<span class="iw-radio-text">
|
|
80
|
+
<span>${optionLabel}</span>
|
|
81
|
+
<span class="iw-radio-description"
|
|
82
|
+
>${optionDescription}</span
|
|
83
|
+
>
|
|
84
|
+
</span>`
|
|
85
|
+
: html`<span>${optionLabel}</span>`
|
|
86
|
+
}
|
|
77
87
|
</label>
|
|
78
88
|
`
|
|
79
89
|
})}
|
|
@@ -8,6 +8,14 @@ export default {
|
|
|
8
8
|
argTypes: {
|
|
9
9
|
value: { control: "number", description: "Current rating value." },
|
|
10
10
|
max: { control: "number", description: "Maximum rating value." },
|
|
11
|
+
name: {
|
|
12
|
+
control: "text",
|
|
13
|
+
description: "Groups the radios and names the value in a form.",
|
|
14
|
+
},
|
|
15
|
+
ariaLabel: {
|
|
16
|
+
control: "text",
|
|
17
|
+
description: 'Names the group for assistive tech. Defaults to "Rating".',
|
|
18
|
+
},
|
|
11
19
|
isDisabled: { control: "boolean", description: "Disables interaction." },
|
|
12
20
|
isReadOnly: {
|
|
13
21
|
control: "boolean",
|
|
@@ -8,7 +8,11 @@ export default {
|
|
|
8
8
|
argTypes: {
|
|
9
9
|
label: { control: "text", description: "Field label." },
|
|
10
10
|
name: { control: "text", description: "Native input name." },
|
|
11
|
-
value: {
|
|
11
|
+
value: {
|
|
12
|
+
control: "object",
|
|
13
|
+
description:
|
|
14
|
+
"One number, or `[low, high]` for a range with a thumb at each end.",
|
|
15
|
+
},
|
|
12
16
|
min: { control: "number", description: "Minimum value." },
|
|
13
17
|
max: { control: "number", description: "Maximum value." },
|
|
14
18
|
step: { control: "number", description: "Step value." },
|
|
@@ -20,6 +24,10 @@ export default {
|
|
|
20
24
|
isDisabled: { control: "boolean", description: "Disables interaction." },
|
|
21
25
|
isValueVisible: { control: "boolean", description: "Shows current value." },
|
|
22
26
|
isFullWidth: { control: "boolean", description: "Expands width to 100%." },
|
|
27
|
+
hasMarks: {
|
|
28
|
+
control: "boolean",
|
|
29
|
+
description: "Draws a tick at every step.",
|
|
30
|
+
},
|
|
23
31
|
onChange: { action: "onChange" },
|
|
24
32
|
},
|
|
25
33
|
parameters: {
|
|
@@ -44,3 +52,22 @@ Default.args = {
|
|
|
44
52
|
isValueVisible: true,
|
|
45
53
|
isFullWidth: false,
|
|
46
54
|
}
|
|
55
|
+
|
|
56
|
+
export const Range = {}
|
|
57
|
+
Range.args = {
|
|
58
|
+
...Default.args,
|
|
59
|
+
label: "Price",
|
|
60
|
+
name: "price",
|
|
61
|
+
value: [20, 80],
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const Marks = {}
|
|
65
|
+
Marks.args = {
|
|
66
|
+
...Default.args,
|
|
67
|
+
label: "Rating",
|
|
68
|
+
name: "rating",
|
|
69
|
+
value: 3,
|
|
70
|
+
min: 1,
|
|
71
|
+
max: 5,
|
|
72
|
+
hasMarks: true,
|
|
73
|
+
}
|
|
@@ -23,6 +23,108 @@
|
|
|
23
23
|
accent-color: var(--iw-slider-accent);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/* A tick per step, under the track: their ends sit under the thumb's ends
|
|
27
|
+
of travel, half a thumb in from the track's. */
|
|
28
|
+
.iw-slider-marks {
|
|
29
|
+
display: flex;
|
|
30
|
+
justify-content: space-between;
|
|
31
|
+
padding-inline: calc(var(--iw-slider-thumb, 1rem) / 2);
|
|
32
|
+
|
|
33
|
+
span {
|
|
34
|
+
inline-size: 1px;
|
|
35
|
+
block-size: var(--iw-space-2);
|
|
36
|
+
background: var(--iw-color-border);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Two thumbs on one track. The inputs lie on top of each other with their
|
|
41
|
+
own tracks hidden, and only their thumbs take presses, so either can be
|
|
42
|
+
dragged; the track below is drawn here, filled between the two. */
|
|
43
|
+
&.iw-slider-range {
|
|
44
|
+
--iw-slider-thumb: 1rem;
|
|
45
|
+
|
|
46
|
+
.iw-slider-track {
|
|
47
|
+
position: relative;
|
|
48
|
+
block-size: var(--iw-slider-thumb);
|
|
49
|
+
|
|
50
|
+
&::before,
|
|
51
|
+
&::after {
|
|
52
|
+
content: "";
|
|
53
|
+
position: absolute;
|
|
54
|
+
inset-block-start: 50%;
|
|
55
|
+
block-size: 0.25rem;
|
|
56
|
+
translate: 0 -50%;
|
|
57
|
+
border-radius: var(--iw-radius-full, 999px);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&::before {
|
|
61
|
+
inset-inline: 0;
|
|
62
|
+
background: color-mix(
|
|
63
|
+
in srgb,
|
|
64
|
+
var(--iw-slider-accent) 25%,
|
|
65
|
+
transparent
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&::after {
|
|
70
|
+
inset-inline-start: var(--iw-slider-low);
|
|
71
|
+
inset-inline-end: calc(100% - var(--iw-slider-high));
|
|
72
|
+
background: var(--iw-slider-accent);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.iw-slider-input {
|
|
77
|
+
position: absolute;
|
|
78
|
+
inset: 0;
|
|
79
|
+
z-index: 1;
|
|
80
|
+
margin: 0;
|
|
81
|
+
appearance: none;
|
|
82
|
+
background: transparent;
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
|
|
85
|
+
&::-webkit-slider-runnable-track {
|
|
86
|
+
background: transparent;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
&::-moz-range-track {
|
|
90
|
+
background: transparent;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&::-webkit-slider-thumb {
|
|
94
|
+
appearance: none;
|
|
95
|
+
inline-size: var(--iw-slider-thumb);
|
|
96
|
+
block-size: var(--iw-slider-thumb);
|
|
97
|
+
border: 2px solid var(--iw-color-surface);
|
|
98
|
+
border-radius: 50%;
|
|
99
|
+
background: var(--iw-slider-accent);
|
|
100
|
+
box-shadow: var(--iw-shadow-sm);
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
pointer-events: auto;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&::-moz-range-thumb {
|
|
106
|
+
inline-size: var(--iw-slider-thumb);
|
|
107
|
+
block-size: var(--iw-slider-thumb);
|
|
108
|
+
border: 2px solid var(--iw-color-surface);
|
|
109
|
+
border-radius: 50%;
|
|
110
|
+
background: var(--iw-slider-accent);
|
|
111
|
+
box-shadow: var(--iw-shadow-sm);
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
pointer-events: auto;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&:focus-visible::-webkit-slider-thumb {
|
|
117
|
+
outline: 2px solid var(--iw-slider-accent);
|
|
118
|
+
outline-offset: 2px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
&:focus-visible::-moz-range-thumb {
|
|
122
|
+
outline: 2px solid var(--iw-slider-accent);
|
|
123
|
+
outline-offset: 2px;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
26
128
|
&.iw-slider-full-width {
|
|
27
129
|
width: 100%;
|
|
28
130
|
}
|
|
@@ -14,10 +14,17 @@ const DEFAULT_VALUE = 0
|
|
|
14
14
|
const DEFAULT_MIN = 0
|
|
15
15
|
const DEFAULT_MAX = 100
|
|
16
16
|
const DEFAULT_STEP = 1
|
|
17
|
+
const PERCENT = 100
|
|
18
|
+
/** Past this many steps, marks would be a smear rather than a scale. */
|
|
19
|
+
const MAX_MARKS = 100
|
|
20
|
+
const RANGE_LENGTH = 2
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* Renders a range slider with optional label and current value display.
|
|
20
24
|
* Supports min/max/step, color, disabled state, and full-width layout.
|
|
25
|
+
* With a `[low, high]` value it has two thumbs, one for each end of a range:
|
|
26
|
+
* two native range inputs on one track, so each keeps the keyboard and
|
|
27
|
+
* assistive tech support of the platform. `hasMarks` draws a tick per step.
|
|
21
28
|
* @param {SliderProps} props
|
|
22
29
|
* @returns {TemplateResult}
|
|
23
30
|
*/
|
|
@@ -35,14 +42,18 @@ export function render(props) {
|
|
|
35
42
|
color = "primary",
|
|
36
43
|
isValueVisible = true,
|
|
37
44
|
isFullWidth = false,
|
|
45
|
+
hasMarks = false,
|
|
38
46
|
onChange,
|
|
39
47
|
...rest
|
|
40
48
|
} = props
|
|
41
49
|
|
|
42
50
|
const inputId = id || name
|
|
51
|
+
const isRange = Array.isArray(value) && value.length === RANGE_LENGTH
|
|
52
|
+
const shown = isRange ? `${value[0]} – ${value[1]}` : value
|
|
43
53
|
|
|
44
54
|
const classes = {
|
|
45
55
|
"iw-slider": true,
|
|
56
|
+
"iw-slider-range": isRange,
|
|
46
57
|
[`iw-slider-${color}`]: color !== "primary",
|
|
47
58
|
"iw-slider-full-width": isFullWidth,
|
|
48
59
|
}
|
|
@@ -59,25 +70,113 @@ export function render(props) {
|
|
|
59
70
|
}
|
|
60
71
|
${
|
|
61
72
|
isValueVisible
|
|
62
|
-
? html`<output class="iw-slider-value">${
|
|
73
|
+
? html`<output class="iw-slider-value">${shown}</output>`
|
|
63
74
|
: null
|
|
64
75
|
}
|
|
65
76
|
</div>`
|
|
66
77
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
${
|
|
79
|
+
isRange
|
|
80
|
+
? renderRange({
|
|
81
|
+
inputId,
|
|
82
|
+
name,
|
|
83
|
+
label,
|
|
84
|
+
value,
|
|
85
|
+
min,
|
|
86
|
+
max,
|
|
87
|
+
step,
|
|
88
|
+
isDisabled,
|
|
89
|
+
onChange,
|
|
90
|
+
rest,
|
|
91
|
+
})
|
|
92
|
+
: html`<input
|
|
93
|
+
id=${inputId || nothing}
|
|
94
|
+
class="iw-slider-input"
|
|
95
|
+
aria-label=${fallbackLabel(inputId, label)}
|
|
96
|
+
type="range"
|
|
97
|
+
name=${name}
|
|
98
|
+
min=${min}
|
|
99
|
+
max=${max}
|
|
100
|
+
step=${step}
|
|
101
|
+
.value=${String(value)}
|
|
102
|
+
?disabled=${isDisabled}
|
|
103
|
+
@input=${(event) => onChange?.(Number(event.target.value))}
|
|
104
|
+
${ref((element) => applyElementProps(element, rest))}
|
|
105
|
+
/>`
|
|
106
|
+
}
|
|
107
|
+
${hasMarks ? renderMarks({ min, max, step }) : nothing}
|
|
81
108
|
</div>
|
|
82
109
|
`
|
|
83
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Two thumbs on one track. Each input stops at the other's value, so the
|
|
114
|
+
* range never turns inside out, and the track is filled between them.
|
|
115
|
+
*/
|
|
116
|
+
function renderRange({
|
|
117
|
+
inputId,
|
|
118
|
+
name,
|
|
119
|
+
label,
|
|
120
|
+
value,
|
|
121
|
+
min,
|
|
122
|
+
max,
|
|
123
|
+
step,
|
|
124
|
+
isDisabled,
|
|
125
|
+
onChange,
|
|
126
|
+
rest,
|
|
127
|
+
}) {
|
|
128
|
+
const [low, high] = value
|
|
129
|
+
const span = max - min || DEFAULT_STEP
|
|
130
|
+
const fill = `--iw-slider-low: ${((low - min) / span) * PERCENT}%; --iw-slider-high: ${((high - min) / span) * PERCENT}%`
|
|
131
|
+
const endName = (end) => (name ? `${name}-${end}` : nothing)
|
|
132
|
+
// Each thumb is named for its end of the range, after the slider's label.
|
|
133
|
+
const endLabel = (end) =>
|
|
134
|
+
typeof label === "string" && label ? `${label} ${end}` : end
|
|
135
|
+
|
|
136
|
+
return html`<div class="iw-slider-track" style=${fill}>
|
|
137
|
+
<input
|
|
138
|
+
id=${inputId || nothing}
|
|
139
|
+
class="iw-slider-input"
|
|
140
|
+
aria-label=${endLabel("minimum")}
|
|
141
|
+
type="range"
|
|
142
|
+
name=${endName("min")}
|
|
143
|
+
min=${min}
|
|
144
|
+
max=${max}
|
|
145
|
+
step=${step}
|
|
146
|
+
.value=${String(low)}
|
|
147
|
+
?disabled=${isDisabled}
|
|
148
|
+
@input=${(event) => {
|
|
149
|
+
const next = Math.min(Number(event.target.value), high)
|
|
150
|
+
event.target.value = String(next)
|
|
151
|
+
onChange?.([next, high])
|
|
152
|
+
}}
|
|
153
|
+
${ref((element) => applyElementProps(element, rest))}
|
|
154
|
+
/>
|
|
155
|
+
<input
|
|
156
|
+
class="iw-slider-input"
|
|
157
|
+
aria-label=${endLabel("maximum")}
|
|
158
|
+
type="range"
|
|
159
|
+
name=${endName("max")}
|
|
160
|
+
min=${min}
|
|
161
|
+
max=${max}
|
|
162
|
+
step=${step}
|
|
163
|
+
.value=${String(high)}
|
|
164
|
+
?disabled=${isDisabled}
|
|
165
|
+
@input=${(event) => {
|
|
166
|
+
const next = Math.max(Number(event.target.value), low)
|
|
167
|
+
event.target.value = String(next)
|
|
168
|
+
onChange?.([low, next])
|
|
169
|
+
}}
|
|
170
|
+
/>
|
|
171
|
+
</div>`
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** A tick per step, spread along the track. Decorative. */
|
|
175
|
+
function renderMarks({ min, max, step }) {
|
|
176
|
+
const count = Math.floor((max - min) / step) + 1
|
|
177
|
+
if (!(count > 1) || count > MAX_MARKS) return nothing
|
|
178
|
+
|
|
179
|
+
return html`<div class="iw-slider-marks" aria-hidden="true">
|
|
180
|
+
${Array.from({ length: count }, () => html`<span></span>`)}
|
|
181
|
+
</div>`
|
|
182
|
+
}
|
|
@@ -43,6 +43,17 @@
|
|
|
43
43
|
transform: translateX(calc(1rem * var(--iw-dir-sign, 1)));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/* With a description, the label and it stack beside the track. */
|
|
47
|
+
.iw-switch-text {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.iw-switch-description {
|
|
53
|
+
font-size: var(--iw-font-size-sm);
|
|
54
|
+
color: var(--iw-color-text-secondary);
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
.iw-switch-label {
|
|
47
58
|
color: var(--iw-color-text);
|
|
48
59
|
font-size: var(--iw-font-size-base);
|
|
@@ -7,6 +7,10 @@ export default {
|
|
|
7
7
|
render: createRender(Switch),
|
|
8
8
|
argTypes: {
|
|
9
9
|
label: { control: "text", description: "Label text." },
|
|
10
|
+
description: {
|
|
11
|
+
control: "text",
|
|
12
|
+
description: "A line of detail under the label.",
|
|
13
|
+
},
|
|
10
14
|
name: { control: "text", description: "Native input name." },
|
|
11
15
|
isChecked: { control: "boolean", description: "Current checked state." },
|
|
12
16
|
isDisabled: { control: "boolean", description: "Disables interaction." },
|
|
@@ -46,3 +50,9 @@ On.args = {
|
|
|
46
50
|
...Default.args,
|
|
47
51
|
isChecked: true,
|
|
48
52
|
}
|
|
53
|
+
|
|
54
|
+
export const WithDescription = {}
|
|
55
|
+
WithDescription.args = {
|
|
56
|
+
...Default.args,
|
|
57
|
+
description: "Alerts when a payment is due or a budget runs out.",
|
|
58
|
+
}
|
|
@@ -22,6 +22,7 @@ export function render(props) {
|
|
|
22
22
|
type, // eslint-disable-line no-unused-vars
|
|
23
23
|
name = "",
|
|
24
24
|
label = "",
|
|
25
|
+
description,
|
|
25
26
|
isChecked = false,
|
|
26
27
|
isDisabled = false,
|
|
27
28
|
color = "primary",
|
|
@@ -57,7 +58,16 @@ export function render(props) {
|
|
|
57
58
|
<span class="iw-switch-track" aria-hidden="true">
|
|
58
59
|
<span class="iw-switch-thumb"></span>
|
|
59
60
|
</span>
|
|
60
|
-
${
|
|
61
|
+
${
|
|
62
|
+
description
|
|
63
|
+
? html`<span class="iw-switch-text">
|
|
64
|
+
${label ? html`<span class="iw-switch-label">${label}</span>` : null}
|
|
65
|
+
<span class="iw-switch-description">${description}</span>
|
|
66
|
+
</span>`
|
|
67
|
+
: label
|
|
68
|
+
? html`<span class="iw-switch-label">${label}</span>`
|
|
69
|
+
: null
|
|
70
|
+
}
|
|
61
71
|
</label>
|
|
62
72
|
`
|
|
63
73
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import sell from "@iconify-icons/material-symbols/sell"
|
|
2
|
+
|
|
1
3
|
import { createRender } from "../../stories/notify-story.js"
|
|
4
|
+
import { Icon } from "../icon"
|
|
2
5
|
import { Chip } from "."
|
|
3
6
|
|
|
4
7
|
export default {
|
|
@@ -7,6 +10,10 @@ export default {
|
|
|
7
10
|
render: createRender(Chip),
|
|
8
11
|
argTypes: {
|
|
9
12
|
children: { control: "text", description: "Chip label content." },
|
|
13
|
+
icon: {
|
|
14
|
+
control: false,
|
|
15
|
+
description: "Shown before the label, such as an `Icon.render(...)`.",
|
|
16
|
+
},
|
|
10
17
|
isRemovable: {
|
|
11
18
|
control: "boolean",
|
|
12
19
|
description: "Shows a remove affordance and emits `#id:remove`.",
|
|
@@ -55,3 +62,13 @@ export const Default = {
|
|
|
55
62
|
shape: "pill",
|
|
56
63
|
},
|
|
57
64
|
}
|
|
65
|
+
|
|
66
|
+
export const WithIcon = {
|
|
67
|
+
args: {
|
|
68
|
+
...Default.args,
|
|
69
|
+
children: "Paid",
|
|
70
|
+
icon: Icon.render({ icon: sell, size: "sm" }),
|
|
71
|
+
isRemovable: false,
|
|
72
|
+
color: "success",
|
|
73
|
+
},
|
|
74
|
+
}
|
|
@@ -7,7 +7,7 @@ import { html } from "@inglorious/web"
|
|
|
7
7
|
import { classMap } from "@inglorious/web/directives/class-map"
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Renders a compact chip label with optional remove action.
|
|
10
|
+
* Renders a compact chip label with an optional leading icon and remove action.
|
|
11
11
|
* Use chips for tags, filters, or selected values.
|
|
12
12
|
* @param {ChipProps} props
|
|
13
13
|
* @returns {TemplateResult}
|
|
@@ -15,6 +15,7 @@ import { classMap } from "@inglorious/web/directives/class-map"
|
|
|
15
15
|
export function render(props) {
|
|
16
16
|
const {
|
|
17
17
|
children,
|
|
18
|
+
icon,
|
|
18
19
|
isRemovable = false,
|
|
19
20
|
color = "default",
|
|
20
21
|
size = "md",
|
|
@@ -30,6 +31,7 @@ export function render(props) {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
return html`<span class=${classMap(classes)}>
|
|
34
|
+
${icon ? html`<span class="iw-chip-icon" aria-hidden="true">${icon}</span>` : null}
|
|
33
35
|
<span class="iw-chip-label">${children}</span>
|
|
34
36
|
${
|
|
35
37
|
isRemovable
|
|
@@ -17,6 +17,11 @@ export default {
|
|
|
17
17
|
control: "boolean",
|
|
18
18
|
description: "Applies start inset for sectional separators.",
|
|
19
19
|
},
|
|
20
|
+
isDecorative: {
|
|
21
|
+
control: "boolean",
|
|
22
|
+
description:
|
|
23
|
+
"Only visual: hidden from assistive tech, which otherwise announces a separator.",
|
|
24
|
+
},
|
|
20
25
|
},
|
|
21
26
|
parameters: {
|
|
22
27
|
docs: {
|
|
@@ -31,6 +36,10 @@ export const Default = {
|
|
|
31
36
|
args: {},
|
|
32
37
|
}
|
|
33
38
|
|
|
39
|
+
export const Decorative = {
|
|
40
|
+
args: { isDecorative: true },
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
export const Vertical = {
|
|
35
44
|
args: {
|
|
36
45
|
...Default.args,
|
|
@@ -3,23 +3,31 @@
|
|
|
3
3
|
* @typedef {import('@inglorious/web').TemplateResult} TemplateResult
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { html } from "@inglorious/web"
|
|
6
|
+
import { html, nothing } from "@inglorious/web"
|
|
7
7
|
import { classMap } from "@inglorious/web/directives/class-map"
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Renders a horizontal or vertical divider line
|
|
10
|
+
* Renders a horizontal or vertical divider line: a native `<hr>`, which
|
|
11
|
+
* assistive tech announces as a separator, unless it is only decorative.
|
|
11
12
|
* Supports inset styling for aligned content blocks.
|
|
12
13
|
* @param {DividerProps} props
|
|
13
14
|
* @returns {TemplateResult}
|
|
14
15
|
*/
|
|
15
16
|
export function render(props) {
|
|
16
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
orientation = "horizontal",
|
|
19
|
+
isInset = false,
|
|
20
|
+
isDecorative = false,
|
|
21
|
+
} = props
|
|
22
|
+
const isVertical = orientation === "vertical"
|
|
17
23
|
|
|
18
24
|
return html`<hr
|
|
19
25
|
class=${classMap({
|
|
20
26
|
"iw-divider": true,
|
|
21
|
-
"iw-divider-vertical":
|
|
27
|
+
"iw-divider-vertical": isVertical,
|
|
22
28
|
"iw-divider-inset": isInset,
|
|
23
29
|
})}
|
|
30
|
+
role=${isDecorative ? "none" : nothing}
|
|
31
|
+
aria-orientation=${isVertical && !isDecorative ? "vertical" : nothing}
|
|
24
32
|
/>`
|
|
25
33
|
}
|
|
@@ -10,7 +10,7 @@ export default {
|
|
|
10
10
|
description: { control: "text" },
|
|
11
11
|
severity: {
|
|
12
12
|
control: "select",
|
|
13
|
-
options: ["info", "success", "warning", "error"],
|
|
13
|
+
options: ["info", "success", "warning", "error", "neutral"],
|
|
14
14
|
},
|
|
15
15
|
variant: { control: "select", options: ["filled", "outlined"] },
|
|
16
16
|
icon: { control: "text" },
|
|
@@ -50,6 +50,14 @@ export const Error = {
|
|
|
50
50
|
},
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
export const Neutral = {
|
|
54
|
+
args: {
|
|
55
|
+
title: "Note",
|
|
56
|
+
description: "A plain remark, with no tone of its own.",
|
|
57
|
+
severity: "neutral",
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
export const Outlined = {
|
|
54
62
|
args: {
|
|
55
63
|
title: "Outlined Alert",
|
|
@@ -81,6 +81,11 @@
|
|
|
81
81
|
--iw-alert-color: var(--iw-color-error, #d14343);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/* A plain note: no tone of its own, just the text colour. */
|
|
85
|
+
.iw-alert-neutral {
|
|
86
|
+
--iw-alert-color: var(--iw-color-text-secondary, var(--iw-color-text));
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
.iw-alert-outlined {
|
|
85
90
|
background: transparent;
|
|
86
91
|
border-color: color-mix(in srgb, var(--iw-alert-color) 55%, transparent);
|
|
@@ -11,7 +11,8 @@ import { applyElementProps } from "../../shared/apply-element-props.js"
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Renders an alert message with optional title, description, icon, and actions.
|
|
14
|
-
* Supports severity and variant styles for info, success, warning, and
|
|
14
|
+
* Supports severity and variant styles for info, success, warning, error and
|
|
15
|
+
* neutral, a plain note.
|
|
15
16
|
* @param {AlertProps} props
|
|
16
17
|
* @returns {TemplateResult}
|
|
17
18
|
*/
|
|
@@ -10,6 +10,7 @@ export default {
|
|
|
10
10
|
argTypes: {
|
|
11
11
|
isOpen: { control: "boolean" },
|
|
12
12
|
isModal: { control: "boolean" },
|
|
13
|
+
size: { control: "select", options: ["sm", "md", "lg"] },
|
|
13
14
|
title: { control: "text" },
|
|
14
15
|
description: { control: "text" },
|
|
15
16
|
onClose: { action: "onClose" },
|
|
@@ -29,6 +30,27 @@ export const Open = {
|
|
|
29
30
|
},
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
export const Small = {
|
|
34
|
+
args: { ...Open.args, size: "sm" },
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const Medium = {
|
|
38
|
+
args: { ...Open.args, size: "md" },
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Large = {
|
|
42
|
+
args: {
|
|
43
|
+
...Open.args,
|
|
44
|
+
size: "lg",
|
|
45
|
+
title: "Release notes",
|
|
46
|
+
description: "What changed in this version.",
|
|
47
|
+
children: html`<p>
|
|
48
|
+
A wider dialog, for content that needs the room: tables, previews or
|
|
49
|
+
longer text.
|
|
50
|
+
</p>`,
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
// Modal takes over the page, so it is left out of the docs page.
|
|
33
55
|
export const Modal = {
|
|
34
56
|
tags: ["!autodocs"],
|
|
@@ -7,12 +7,25 @@
|
|
|
7
7
|
color: var(--iw-color-text);
|
|
8
8
|
border-radius: var(--iw-radius-md);
|
|
9
9
|
border: 1px solid color-mix(in srgb, var(--iw-color-border) 70%, transparent);
|
|
10
|
-
min-width: min(32rem, 90vw);
|
|
11
|
-
max-width: min(48rem, 90vw);
|
|
12
10
|
box-shadow: var(--iw-shadow-lg, 0 12px 40px rgba(0, 0, 0, 0.3));
|
|
13
11
|
padding: 0;
|
|
14
12
|
}
|
|
15
13
|
|
|
14
|
+
.iw-dialog-sm {
|
|
15
|
+
min-width: min(20rem, 90vw);
|
|
16
|
+
max-width: min(28rem, 90vw);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.iw-dialog-md {
|
|
20
|
+
min-width: min(32rem, 90vw);
|
|
21
|
+
max-width: min(48rem, 90vw);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.iw-dialog-lg {
|
|
25
|
+
min-width: min(40rem, 90vw);
|
|
26
|
+
max-width: min(64rem, 90vw);
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
.iw-dialog::backdrop {
|
|
17
30
|
background: color-mix(in srgb, var(--iw-color-black) 55%, transparent);
|
|
18
31
|
backdrop-filter: blur(2px);
|
|
@@ -28,6 +28,7 @@ export function render(props) {
|
|
|
28
28
|
id,
|
|
29
29
|
isOpen = false,
|
|
30
30
|
isModal = true,
|
|
31
|
+
size = "md",
|
|
31
32
|
title,
|
|
32
33
|
description,
|
|
33
34
|
children,
|
|
@@ -54,7 +55,11 @@ export function render(props) {
|
|
|
54
55
|
// also clicks the dialog, and must not close it.
|
|
55
56
|
return html`<dialog
|
|
56
57
|
id=${id || nothing}
|
|
57
|
-
class=${classMap({
|
|
58
|
+
class=${classMap({
|
|
59
|
+
"iw-dialog": true,
|
|
60
|
+
[`iw-dialog-${size}`]: true,
|
|
61
|
+
...extraClasses,
|
|
62
|
+
})}
|
|
58
63
|
aria-labelledby=${titleId || nothing}
|
|
59
64
|
aria-describedby=${descriptionId || nothing}
|
|
60
65
|
@pointerdown=${(event) => {
|
|
@@ -8,6 +8,11 @@ export default {
|
|
|
8
8
|
argTypes: {
|
|
9
9
|
variant: { control: "select", options: ["linear", "circular"] },
|
|
10
10
|
value: { control: "number" },
|
|
11
|
+
ariaLabel: {
|
|
12
|
+
control: "text",
|
|
13
|
+
description:
|
|
14
|
+
'Names the indicator for assistive tech, e.g. "Uploading photo".',
|
|
15
|
+
},
|
|
11
16
|
size: { control: "number" },
|
|
12
17
|
thickness: { control: "number" },
|
|
13
18
|
color: {
|
|
@@ -85,6 +85,10 @@
|
|
|
85
85
|
gap: 0;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
&.iw-flex-gap-xs {
|
|
89
|
+
gap: var(--iw-space-1);
|
|
90
|
+
}
|
|
91
|
+
|
|
88
92
|
&.iw-flex-gap-sm {
|
|
89
93
|
gap: var(--iw-space-2);
|
|
90
94
|
}
|
|
@@ -101,6 +105,10 @@
|
|
|
101
105
|
gap: var(--iw-space-8);
|
|
102
106
|
}
|
|
103
107
|
|
|
108
|
+
&.iw-flex-gap-2xl {
|
|
109
|
+
gap: var(--iw-space-12);
|
|
110
|
+
}
|
|
111
|
+
|
|
104
112
|
&.iw-flex-padding-none {
|
|
105
113
|
padding: 0;
|
|
106
114
|
}
|
|
@@ -12,6 +12,11 @@ export default {
|
|
|
12
12
|
control: "object",
|
|
13
13
|
description: "Accordion sections with title, content, and state flags.",
|
|
14
14
|
},
|
|
15
|
+
name: {
|
|
16
|
+
control: "text",
|
|
17
|
+
description:
|
|
18
|
+
"Items sharing a name close each other: at most one is open at a time.",
|
|
19
|
+
},
|
|
15
20
|
onItemToggle: { action: "onItemToggle" },
|
|
16
21
|
},
|
|
17
22
|
parameters: {
|
|
@@ -44,6 +49,10 @@ export const Default = {
|
|
|
44
49
|
},
|
|
45
50
|
}
|
|
46
51
|
|
|
52
|
+
export const Exclusive = {
|
|
53
|
+
args: { ...Default.args, name: "settings" },
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
export const WithIcons = {
|
|
48
57
|
args: {
|
|
49
58
|
items: [
|
|
@@ -85,7 +85,11 @@ export const Accordion = {
|
|
|
85
85
|
name=${props.name || nothing}
|
|
86
86
|
.open=${isExpanded}
|
|
87
87
|
@toggle=${(event) => {
|
|
88
|
-
|
|
88
|
+
// newState is what the browser says; an environment whose toggle
|
|
89
|
+
// event lacks it, such as jsdom, still has the element's own state.
|
|
90
|
+
const isOpen = event.newState
|
|
91
|
+
? event.newState === "open"
|
|
92
|
+
: event.currentTarget.open
|
|
89
93
|
// Also fires when isExpanded opened it, which needs no report.
|
|
90
94
|
if (isOpen === isExpanded) return
|
|
91
95
|
onToggle?.(item, index, isOpen)
|
|
@@ -53,6 +53,12 @@ export default {
|
|
|
53
53
|
options: ["none", "sm", "md", "lg", "xl"],
|
|
54
54
|
description: "Footer padding preset.",
|
|
55
55
|
},
|
|
56
|
+
variant: {
|
|
57
|
+
control: "select",
|
|
58
|
+
options: ["default", "sunk", "clear"],
|
|
59
|
+
description:
|
|
60
|
+
"The surface: raised, sunk into the page for content inside another surface, or clear.",
|
|
61
|
+
},
|
|
56
62
|
isHoverable: {
|
|
57
63
|
control: "boolean",
|
|
58
64
|
description: "Enable hover visual feedback.",
|
|
@@ -97,6 +103,24 @@ export const WithFooter = {
|
|
|
97
103
|
},
|
|
98
104
|
}
|
|
99
105
|
|
|
106
|
+
export const Sunk = {
|
|
107
|
+
args: {
|
|
108
|
+
title: "Sunk card",
|
|
109
|
+
subtitle: "Content inside another surface",
|
|
110
|
+
children: "Body content",
|
|
111
|
+
variant: "sunk",
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const Clear = {
|
|
116
|
+
args: {
|
|
117
|
+
title: "Clear card",
|
|
118
|
+
subtitle: "Groups content with no surface of its own",
|
|
119
|
+
children: "Body content",
|
|
120
|
+
variant: "clear",
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
export const Interactive = {
|
|
101
125
|
args: {
|
|
102
126
|
title: "Interactive Card",
|
|
@@ -11,6 +11,21 @@
|
|
|
11
11
|
transform var(--iw-transition-normal);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/* Set into the page rather than raised from it, for content grouped inside
|
|
15
|
+
another surface. */
|
|
16
|
+
.iw-card-sunk {
|
|
17
|
+
background-color: var(--iw-color-bg-secondary, var(--iw-card-bg));
|
|
18
|
+
border-color: transparent;
|
|
19
|
+
box-shadow: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Only the grouping: no surface at all. */
|
|
23
|
+
.iw-card-clear {
|
|
24
|
+
background-color: transparent;
|
|
25
|
+
border-color: transparent;
|
|
26
|
+
box-shadow: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
14
29
|
.iw-card-hoverable:hover {
|
|
15
30
|
box-shadow: var(--iw-card-shadow-hover);
|
|
16
31
|
}
|
|
@@ -30,6 +30,7 @@ export const Card = {
|
|
|
30
30
|
const {
|
|
31
31
|
type, // eslint-disable-line no-unused-vars
|
|
32
32
|
element = "article",
|
|
33
|
+
variant = "default",
|
|
33
34
|
isHoverable = false,
|
|
34
35
|
isClickable = false,
|
|
35
36
|
isFullWidth = false,
|
|
@@ -47,6 +48,7 @@ export const Card = {
|
|
|
47
48
|
|
|
48
49
|
const classes = {
|
|
49
50
|
"iw-card": true,
|
|
51
|
+
[`iw-card-${variant}`]: variant !== "default",
|
|
50
52
|
"iw-card-hoverable": isHoverable || isClickable,
|
|
51
53
|
"iw-card-clickable": isClickable,
|
|
52
54
|
"iw-card-full-width": isFullWidth,
|
|
@@ -4,7 +4,8 @@ export interface SliderProps {
|
|
|
4
4
|
id?: string
|
|
5
5
|
name?: string
|
|
6
6
|
label?: string
|
|
7
|
-
|
|
7
|
+
/** One number, or `[low, high]` for a range with a thumb at each end. */
|
|
8
|
+
value?: number | [number, number]
|
|
8
9
|
min?: number
|
|
9
10
|
max?: number
|
|
10
11
|
step?: number
|
|
@@ -12,7 +13,10 @@ export interface SliderProps {
|
|
|
12
13
|
isDisabled?: boolean
|
|
13
14
|
isValueVisible?: boolean
|
|
14
15
|
isFullWidth?: boolean
|
|
15
|
-
|
|
16
|
+
/** Draws a tick at every step, for a slider that moves in clear steps. */
|
|
17
|
+
hasMarks?: boolean
|
|
18
|
+
/** The new value, in the shape `value` has: a number, or `[low, high]`. */
|
|
19
|
+
onChange?: (value: number | [number, number]) => void
|
|
16
20
|
[key: string]: unknown
|
|
17
21
|
}
|
|
18
22
|
|
|
@@ -3,6 +3,8 @@ import type { TemplateResult } from "@inglorious/web"
|
|
|
3
3
|
export interface ChipProps {
|
|
4
4
|
id?: string
|
|
5
5
|
children?: TemplateResult | string | number
|
|
6
|
+
/** Shown before the label, such as an `Icon.render(...)`. Decorative. */
|
|
7
|
+
icon?: TemplateResult
|
|
6
8
|
isRemovable?: boolean
|
|
7
9
|
color?:
|
|
8
10
|
| "default"
|
|
@@ -6,7 +6,7 @@ export interface AlertProps {
|
|
|
6
6
|
title?: TemplateResult | string | number
|
|
7
7
|
description?: TemplateResult | string | number
|
|
8
8
|
children?: TemplateResult | string | number
|
|
9
|
-
severity?: "info" | "success" | "warning" | "error"
|
|
9
|
+
severity?: "info" | "success" | "warning" | "error" | "neutral"
|
|
10
10
|
variant?: "filled" | "outlined"
|
|
11
11
|
icon?: TemplateResult | string | number
|
|
12
12
|
action?: TemplateResult | string | number
|
|
@@ -6,6 +6,8 @@ export interface DialogProps {
|
|
|
6
6
|
isOpen?: boolean
|
|
7
7
|
/** Modal by default; `false` shows the dialog in place, with the page still usable. */
|
|
8
8
|
isModal?: boolean
|
|
9
|
+
/** Its width: `"sm"`, `"md"` (default) or `"lg"`. */
|
|
10
|
+
size?: "sm" | "md" | "lg"
|
|
9
11
|
title?: TemplateResult | string | number
|
|
10
12
|
description?: TemplateResult | string | number
|
|
11
13
|
children?: TemplateResult | string | number
|
package/types/layout/flex.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface FlexProps {
|
|
|
16
16
|
wrap?: "nowrap" | "wrap" | "wrap-reverse"
|
|
17
17
|
justify?: "start" | "center" | "end" | "between" | "around" | "evenly"
|
|
18
18
|
align?: "stretch" | "start" | "center" | "end" | "baseline"
|
|
19
|
-
gap?: "none" | "sm" | "md" | "lg" | "xl"
|
|
19
|
+
gap?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
20
20
|
padding?: "none" | "sm" | "md" | "lg" | "xl"
|
|
21
21
|
overflow?: "visible" | "hidden" | "clip" | "scroll" | "auto"
|
|
22
22
|
isInline?: boolean
|
package/types/surfaces/card.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ export interface CardProps {
|
|
|
12
12
|
| "footer"
|
|
13
13
|
| "nav"
|
|
14
14
|
| "aside"
|
|
15
|
+
/**
|
|
16
|
+
* The surface: raised (`"default"`), `"sunk"` into the page for content
|
|
17
|
+
* inside another surface, or `"clear"` with none.
|
|
18
|
+
*/
|
|
19
|
+
variant?: "default" | "sunk" | "clear"
|
|
15
20
|
title?: TemplateResult | string | number
|
|
16
21
|
subtitle?: TemplateResult | string | number
|
|
17
22
|
header?: TemplateResult | string | number
|