@scalewing/react 1.27.0 → 1.29.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/CHANGELOG.md +60 -0
- package/README.md +99 -3
- package/dist/components/Checkbox.js +5 -4
- package/dist/components/DenominationGrid.d.ts +4 -1
- package/dist/components/DenominationGrid.js +8 -3
- package/dist/components/Dialog.d.ts +28 -4
- package/dist/components/Dialog.js +20 -2
- package/dist/components/GlyphTile.d.ts +21 -0
- package/dist/components/GlyphTile.js +17 -0
- package/dist/components/MultiSelect.d.ts +10 -0
- package/dist/components/MultiSelect.js +62 -0
- package/dist/components/Notice.d.ts +69 -0
- package/dist/components/Notice.js +48 -0
- package/dist/components/Progress.d.ts +3 -1
- package/dist/components/Progress.js +4 -0
- package/dist/components/SegmentedControl.d.ts +8 -0
- package/dist/components/SegmentedControl.js +4 -3
- package/dist/components/Toast.d.ts +20 -4
- package/dist/components/Toast.js +44 -21
- package/dist/components/checkbox/CheckboxControl.d.ts +9 -0
- package/dist/components/checkbox/CheckboxControl.js +9 -0
- package/dist/components/denomination-grid/DenominationStrip.d.ts +5 -2
- package/dist/components/denomination-grid/DenominationStrip.js +2 -2
- package/dist/components/denomination-grid/DenominationTiles.d.ts +5 -2
- package/dist/components/denomination-grid/DenominationTiles.js +2 -2
- package/dist/components/denomination-grid/types.d.ts +9 -0
- package/dist/components/dialog/DialogFooter.d.ts +14 -0
- package/dist/components/dialog/DialogFooter.js +11 -0
- package/dist/components/dialog/DialogTitle.d.ts +11 -4
- package/dist/components/dialog/DialogTitle.js +8 -6
- package/dist/components/multi-select/MultiSelectPanel.d.ts +25 -0
- package/dist/components/multi-select/MultiSelectPanel.js +41 -0
- package/dist/components/multi-select/types.d.ts +35 -0
- package/dist/components/multi-select/types.js +1 -0
- package/dist/components/multi-select/validate.d.ts +3 -0
- package/dist/components/multi-select/validate.js +25 -0
- package/dist/components/toast/ToastContent.d.ts +22 -0
- package/dist/components/toast/ToastContent.js +21 -0
- package/dist/components/toast/use-toast-hold.d.ts +28 -0
- package/dist/components/toast/use-toast-hold.js +53 -0
- package/dist/components/toast/use-toast-timer.d.ts +15 -0
- package/dist/components/toast/use-toast-timer.js +34 -0
- package/dist/css/css-components.js +16 -0
- package/dist/css/css-denomination-grid.js +4 -0
- package/dist/css/css-denomination-label.d.ts +10 -0
- package/dist/css/css-denomination-label.js +36 -0
- package/dist/css/css-dialog-frame.d.ts +2 -0
- package/dist/css/css-dialog-frame.js +83 -0
- package/dist/css/css-dialog.js +20 -4
- package/dist/css/css-glyph-tile.d.ts +5 -0
- package/dist/css/css-glyph-tile.js +57 -0
- package/dist/css/css-multi-select.d.ts +2 -0
- package/dist/css/css-multi-select.js +156 -0
- package/dist/css/css-notice.d.ts +22 -0
- package/dist/css/css-notice.js +168 -0
- package/dist/css/css-progress.d.ts +3 -0
- package/dist/css/css-progress.js +13 -6
- package/dist/css/css-segmented.js +58 -0
- package/dist/css/css-toast-card.d.ts +5 -0
- package/dist/css/css-toast-card.js +122 -0
- package/dist/css/css-variables.js +12 -1
- package/dist/css/stacking.js +5 -2
- package/dist/css/stylesheet.js +10 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +7 -4
- package/dist/styles.css +522 -3
- package/package.json +2 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const noticeTones: readonly ["info", "success", "warning", "danger"];
|
|
2
|
+
export declare const noticeVariants: readonly ["default", "band"];
|
|
3
|
+
/** `default` is a rounded note in the flow; `band` a full-width strip of page chrome. */
|
|
4
|
+
export type NoticeVariant = (typeof noticeVariants)[number];
|
|
5
|
+
/** The notice's meaning: information, a good outcome, a caution, a refusal. */
|
|
6
|
+
export type NoticeTone = (typeof noticeTones)[number];
|
|
7
|
+
/**
|
|
8
|
+
* How much of a tone's color the notice's fill mixes into the surface. Info
|
|
9
|
+
* uses the derived accent tint instead (ADR 0011), which already keeps the
|
|
10
|
+
* accent readable on every palette.
|
|
11
|
+
*/
|
|
12
|
+
export declare const noticeTintShare = 0.1;
|
|
13
|
+
/**
|
|
14
|
+
* How far the notice's words move from the tone's color toward the text
|
|
15
|
+
* color, so they read darker than the tone on a light fill (lighter on a
|
|
16
|
+
* dark one) and keep 4.5:1 on the tint (`notice.test.tsx`).
|
|
17
|
+
*/
|
|
18
|
+
export declare const noticeInkTextShare = 0.3;
|
|
19
|
+
/** The semantic color a tone is drawn from. */
|
|
20
|
+
export declare function noticeToneColor(tone: NoticeTone): string;
|
|
21
|
+
export declare function cssNoticeClasses(): string;
|
|
22
|
+
export declare function noticeClassCatalog(): string[];
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
export const noticeTones = ['info', 'success', 'warning', 'danger'];
|
|
3
|
+
export const noticeVariants = ['default', 'band'];
|
|
4
|
+
/**
|
|
5
|
+
* How much of a tone's color the notice's fill mixes into the surface. Info
|
|
6
|
+
* uses the derived accent tint instead (ADR 0011), which already keeps the
|
|
7
|
+
* accent readable on every palette.
|
|
8
|
+
*/
|
|
9
|
+
export const noticeTintShare = 0.1;
|
|
10
|
+
/**
|
|
11
|
+
* How far the notice's words move from the tone's color toward the text
|
|
12
|
+
* color, so they read darker than the tone on a light fill (lighter on a
|
|
13
|
+
* dark one) and keep 4.5:1 on the tint (`notice.test.tsx`).
|
|
14
|
+
*/
|
|
15
|
+
export const noticeInkTextShare = 0.3;
|
|
16
|
+
/** The semantic color a tone is drawn from. */
|
|
17
|
+
export function noticeToneColor(tone) {
|
|
18
|
+
return tone === 'info' ? 'accent' : tone;
|
|
19
|
+
}
|
|
20
|
+
function toneFill(tone) {
|
|
21
|
+
if (tone === 'info')
|
|
22
|
+
return 'var(--sw-color-accentSubtle)';
|
|
23
|
+
return `color-mix(in srgb, var(--sw-color-${tone}) ${noticeTintShare * 100}%, var(--sw-color-surface))`;
|
|
24
|
+
}
|
|
25
|
+
function toneInk(tone) {
|
|
26
|
+
const toneShare = Math.round((1 - noticeInkTextShare) * 100);
|
|
27
|
+
return `color-mix(in srgb, var(--sw-color-${noticeToneColor(tone)}) ${toneShare}%, var(--sw-color-text))`;
|
|
28
|
+
}
|
|
29
|
+
function toneRules() {
|
|
30
|
+
return noticeTones
|
|
31
|
+
.map((tone) => `.sw-notice-${tone} { --sw-notice-fill: ${toneFill(tone)}; --sw-notice-ink: ${toneInk(tone)}; }`)
|
|
32
|
+
.join('\n');
|
|
33
|
+
}
|
|
34
|
+
const label = typographyVariants.label;
|
|
35
|
+
const body = typographyVariants.body;
|
|
36
|
+
const caption = typographyVariants.caption;
|
|
37
|
+
/*
|
|
38
|
+
* A tinted block in the page: the tone's fill, its words in the tone's ink,
|
|
39
|
+
* label-size type. An optional glyph leads; the title (a bold lead) and a
|
|
40
|
+
* text message share a row while they fit and wrap under one another when
|
|
41
|
+
* they do not; a message of elements (a field, a checkbox) is stacked under
|
|
42
|
+
* the title. An action ends the row (a small Button
|
|
43
|
+
* overhangs the padding rather than growing it) and drops under the text on
|
|
44
|
+
* a narrow column. Controls inside keep their own colors. Forced
|
|
45
|
+
* colors draw a border instead of the fill.
|
|
46
|
+
*/
|
|
47
|
+
export function cssNoticeClasses() {
|
|
48
|
+
return `${toneRules()}
|
|
49
|
+
|
|
50
|
+
.sw-notice {
|
|
51
|
+
align-items: flex-start;
|
|
52
|
+
background: var(--sw-notice-fill);
|
|
53
|
+
border-radius: var(--sw-radius-sm);
|
|
54
|
+
box-sizing: border-box;
|
|
55
|
+
color: var(--sw-notice-ink);
|
|
56
|
+
column-gap: var(--sw-space-2);
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-wrap: wrap;
|
|
59
|
+
font-family: var(--sw-font-sans);
|
|
60
|
+
font-size: ${label.fontSize}px;
|
|
61
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
62
|
+
line-height: ${label.lineHeight}px;
|
|
63
|
+
min-width: 0;
|
|
64
|
+
padding: var(--sw-space-2) var(--sw-space-3);
|
|
65
|
+
row-gap: var(--sw-space-2);
|
|
66
|
+
/* Muted words of a control inside (a field's or a checkbox's
|
|
67
|
+
description) take the ink, which keeps 4.5:1 on the fill. */
|
|
68
|
+
--sw-color-muted: var(--sw-notice-ink);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.sw-notice-icon {
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
flex: none;
|
|
74
|
+
min-height: ${label.lineHeight}px;
|
|
75
|
+
align-items: center;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.sw-notice-content {
|
|
79
|
+
align-items: baseline;
|
|
80
|
+
column-gap: var(--sw-space-2);
|
|
81
|
+
display: flex;
|
|
82
|
+
flex: 1 1 16rem;
|
|
83
|
+
flex-wrap: wrap;
|
|
84
|
+
min-width: 0;
|
|
85
|
+
row-gap: var(--sw-space-1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.sw-notice-stacked {
|
|
89
|
+
align-items: stretch;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
row-gap: var(--sw-space-2);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.sw-notice-title {
|
|
95
|
+
font-weight: ${label.fontWeight};
|
|
96
|
+
min-width: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.sw-notice-body {
|
|
100
|
+
flex: 1 1 auto;
|
|
101
|
+
font-weight: ${body.fontWeight};
|
|
102
|
+
min-width: 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.sw-notice-action {
|
|
106
|
+
align-items: center;
|
|
107
|
+
align-self: flex-start;
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
flex: none;
|
|
110
|
+
min-height: ${label.lineHeight}px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* A small Button keeps the note one text line tall: it overhangs the
|
|
114
|
+
padding evenly instead of growing the row. */
|
|
115
|
+
.sw-notice-action > .sw-button {
|
|
116
|
+
margin-block: calc((${label.lineHeight}px - var(--sw-control-sm-min-height)) / 2);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* A band across the page's full width, such as an environment strip
|
|
120
|
+
above the app header: square, the xs control height, caption type,
|
|
121
|
+
its words centered on one line that wraps on a phone. A glyph or an
|
|
122
|
+
action stays on the words' row (no wrap): the words wrap instead. */
|
|
123
|
+
.sw-notice-band {
|
|
124
|
+
align-items: center;
|
|
125
|
+
border-radius: 0;
|
|
126
|
+
flex-wrap: nowrap;
|
|
127
|
+
font-size: ${caption.fontSize}px;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
130
|
+
line-height: ${caption.lineHeight}px;
|
|
131
|
+
min-height: var(--sw-control-xs-min-height);
|
|
132
|
+
padding: var(--sw-space-1) var(--sw-space-4);
|
|
133
|
+
text-align: center;
|
|
134
|
+
width: 100%;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.sw-notice-band .sw-notice-content {
|
|
138
|
+
flex: 0 1 auto;
|
|
139
|
+
justify-content: center;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.sw-notice-band .sw-notice-icon,
|
|
143
|
+
.sw-notice-band .sw-notice-action { min-height: ${caption.lineHeight}px; }
|
|
144
|
+
|
|
145
|
+
.sw-notice-band .sw-notice-action { align-self: center; }
|
|
146
|
+
|
|
147
|
+
.sw-notice-band .sw-notice-action > .sw-button {
|
|
148
|
+
margin-block: calc((${caption.lineHeight}px - var(--sw-control-sm-min-height)) / 2);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@media (forced-colors: active) {
|
|
152
|
+
.sw-notice { border: 1px solid CanvasText; }
|
|
153
|
+
.sw-notice-band { border-width: 0 0 1px; }
|
|
154
|
+
}`;
|
|
155
|
+
}
|
|
156
|
+
export function noticeClassCatalog() {
|
|
157
|
+
return [
|
|
158
|
+
'sw-notice',
|
|
159
|
+
...noticeTones.map((tone) => `sw-notice-${tone}`),
|
|
160
|
+
'sw-notice-icon',
|
|
161
|
+
'sw-notice-content',
|
|
162
|
+
'sw-notice-stacked',
|
|
163
|
+
'sw-notice-title',
|
|
164
|
+
'sw-notice-body',
|
|
165
|
+
'sw-notice-action',
|
|
166
|
+
'sw-notice-band',
|
|
167
|
+
];
|
|
168
|
+
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
+
export declare const progressTones: readonly ["accent", "success", "warning", "danger"];
|
|
2
|
+
/** The bar's color: the accent, or success, warning (time running out) or danger. */
|
|
3
|
+
export type ProgressTone = (typeof progressTones)[number];
|
|
1
4
|
export declare function cssProgressClasses(): string;
|
|
2
5
|
export declare function progressClassCatalog(): string[];
|
package/dist/css/css-progress.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
export const progressTones = [
|
|
3
|
+
'accent',
|
|
4
|
+
'success',
|
|
5
|
+
'warning',
|
|
6
|
+
'danger',
|
|
7
|
+
];
|
|
8
|
+
function toneRules() {
|
|
9
|
+
return progressTones
|
|
10
|
+
.map((tone) => `.sw-progress-${tone} { --sw-progress-color: var(--sw-color-${tone}); }`)
|
|
11
|
+
.join('\n');
|
|
12
|
+
}
|
|
2
13
|
const label = typographyVariants.label;
|
|
3
14
|
const caption = typographyVariants.caption;
|
|
4
15
|
export function cssProgressClasses() {
|
|
@@ -11,9 +22,7 @@ export function cssProgressClasses() {
|
|
|
11
22
|
width: 100%;
|
|
12
23
|
}
|
|
13
24
|
|
|
14
|
-
|
|
15
|
-
.sw-progress-success { --sw-progress-color: var(--sw-color-success); }
|
|
16
|
-
.sw-progress-danger { --sw-progress-color: var(--sw-color-danger); }
|
|
25
|
+
${toneRules()}
|
|
17
26
|
|
|
18
27
|
.sw-progress-heading {
|
|
19
28
|
align-items: baseline;
|
|
@@ -66,9 +75,7 @@ export function cssProgressClasses() {
|
|
|
66
75
|
export function progressClassCatalog() {
|
|
67
76
|
return [
|
|
68
77
|
'sw-progress',
|
|
69
|
-
|
|
70
|
-
'sw-progress-success',
|
|
71
|
-
'sw-progress-danger',
|
|
78
|
+
...progressTones.map((tone) => `sw-progress-${tone}`),
|
|
72
79
|
'sw-progress-heading',
|
|
73
80
|
'sw-progress-label',
|
|
74
81
|
'sw-progress-count',
|
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
import { trackInset, typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
const body = typographyVariants.body;
|
|
3
3
|
const data = typographyVariants.data;
|
|
4
|
+
const label = typographyVariants.label;
|
|
5
|
+
/*
|
|
6
|
+
* Items with a mark (a glyph tile before the label) centre the mark and
|
|
7
|
+
* the label a space-2 gap apart; the mark keeps its size. On the compact
|
|
8
|
+
* track every item also takes the md control height and label type, so
|
|
9
|
+
* the row stays even; the track is the subtle fill (two classes, so
|
|
10
|
+
* reduced transparency keeps it) and the selected item is the surface
|
|
11
|
+
* raised by the small elevation, so the choice shows on a white canvas
|
|
12
|
+
* too. A filled track keeps its own look and only gains the marks. The
|
|
13
|
+
* error outline is restated after these rules so an icon track keeps it.
|
|
14
|
+
* In forced colours the selected item is outlined in Highlight; a focused
|
|
15
|
+
* selected item keeps that outline, offset by the focus ring's offset.
|
|
16
|
+
*/
|
|
17
|
+
function iconRules() {
|
|
18
|
+
const compact = '.sw-segmented-with-icons:not(.sw-segmented-filled)';
|
|
19
|
+
return `.sw-segmented${compact} {
|
|
20
|
+
background: var(--sw-color-subtle);
|
|
21
|
+
border-color: transparent;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
${compact} .sw-segmented-item-selected {
|
|
25
|
+
box-shadow: var(--sw-elevation-sm);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.sw-segmented-with-icons .sw-segmented-item {
|
|
29
|
+
align-items: center;
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
gap: var(--sw-space-2);
|
|
32
|
+
justify-content: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
${compact} .sw-segmented-item {
|
|
36
|
+
font-size: ${label.fontSize}px;
|
|
37
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
38
|
+
line-height: ${label.lineHeight}px;
|
|
39
|
+
min-height: var(--sw-control-md-min-height);
|
|
40
|
+
padding-inline: var(--sw-space-2) var(--sw-space-3);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.sw-segmented-item-icon {
|
|
44
|
+
display: inline-flex;
|
|
45
|
+
flex: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.sw-segmented.sw-segmented-with-icons[aria-invalid='true'] {
|
|
49
|
+
border-color: var(--sw-color-danger);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@media (forced-colors: active) {
|
|
53
|
+
.sw-segmented${compact} { border-color: CanvasText; }
|
|
54
|
+
${compact} .sw-segmented-item-selected { outline: 2px solid Highlight; }
|
|
55
|
+
.sw-segmented.sw-segmented-with-icons[aria-invalid='true'] { border-color: Mark; }
|
|
56
|
+
}`;
|
|
57
|
+
}
|
|
4
58
|
/*
|
|
5
59
|
* The control and its error message. The wrapper takes the track's place in
|
|
6
60
|
* the layout: inline beside text and stretched in a Stack (compact), block
|
|
@@ -106,6 +160,8 @@ export function cssSegmentedClasses() {
|
|
|
106
160
|
color: var(--sw-color-onAccent);
|
|
107
161
|
}
|
|
108
162
|
|
|
163
|
+
${iconRules()}
|
|
164
|
+
|
|
109
165
|
.sw-segmented-disabled {
|
|
110
166
|
opacity: var(--sw-disabled-opacity);
|
|
111
167
|
}
|
|
@@ -122,6 +178,8 @@ export function segmentedClassCatalog() {
|
|
|
122
178
|
'sw-segmented-item',
|
|
123
179
|
'sw-segmented-item-selected',
|
|
124
180
|
'sw-segmented-filled',
|
|
181
|
+
'sw-segmented-with-icons',
|
|
182
|
+
'sw-segmented-item-icon',
|
|
125
183
|
'sw-segmented-disabled',
|
|
126
184
|
];
|
|
127
185
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const toastPlacements: readonly ["bottom", "top-end"];
|
|
2
|
+
/** Where a toast that does not travel shows: centered at the bottom, or the top end corner. */
|
|
3
|
+
export type ToastPlacement = (typeof toastPlacements)[number];
|
|
4
|
+
export declare function cssToastCardClasses(): string;
|
|
5
|
+
export declare function toastCardClassCatalog(): string[];
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { toastMaxWidth } from './css-toast.js';
|
|
3
|
+
export const toastPlacements = ['bottom', 'top-end'];
|
|
4
|
+
const label = typographyVariants.label;
|
|
5
|
+
const body = typographyVariants.body;
|
|
6
|
+
/*
|
|
7
|
+
* The toast as a card: a bold title over a muted detail, an action at the
|
|
8
|
+
* end of the row, and a thin line that runs down with the time left.
|
|
9
|
+
*
|
|
10
|
+
* `top-end` puts it in the top corner at the end of the line, clear of the
|
|
11
|
+
* safe area, at most a dialog's reading width; it drops in from above. A
|
|
12
|
+
* toast with an action or the remaining line takes the pointer, so hover
|
|
13
|
+
* can hold it (and the action can be pressed); the bottom toast stays
|
|
14
|
+
* click-through. The line is a scale from full to empty over the toast's
|
|
15
|
+
* duration (`--sw-toast-duration`), held while the toast is paused; it is
|
|
16
|
+
* a measure of time, not decoration, so it runs under reduced motion too.
|
|
17
|
+
*/
|
|
18
|
+
export function cssToastCardClasses() {
|
|
19
|
+
return `.sw-toast-title {
|
|
20
|
+
display: block;
|
|
21
|
+
font-size: ${label.fontSize}px;
|
|
22
|
+
font-weight: ${label.fontWeight};
|
|
23
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
24
|
+
line-height: ${label.lineHeight}px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.sw-toast-detail {
|
|
28
|
+
color: var(--sw-color-muted);
|
|
29
|
+
font-size: ${label.fontSize}px;
|
|
30
|
+
font-weight: ${body.fontWeight};
|
|
31
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
32
|
+
line-height: ${label.lineHeight}px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sw-toast-row:has(.sw-toast-title) { align-items: flex-start; }
|
|
36
|
+
|
|
37
|
+
.sw-toast-row .sw-toast-body { flex: 1 1 auto; }
|
|
38
|
+
|
|
39
|
+
.sw-button.sw-toast-action {
|
|
40
|
+
flex: none;
|
|
41
|
+
margin-block: calc((${label.lineHeight}px - var(--sw-control-sm-min-height)) / 2);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.sw-toast-interactive { pointer-events: auto; }
|
|
45
|
+
|
|
46
|
+
.sw-toast-top-end {
|
|
47
|
+
bottom: auto;
|
|
48
|
+
left: auto;
|
|
49
|
+
max-width: min(var(--sw-dialog-max), ${toastMaxWidth});
|
|
50
|
+
right: max(var(--sw-space-4), env(safe-area-inset-right, 0px));
|
|
51
|
+
top: max(var(--sw-space-4), env(safe-area-inset-top, 0px));
|
|
52
|
+
translate: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sw-toast-top-end:dir(rtl) {
|
|
56
|
+
left: max(var(--sw-space-4), env(safe-area-inset-left, 0px));
|
|
57
|
+
right: auto;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.sw-toast-top-end:popover-open {
|
|
61
|
+
animation: sw-toast-drop var(--sw-motion-default) var(--sw-motion-easing);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@keyframes sw-toast-drop {
|
|
65
|
+
from {
|
|
66
|
+
opacity: 0;
|
|
67
|
+
translate: 0 calc(-1 * var(--sw-space-3));
|
|
68
|
+
}
|
|
69
|
+
to {
|
|
70
|
+
opacity: 1;
|
|
71
|
+
translate: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.sw-toast-remaining {
|
|
76
|
+
background: var(--sw-color-border);
|
|
77
|
+
border-radius: var(--sw-radius-pill);
|
|
78
|
+
display: block;
|
|
79
|
+
height: var(--sw-space-1);
|
|
80
|
+
margin-top: var(--sw-space-2);
|
|
81
|
+
overflow: hidden;
|
|
82
|
+
position: relative;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.sw-toast-remaining::after {
|
|
86
|
+
animation: sw-toast-remaining var(--sw-toast-duration, 0ms) linear forwards;
|
|
87
|
+
background: var(--sw-toast-tone, var(--sw-color-accent));
|
|
88
|
+
content: '';
|
|
89
|
+
inset: 0;
|
|
90
|
+
position: absolute;
|
|
91
|
+
transform-origin: left center;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.sw-toast-remaining:dir(rtl)::after { transform-origin: right center; }
|
|
95
|
+
|
|
96
|
+
.sw-toast-paused .sw-toast-remaining::after { animation-play-state: paused; }
|
|
97
|
+
|
|
98
|
+
@keyframes sw-toast-remaining {
|
|
99
|
+
from { transform: scaleX(1); }
|
|
100
|
+
to { transform: scaleX(0); }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@media (prefers-reduced-motion: reduce) {
|
|
104
|
+
.sw-toast-top-end:popover-open { animation: none; }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@media (forced-colors: active) {
|
|
108
|
+
.sw-toast-remaining { background: Canvas; border: 1px solid CanvasText; }
|
|
109
|
+
.sw-toast-remaining::after { background: CanvasText; }
|
|
110
|
+
}`;
|
|
111
|
+
}
|
|
112
|
+
export function toastCardClassCatalog() {
|
|
113
|
+
return [
|
|
114
|
+
'sw-toast-title',
|
|
115
|
+
'sw-toast-detail',
|
|
116
|
+
'sw-toast-action',
|
|
117
|
+
'sw-toast-interactive',
|
|
118
|
+
'sw-toast-top-end',
|
|
119
|
+
'sw-toast-remaining',
|
|
120
|
+
'sw-toast-paused',
|
|
121
|
+
];
|
|
122
|
+
}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import { controlScale, disabledOpacity, focusRing, quietOpacity, radiusScale, secondaryActionBorder, semanticColorKeys, spacingScale, spacingSteps, splitScale, } from '@scalewing/tokens';
|
|
1
|
+
import { categoricalColorKeys, categoricalColors, onCategorical, controlScale, disabledOpacity, focusRing, quietOpacity, radiusScale, secondaryActionBorder, semanticColorKeys, spacingScale, spacingSteps, splitScale, } from '@scalewing/tokens';
|
|
2
2
|
function colorDeclarations(theme) {
|
|
3
3
|
return [
|
|
4
4
|
...semanticColorKeys.map((key) => ` --sw-color-${key}: ${theme.colors[key]};`),
|
|
5
5
|
` --sw-button-secondary-border: ${secondaryActionBorder(theme.colors)};`,
|
|
6
6
|
].join('\n');
|
|
7
7
|
}
|
|
8
|
+
/* The categorical fills of the theme's scheme and the glyph drawn on them. */
|
|
9
|
+
function categoricalDeclarations(theme) {
|
|
10
|
+
const fills = categoricalColors[theme.colorScheme];
|
|
11
|
+
return [
|
|
12
|
+
...categoricalColorKeys.map((key) => ` --sw-categorical-${key}: ${fills[key]};`),
|
|
13
|
+
` --sw-categorical-on: ${onCategorical};`,
|
|
14
|
+
].join('\n');
|
|
15
|
+
}
|
|
8
16
|
function glassDeclarations(theme) {
|
|
9
17
|
return ` --sw-glass-blur: ${theme.glass.blur}px;
|
|
10
18
|
--sw-glass-saturate: ${theme.glass.saturate};
|
|
@@ -38,6 +46,7 @@ ${control}
|
|
|
38
46
|
--sw-container-max: 72rem;
|
|
39
47
|
--sw-dialog-max: 32rem;
|
|
40
48
|
--sw-dialog-max-lg: 56rem;
|
|
49
|
+
--sw-dialog-max-xl: 65rem;
|
|
41
50
|
--sw-select-max: 16rem;
|
|
42
51
|
--sw-split-min: ${splitScale.min}rem;
|
|
43
52
|
--sw-split-size: ${splitScale.size}rem;
|
|
@@ -53,11 +62,13 @@ export function cssVariables(light, dark) {
|
|
|
53
62
|
return `:root,
|
|
54
63
|
[data-theme='light'] {
|
|
55
64
|
${colorDeclarations(light)}
|
|
65
|
+
${categoricalDeclarations(light)}
|
|
56
66
|
${sharedDeclarations(light)}
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
[data-theme='dark'] {
|
|
60
70
|
${colorDeclarations(dark)}
|
|
71
|
+
${categoricalDeclarations(dark)}
|
|
61
72
|
${sharedDeclarations(dark)}
|
|
62
73
|
}`;
|
|
63
74
|
}
|
package/dist/css/stacking.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* surface that scrolls up under it (the header is the page's way back, the
|
|
15
15
|
* strip its way between sections, and a popup opens downward).
|
|
16
16
|
* 5. `popup`: a popup outside any lifted surface (Select list, ActionMenu
|
|
17
|
-
* list, Tooltip, the DateField and CalendarButton
|
|
18
|
-
* everything in the page.
|
|
17
|
+
* list, MultiSelect panel, Tooltip, the DateField and CalendarButton
|
|
18
|
+
* calendar) over everything in the page.
|
|
19
19
|
*
|
|
20
20
|
* Dialog and Toast sit on the browser's top layer, above all of these.
|
|
21
21
|
*/
|
|
@@ -33,6 +33,9 @@ const openPopups = [
|
|
|
33
33
|
'.sw-select-list',
|
|
34
34
|
// Rendered only while open; on the top layer where the popover API exists.
|
|
35
35
|
'.sw-action-menu-list',
|
|
36
|
+
// MultiSelect's panel. Rendered only while open; on the top layer where
|
|
37
|
+
// the popover API exists.
|
|
38
|
+
'.sw-multi-select-panel',
|
|
36
39
|
'.sw-tooltip:not([hidden])',
|
|
37
40
|
// DateField and CalendarButton share it. Rendered only while open; on the
|
|
38
41
|
// top layer where the popover API exists.
|
package/dist/css/stylesheet.js
CHANGED
|
@@ -9,6 +9,8 @@ import { checkboxClassCatalog } from './css-checkbox.js';
|
|
|
9
9
|
import { radioGroupClassCatalog } from './css-radio-group.js';
|
|
10
10
|
import { spinnerClassCatalog } from './css-spinner.js';
|
|
11
11
|
import { progressClassCatalog } from './css-progress.js';
|
|
12
|
+
import { noticeClassCatalog } from './css-notice.js';
|
|
13
|
+
import { glyphTileClassCatalog } from './css-glyph-tile.js';
|
|
12
14
|
import { tooltipClassCatalog } from './css-tooltip.js';
|
|
13
15
|
import { infoTipClassCatalog } from './css-info-tip.js';
|
|
14
16
|
import { separatorClassCatalog } from './css-separator.js';
|
|
@@ -34,9 +36,12 @@ import { tableClassCatalog } from './css-table.js';
|
|
|
34
36
|
import { chromeClassCatalog } from './css-chrome.js';
|
|
35
37
|
import { sectionNavClassCatalog } from './css-section-nav.js';
|
|
36
38
|
import { dialogClassCatalog } from './css-dialog.js';
|
|
39
|
+
import { dialogFrameClassCatalog } from './css-dialog-frame.js';
|
|
37
40
|
import { selectClassCatalog } from './css-select.js';
|
|
41
|
+
import { multiSelectClassCatalog } from './css-multi-select.js';
|
|
38
42
|
import { splitClassCatalog } from './css-split.js';
|
|
39
43
|
import { toastClassCatalog } from './css-toast.js';
|
|
44
|
+
import { toastCardClassCatalog } from './css-toast-card.js';
|
|
40
45
|
import { cssDocumentCanvas } from './css-document.js';
|
|
41
46
|
import { cssPaletteAttributes } from './css-palettes.js';
|
|
42
47
|
import { cssUtilities } from './css-utilities.js';
|
|
@@ -64,9 +69,11 @@ export function utilityClassCatalog() {
|
|
|
64
69
|
...chromeClassCatalog(),
|
|
65
70
|
...sectionNavClassCatalog(),
|
|
66
71
|
...dialogClassCatalog(),
|
|
72
|
+
...dialogFrameClassCatalog(),
|
|
67
73
|
...accordionClassCatalog(),
|
|
68
74
|
...selectClassCatalog(),
|
|
69
75
|
...actionMenuClassCatalog(),
|
|
76
|
+
...multiSelectClassCatalog(),
|
|
70
77
|
...actionBarClassCatalog(),
|
|
71
78
|
...switchClassCatalog(),
|
|
72
79
|
...dateFieldClassCatalog(),
|
|
@@ -75,6 +82,8 @@ export function utilityClassCatalog() {
|
|
|
75
82
|
...radioGroupClassCatalog(),
|
|
76
83
|
...spinnerClassCatalog(),
|
|
77
84
|
...progressClassCatalog(),
|
|
85
|
+
...noticeClassCatalog(),
|
|
86
|
+
...glyphTileClassCatalog(),
|
|
78
87
|
...tooltipClassCatalog(),
|
|
79
88
|
...infoTipClassCatalog(),
|
|
80
89
|
...separatorClassCatalog(),
|
|
@@ -90,6 +99,7 @@ export function utilityClassCatalog() {
|
|
|
90
99
|
...stepsClassCatalog(),
|
|
91
100
|
...splitClassCatalog(),
|
|
92
101
|
...toastClassCatalog(),
|
|
102
|
+
...toastCardClassCatalog(),
|
|
93
103
|
...responsiveClassCatalog(),
|
|
94
104
|
...boxBorderClassCatalog(),
|
|
95
105
|
];
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,9 @@ export { DateField, type DateFieldLabels, type DateFieldProps, type WeekStart, }
|
|
|
7
7
|
export { CalendarButton, type CalendarButtonLabels, type CalendarButtonProps, type CalendarButtonRange, } from './components/CalendarButton.js';
|
|
8
8
|
export { Checkbox, type CheckboxProps } from './components/Checkbox.js';
|
|
9
9
|
export { Spinner, type SpinnerProps, type SpinnerSize, } from './components/Spinner.js';
|
|
10
|
-
export {
|
|
10
|
+
export { GlyphTile, glyphTileSizes, type GlyphTileHue, type GlyphTileProps, type GlyphTileSize, } from './components/GlyphTile.js';
|
|
11
|
+
export { Notice, noticeTones, noticeVariants, type NoticeProps, type NoticeRole, type NoticeTone, type NoticeVariant, } from './components/Notice.js';
|
|
12
|
+
export { Progress, progressTones, type ProgressProps, type ProgressTone, } from './components/Progress.js';
|
|
11
13
|
export { Tooltip, type TooltipProps, type TooltipRelationship, } from './components/Tooltip.js';
|
|
12
14
|
export { InfoTip, type InfoTipProps } from './components/InfoTip.js';
|
|
13
15
|
export { RadioGroup, type RadioGroupOption, type RadioGroupProps, } from './components/RadioGroup.js';
|
|
@@ -18,10 +20,10 @@ export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, } from '
|
|
|
18
20
|
export { Box, type BoxBorder, type BoxElement, type BoxProps, } from './components/Box.js';
|
|
19
21
|
export { ButtonGroup, type ButtonGroupJustify, type ButtonGroupProps, } from './components/ButtonGroup.js';
|
|
20
22
|
export { Card, type CardProps, type CardVariant } from './components/Card.js';
|
|
21
|
-
export { Dialog, type DialogProps, type DialogSize, type DialogTitleLevel, } from './components/Dialog.js';
|
|
23
|
+
export { Dialog, dialogSizes, type DialogProps, type DialogRole, type DialogSize, type DialogTitleLevel, } from './components/Dialog.js';
|
|
22
24
|
export { StatTile, type StatTileEmphasis, type StatTileProps, type StatTileTone, statTileTones, } from './components/StatTile.js';
|
|
23
25
|
export { TabPanel, type TabItem, type TabPanelProps, Tabs, type TabsProps, tabId, tabPanelId, } from './components/Tabs.js';
|
|
24
|
-
export { Toast, toastTones } from './components/Toast.js';
|
|
26
|
+
export { Toast, toastPlacements, toastTones, type ToastAction, type ToastPlacement, } from './components/Toast.js';
|
|
25
27
|
export type { ToastProps, ToastTone } from './components/Toast.js';
|
|
26
28
|
export { Field, type FieldProps, type FieldSize } from './components/Field.js';
|
|
27
29
|
export { Step, type StepHeadingLevel, type StepProps, Steps, type StepsLabels, type StepsProps, type StepStatus, } from './components/Steps.js';
|
|
@@ -34,6 +36,7 @@ export { SectionNav, type SectionNavItem, type SectionNavProps, } from './compon
|
|
|
34
36
|
export { SegmentedControl, type SegmentedControlProps, type SegmentedControlVariant, type SegmentedItem, } from './components/SegmentedControl.js';
|
|
35
37
|
export { Select } from './components/Select.js';
|
|
36
38
|
export type { SelectAction, SelectOption, SelectProps, SelectWidth, } from './components/Select.js';
|
|
39
|
+
export { MultiSelect, type MultiSelectAlign, type MultiSelectOption, type MultiSelectProps, } from './components/MultiSelect.js';
|
|
37
40
|
export { Stack, type Align, type Justify, type StackProps, } from './components/Stack.js';
|
|
38
41
|
export { Table, TableBody, TableCell, TableHeader, TableRow, type TableBodyProps, type TableCellProps, type TableColumnWidth, type TableDensity, type TableHeaderProps, type TableLayout, type TableProps, type TableRowProps, type TableSort, type TableVerticalAlign, } from './components/Table.js';
|
|
39
42
|
export { Text, type TextAlign, type TextElement, type TextProps, } from './components/Text.js';
|
|
@@ -50,7 +53,7 @@ export { Grid } from './components/Grid.js';
|
|
|
50
53
|
export type { GridColumns, GridProps } from './components/Grid.js';
|
|
51
54
|
export type { GridColumnSpan } from './css/css-grid-span.js';
|
|
52
55
|
export type { ColumnSpanProps } from './column-span-classes.js';
|
|
53
|
-
export { DenominationGrid } from './components/DenominationGrid.js';
|
|
54
|
-
export type { DenominationGridColumn, DenominationGridEntry, DenominationGridLayout, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationLabelWidth, } from './components/DenominationGrid.js';
|
|
56
|
+
export { DenominationGrid, denominationLabelAppearances, } from './components/DenominationGrid.js';
|
|
57
|
+
export type { DenominationGridColumn, DenominationGridEntry, DenominationGridLayout, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationLabelAppearance, DenominationLabelWidth, } from './components/DenominationGrid.js';
|
|
55
58
|
export { FilterChips } from './components/FilterChips.js';
|
|
56
59
|
export type { FilterChipOption, FilterChipsProps, } from './components/FilterChips.js';
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,9 @@ export { DateField, } from './components/DateField.js';
|
|
|
6
6
|
export { CalendarButton, } from './components/CalendarButton.js';
|
|
7
7
|
export { Checkbox } from './components/Checkbox.js';
|
|
8
8
|
export { Spinner, } from './components/Spinner.js';
|
|
9
|
-
export {
|
|
9
|
+
export { GlyphTile, glyphTileSizes, } from './components/GlyphTile.js';
|
|
10
|
+
export { Notice, noticeTones, noticeVariants, } from './components/Notice.js';
|
|
11
|
+
export { Progress, progressTones, } from './components/Progress.js';
|
|
10
12
|
export { Tooltip, } from './components/Tooltip.js';
|
|
11
13
|
export { InfoTip } from './components/InfoTip.js';
|
|
12
14
|
export { RadioGroup, } from './components/RadioGroup.js';
|
|
@@ -17,10 +19,10 @@ export { Button, } from './components/Button.js';
|
|
|
17
19
|
export { Box, } from './components/Box.js';
|
|
18
20
|
export { ButtonGroup, } from './components/ButtonGroup.js';
|
|
19
21
|
export { Card } from './components/Card.js';
|
|
20
|
-
export { Dialog, } from './components/Dialog.js';
|
|
22
|
+
export { Dialog, dialogSizes, } from './components/Dialog.js';
|
|
21
23
|
export { StatTile, statTileTones, } from './components/StatTile.js';
|
|
22
24
|
export { TabPanel, Tabs, tabId, tabPanelId, } from './components/Tabs.js';
|
|
23
|
-
export { Toast, toastTones } from './components/Toast.js';
|
|
25
|
+
export { Toast, toastPlacements, toastTones, } from './components/Toast.js';
|
|
24
26
|
export { Field } from './components/Field.js';
|
|
25
27
|
export { Step, Steps, } from './components/Steps.js';
|
|
26
28
|
export { Stepper, } from './components/Stepper.js';
|
|
@@ -30,6 +32,7 @@ export { Nav } from './components/Nav.js';
|
|
|
30
32
|
export { SectionNav, } from './components/SectionNav.js';
|
|
31
33
|
export { SegmentedControl, } from './components/SegmentedControl.js';
|
|
32
34
|
export { Select } from './components/Select.js';
|
|
35
|
+
export { MultiSelect, } from './components/MultiSelect.js';
|
|
33
36
|
export { Stack, } from './components/Stack.js';
|
|
34
37
|
export { Table, TableBody, TableCell, TableHeader, TableRow, } from './components/Table.js';
|
|
35
38
|
export { Text, } from './components/Text.js';
|
|
@@ -39,5 +42,5 @@ export { breakpointQuery } from './css/breakpoints.js';
|
|
|
39
42
|
export { Separator } from './components/Separator.js';
|
|
40
43
|
export { DescriptionItem, DescriptionList, } from './components/DescriptionList.js';
|
|
41
44
|
export { Grid } from './components/Grid.js';
|
|
42
|
-
export { DenominationGrid } from './components/DenominationGrid.js';
|
|
45
|
+
export { DenominationGrid, denominationLabelAppearances, } from './components/DenominationGrid.js';
|
|
43
46
|
export { FilterChips } from './components/FilterChips.js';
|