@mystravil/hardpoint 0.2.0 → 0.2.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/CHANGELOG.md +42 -38
- package/LICENSE +25 -25
- package/README.md +67 -64
- package/dist/base.css +625 -625
- package/dist/components/AppShell.svelte +698 -698
- package/dist/components/Button.svelte +174 -174
- package/dist/components/Checkbox.svelte +235 -235
- package/dist/components/CheckboxGroup.svelte +207 -207
- package/dist/components/Combobox.svelte +901 -901
- package/dist/components/Dialog.svelte +359 -359
- package/dist/components/Disclosure.svelte +201 -201
- package/dist/components/EmptyState.svelte +88 -88
- package/dist/components/ErrorState.svelte +135 -135
- package/dist/components/ImageViewer.svelte +764 -764
- package/dist/components/KeyValueList.svelte +114 -114
- package/dist/components/ListDetail.svelte +218 -218
- package/dist/components/LoadRegion.svelte +219 -219
- package/dist/components/MediaFrame.svelte +110 -110
- package/dist/components/MediaImage.svelte +256 -256
- package/dist/components/Menu.svelte +258 -258
- package/dist/components/MenuCheckboxItem.svelte +119 -119
- package/dist/components/MenuGroup.svelte +50 -50
- package/dist/components/MenuItem.svelte +94 -94
- package/dist/components/MenuRadioGroup.svelte +62 -62
- package/dist/components/MenuRadioItem.svelte +110 -110
- package/dist/components/MenuSeparator.svelte +28 -28
- package/dist/components/Meter.svelte +283 -283
- package/dist/components/NativeSelect.svelte +135 -135
- package/dist/components/Notice.svelte +262 -262
- package/dist/components/Popover.svelte +222 -222
- package/dist/components/Progress.svelte +157 -157
- package/dist/components/RadioGroup.svelte +440 -440
- package/dist/components/Select.svelte +471 -471
- package/dist/components/Skeleton.svelte +149 -149
- package/dist/components/Spinner.svelte +118 -118
- package/dist/components/Stat.svelte +253 -253
- package/dist/components/Steps.svelte +189 -189
- package/dist/components/Switch.svelte +222 -222
- package/dist/components/Table.svelte +504 -504
- package/dist/components/Tabs.svelte +246 -246
- package/dist/components/Tag.svelte +40 -40
- package/dist/components/TextArea.svelte +272 -272
- package/dist/components/TextField.svelte +256 -256
- package/dist/components/Timeline.svelte +156 -156
- package/dist/components/Toaster.svelte +411 -411
- package/dist/components/Tooltip.svelte +200 -200
- package/dist/components/TooltipGroup.svelte +46 -46
- package/dist/components/internal/Scrim.svelte +52 -52
- package/dist/components/internal/Sheet.svelte +263 -263
- package/dist/fonts.css +71 -71
- package/dist/tokens.css +283 -283
- package/package.json +81 -76
|
@@ -1,189 +1,189 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { HTMLOlAttributes } from 'svelte/elements';
|
|
3
|
-
|
|
4
|
-
export type StepsItem = {
|
|
5
|
-
/** The step's caps label. A short fixed string the app defines. */
|
|
6
|
-
label: string;
|
|
7
|
-
/** A supporting line in `--muted`, as written. */
|
|
8
|
-
detail?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/** Where a step stands, from `current`. Each step's `<li>` carries it in `data-state`. */
|
|
12
|
-
export type StepsState = 'done' | 'current' | 'upcoming';
|
|
13
|
-
|
|
14
|
-
/** From which width the steps sit in a row: 600px, 900px or 1200px. */
|
|
15
|
-
export type StepsBreakpoint = 'medium' | 'expanded' | 'large';
|
|
16
|
-
|
|
17
|
-
export type StepsProps = Omit<HTMLOlAttributes, 'children'> & {
|
|
18
|
-
/** In order, first to last. */
|
|
19
|
-
steps: StepsItem[];
|
|
20
|
-
/**
|
|
21
|
-
* The index of the current step, from 0. Steps before it are done,
|
|
22
|
-
* steps after it upcoming. `steps.length` marks every step done.
|
|
23
|
-
*/
|
|
24
|
-
current: number;
|
|
25
|
-
/**
|
|
26
|
-
* From which width the steps sit in a row of equal columns; narrower,
|
|
27
|
-
* they stack. Default `medium` (600px). Pick a later one when long
|
|
28
|
-
* labels or many steps would not fit their columns.
|
|
29
|
-
*/
|
|
30
|
-
rowFrom?: StepsBreakpoint;
|
|
31
|
-
/** Screen-reader text after a done step's label. Default `done`. */
|
|
32
|
-
doneLabel?: string;
|
|
33
|
-
};
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<script lang="ts">
|
|
37
|
-
let {
|
|
38
|
-
steps,
|
|
39
|
-
current,
|
|
40
|
-
rowFrom = 'medium',
|
|
41
|
-
doneLabel = 'done',
|
|
42
|
-
class: className,
|
|
43
|
-
...rest
|
|
44
|
-
}: StepsProps = $props();
|
|
45
|
-
|
|
46
|
-
function stateOf(index: number): StepsState {
|
|
47
|
-
return index < current ? 'done' : index === current ? 'current' : 'upcoming';
|
|
48
|
-
}
|
|
49
|
-
</script>
|
|
50
|
-
|
|
51
|
-
<!--
|
|
52
|
-
Ordered steps as discrete segments (BRIEF, visual rule 7): each step has a
|
|
53
|
-
3px edge, titanium once reached and --border while upcoming, so the edges
|
|
54
|
-
read as a segmented bar. The current step adds the selection tint and
|
|
55
|
-
aria-current="step"; a done step shows a check for its number. A row from
|
|
56
|
-
`rowFrom` (600px by default), stacked below. When the current step
|
|
57
|
-
changes, the edges and the tint fade their colour over --dur-segment.
|
|
58
|
-
Extra attributes (an `aria-label` naming the process)
|
|
59
|
-
and `class` go to the <ol>.
|
|
60
|
-
-->
|
|
61
|
-
<ol role="list" {...rest} class={['hp-steps', className]} data-row-from={rowFrom}>
|
|
62
|
-
{#each steps as step, index}
|
|
63
|
-
{@const state = stateOf(index)}
|
|
64
|
-
<li class="hp-steps-step" data-state={state} aria-current={state === 'current' ? 'step' : undefined}>
|
|
65
|
-
<span class="hp-steps-mark" aria-hidden="true">
|
|
66
|
-
{#if state === 'done'}
|
|
67
|
-
<svg viewBox="0 0 16 16" width="16" height="16" focusable="false">
|
|
68
|
-
<path d="m3 8.5 3.5 3.5 6.5-7.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" />
|
|
69
|
-
</svg>
|
|
70
|
-
{:else}
|
|
71
|
-
{index + 1}
|
|
72
|
-
{/if}
|
|
73
|
-
</span>
|
|
74
|
-
<span class="hp-steps-label hp-label">{step.label}</span>
|
|
75
|
-
{#if state === 'done'}<span class="hp-visually-hidden">, {doneLabel}</span>{/if}
|
|
76
|
-
{#if step.detail}<span class="hp-steps-detail">{step.detail}</span>{/if}
|
|
77
|
-
</li>
|
|
78
|
-
{/each}
|
|
79
|
-
</ol>
|
|
80
|
-
|
|
81
|
-
<style>
|
|
82
|
-
/* Stacked below 600px. The edges and the current tint reach --bleed into
|
|
83
|
-
the gutter, so the labels keep the page edge, as table rows do. */
|
|
84
|
-
.hp-steps {
|
|
85
|
-
display: grid;
|
|
86
|
-
gap: var(--space-1);
|
|
87
|
-
margin: 0 calc(-1 * var(--bleed));
|
|
88
|
-
padding: 0;
|
|
89
|
-
list-style: none;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/* The edge colour is a registered colour property, so it can transition
|
|
93
|
-
on its own while the edge's shape switches at once between the stacked
|
|
94
|
-
and the row form. */
|
|
95
|
-
@property --steps-edge {
|
|
96
|
-
syntax: '<color>';
|
|
97
|
-
inherits: false;
|
|
98
|
-
initial-value: transparent;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/* When the current step changes, the edge and the tint fade their colour
|
|
102
|
-
over --dur-segment (BRIEF, short motion). A CSS transition never runs
|
|
103
|
-
on an element's first style, so steps show their state at once when
|
|
104
|
-
they render. 0ms is a snap. Colour only, so reduced motion keeps it.
|
|
105
|
-
The text colour and the number or check change at once. */
|
|
106
|
-
.hp-steps-step {
|
|
107
|
-
--steps-edge: var(--accent);
|
|
108
|
-
position: relative;
|
|
109
|
-
display: grid;
|
|
110
|
-
grid-template-columns: var(--space-4) minmax(0, 1fr);
|
|
111
|
-
column-gap: var(--space-2);
|
|
112
|
-
row-gap: var(--space-1);
|
|
113
|
-
align-content: start;
|
|
114
|
-
padding: var(--space-3) var(--space-3) var(--space-3) var(--bleed);
|
|
115
|
-
/* the brief's 3px selection edge */
|
|
116
|
-
box-shadow: inset 3px 0 0 var(--steps-edge);
|
|
117
|
-
overflow-wrap: anywhere;
|
|
118
|
-
transition:
|
|
119
|
-
--steps-edge var(--dur-segment) var(--settle),
|
|
120
|
-
background-color var(--dur-segment) var(--settle);
|
|
121
|
-
}
|
|
122
|
-
.hp-steps-step[data-state='current'] {
|
|
123
|
-
background: var(--surface-selected);
|
|
124
|
-
}
|
|
125
|
-
.hp-steps-step[data-state='upcoming'] {
|
|
126
|
-
--steps-edge: var(--border);
|
|
127
|
-
color: var(--muted);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/* The number or the check, in a 16px box beside the label's first line. */
|
|
131
|
-
.hp-steps-mark {
|
|
132
|
-
display: grid;
|
|
133
|
-
place-items: center;
|
|
134
|
-
height: var(--space-4);
|
|
135
|
-
font-size: var(--type-label);
|
|
136
|
-
font-weight: 500;
|
|
137
|
-
line-height: 16px;
|
|
138
|
-
font-variant-numeric: tabular-nums;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.hp-steps-detail {
|
|
142
|
-
grid-column: 2;
|
|
143
|
-
color: var(--muted);
|
|
144
|
-
font-size: var(--type-body);
|
|
145
|
-
line-height: 24px;
|
|
146
|
-
}
|
|
147
|
-
@media (pointer: fine) {
|
|
148
|
-
.hp-steps-detail {
|
|
149
|
-
font-size: var(--type-dense);
|
|
150
|
-
line-height: 20px;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/* A row of equal columns from the rowFrom width, the edge on top. A label
|
|
155
|
-
longer than its column still breaks rather than widen the page. */
|
|
156
|
-
@media (min-width: 600px) {
|
|
157
|
-
.hp-steps[data-row-from='medium'] {
|
|
158
|
-
grid-auto-columns: minmax(0, 1fr);
|
|
159
|
-
grid-auto-flow: column;
|
|
160
|
-
}
|
|
161
|
-
[data-row-from='medium'] > .hp-steps-step {
|
|
162
|
-
padding: var(--space-4) var(--space-2) var(--space-3) var(--bleed);
|
|
163
|
-
/* the brief's 3px selection edge */
|
|
164
|
-
box-shadow: inset 0 3px 0 var(--steps-edge);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
@media (min-width: 900px) {
|
|
168
|
-
.hp-steps[data-row-from='expanded'] {
|
|
169
|
-
grid-auto-columns: minmax(0, 1fr);
|
|
170
|
-
grid-auto-flow: column;
|
|
171
|
-
}
|
|
172
|
-
[data-row-from='expanded'] > .hp-steps-step {
|
|
173
|
-
padding: var(--space-4) var(--space-2) var(--space-3) var(--bleed);
|
|
174
|
-
/* the brief's 3px selection edge */
|
|
175
|
-
box-shadow: inset 0 3px 0 var(--steps-edge);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
@media (min-width: 1200px) {
|
|
179
|
-
.hp-steps[data-row-from='large'] {
|
|
180
|
-
grid-auto-columns: minmax(0, 1fr);
|
|
181
|
-
grid-auto-flow: column;
|
|
182
|
-
}
|
|
183
|
-
[data-row-from='large'] > .hp-steps-step {
|
|
184
|
-
padding: var(--space-4) var(--space-2) var(--space-3) var(--bleed);
|
|
185
|
-
/* the brief's 3px selection edge */
|
|
186
|
-
box-shadow: inset 0 3px 0 var(--steps-edge);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
</style>
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { HTMLOlAttributes } from 'svelte/elements';
|
|
3
|
+
|
|
4
|
+
export type StepsItem = {
|
|
5
|
+
/** The step's caps label. A short fixed string the app defines. */
|
|
6
|
+
label: string;
|
|
7
|
+
/** A supporting line in `--muted`, as written. */
|
|
8
|
+
detail?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Where a step stands, from `current`. Each step's `<li>` carries it in `data-state`. */
|
|
12
|
+
export type StepsState = 'done' | 'current' | 'upcoming';
|
|
13
|
+
|
|
14
|
+
/** From which width the steps sit in a row: 600px, 900px or 1200px. */
|
|
15
|
+
export type StepsBreakpoint = 'medium' | 'expanded' | 'large';
|
|
16
|
+
|
|
17
|
+
export type StepsProps = Omit<HTMLOlAttributes, 'children'> & {
|
|
18
|
+
/** In order, first to last. */
|
|
19
|
+
steps: StepsItem[];
|
|
20
|
+
/**
|
|
21
|
+
* The index of the current step, from 0. Steps before it are done,
|
|
22
|
+
* steps after it upcoming. `steps.length` marks every step done.
|
|
23
|
+
*/
|
|
24
|
+
current: number;
|
|
25
|
+
/**
|
|
26
|
+
* From which width the steps sit in a row of equal columns; narrower,
|
|
27
|
+
* they stack. Default `medium` (600px). Pick a later one when long
|
|
28
|
+
* labels or many steps would not fit their columns.
|
|
29
|
+
*/
|
|
30
|
+
rowFrom?: StepsBreakpoint;
|
|
31
|
+
/** Screen-reader text after a done step's label. Default `done`. */
|
|
32
|
+
doneLabel?: string;
|
|
33
|
+
};
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<script lang="ts">
|
|
37
|
+
let {
|
|
38
|
+
steps,
|
|
39
|
+
current,
|
|
40
|
+
rowFrom = 'medium',
|
|
41
|
+
doneLabel = 'done',
|
|
42
|
+
class: className,
|
|
43
|
+
...rest
|
|
44
|
+
}: StepsProps = $props();
|
|
45
|
+
|
|
46
|
+
function stateOf(index: number): StepsState {
|
|
47
|
+
return index < current ? 'done' : index === current ? 'current' : 'upcoming';
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<!--
|
|
52
|
+
Ordered steps as discrete segments (BRIEF, visual rule 7): each step has a
|
|
53
|
+
3px edge, titanium once reached and --border while upcoming, so the edges
|
|
54
|
+
read as a segmented bar. The current step adds the selection tint and
|
|
55
|
+
aria-current="step"; a done step shows a check for its number. A row from
|
|
56
|
+
`rowFrom` (600px by default), stacked below. When the current step
|
|
57
|
+
changes, the edges and the tint fade their colour over --dur-segment.
|
|
58
|
+
Extra attributes (an `aria-label` naming the process)
|
|
59
|
+
and `class` go to the <ol>.
|
|
60
|
+
-->
|
|
61
|
+
<ol role="list" {...rest} class={['hp-steps', className]} data-row-from={rowFrom}>
|
|
62
|
+
{#each steps as step, index}
|
|
63
|
+
{@const state = stateOf(index)}
|
|
64
|
+
<li class="hp-steps-step" data-state={state} aria-current={state === 'current' ? 'step' : undefined}>
|
|
65
|
+
<span class="hp-steps-mark" aria-hidden="true">
|
|
66
|
+
{#if state === 'done'}
|
|
67
|
+
<svg viewBox="0 0 16 16" width="16" height="16" focusable="false">
|
|
68
|
+
<path d="m3 8.5 3.5 3.5 6.5-7.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" />
|
|
69
|
+
</svg>
|
|
70
|
+
{:else}
|
|
71
|
+
{index + 1}
|
|
72
|
+
{/if}
|
|
73
|
+
</span>
|
|
74
|
+
<span class="hp-steps-label hp-label">{step.label}</span>
|
|
75
|
+
{#if state === 'done'}<span class="hp-visually-hidden">, {doneLabel}</span>{/if}
|
|
76
|
+
{#if step.detail}<span class="hp-steps-detail">{step.detail}</span>{/if}
|
|
77
|
+
</li>
|
|
78
|
+
{/each}
|
|
79
|
+
</ol>
|
|
80
|
+
|
|
81
|
+
<style>
|
|
82
|
+
/* Stacked below 600px. The edges and the current tint reach --bleed into
|
|
83
|
+
the gutter, so the labels keep the page edge, as table rows do. */
|
|
84
|
+
.hp-steps {
|
|
85
|
+
display: grid;
|
|
86
|
+
gap: var(--space-1);
|
|
87
|
+
margin: 0 calc(-1 * var(--bleed));
|
|
88
|
+
padding: 0;
|
|
89
|
+
list-style: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* The edge colour is a registered colour property, so it can transition
|
|
93
|
+
on its own while the edge's shape switches at once between the stacked
|
|
94
|
+
and the row form. */
|
|
95
|
+
@property --steps-edge {
|
|
96
|
+
syntax: '<color>';
|
|
97
|
+
inherits: false;
|
|
98
|
+
initial-value: transparent;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* When the current step changes, the edge and the tint fade their colour
|
|
102
|
+
over --dur-segment (BRIEF, short motion). A CSS transition never runs
|
|
103
|
+
on an element's first style, so steps show their state at once when
|
|
104
|
+
they render. 0ms is a snap. Colour only, so reduced motion keeps it.
|
|
105
|
+
The text colour and the number or check change at once. */
|
|
106
|
+
.hp-steps-step {
|
|
107
|
+
--steps-edge: var(--accent);
|
|
108
|
+
position: relative;
|
|
109
|
+
display: grid;
|
|
110
|
+
grid-template-columns: var(--space-4) minmax(0, 1fr);
|
|
111
|
+
column-gap: var(--space-2);
|
|
112
|
+
row-gap: var(--space-1);
|
|
113
|
+
align-content: start;
|
|
114
|
+
padding: var(--space-3) var(--space-3) var(--space-3) var(--bleed);
|
|
115
|
+
/* the brief's 3px selection edge */
|
|
116
|
+
box-shadow: inset 3px 0 0 var(--steps-edge);
|
|
117
|
+
overflow-wrap: anywhere;
|
|
118
|
+
transition:
|
|
119
|
+
--steps-edge var(--dur-segment) var(--settle),
|
|
120
|
+
background-color var(--dur-segment) var(--settle);
|
|
121
|
+
}
|
|
122
|
+
.hp-steps-step[data-state='current'] {
|
|
123
|
+
background: var(--surface-selected);
|
|
124
|
+
}
|
|
125
|
+
.hp-steps-step[data-state='upcoming'] {
|
|
126
|
+
--steps-edge: var(--border);
|
|
127
|
+
color: var(--muted);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* The number or the check, in a 16px box beside the label's first line. */
|
|
131
|
+
.hp-steps-mark {
|
|
132
|
+
display: grid;
|
|
133
|
+
place-items: center;
|
|
134
|
+
height: var(--space-4);
|
|
135
|
+
font-size: var(--type-label);
|
|
136
|
+
font-weight: 500;
|
|
137
|
+
line-height: 16px;
|
|
138
|
+
font-variant-numeric: tabular-nums;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.hp-steps-detail {
|
|
142
|
+
grid-column: 2;
|
|
143
|
+
color: var(--muted);
|
|
144
|
+
font-size: var(--type-body);
|
|
145
|
+
line-height: 24px;
|
|
146
|
+
}
|
|
147
|
+
@media (pointer: fine) {
|
|
148
|
+
.hp-steps-detail {
|
|
149
|
+
font-size: var(--type-dense);
|
|
150
|
+
line-height: 20px;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* A row of equal columns from the rowFrom width, the edge on top. A label
|
|
155
|
+
longer than its column still breaks rather than widen the page. */
|
|
156
|
+
@media (min-width: 600px) {
|
|
157
|
+
.hp-steps[data-row-from='medium'] {
|
|
158
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
159
|
+
grid-auto-flow: column;
|
|
160
|
+
}
|
|
161
|
+
[data-row-from='medium'] > .hp-steps-step {
|
|
162
|
+
padding: var(--space-4) var(--space-2) var(--space-3) var(--bleed);
|
|
163
|
+
/* the brief's 3px selection edge */
|
|
164
|
+
box-shadow: inset 0 3px 0 var(--steps-edge);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
@media (min-width: 900px) {
|
|
168
|
+
.hp-steps[data-row-from='expanded'] {
|
|
169
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
170
|
+
grid-auto-flow: column;
|
|
171
|
+
}
|
|
172
|
+
[data-row-from='expanded'] > .hp-steps-step {
|
|
173
|
+
padding: var(--space-4) var(--space-2) var(--space-3) var(--bleed);
|
|
174
|
+
/* the brief's 3px selection edge */
|
|
175
|
+
box-shadow: inset 0 3px 0 var(--steps-edge);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
@media (min-width: 1200px) {
|
|
179
|
+
.hp-steps[data-row-from='large'] {
|
|
180
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
181
|
+
grid-auto-flow: column;
|
|
182
|
+
}
|
|
183
|
+
[data-row-from='large'] > .hp-steps-step {
|
|
184
|
+
padding: var(--space-4) var(--space-2) var(--space-3) var(--bleed);
|
|
185
|
+
/* the brief's 3px selection edge */
|
|
186
|
+
box-shadow: inset 0 3px 0 var(--steps-edge);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
</style>
|