@scalewing/react 1.47.0 → 1.48.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 +67 -0
- package/README.md +171 -4
- package/dist/command-palette.test-support.d.ts +21 -0
- package/dist/command-palette.test-support.js +55 -0
- package/dist/components/AppHeader.d.ts +3 -0
- package/dist/components/AppShell.d.ts +4 -3
- package/dist/components/AppShell.js +24 -7
- package/dist/components/Band.d.ts +30 -0
- package/dist/components/Band.js +23 -0
- package/dist/components/ButtonLink.d.ts +33 -0
- package/dist/components/ButtonLink.js +27 -0
- package/dist/components/CommandPalette.d.ts +12 -0
- package/dist/components/CommandPalette.js +143 -0
- package/dist/components/CommandPaletteTrigger.d.ts +9 -0
- package/dist/components/CommandPaletteTrigger.js +16 -0
- package/dist/components/ContextSwitcher.d.ts +12 -0
- package/dist/components/ContextSwitcher.js +62 -0
- package/dist/components/FixtureGroup.d.ts +9 -0
- package/dist/components/FixtureGroup.js +16 -0
- package/dist/components/FixtureRow.d.ts +10 -0
- package/dist/components/FixtureRow.js +46 -0
- package/dist/components/GlyphTile.d.ts +9 -3
- package/dist/components/GlyphTile.js +15 -4
- package/dist/components/SiteFooter.d.ts +12 -0
- package/dist/components/SiteFooter.js +23 -0
- package/dist/components/SiteHeader.d.ts +14 -0
- package/dist/components/SiteHeader.js +24 -0
- package/dist/components/Skeleton.d.ts +22 -0
- package/dist/components/Skeleton.js +30 -0
- package/dist/components/app-shell/AppShellBar.d.ts +23 -0
- package/dist/components/app-shell/AppShellBar.js +25 -0
- package/dist/components/app-shell/types.d.ts +36 -1
- package/dist/components/app-shell/validate.d.ts +4 -3
- package/dist/components/app-shell/validate.js +21 -3
- package/dist/components/command-palette/PaletteList.d.ts +20 -0
- package/dist/components/command-palette/PaletteList.js +21 -0
- package/dist/components/command-palette/shortcut.d.ts +19 -0
- package/dist/components/command-palette/shortcut.js +75 -0
- package/dist/components/command-palette/types.d.ts +72 -0
- package/dist/components/command-palette/types.js +2 -0
- package/dist/components/command-palette/validate.d.ts +10 -0
- package/dist/components/command-palette/validate.js +50 -0
- package/dist/components/context-switcher/SwitcherOption.d.ts +17 -0
- package/dist/components/context-switcher/SwitcherOption.js +20 -0
- package/dist/components/context-switcher/SwitcherPopup.d.ts +31 -0
- package/dist/components/context-switcher/SwitcherPopup.js +111 -0
- package/dist/components/context-switcher/options.d.ts +33 -0
- package/dist/components/context-switcher/options.js +60 -0
- package/dist/components/context-switcher/types.d.ts +96 -0
- package/dist/components/context-switcher/types.js +1 -0
- package/dist/components/context-switcher/use-switcher-list.d.ts +29 -0
- package/dist/components/context-switcher/use-switcher-list.js +93 -0
- package/dist/components/context-switcher/validate.d.ts +8 -0
- package/dist/components/context-switcher/validate.js +94 -0
- package/dist/components/fixture/fixture-list-context.d.ts +4 -0
- package/dist/components/fixture/fixture-list-context.js +9 -0
- package/dist/components/fixture/types.d.ts +50 -0
- package/dist/components/fixture/types.js +1 -0
- package/dist/components/fixture/validate.d.ts +8 -0
- package/dist/components/fixture/validate.js +36 -0
- package/dist/components/site-footer/types.d.ts +31 -0
- package/dist/components/site-footer/types.js +1 -0
- package/dist/components/site-footer/validate.d.ts +7 -0
- package/dist/components/site-footer/validate.js +22 -0
- package/dist/components/site-header/SiteHeaderLinks.d.ts +7 -0
- package/dist/components/site-header/SiteHeaderLinks.js +7 -0
- package/dist/components/site-header/types.d.ts +38 -0
- package/dist/components/site-header/types.js +1 -0
- package/dist/components/site-header/use-menu-dismiss.d.ts +8 -0
- package/dist/components/site-header/use-menu-dismiss.js +62 -0
- package/dist/components/site-header/validate.d.ts +7 -0
- package/dist/components/site-header/validate.js +17 -0
- package/dist/components/use-element-height.d.ts +10 -0
- package/dist/components/use-element-height.js +35 -0
- package/dist/context-switcher.test-support.d.ts +9 -0
- package/dist/context-switcher.test-support.js +41 -0
- package/dist/css/css-app-shell-page-bar.d.ts +3 -0
- package/dist/css/css-app-shell-page-bar.js +81 -0
- package/dist/css/css-app-shell.js +6 -1
- package/dist/css/css-band.d.ts +10 -0
- package/dist/css/css-band.js +101 -0
- package/dist/css/css-button-link.d.ts +3 -0
- package/dist/css/css-button-link.js +48 -0
- package/dist/css/css-command-palette-key.d.ts +1 -0
- package/dist/css/css-command-palette-key.js +33 -0
- package/dist/css/css-command-palette-trigger.d.ts +2 -0
- package/dist/css/css-command-palette-trigger.js +88 -0
- package/dist/css/css-command-palette.d.ts +2 -0
- package/dist/css/css-command-palette.js +209 -0
- package/dist/css/css-components.js +24 -0
- package/dist/css/css-context-switcher-trigger.d.ts +15 -0
- package/dist/css/css-context-switcher-trigger.js +175 -0
- package/dist/css/css-context-switcher.d.ts +4 -0
- package/dist/css/css-context-switcher.js +219 -0
- package/dist/css/css-count-pill.d.ts +2 -2
- package/dist/css/css-count-pill.js +11 -3
- package/dist/css/css-fixture.d.ts +5 -0
- package/dist/css/css-fixture.js +260 -0
- package/dist/css/css-glyph-tile.d.ts +2 -0
- package/dist/css/css-glyph-tile.js +29 -1
- package/dist/css/css-site-footer.d.ts +2 -0
- package/dist/css/css-site-footer.js +152 -0
- package/dist/css/css-site-header.d.ts +2 -0
- package/dist/css/css-site-header.js +262 -0
- package/dist/css/css-skeleton.d.ts +10 -0
- package/dist/css/css-skeleton.js +110 -0
- package/dist/css/stacking.js +7 -4
- package/dist/css/stylesheet.js +16 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +10 -0
- package/dist/styles.css +2008 -719
- package/package.json +2 -2
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { checkStrokeIn } from './chevron.js';
|
|
3
|
+
import { contextSwitcherTriggerClassCatalog, cssContextSwitcherTriggerClasses, } from './css-context-switcher-trigger.js';
|
|
4
|
+
import { quietFill } from './quiet-fill.js';
|
|
5
|
+
import { zIndex } from './stacking.js';
|
|
6
|
+
import { coarsePointerQuery, touchTarget } from './touch-target.js';
|
|
7
|
+
const caption = typographyVariants.caption;
|
|
8
|
+
const label = typographyVariants.label;
|
|
9
|
+
/* The popup's least width, a named geometry of this control. */
|
|
10
|
+
const popupMinWidth = '15rem';
|
|
11
|
+
/** The trigger's width, set on the open popup so it is never narrower. */
|
|
12
|
+
export const contextSwitcherTriggerWidthVariable = '--sw-context-switcher-trigger-width';
|
|
13
|
+
const viewportCap = 'calc(100% - var(--sw-space-2) - var(--sw-space-2))';
|
|
14
|
+
/*
|
|
15
|
+
* The popup: a glass panel on the top layer beside the trigger (placed by
|
|
16
|
+
* script, as the menus are), at least 15rem and as wide as the trigger
|
|
17
|
+
* (its width set by the component), capped by the dialog width (or the
|
|
18
|
+
* trigger's, when wider) and the viewport. A column: the filter field,
|
|
19
|
+
* the listbox (the only part that scrolls), the empty words, the footer.
|
|
20
|
+
*/
|
|
21
|
+
function popupRules() {
|
|
22
|
+
return `.sw-context-switcher-popup {
|
|
23
|
+
background: var(--sw-glass-fill);
|
|
24
|
+
border: 1px solid var(--sw-glass-border);
|
|
25
|
+
border-radius: var(--sw-radius-sm);
|
|
26
|
+
box-shadow: var(--sw-elevation-sm), inset 0 1px 0 var(--sw-glass-specular);
|
|
27
|
+
backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
|
|
28
|
+
-webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
|
|
29
|
+
box-sizing: border-box;
|
|
30
|
+
color: var(--sw-color-text);
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: var(--sw-space-1);
|
|
34
|
+
inset: auto;
|
|
35
|
+
margin: 0;
|
|
36
|
+
max-height: ${viewportCap};
|
|
37
|
+
max-width: min(max(var(--sw-dialog-max), var(${contextSwitcherTriggerWidthVariable}, 0px)), ${viewportCap});
|
|
38
|
+
min-width: min(max(${popupMinWidth}, var(${contextSwitcherTriggerWidthVariable}, 0px)), ${viewportCap});
|
|
39
|
+
padding: var(--sw-space-1);
|
|
40
|
+
position: fixed;
|
|
41
|
+
width: max-content;
|
|
42
|
+
${zIndex('popup')}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.sw-context-switcher-filter {
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
flex: none;
|
|
48
|
+
margin: var(--sw-space-1);
|
|
49
|
+
width: calc(100% - var(--sw-space-2));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.sw-context-switcher-list {
|
|
53
|
+
flex: 1 1 auto;
|
|
54
|
+
max-height: var(--sw-select-max);
|
|
55
|
+
min-height: 0;
|
|
56
|
+
overflow-y: auto;
|
|
57
|
+
overscroll-behavior: contain;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.sw-context-switcher-list:focus {
|
|
61
|
+
outline: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.sw-context-switcher-heading {
|
|
65
|
+
color: var(--sw-color-muted);
|
|
66
|
+
font-family: var(--sw-font-sans);
|
|
67
|
+
font-size: ${caption.fontSize}px;
|
|
68
|
+
font-weight: 600;
|
|
69
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
70
|
+
line-height: ${caption.lineHeight}px;
|
|
71
|
+
padding: var(--sw-space-2) var(--sw-space-2) var(--sw-space-1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.sw-context-switcher-empty {
|
|
75
|
+
color: var(--sw-color-muted);
|
|
76
|
+
font-family: var(--sw-font-sans);
|
|
77
|
+
font-size: ${caption.fontSize}px;
|
|
78
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
79
|
+
line-height: ${caption.lineHeight}px;
|
|
80
|
+
margin: 0;
|
|
81
|
+
padding: var(--sw-space-2);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.sw-context-switcher-footer {
|
|
85
|
+
border-top: 1px solid var(--sw-color-border);
|
|
86
|
+
display: flex;
|
|
87
|
+
flex: none;
|
|
88
|
+
flex-wrap: wrap;
|
|
89
|
+
gap: var(--sw-space-1);
|
|
90
|
+
padding-top: var(--sw-space-1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.sw-context-switcher-action-icon {
|
|
94
|
+
display: inline-flex;
|
|
95
|
+
flex: none;
|
|
96
|
+
}`;
|
|
97
|
+
}
|
|
98
|
+
/*
|
|
99
|
+
* An option: the mark, the label over its muted detail, then the badge,
|
|
100
|
+
* the count pill and the current one's check at the inline end. The sm
|
|
101
|
+
* control height (44 px on a coarse pointer). The active row (the arrow
|
|
102
|
+
* keys' or the pointer's) takes the quiet fill, and an accent ring while
|
|
103
|
+
* the list itself has visible focus; the current one is at label weight
|
|
104
|
+
* with the accent check. Forced colours draw the active row in Highlight.
|
|
105
|
+
*/
|
|
106
|
+
function optionRules() {
|
|
107
|
+
return `.sw-context-switcher-option {
|
|
108
|
+
align-items: center;
|
|
109
|
+
border-radius: var(--sw-radius-sm);
|
|
110
|
+
box-sizing: border-box;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
display: flex;
|
|
113
|
+
font-family: var(--sw-font-sans);
|
|
114
|
+
font-size: ${label.fontSize}px;
|
|
115
|
+
gap: var(--sw-space-2);
|
|
116
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
117
|
+
line-height: ${label.lineHeight}px;
|
|
118
|
+
min-height: var(--sw-control-sm-min-height);
|
|
119
|
+
overflow-wrap: anywhere;
|
|
120
|
+
padding: var(--sw-space-1) var(--sw-space-2);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.sw-context-switcher-option[data-active='true'] {
|
|
124
|
+
background: ${quietFill};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* On the quiet fill the muted detail moves toward the text colour, keeping 4.5:1. */
|
|
128
|
+
.sw-context-switcher-option[data-active='true'] .sw-context-switcher-detail {
|
|
129
|
+
color: color-mix(in srgb, var(--sw-color-muted) 70%, var(--sw-color-text));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.sw-context-switcher-list:focus-visible .sw-context-switcher-option[data-active='true'] {
|
|
133
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
134
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.sw-context-switcher-icon {
|
|
138
|
+
display: inline-flex;
|
|
139
|
+
flex: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.sw-context-switcher-words {
|
|
143
|
+
display: flex;
|
|
144
|
+
flex: 1 1 auto;
|
|
145
|
+
flex-direction: column;
|
|
146
|
+
min-width: 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.sw-context-switcher-option[aria-selected='true'] .sw-context-switcher-label {
|
|
150
|
+
font-weight: ${label.fontWeight};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.sw-context-switcher-detail {
|
|
154
|
+
color: var(--sw-color-muted);
|
|
155
|
+
font-size: ${caption.fontSize}px;
|
|
156
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
157
|
+
line-height: ${caption.lineHeight}px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.sw-context-switcher-count {
|
|
161
|
+
flex: none;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.sw-context-switcher-check {
|
|
165
|
+
${checkStrokeIn('var(--sw-color-accent)')}
|
|
166
|
+
box-sizing: border-box;
|
|
167
|
+
flex: none;
|
|
168
|
+
height: var(--sw-space-3);
|
|
169
|
+
margin-inline: var(--sw-space-1);
|
|
170
|
+
transform: rotate(45deg);
|
|
171
|
+
width: var(--sw-space-2);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@media ${coarsePointerQuery} {
|
|
175
|
+
.sw-context-switcher-option { min-height: ${touchTarget}; }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@media (forced-colors: active) {
|
|
179
|
+
.sw-context-switcher-popup { border-color: CanvasText; }
|
|
180
|
+
.sw-context-switcher-option[data-active='true'] { background: Highlight; color: HighlightText; forced-color-adjust: none; }
|
|
181
|
+
.sw-context-switcher-option[data-active='true'] .sw-context-switcher-detail { color: HighlightText; }
|
|
182
|
+
.sw-context-switcher-option[data-active='true'] .sw-badge,
|
|
183
|
+
.sw-context-switcher-option[data-active='true'] .sw-context-switcher-count { forced-color-adjust: auto; }
|
|
184
|
+
.sw-context-switcher-check { border-color: CanvasText; }
|
|
185
|
+
.sw-context-switcher-option[data-active='true'] .sw-context-switcher-check { border-color: HighlightText; }
|
|
186
|
+
.sw-context-switcher-footer { border-color: CanvasText; }
|
|
187
|
+
}`;
|
|
188
|
+
}
|
|
189
|
+
/*
|
|
190
|
+
* ContextSwitcher (see components/ContextSwitcher.tsx): the trigger is
|
|
191
|
+
* `css-context-switcher-trigger.ts`; its count joins the shared pill
|
|
192
|
+
* (`css-count-pill.ts`).
|
|
193
|
+
*/
|
|
194
|
+
export function cssContextSwitcherClasses() {
|
|
195
|
+
return `${cssContextSwitcherTriggerClasses()}
|
|
196
|
+
|
|
197
|
+
${popupRules()}
|
|
198
|
+
|
|
199
|
+
${optionRules()}`;
|
|
200
|
+
}
|
|
201
|
+
export function contextSwitcherClassCatalog() {
|
|
202
|
+
return [
|
|
203
|
+
...contextSwitcherTriggerClassCatalog(),
|
|
204
|
+
'sw-context-switcher-popup',
|
|
205
|
+
'sw-context-switcher-filter',
|
|
206
|
+
'sw-context-switcher-list',
|
|
207
|
+
'sw-context-switcher-heading',
|
|
208
|
+
'sw-context-switcher-option',
|
|
209
|
+
'sw-context-switcher-icon',
|
|
210
|
+
'sw-context-switcher-words',
|
|
211
|
+
'sw-context-switcher-label',
|
|
212
|
+
'sw-context-switcher-detail',
|
|
213
|
+
'sw-context-switcher-check',
|
|
214
|
+
'sw-context-switcher-empty',
|
|
215
|
+
'sw-context-switcher-footer',
|
|
216
|
+
'sw-context-switcher-action-icon',
|
|
217
|
+
// sw-context-switcher-count is the shared pill's (css-count-pill.ts).
|
|
218
|
+
];
|
|
219
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** The pills that take a tone modifier:
|
|
2
|
-
declare const tonedPills: readonly ["sw-nav-count", "sw-app-shell-count"];
|
|
1
|
+
/** The pills that take a tone modifier: all but SectionNav's. */
|
|
2
|
+
declare const tonedPills: readonly ["sw-nav-count", "sw-app-shell-count", "sw-context-switcher-count"];
|
|
3
3
|
/** The tones other than the pill's own danger. */
|
|
4
4
|
declare const pillTones: readonly ["accent", "warning"];
|
|
5
5
|
/** A toned pill's modifier class, such as `sw-nav-count-warning`. */
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
import { toneTintFill, toneTintInk } from './tone-tint.js';
|
|
3
3
|
const caption = typographyVariants.caption;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The counts drawn as the pill: SectionNav's, a Nav word's, AppShell's and
|
|
6
|
+
* a ContextSwitcher option's.
|
|
7
|
+
*/
|
|
5
8
|
const pills = [
|
|
6
9
|
'sw-section-nav-count',
|
|
7
10
|
'sw-nav-count',
|
|
8
11
|
'sw-app-shell-count',
|
|
12
|
+
'sw-context-switcher-count',
|
|
13
|
+
];
|
|
14
|
+
/** The pills that take a tone modifier: all but SectionNav's. */
|
|
15
|
+
const tonedPills = [
|
|
16
|
+
'sw-nav-count',
|
|
17
|
+
'sw-app-shell-count',
|
|
18
|
+
'sw-context-switcher-count',
|
|
9
19
|
];
|
|
10
|
-
/** The pills that take a tone modifier: NavCount's and AppShell's item count. */
|
|
11
|
-
const tonedPills = ['sw-nav-count', 'sw-app-shell-count'];
|
|
12
20
|
/** The tones other than the pill's own danger. */
|
|
13
21
|
const pillTones = ['accent', 'warning'];
|
|
14
22
|
/** A toned pill's modifier class, such as `sw-nav-count-warning`. */
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const fixtureCenterKinds: readonly ["time", "score"];
|
|
2
|
+
/** `time` is a kickoff time in a grey chip; `score` is bold figures. */
|
|
3
|
+
export type FixtureCenterKind = (typeof fixtureCenterKinds)[number];
|
|
4
|
+
export declare function cssFixtureClasses(): string;
|
|
5
|
+
export declare function fixtureClassCatalog(): string[];
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { breakpointQuery } from './breakpoints.js';
|
|
3
|
+
import { chevronStrokeIn } from './chevron.js';
|
|
4
|
+
import { quietFill } from './quiet-fill.js';
|
|
5
|
+
import { touchTarget } from './touch-target.js';
|
|
6
|
+
const caption = typographyVariants.caption;
|
|
7
|
+
const label = typographyVariants.label;
|
|
8
|
+
export const fixtureCenterKinds = ['time', 'score'];
|
|
9
|
+
const belowMd = breakpointQuery('below', 'md');
|
|
10
|
+
/*
|
|
11
|
+
* The run: one grid whose columns are the home side, the centre, the away
|
|
12
|
+
* side, the end (details and status) and the chevron. Each item and its
|
|
13
|
+
* row are subgrids of it, so every row's centre and end line up down the
|
|
14
|
+
* run. The space between the columns is the centre's, the end's and the
|
|
15
|
+
* chevron's own margin, so a run with no end or chevron keeps no gap for
|
|
16
|
+
* them.
|
|
17
|
+
*/
|
|
18
|
+
function listRules() {
|
|
19
|
+
return `.sw-fixture-group {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sw-fixture-group-title {
|
|
25
|
+
color: var(--sw-color-muted);
|
|
26
|
+
font-family: var(--sw-font-sans);
|
|
27
|
+
font-size: ${caption.fontSize}px;
|
|
28
|
+
font-weight: 600;
|
|
29
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
30
|
+
line-height: ${caption.lineHeight}px;
|
|
31
|
+
padding-block: var(--sw-space-2) var(--sw-space-1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.sw-fixture-list {
|
|
35
|
+
display: grid;
|
|
36
|
+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto auto;
|
|
37
|
+
list-style: none;
|
|
38
|
+
margin: 0;
|
|
39
|
+
padding: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.sw-fixture-item,
|
|
43
|
+
.sw-fixture-row {
|
|
44
|
+
display: grid;
|
|
45
|
+
grid-column: 1 / -1;
|
|
46
|
+
grid-template-columns: subgrid;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.sw-fixture-item {
|
|
50
|
+
border-top: 1px solid var(--sw-color-border);
|
|
51
|
+
}`;
|
|
52
|
+
}
|
|
53
|
+
/*
|
|
54
|
+
* A row: the md control height (44 px), its parts centred on one line a
|
|
55
|
+
* space-3 apart; a link or button row is the whole target, the text
|
|
56
|
+
* colour, the quiet fill on hover and an inset accent ring, with the
|
|
57
|
+
* shared chevron at the end. The sides' names are label type at weight 500
|
|
58
|
+
* and wrap; the home side ends at the centre (its mark nearest it), the
|
|
59
|
+
* away side starts from it, mirrored in right-to-left.
|
|
60
|
+
*/
|
|
61
|
+
function rowRules() {
|
|
62
|
+
return `.sw-fixture-row {
|
|
63
|
+
align-items: center;
|
|
64
|
+
appearance: none;
|
|
65
|
+
background: transparent;
|
|
66
|
+
border: 0;
|
|
67
|
+
box-sizing: border-box;
|
|
68
|
+
color: var(--sw-color-text);
|
|
69
|
+
font-family: var(--sw-font-sans);
|
|
70
|
+
font-size: ${label.fontSize}px;
|
|
71
|
+
letter-spacing: ${label.letterSpacing}px;
|
|
72
|
+
line-height: ${label.lineHeight}px;
|
|
73
|
+
margin: 0;
|
|
74
|
+
min-height: ${touchTarget};
|
|
75
|
+
padding: var(--sw-space-2);
|
|
76
|
+
row-gap: var(--sw-space-1);
|
|
77
|
+
text-align: start;
|
|
78
|
+
text-decoration: none;
|
|
79
|
+
width: 100%;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.sw-fixture-row-pressable { cursor: pointer; }
|
|
83
|
+
|
|
84
|
+
@media (hover: hover) {
|
|
85
|
+
.sw-fixture-row-pressable:hover { background: ${quietFill}; }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.sw-fixture-row-pressable:focus { outline: none; }
|
|
89
|
+
|
|
90
|
+
.sw-fixture-row-pressable:focus-visible {
|
|
91
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
92
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[data-theme] a.sw-fixture-row,
|
|
96
|
+
[data-theme] a.sw-fixture-row:hover {
|
|
97
|
+
color: var(--sw-color-text);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[data-theme] a.sw-fixture-row:focus-visible {
|
|
101
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.sw-fixture-team {
|
|
105
|
+
align-items: center;
|
|
106
|
+
display: flex;
|
|
107
|
+
gap: var(--sw-space-2);
|
|
108
|
+
min-width: 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.sw-fixture-team-home {
|
|
112
|
+
grid-column: 1;
|
|
113
|
+
justify-content: flex-end;
|
|
114
|
+
text-align: end;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.sw-fixture-team-away {
|
|
118
|
+
grid-column: 3;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.sw-fixture-name {
|
|
122
|
+
font-weight: 500;
|
|
123
|
+
min-width: 0;
|
|
124
|
+
overflow-wrap: anywhere;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.sw-fixture-mark {
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
flex: none;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.sw-fixture-center {
|
|
133
|
+
font-variant-numeric: tabular-nums;
|
|
134
|
+
grid-column: 2;
|
|
135
|
+
margin-inline: var(--sw-space-3);
|
|
136
|
+
justify-self: center;
|
|
137
|
+
white-space: nowrap;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.sw-fixture-center-time {
|
|
141
|
+
background: var(--sw-color-subtle);
|
|
142
|
+
border-radius: var(--sw-radius-sm);
|
|
143
|
+
font-size: ${caption.fontSize}px;
|
|
144
|
+
font-weight: 600;
|
|
145
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
146
|
+
line-height: ${caption.lineHeight}px;
|
|
147
|
+
padding: calc(var(--sw-space-1) / 2) var(--sw-space-2);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.sw-fixture-center-score {
|
|
151
|
+
font-weight: 700;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.sw-fixture-end {
|
|
155
|
+
align-items: center;
|
|
156
|
+
color: var(--sw-color-muted);
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-wrap: wrap;
|
|
159
|
+
font-size: ${caption.fontSize}px;
|
|
160
|
+
gap: var(--sw-space-2);
|
|
161
|
+
grid-column: 4;
|
|
162
|
+
justify-content: flex-end;
|
|
163
|
+
letter-spacing: ${caption.letterSpacing}px;
|
|
164
|
+
margin-inline-start: var(--sw-space-3);
|
|
165
|
+
line-height: ${caption.lineHeight}px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.sw-fixture-chevron {
|
|
169
|
+
${chevronStrokeIn('var(--sw-color-muted)')}
|
|
170
|
+
grid-column: 5;
|
|
171
|
+
justify-self: end;
|
|
172
|
+
margin-inline: var(--sw-space-3) var(--sw-space-1);
|
|
173
|
+
transform: rotate(-45deg);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.sw-fixture-chevron:dir(rtl) { transform: rotate(135deg); }
|
|
177
|
+
|
|
178
|
+
@media (forced-colors: active) {
|
|
179
|
+
.sw-fixture-row-pressable:hover {
|
|
180
|
+
outline: var(--sw-focus-ring-width) solid Highlight;
|
|
181
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
182
|
+
}
|
|
183
|
+
.sw-fixture-center-time { border: 1px solid CanvasText; }
|
|
184
|
+
.sw-fixture-chevron { border-color: CanvasText; }
|
|
185
|
+
}`;
|
|
186
|
+
}
|
|
187
|
+
/*
|
|
188
|
+
* Below `md`: three columns and the chevron, the end on a second line
|
|
189
|
+
* from the start. After the row rules, so it wins over their placement.
|
|
190
|
+
*/
|
|
191
|
+
function narrowRules() {
|
|
192
|
+
return `@media ${belowMd} {
|
|
193
|
+
.sw-fixture-list {
|
|
194
|
+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.sw-fixture-end {
|
|
198
|
+
grid-column: 1 / 4;
|
|
199
|
+
grid-row: 2;
|
|
200
|
+
justify-content: flex-start;
|
|
201
|
+
margin-inline-start: 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.sw-fixture-chevron {
|
|
205
|
+
grid-column: 4;
|
|
206
|
+
grid-row: 1 / span 2;
|
|
207
|
+
}
|
|
208
|
+
}`;
|
|
209
|
+
}
|
|
210
|
+
/*
|
|
211
|
+
* Without subgrid (Chrome before 117, Safari before 16): each row is its
|
|
212
|
+
* own grid of the same columns, so a row still reads in order and the
|
|
213
|
+
* centres sit near the middle, but they do not line up down the run.
|
|
214
|
+
*/
|
|
215
|
+
function fallbackRules() {
|
|
216
|
+
return `@supports not (grid-template-columns: subgrid) {
|
|
217
|
+
.sw-fixture-item {
|
|
218
|
+
display: block;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.sw-fixture-row {
|
|
222
|
+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto auto;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@media ${belowMd} {
|
|
226
|
+
.sw-fixture-row {
|
|
227
|
+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}`;
|
|
231
|
+
}
|
|
232
|
+
/* FixtureGroup and FixtureRow (see components/FixtureRow.tsx). */
|
|
233
|
+
export function cssFixtureClasses() {
|
|
234
|
+
return `${listRules()}
|
|
235
|
+
|
|
236
|
+
${rowRules()}
|
|
237
|
+
|
|
238
|
+
${narrowRules()}
|
|
239
|
+
|
|
240
|
+
${fallbackRules()}`;
|
|
241
|
+
}
|
|
242
|
+
export function fixtureClassCatalog() {
|
|
243
|
+
return [
|
|
244
|
+
'sw-fixture-group',
|
|
245
|
+
'sw-fixture-group-title',
|
|
246
|
+
'sw-fixture-list',
|
|
247
|
+
'sw-fixture-item',
|
|
248
|
+
'sw-fixture-row',
|
|
249
|
+
'sw-fixture-row-pressable',
|
|
250
|
+
'sw-fixture-team',
|
|
251
|
+
'sw-fixture-team-home',
|
|
252
|
+
'sw-fixture-team-away',
|
|
253
|
+
'sw-fixture-name',
|
|
254
|
+
'sw-fixture-mark',
|
|
255
|
+
'sw-fixture-center',
|
|
256
|
+
...fixtureCenterKinds.map((kind) => `sw-fixture-center-${kind}`),
|
|
257
|
+
'sw-fixture-end',
|
|
258
|
+
'sw-fixture-chevron',
|
|
259
|
+
];
|
|
260
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare const glyphTileSizes: readonly ["sm", "md", "lg"];
|
|
2
2
|
/** `sm` 24, `md` 28 (the xs control height), `lg` 32. */
|
|
3
3
|
export type GlyphTileSize = (typeof glyphTileSizes)[number];
|
|
4
|
+
/** The most letters a tile holds, such as a three-letter crest ("NSL"). */
|
|
5
|
+
export declare const glyphTileLetterLimit = 3;
|
|
4
6
|
export declare function cssGlyphTileClasses(): string;
|
|
5
7
|
export declare function glyphTileClassCatalog(): string[];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { categoricalColorKeys } from '@scalewing/tokens';
|
|
2
2
|
export const glyphTileSizes = ['sm', 'md', 'lg'];
|
|
3
|
+
/** The most letters a tile holds, such as a three-letter crest ("NSL"). */
|
|
4
|
+
export const glyphTileLetterLimit = 3;
|
|
3
5
|
const tileSide = {
|
|
4
6
|
sm: 'var(--sw-space-5)',
|
|
5
7
|
md: 'var(--sw-control-xs-min-height)',
|
|
@@ -12,7 +14,7 @@ function hueRules() {
|
|
|
12
14
|
}
|
|
13
15
|
function sizeRules() {
|
|
14
16
|
return Object.entries(tileSide)
|
|
15
|
-
.map(([size, side]) => `.sw-glyph-tile-${size} { height: ${side}; width: ${side}; }`)
|
|
17
|
+
.map(([size, side]) => `.sw-glyph-tile-${size} { --sw-glyph-tile-side: ${side}; height: ${side}; width: ${side}; }`)
|
|
16
18
|
.join('\n');
|
|
17
19
|
}
|
|
18
20
|
/*
|
|
@@ -40,6 +42,28 @@ export function cssGlyphTileClasses() {
|
|
|
40
42
|
width: var(--sw-space-4);
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
/*
|
|
46
|
+
* Letters in place of a glyph: one line, centred, weight 600, the line as
|
|
47
|
+
* tall as the letters, sized from the tile's side rather than the text
|
|
48
|
+
* round it, so they fit at every size: one letter at half the side, two
|
|
49
|
+
* at 0.42 of it, three at a third, tightened a little, so even a wide
|
|
50
|
+
* trio ("WMW") fits inside the smallest tile.
|
|
51
|
+
*/
|
|
52
|
+
.sw-glyph-tile-text {
|
|
53
|
+
font-weight: 600;
|
|
54
|
+
line-height: 1;
|
|
55
|
+
white-space: nowrap;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.sw-glyph-tile-text-1 { font-size: calc(var(--sw-glyph-tile-side) / 2); }
|
|
59
|
+
|
|
60
|
+
.sw-glyph-tile-text-2 { font-size: calc(var(--sw-glyph-tile-side) * 0.42); }
|
|
61
|
+
|
|
62
|
+
.sw-glyph-tile-text-3 {
|
|
63
|
+
font-size: calc(var(--sw-glyph-tile-side) / 3);
|
|
64
|
+
letter-spacing: -0.02em;
|
|
65
|
+
}
|
|
66
|
+
|
|
43
67
|
${hueRules()}
|
|
44
68
|
|
|
45
69
|
${sizeRules()}
|
|
@@ -53,5 +77,9 @@ export function glyphTileClassCatalog() {
|
|
|
53
77
|
'sw-glyph-tile',
|
|
54
78
|
...categoricalColorKeys.map((key) => `sw-glyph-tile-${key}`),
|
|
55
79
|
...glyphTileSizes.map((size) => `sw-glyph-tile-${size}`),
|
|
80
|
+
'sw-glyph-tile-text',
|
|
81
|
+
'sw-glyph-tile-text-1',
|
|
82
|
+
'sw-glyph-tile-text-2',
|
|
83
|
+
'sw-glyph-tile-text-3',
|
|
56
84
|
];
|
|
57
85
|
}
|