@scalewing/react 1.31.0 → 1.32.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 +30 -0
- package/README.md +19 -5
- package/dist/components/ActionMenu.d.ts +10 -1
- package/dist/components/ActionMenu.js +7 -2
- package/dist/components/AppHeader.d.ts +9 -1
- package/dist/components/AppHeader.js +6 -2
- package/dist/components/Box.d.ts +10 -2
- package/dist/components/Button.d.ts +27 -2
- package/dist/components/Button.js +5 -3
- package/dist/components/ButtonGroup.d.ts +9 -1
- package/dist/components/ButtonGroup.js +8 -2
- package/dist/components/Combobox.js +2 -2
- package/dist/components/DateField.d.ts +9 -1
- package/dist/components/DateField.js +4 -3
- package/dist/components/DenominationGrid.d.ts +5 -3
- package/dist/components/DenominationGrid.js +21 -11
- package/dist/components/Dialog.d.ts +9 -1
- package/dist/components/Dialog.js +8 -4
- package/dist/components/Field.d.ts +8 -0
- package/dist/components/Field.js +4 -3
- package/dist/components/FieldLabelText.d.ts +21 -3
- package/dist/components/FieldLabelText.js +16 -4
- package/dist/components/FilterChips.d.ts +9 -1
- package/dist/components/FilterChips.js +4 -2
- package/dist/components/Nav.d.ts +14 -2
- package/dist/components/Nav.js +6 -2
- package/dist/components/SegmentedControl.d.ts +5 -2
- package/dist/components/SegmentedControl.js +2 -1
- package/dist/components/Select.d.ts +9 -1
- package/dist/components/Select.js +4 -3
- package/dist/components/Stepper.d.ts +13 -0
- package/dist/components/Stepper.js +8 -2
- package/dist/components/combobox/types.d.ts +8 -0
- package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -2
- package/dist/components/denomination-grid/DenominationStrip.js +3 -2
- package/dist/components/denomination-grid/DenominationTiles.d.ts +1 -1
- package/dist/components/denomination-grid/EntryCell.js +1 -1
- package/dist/components/denomination-grid/StripRow.js +5 -2
- package/dist/components/denomination-grid/types.d.ts +35 -1
- package/dist/components/dialog/DialogTitle.d.ts +5 -3
- package/dist/components/dialog/DialogTitle.js +4 -4
- package/dist/css/css-action-menu-trigger.d.ts +11 -0
- package/dist/css/css-action-menu-trigger.js +66 -0
- package/dist/css/css-action-menu.js +7 -2
- package/dist/css/css-app-header-bar.d.ts +10 -0
- package/dist/css/css-app-header-bar.js +26 -0
- package/dist/css/css-box-border.d.ts +6 -1
- package/dist/css/css-box-border.js +8 -4
- package/dist/css/css-button-group-attached.js +5 -2
- package/dist/css/css-button-group-track.d.ts +11 -0
- package/dist/css/css-button-group-track.js +48 -0
- package/dist/css/css-button.d.ts +19 -2
- package/dist/css/css-button.js +31 -1
- package/dist/css/css-chrome.js +14 -1
- package/dist/css/css-combobox.js +2 -1
- package/dist/css/css-components.js +3 -0
- package/dist/css/css-data.js +3 -2
- package/dist/css/css-date-field.js +2 -1
- package/dist/css/css-denomination-appearance.d.ts +21 -0
- package/dist/css/css-denomination-appearance.js +114 -0
- package/dist/css/css-denomination-cell-tones.d.ts +8 -0
- package/dist/css/css-denomination-cell-tones.js +20 -1
- package/dist/css/css-denomination-grid.js +4 -0
- package/dist/css/css-dialog-banded.d.ts +11 -0
- package/dist/css/css-dialog-banded.js +84 -0
- package/dist/css/css-multi-select.js +2 -1
- package/dist/css/css-nav-words.d.ts +13 -0
- package/dist/css/css-nav-words.js +51 -0
- package/dist/css/css-notice.d.ts +4 -11
- package/dist/css/css-notice.js +6 -22
- package/dist/css/css-segmented-raised.d.ts +3 -0
- package/dist/css/css-segmented-raised.js +72 -0
- package/dist/css/css-segmented.js +9 -3
- package/dist/css/css-select.js +2 -1
- package/dist/css/css-split.js +2 -1
- package/dist/css/css-stepper.js +7 -0
- package/dist/css/quiet-fill.d.ts +7 -0
- package/dist/css/quiet-fill.js +7 -0
- package/dist/css/stacking.js +2 -1
- package/dist/css/stylesheet.js +2 -0
- package/dist/css/tone-tint.d.ts +21 -0
- package/dist/css/tone-tint.js +23 -0
- package/dist/index.d.ts +11 -9
- package/dist/index.js +9 -7
- package/dist/styles.css +300 -10
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { badgeTones } from './css-data.js';
|
|
2
|
+
import { toneTintFill, toneTintInk } from './tone-tint.js';
|
|
3
|
+
export const denominationCellToneAppearances = ['text', 'pill'];
|
|
4
|
+
export const denominationCellTonesPillClass = 'sw-denomination-cell-tones-pill';
|
|
2
5
|
/**
|
|
3
6
|
* The tones a single count can take. `neutral` is the cell's own look, so it
|
|
4
7
|
* adds no class: a cell is toned only by a tone that says something.
|
|
@@ -21,11 +24,15 @@ export function denominationCellToneClassNames(tone) {
|
|
|
21
24
|
* carries meaning alone: the consumer's words say why a count is toned.
|
|
22
25
|
* Forced colors replace the tone with the system text color, and a toned
|
|
23
26
|
* zero keeps the zero's GrayText there, so it does not read as a count.
|
|
27
|
+
* Under the `pill` appearance a strip's read-only count sits on a rounded
|
|
28
|
+
* tint of its tone in the tone's ink (the Notice's fill and words); forced
|
|
29
|
+
* colors outline the pill instead, so the mark survives without its fill.
|
|
24
30
|
*/
|
|
25
31
|
export function cssDenominationCellToneClasses() {
|
|
26
32
|
const toneRules = cellTones
|
|
27
|
-
.map((tone) => `.sw-denomination-cell-tone-${tone} { --sw-denomination-cell-tone: var(--sw-color-${tone}); }`)
|
|
33
|
+
.map((tone) => `.sw-denomination-cell-tone-${tone} { --sw-denomination-cell-tone: var(--sw-color-${tone}); --sw-denomination-cell-fill: ${toneTintFill(tone)}; --sw-denomination-cell-ink: ${toneTintInk(tone)}; }`)
|
|
28
34
|
.join('\n');
|
|
35
|
+
const pill = `.${denominationCellTonesPillClass} .sw-denomination-cell-toned .sw-denomination-cell-value:not(:empty)`;
|
|
29
36
|
return `${toneRules}
|
|
30
37
|
|
|
31
38
|
.sw-denomination-grid .sw-denomination-cell.sw-denomination-cell-toned,
|
|
@@ -39,13 +46,25 @@ export function cssDenominationCellToneClasses() {
|
|
|
39
46
|
box-shadow: inset 0 0 0 1px var(--sw-denomination-cell-tone);
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
/* A pill: the count on its tone's tint, in the tone's ink (a Notice's words: 4.5:1 on the tint unless the palette's own tone is under it). */
|
|
50
|
+
${pill} {
|
|
51
|
+
background: var(--sw-denomination-cell-fill);
|
|
52
|
+
border-radius: var(--sw-radius-sm);
|
|
53
|
+
color: var(--sw-denomination-cell-ink);
|
|
54
|
+
display: inline-block;
|
|
55
|
+
padding: calc(var(--sw-space-1) / 2) var(--sw-space-2);
|
|
56
|
+
}
|
|
57
|
+
|
|
42
58
|
@media (forced-colors: active) {
|
|
43
59
|
.sw-denomination-grid .sw-denomination-cell-zero.sw-denomination-cell-toned,
|
|
44
60
|
.sw-denomination-grid .sw-denomination-cell-toned .sw-denomination-cell-zero { color: GrayText; }
|
|
61
|
+
${pill} { color: inherit; outline: 1px solid CanvasText; }
|
|
45
62
|
}`;
|
|
46
63
|
}
|
|
47
64
|
export function denominationCellToneClassCatalog() {
|
|
48
65
|
return [
|
|
66
|
+
'sw-denomination-cell-value',
|
|
67
|
+
denominationCellTonesPillClass,
|
|
49
68
|
'sw-denomination-cell-toned',
|
|
50
69
|
...cellTones.map((tone) => `sw-denomination-cell-tone-${tone}`),
|
|
51
70
|
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
import { breakpointQuery } from './breakpoints.js';
|
|
3
3
|
import { badgeTones } from './css-data.js';
|
|
4
|
+
import { cssDenominationAppearanceClasses, denominationAppearanceClassCatalog, } from './css-denomination-appearance.js';
|
|
4
5
|
import { cssDenominationLabelClasses, denominationLabelClassCatalog, } from './css-denomination-label.js';
|
|
5
6
|
import { cssDenominationAlignedClasses, denominationAlignedClassCatalog, } from './css-denomination-aligned.js';
|
|
6
7
|
import { cssDenominationEntryClasses, denominationEntryClassCatalog, } from './css-denomination-entry.js';
|
|
@@ -257,6 +258,8 @@ ${cssDenominationAlignedClasses()}
|
|
|
257
258
|
|
|
258
259
|
${cssDenominationLabelClasses()}
|
|
259
260
|
|
|
261
|
+
${cssDenominationAppearanceClasses()}
|
|
262
|
+
|
|
260
263
|
@media (forced-colors: active) {
|
|
261
264
|
.sw-denomination-label { border-inline-start-color: CanvasText; color: CanvasText; }
|
|
262
265
|
.sw-denomination-strip .sw-denomination-label::before { background: CanvasText; forced-color-adjust: none; }
|
|
@@ -299,5 +302,6 @@ export function denominationGridClassCatalog() {
|
|
|
299
302
|
...denominationEntryClassCatalog(),
|
|
300
303
|
...denominationAlignedClassCatalog(),
|
|
301
304
|
...denominationLabelClassCatalog(),
|
|
305
|
+
...denominationAppearanceClassCatalog(),
|
|
302
306
|
];
|
|
303
307
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const dialogAppearances: readonly ["glass", "banded"];
|
|
2
|
+
/**
|
|
3
|
+
* How the dialog's surface reads: `glass` (the default) is one frosted
|
|
4
|
+
* panel; `banded` is a solid surface whose title row and footer are bands
|
|
5
|
+
* across its full width, ruled off from the content by hairlines, with the
|
|
6
|
+
* close button on a quiet round fill.
|
|
7
|
+
*/
|
|
8
|
+
export type DialogAppearance = (typeof dialogAppearances)[number];
|
|
9
|
+
export declare const dialogBandedClass = "sw-dialog-banded";
|
|
10
|
+
export declare function cssDialogBandedClasses(): string;
|
|
11
|
+
export declare function dialogBandedClassCatalog(): string[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { breakpointQuery, breakpoints } from './breakpoints.js';
|
|
2
|
+
import { dialogSheetClass } from './css-dialog.js';
|
|
3
|
+
import { zIndex } from './stacking.js';
|
|
4
|
+
import { quietFill } from './quiet-fill.js';
|
|
5
|
+
export const dialogAppearances = ['glass', 'banded'];
|
|
6
|
+
export const dialogBandedClass = 'sw-dialog-banded';
|
|
7
|
+
const banded = `.${dialogBandedClass}`;
|
|
8
|
+
/* The dialog's own padding, which a band steps past to reach its edges. */
|
|
9
|
+
const bleed = 'calc(-1 * var(--sw-space-5))';
|
|
10
|
+
/* A bottom sheet's side padding, which clears a wide safe area. */
|
|
11
|
+
const sheetSide = (side) => `max(var(--sw-space-5), env(safe-area-inset-${side}, 0px))`;
|
|
12
|
+
/*
|
|
13
|
+
* In a bottom sheet the dialog's side padding clears the safe areas, so
|
|
14
|
+
* the band steps past that padding instead of space-5, and pads itself
|
|
15
|
+
* the same, so its hairline still meets both edges.
|
|
16
|
+
*/
|
|
17
|
+
function sheetBandRules() {
|
|
18
|
+
return breakpoints
|
|
19
|
+
.map((breakpoint) => `@media ${breakpointQuery('below', breakpoint)} {
|
|
20
|
+
.${dialogSheetClass(breakpoint)}${banded} .sw-dialog-header {
|
|
21
|
+
margin-left: calc(-1 * ${sheetSide('left')});
|
|
22
|
+
margin-right: calc(-1 * ${sheetSide('right')});
|
|
23
|
+
padding-left: ${sheetSide('left')};
|
|
24
|
+
padding-right: ${sheetSide('right')};
|
|
25
|
+
}
|
|
26
|
+
}`)
|
|
27
|
+
.join('\n\n');
|
|
28
|
+
}
|
|
29
|
+
/*
|
|
30
|
+
* A banded dialog: the solid surface (no blur) with the medium elevation in
|
|
31
|
+
* place of the glass border, so it reads as a sheet over the page. The
|
|
32
|
+
* title row bleeds to the top and side edges as a band, a space-4 step
|
|
33
|
+
* down and the dialog's space-5 across, over a hairline, and stays at the
|
|
34
|
+
* top while the content scrolls under it (the top-chrome layer, under any
|
|
35
|
+
* popup the content opens); the pinned footer is already such a band at
|
|
36
|
+
* the bottom. The close button sits on the muted 16 % fill as a circle
|
|
37
|
+
* inside the band's padding, in the text color, and keeps its square size
|
|
38
|
+
* and touch target; a hover darkens the fill where the pointer can hover.
|
|
39
|
+
* Forced colors keep the hairline and outline the dialog, since its shadow
|
|
40
|
+
* is not drawn there.
|
|
41
|
+
*/
|
|
42
|
+
export function cssDialogBandedClasses() {
|
|
43
|
+
return `${banded} {
|
|
44
|
+
backdrop-filter: none;
|
|
45
|
+
-webkit-backdrop-filter: none;
|
|
46
|
+
background: var(--sw-color-surface);
|
|
47
|
+
border-color: transparent;
|
|
48
|
+
box-shadow: var(--sw-elevation-md);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
${banded} .sw-dialog-header {
|
|
52
|
+
align-items: center;
|
|
53
|
+
background: var(--sw-color-surface);
|
|
54
|
+
border-bottom: 1px solid var(--sw-color-border);
|
|
55
|
+
margin: ${bleed} ${bleed} 0;
|
|
56
|
+
padding: var(--sw-space-4) var(--sw-space-5);
|
|
57
|
+
position: sticky;
|
|
58
|
+
top: ${bleed};
|
|
59
|
+
${zIndex('topChrome')}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
${sheetBandRules()}
|
|
63
|
+
|
|
64
|
+
${banded} .sw-button.sw-dialog-close {
|
|
65
|
+
background: ${quietFill};
|
|
66
|
+
border-radius: var(--sw-radius-pill);
|
|
67
|
+
color: var(--sw-color-text);
|
|
68
|
+
margin: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@media (hover: hover) {
|
|
72
|
+
${banded} .sw-button.sw-dialog-close:hover {
|
|
73
|
+
background: color-mix(in srgb, var(--sw-color-muted) 24%, transparent);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@media (forced-colors: active) {
|
|
78
|
+
${banded} { border-color: CanvasText; }
|
|
79
|
+
${banded} .sw-dialog-header { border-bottom-color: CanvasText; }
|
|
80
|
+
}`;
|
|
81
|
+
}
|
|
82
|
+
export function dialogBandedClassCatalog() {
|
|
83
|
+
return [dialogBandedClass];
|
|
84
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
import { chevronStroke } from './chevron.js';
|
|
3
3
|
import { zIndex } from './stacking.js';
|
|
4
|
+
import { quietFill } from './quiet-fill.js';
|
|
4
5
|
const label = typographyVariants.label;
|
|
5
6
|
const body = typographyVariants.body;
|
|
6
7
|
/*
|
|
@@ -120,7 +121,7 @@ export function cssMultiSelectClasses() {
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
.sw-multi-select-option:hover {
|
|
123
|
-
background:
|
|
124
|
+
background: ${quietFill};
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
.sw-multi-select-icon {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const navAppearances: readonly ["default", "words"];
|
|
2
|
+
/**
|
|
3
|
+
* How a Nav draws its destinations: `default` keeps each link or Button's
|
|
4
|
+
* own look; `words` sets every destination as plain words, the others in
|
|
5
|
+
* the muted color at medium weight and the current one (`aria-current`)
|
|
6
|
+
* in the text color at label weight, with no fill, visible border or
|
|
7
|
+
* underline. The words must be visible: a glyph-only destination keeps
|
|
8
|
+
* `default`.
|
|
9
|
+
*/
|
|
10
|
+
export type NavAppearance = (typeof navAppearances)[number];
|
|
11
|
+
export declare const navWordsClass = "sw-nav-words";
|
|
12
|
+
export declare function cssNavWordsClasses(): string;
|
|
13
|
+
export declare function navWordsClassCatalog(): string[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
const label = typographyVariants.label;
|
|
3
|
+
export const navAppearances = ['default', 'words'];
|
|
4
|
+
export const navWordsClass = 'sw-nav-words';
|
|
5
|
+
const words = `.sw-nav.${navWordsClass}`;
|
|
6
|
+
const destinations = `:is(a, .sw-button)`;
|
|
7
|
+
const current = `[aria-current]:not([aria-current='false'])`;
|
|
8
|
+
/*
|
|
9
|
+
* Words-only destinations. A Button keeps its size, padding, touch target
|
|
10
|
+
* and focus ring; only its fill, border color and color go, so a primary
|
|
11
|
+
* or ghost Button in the Nav reads the same. Links lose the canvas's accent
|
|
12
|
+
* and underline, and take a transparent hairline border like a Button's.
|
|
13
|
+
* `:is()` counts as its most specific argument, so the selector is three
|
|
14
|
+
* classes (0,3,0): it outranks a Button's variant and the canvas's link
|
|
15
|
+
* rules. The current destination differs by color and weight, so the
|
|
16
|
+
* words must be visible: a glyph-only destination has no weight to change
|
|
17
|
+
* (keep `default` for those). Hover lifts the color only where the pointer
|
|
18
|
+
* hovers, and never on a disabled destination. Forced colors draw the
|
|
19
|
+
* current one's border in Highlight and underline its words, since color
|
|
20
|
+
* and weight may not show there.
|
|
21
|
+
*/
|
|
22
|
+
export function cssNavWordsClasses() {
|
|
23
|
+
return `${words} ${destinations} {
|
|
24
|
+
background: transparent;
|
|
25
|
+
border: 1px solid transparent;
|
|
26
|
+
color: var(--sw-color-muted);
|
|
27
|
+
font-size: ${label.fontSize}px;
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
30
|
+
line-height: ${label.lineHeight}px;
|
|
31
|
+
text-decoration: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@media (hover: hover) {
|
|
35
|
+
${words} ${destinations}:hover:not(:disabled, [aria-disabled='true']) {
|
|
36
|
+
color: var(--sw-color-text);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
${words} ${destinations}${current} {
|
|
41
|
+
color: var(--sw-color-text);
|
|
42
|
+
font-weight: ${label.fontWeight};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@media (forced-colors: active) {
|
|
46
|
+
${words} ${destinations}${current} { border-color: Highlight; text-decoration: underline; }
|
|
47
|
+
}`;
|
|
48
|
+
}
|
|
49
|
+
export function navWordsClassCatalog() {
|
|
50
|
+
return [navWordsClass];
|
|
51
|
+
}
|
package/dist/css/css-notice.d.ts
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
|
+
import { type TintColor } from './tone-tint.js';
|
|
1
2
|
export declare const noticeTones: readonly ["info", "success", "warning", "danger"];
|
|
2
3
|
export declare const noticeVariants: readonly ["default", "band"];
|
|
3
4
|
/** `default` is a rounded note in the flow; `band` a full-width strip of page chrome. */
|
|
4
5
|
export type NoticeVariant = (typeof noticeVariants)[number];
|
|
5
6
|
/** The notice's meaning: information, a good outcome, a caution, a refusal. */
|
|
6
7
|
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
|
-
*/
|
|
8
|
+
/** How much of a tone's color the notice's fill mixes into the surface. */
|
|
12
9
|
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
|
-
*/
|
|
10
|
+
/** How far the notice's words move from the tone's color toward the text color. */
|
|
18
11
|
export declare const noticeInkTextShare = 0.3;
|
|
19
12
|
/** The semantic color a tone is drawn from. */
|
|
20
|
-
export declare function noticeToneColor(tone: NoticeTone):
|
|
13
|
+
export declare function noticeToneColor(tone: NoticeTone): TintColor;
|
|
21
14
|
export declare function cssNoticeClasses(): string;
|
|
22
15
|
export declare function noticeClassCatalog(): string[];
|
package/dist/css/css-notice.js
CHANGED
|
@@ -1,34 +1,18 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { toneInkTextShare, toneTintFill, toneTintInk, toneTintShare, } from './tone-tint.js';
|
|
2
3
|
export const noticeTones = ['info', 'success', 'warning', 'danger'];
|
|
3
4
|
export const noticeVariants = ['default', 'band'];
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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;
|
|
5
|
+
/** How much of a tone's color the notice's fill mixes into the surface. */
|
|
6
|
+
export const noticeTintShare = toneTintShare;
|
|
7
|
+
/** How far the notice's words move from the tone's color toward the text color. */
|
|
8
|
+
export const noticeInkTextShare = toneInkTextShare;
|
|
16
9
|
/** The semantic color a tone is drawn from. */
|
|
17
10
|
export function noticeToneColor(tone) {
|
|
18
11
|
return tone === 'info' ? 'accent' : tone;
|
|
19
12
|
}
|
|
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
13
|
function toneRules() {
|
|
30
14
|
return noticeTones
|
|
31
|
-
.map((tone) => `.sw-notice-${tone} { --sw-notice-fill: ${
|
|
15
|
+
.map((tone) => `.sw-notice-${tone} { --sw-notice-fill: ${toneTintFill(noticeToneColor(tone))}; --sw-notice-ink: ${toneTintInk(noticeToneColor(tone))}; }`)
|
|
32
16
|
.join('\n');
|
|
33
17
|
}
|
|
34
18
|
const label = typographyVariants.label;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { trackInset, typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { quietFill } from './quiet-fill.js';
|
|
3
|
+
const label = typographyVariants.label;
|
|
4
|
+
export const segmentedRaisedClass = 'sw-segmented-raised';
|
|
5
|
+
const raised = `.sw-segmented.${segmentedRaisedClass}`;
|
|
6
|
+
/*
|
|
7
|
+
* The raised track: the quiet grey fill (no border) with corners one track
|
|
8
|
+
* inset rounder than the segments' small radius, so the two curves stay
|
|
9
|
+
* concentric, sized to its segments even in a Stack (unlike compact).
|
|
10
|
+
* Every segment is the md control height in label type with its words in
|
|
11
|
+
* the text color at medium weight; with marks, a segment pads a step less
|
|
12
|
+
* before its mark. The selected one is the surface raised by the small
|
|
13
|
+
* elevation, its words at label weight. In the dark scheme a shadow does
|
|
14
|
+
* not show and the surface is about the track's grey, so the selected
|
|
15
|
+
* segment draws a hairline ring in the muted color instead (3:1 or more
|
|
16
|
+
* against the track in every dark palette, on the canvas or a card). Two classes,
|
|
17
|
+
* so these win over the compact track's rules and the reduced-transparency
|
|
18
|
+
* surface; the track's transparent border would also win over the error
|
|
19
|
+
* outline (`.sw-segmented[aria-invalid='true']`, the same specificity,
|
|
20
|
+
* earlier), so the danger border, and Mark in forced colors, is restated
|
|
21
|
+
* last. Forced colors outline the track and the selected segment.
|
|
22
|
+
*/
|
|
23
|
+
export function cssSegmentedRaisedClasses() {
|
|
24
|
+
return `${raised} {
|
|
25
|
+
background: ${quietFill};
|
|
26
|
+
border-color: transparent;
|
|
27
|
+
border-radius: calc(var(--sw-radius-sm) + ${trackInset}px);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Sized to its segments even where the field is stretched (a Stack). */
|
|
31
|
+
.sw-segmented-field > ${raised} {
|
|
32
|
+
align-self: flex-start;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
${raised} .sw-segmented-item {
|
|
36
|
+
border-radius: var(--sw-radius-sm);
|
|
37
|
+
color: var(--sw-color-text);
|
|
38
|
+
font-size: ${label.fontSize}px;
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
41
|
+
line-height: ${label.lineHeight}px;
|
|
42
|
+
min-height: var(--sw-control-md-min-height);
|
|
43
|
+
padding-inline: var(--sw-space-4);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
${raised}.sw-segmented-with-icons .sw-segmented-item {
|
|
47
|
+
padding-inline: var(--sw-space-2) var(--sw-space-3);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
${raised} .sw-segmented-item-selected {
|
|
51
|
+
background: var(--sw-color-surface);
|
|
52
|
+
box-shadow: var(--sw-elevation-sm);
|
|
53
|
+
font-weight: ${label.fontWeight};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
[data-theme='dark'] ${raised} .sw-segmented-item-selected {
|
|
57
|
+
box-shadow: inset 0 0 0 1px var(--sw-color-muted);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
${raised}[aria-invalid='true'] {
|
|
61
|
+
border-color: var(--sw-color-danger);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@media (forced-colors: active) {
|
|
65
|
+
${raised} { border-color: CanvasText; }
|
|
66
|
+
${raised} .sw-segmented-item-selected { outline: 2px solid Highlight; }
|
|
67
|
+
${raised}[aria-invalid='true'] { border-color: Mark; }
|
|
68
|
+
}`;
|
|
69
|
+
}
|
|
70
|
+
export function segmentedRaisedClassCatalog() {
|
|
71
|
+
return [segmentedRaisedClass];
|
|
72
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { trackInset, typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { cssSegmentedRaisedClasses, segmentedRaisedClassCatalog, } from './css-segmented-raised.js';
|
|
2
3
|
const body = typographyVariants.body;
|
|
3
4
|
const data = typographyVariants.data;
|
|
4
5
|
const label = typographyVariants.label;
|
|
@@ -9,13 +10,15 @@ const label = typographyVariants.label;
|
|
|
9
10
|
* the row stays even; the track is the subtle fill (two classes, so
|
|
10
11
|
* reduced transparency keeps it) and the selected item is the surface
|
|
11
12
|
* 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
|
|
13
|
-
*
|
|
13
|
+
* too. A filled or raised track keeps its own look and only gains the
|
|
14
|
+
* marks (one `:not()` of both, so the compact rules keep their
|
|
15
|
+
* specificity). The error outline is restated after these rules so an
|
|
16
|
+
* icon track keeps it.
|
|
14
17
|
* In forced colours the selected item is outlined in Highlight; a focused
|
|
15
18
|
* selected item keeps that outline, offset by the focus ring's offset.
|
|
16
19
|
*/
|
|
17
20
|
function iconRules() {
|
|
18
|
-
const compact = '.sw-segmented-with-icons:not(.sw-segmented-filled)';
|
|
21
|
+
const compact = '.sw-segmented-with-icons:not(.sw-segmented-filled, .sw-segmented-raised)';
|
|
19
22
|
return `.sw-segmented${compact} {
|
|
20
23
|
background: var(--sw-color-subtle);
|
|
21
24
|
border-color: transparent;
|
|
@@ -162,6 +165,8 @@ export function cssSegmentedClasses() {
|
|
|
162
165
|
|
|
163
166
|
${iconRules()}
|
|
164
167
|
|
|
168
|
+
${cssSegmentedRaisedClasses()}
|
|
169
|
+
|
|
165
170
|
.sw-segmented-disabled {
|
|
166
171
|
opacity: var(--sw-disabled-opacity);
|
|
167
172
|
}
|
|
@@ -181,5 +186,6 @@ export function segmentedClassCatalog() {
|
|
|
181
186
|
'sw-segmented-with-icons',
|
|
182
187
|
'sw-segmented-item-icon',
|
|
183
188
|
'sw-segmented-disabled',
|
|
189
|
+
...segmentedRaisedClassCatalog(),
|
|
184
190
|
];
|
|
185
191
|
}
|
package/dist/css/css-select.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
import { chevronStroke } from './chevron.js';
|
|
3
3
|
import { zIndex } from './stacking.js';
|
|
4
|
+
import { quietFill } from './quiet-fill.js';
|
|
4
5
|
const caption = typographyVariants.caption;
|
|
5
6
|
const label = typographyVariants.label;
|
|
6
7
|
export function cssSelectClasses() {
|
|
@@ -172,7 +173,7 @@ export function cssSelectClasses() {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
.sw-select-option[data-active='true'] {
|
|
175
|
-
background:
|
|
176
|
+
background: ${quietFill};
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
.sw-select-xs .sw-select-option {
|
package/dist/css/css-split.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { quietFill } from './quiet-fill.js';
|
|
1
2
|
export function cssSplitClasses() {
|
|
2
3
|
return `.sw-split {
|
|
3
4
|
align-items: stretch;
|
|
@@ -39,7 +40,7 @@ export function cssSplitClasses() {
|
|
|
39
40
|
|
|
40
41
|
.sw-split-handle:hover,
|
|
41
42
|
.sw-split-handle:focus-visible {
|
|
42
|
-
background:
|
|
43
|
+
background: ${quietFill};
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
.sw-split-handle:focus-visible {
|
package/dist/css/css-stepper.js
CHANGED
|
@@ -25,6 +25,12 @@ function stateRules() {
|
|
|
25
25
|
background-image: ${changedTintLayer};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/* A plain limit: − at min and + at max keep their look, still disabled. */
|
|
29
|
+
.sw-stepper-limit-plain .sw-stepper-button:disabled {
|
|
30
|
+
cursor: default;
|
|
31
|
+
opacity: 1;
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
/* Read-only: the buttons keep their room, so the count lines up with an editable one. */
|
|
29
35
|
.sw-stepper-readonly .sw-stepper-button { visibility: hidden; }
|
|
30
36
|
|
|
@@ -122,5 +128,6 @@ export function stepperClassCatalog() {
|
|
|
122
128
|
'sw-stepper-invalid',
|
|
123
129
|
'sw-stepper-changed',
|
|
124
130
|
'sw-stepper-readonly',
|
|
131
|
+
'sw-stepper-limit-plain',
|
|
125
132
|
];
|
|
126
133
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The quiet grey fill: the muted color at 16 % over whatever is beneath
|
|
3
|
+
* (about #E8E8E9 on white). An open menu or list row, a held separator,
|
|
4
|
+
* today's calendar ring fill, a neutral button and a banded dialog's close
|
|
5
|
+
* button all take it, so they read as one grey.
|
|
6
|
+
*/
|
|
7
|
+
export declare const quietFill = "color-mix(in srgb, var(--sw-color-muted) 16%, transparent)";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The quiet grey fill: the muted color at 16 % over whatever is beneath
|
|
3
|
+
* (about #E8E8E9 on white). An open menu or list row, a held separator,
|
|
4
|
+
* today's calendar ring fill, a neutral button and a banded dialog's close
|
|
5
|
+
* button all take it, so they read as one grey.
|
|
6
|
+
*/
|
|
7
|
+
export const quietFill = 'color-mix(in srgb, var(--sw-color-muted) 16%, transparent)';
|
package/dist/css/stacking.js
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* its popup can only paint as high as the surface does; lifting the surface
|
|
14
14
|
* over the ActionBar keeps an open list tappable where the bar would cover
|
|
15
15
|
* it, and over the next surface in the flow.
|
|
16
|
-
* 5. `topChrome`: the sticky AppHeader or sticky Tabs strip
|
|
16
|
+
* 5. `topChrome`: the sticky AppHeader or sticky Tabs strip (and a banded
|
|
17
|
+
* Dialog's title band, inside its dialog), over a lifted
|
|
17
18
|
* surface that scrolls up under it (the header is the page's way back, the
|
|
18
19
|
* strip its way between sections, and a popup opens downward).
|
|
19
20
|
* 6. `popup`: a popup outside any lifted surface (Select list, ActionMenu
|
package/dist/css/stylesheet.js
CHANGED
|
@@ -36,6 +36,7 @@ import { tableClassCatalog } from './css-table.js';
|
|
|
36
36
|
import { chromeClassCatalog } from './css-chrome.js';
|
|
37
37
|
import { sectionNavClassCatalog } from './css-section-nav.js';
|
|
38
38
|
import { dialogClassCatalog } from './css-dialog.js';
|
|
39
|
+
import { dialogBandedClassCatalog } from './css-dialog-banded.js';
|
|
39
40
|
import { dialogFrameClassCatalog } from './css-dialog-frame.js';
|
|
40
41
|
import { selectClassCatalog } from './css-select.js';
|
|
41
42
|
import { multiSelectClassCatalog } from './css-multi-select.js';
|
|
@@ -71,6 +72,7 @@ export function utilityClassCatalog() {
|
|
|
71
72
|
...sectionNavClassCatalog(),
|
|
72
73
|
...dialogClassCatalog(),
|
|
73
74
|
...dialogFrameClassCatalog(),
|
|
75
|
+
...dialogBandedClassCatalog(),
|
|
74
76
|
...accordionClassCatalog(),
|
|
75
77
|
...selectClassCatalog(),
|
|
76
78
|
...actionMenuClassCatalog(),
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The semantic colors a tinted mark can be drawn from: a note's tone or a
|
|
3
|
+
* single count's.
|
|
4
|
+
*/
|
|
5
|
+
export type TintColor = 'accent' | 'success' | 'warning' | 'danger';
|
|
6
|
+
/**
|
|
7
|
+
* How much of a tone's color a tint mixes into the surface. The accent uses
|
|
8
|
+
* the derived accent tint instead (ADR 0011), which already keeps the accent
|
|
9
|
+
* readable on every palette.
|
|
10
|
+
*/
|
|
11
|
+
export declare const toneTintShare = 0.1;
|
|
12
|
+
/**
|
|
13
|
+
* How far a tint's words move from the tone's color toward the text color,
|
|
14
|
+
* so they read darker than the tone on a light fill (lighter on a dark one)
|
|
15
|
+
* and keep 4.5:1 on the tint (`notice.test.tsx`).
|
|
16
|
+
*/
|
|
17
|
+
export declare const toneInkTextShare = 0.3;
|
|
18
|
+
/** A tone's quiet fill: the tone mixed into the surface. */
|
|
19
|
+
export declare function toneTintFill(color: TintColor): string;
|
|
20
|
+
/** The words on that fill: the tone moved toward the text color. */
|
|
21
|
+
export declare function toneTintInk(color: TintColor): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much of a tone's color a tint mixes into the surface. The accent uses
|
|
3
|
+
* the derived accent tint instead (ADR 0011), which already keeps the accent
|
|
4
|
+
* readable on every palette.
|
|
5
|
+
*/
|
|
6
|
+
export const toneTintShare = 0.1;
|
|
7
|
+
/**
|
|
8
|
+
* How far a tint's words move from the tone's color toward the text color,
|
|
9
|
+
* so they read darker than the tone on a light fill (lighter on a dark one)
|
|
10
|
+
* and keep 4.5:1 on the tint (`notice.test.tsx`).
|
|
11
|
+
*/
|
|
12
|
+
export const toneInkTextShare = 0.3;
|
|
13
|
+
/** A tone's quiet fill: the tone mixed into the surface. */
|
|
14
|
+
export function toneTintFill(color) {
|
|
15
|
+
if (color === 'accent')
|
|
16
|
+
return 'var(--sw-color-accentSubtle)';
|
|
17
|
+
return `color-mix(in srgb, var(--sw-color-${color}) ${toneTintShare * 100}%, var(--sw-color-surface))`;
|
|
18
|
+
}
|
|
19
|
+
/** The words on that fill: the tone moved toward the text color. */
|
|
20
|
+
export function toneTintInk(color) {
|
|
21
|
+
const toneShare = Math.round((1 - toneInkTextShare) * 100);
|
|
22
|
+
return `color-mix(in srgb, var(--sw-color-${color}) ${toneShare}%, var(--sw-color-text))`;
|
|
23
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ActionMenu, type ActionMenuAlign, type ActionMenuItem, type ActionMenuProps, } from './components/ActionMenu.js';
|
|
1
|
+
export { ActionMenu, type ActionMenuAlign, type ActionMenuItem, type ActionMenuProps, actionMenuTriggerAppearances, type ActionMenuTriggerAppearance, } from './components/ActionMenu.js';
|
|
2
2
|
export { ActionBar, type ActionBarProps, type ActionBarSummary, type ActionBarSummaryTone, } from './components/ActionBar.js';
|
|
3
3
|
export { Accordion } from './components/Accordion.js';
|
|
4
4
|
export type { AccordionProps, AccordionSize } from './components/Accordion.js';
|
|
@@ -13,25 +13,27 @@ export { Progress, progressTones, type ProgressProps, type ProgressTone, } from
|
|
|
13
13
|
export { Tooltip, type TooltipProps, type TooltipRelationship, } from './components/Tooltip.js';
|
|
14
14
|
export { InfoTip, type InfoTipProps } from './components/InfoTip.js';
|
|
15
15
|
export { RadioGroup, type RadioGroupOption, type RadioGroupProps, } from './components/RadioGroup.js';
|
|
16
|
-
export { AppHeader, type AppHeaderProps } from './components/AppHeader.js';
|
|
16
|
+
export { AppHeader, appHeaderAppearances, type AppHeaderAppearance, type AppHeaderProps, } from './components/AppHeader.js';
|
|
17
17
|
export { Badge, type BadgeProps, type BadgeSize, type BadgeTone, badgeSizes, badgeTones, } from './components/Badge.js';
|
|
18
18
|
export { BarChart, type BarChartItem, type BarChartProps, type BarChartTone, barChartTones, } from './components/BarChart.js';
|
|
19
|
-
export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, } from './components/Button.js';
|
|
19
|
+
export { Button, type ButtonDisabledAppearance, type ButtonProps, type ButtonSize, type ButtonVariant, } from './components/Button.js';
|
|
20
|
+
export { buttonDisabledAppearances, webButtonVariants, } from './css/css-button.js';
|
|
20
21
|
export { Box, type BoxBorder, type BoxElement, type BoxProps, } from './components/Box.js';
|
|
21
|
-
export { ButtonGroup, type ButtonGroupJustify, type ButtonGroupProps, } from './components/ButtonGroup.js';
|
|
22
|
+
export { ButtonGroup, buttonGroupAppearances, type ButtonGroupAppearance, type ButtonGroupJustify, type ButtonGroupProps, } from './components/ButtonGroup.js';
|
|
22
23
|
export { Card, type CardProps, type CardVariant } from './components/Card.js';
|
|
23
|
-
export { Dialog, dialogSizes, type DialogProps, type DialogRole, type DialogSize, type DialogTitleLevel, } from './components/Dialog.js';
|
|
24
|
+
export { Dialog, dialogAppearances, dialogSizes, type DialogAppearance, type DialogProps, type DialogRole, type DialogSize, type DialogTitleLevel, } from './components/Dialog.js';
|
|
24
25
|
export { StatTile, type StatTileEmphasis, type StatTileProps, type StatTileTone, statTileTones, } from './components/StatTile.js';
|
|
25
26
|
export { TabPanel, type TabItem, type TabPanelProps, Tabs, type TabsProps, tabId, tabPanelId, } from './components/Tabs.js';
|
|
26
27
|
export { Toast, toastPlacements, toastTones, type ToastAction, type ToastPlacement, } from './components/Toast.js';
|
|
27
28
|
export type { ToastProps, ToastTone } from './components/Toast.js';
|
|
28
29
|
export { Field, fieldVariants, type FieldProps, type FieldSize, type FieldVariant, } from './components/Field.js';
|
|
30
|
+
export { requiredMarks, type RequiredMark, } from './components/FieldLabelText.js';
|
|
29
31
|
export { Step, type StepHeadingLevel, type StepProps, Steps, type StepsLabels, type StepsProps, type StepStatus, } from './components/Steps.js';
|
|
30
|
-
export { Stepper, type StepperProps, type StepperWidth, } from './components/Stepper.js';
|
|
32
|
+
export { Stepper, stepperLimitAppearances, type StepperLimitAppearance, type StepperProps, type StepperWidth, } from './components/Stepper.js';
|
|
31
33
|
export { Inline, type InlineProps } from './components/Inline.js';
|
|
32
34
|
export { Split } from './components/Split.js';
|
|
33
35
|
export type { SplitProps } from './components/Split.js';
|
|
34
|
-
export { Nav, type NavProps } from './components/Nav.js';
|
|
36
|
+
export { Nav, navAppearances, type NavAppearance, type NavProps, } from './components/Nav.js';
|
|
35
37
|
export { SectionNav, sectionNavAppearances, type SectionNavAppearance, type SectionNavItem, type SectionNavProps, } from './components/SectionNav.js';
|
|
36
38
|
export { SegmentedControl, type SegmentedControlProps, type SegmentedControlVariant, type SegmentedItem, } from './components/SegmentedControl.js';
|
|
37
39
|
export { Combobox, comboboxSizes, type ComboboxAction, type ComboboxBadge, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type ComboboxSize, } from './components/Combobox.js';
|
|
@@ -54,7 +56,7 @@ export { Grid } from './components/Grid.js';
|
|
|
54
56
|
export type { GridColumns, GridProps } from './components/Grid.js';
|
|
55
57
|
export type { GridColumnSpan } from './css/css-grid-span.js';
|
|
56
58
|
export type { ColumnSpanProps } from './column-span-classes.js';
|
|
57
|
-
export { DenominationGrid, denominationLabelAppearances, } from './components/DenominationGrid.js';
|
|
58
|
-
export type { DenominationGridColumn, DenominationGridEntry, DenominationGridLayout, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationLabelAppearance, DenominationLabelWidth, } from './components/DenominationGrid.js';
|
|
59
|
+
export { DenominationGrid, denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationTotalEmphases, } from './components/DenominationGrid.js';
|
|
60
|
+
export type { DenominationCellToneAppearance, DenominationGridColumn, DenominationGridEntry, DenominationGridFrame, DenominationGridLayout, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationLabelAppearance, DenominationLabelWidth, DenominationTotalEmphasis, } from './components/DenominationGrid.js';
|
|
59
61
|
export { FilterChips } from './components/FilterChips.js';
|
|
60
62
|
export type { FilterChipOption, FilterChipsProps, } from './components/FilterChips.js';
|