@cosxai/ui 1.0.0-alpha.2 → 1.0.0-alpha.4
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 +14 -0
- package/package.json +4 -3
- package/src/components/Button.tsx +31 -38
- package/src/components/Toast.tsx +45 -8
- package/src/index.ts +1 -1
- package/src/theme-base.css +123 -0
- package/src/theme-reset.css +14 -0
- package/src/theme.css +2 -125
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 1.0.0-alpha.4 (2026-09-29)
|
|
2
|
+
|
|
3
|
+
- ToastCard: one toast drawn in place (documentation specimens, previews).
|
|
4
|
+
- theme.css is now theme-reset.css + theme-base.css. An app moving to the
|
|
5
|
+
kit screen by screen imports `@cosxai/ui/theme-base.css`: the kit's
|
|
6
|
+
utilities are added and Tailwind's own palette and sizes keep working.
|
|
7
|
+
New apps keep importing theme.css (unchanged result).
|
|
8
|
+
|
|
9
|
+
## 1.0.0-alpha.3 (2026-09-29)
|
|
10
|
+
|
|
11
|
+
- Button: busy and done draw over the idle content, kept in place and
|
|
12
|
+
hidden, so the width never changes — also when the button first
|
|
13
|
+
renders busy (it used to shrink to the spinner). No width measuring.
|
|
14
|
+
|
|
1
15
|
## 1.0.0-alpha.2 (2026-09-29)
|
|
2
16
|
|
|
3
17
|
MetaRoom product patterns (spec P0), checked light / ink × en / zh.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosxai/ui",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
4
|
-
"description": "COSX Design System 3.0
|
|
3
|
+
"version": "1.0.0-alpha.4",
|
|
4
|
+
"description": "COSX Design System 3.0 \u2014 tokens, Tailwind v4 theme and React components",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./src/index.ts",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
".": "./src/index.ts",
|
|
11
11
|
"./styles.css": "./src/styles.css",
|
|
12
12
|
"./theme.css": "./src/theme.css",
|
|
13
|
-
"./tokens/*": "./src/tokens/*"
|
|
13
|
+
"./tokens/*": "./src/tokens/*",
|
|
14
|
+
"./theme-base.css": "./src/theme-base.css"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"src",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Slot } from '@radix-ui/react-slot';
|
|
2
2
|
import { cva } from 'class-variance-authority';
|
|
3
3
|
import { Check } from 'lucide-react';
|
|
4
|
-
import {
|
|
4
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
5
5
|
|
|
6
6
|
import { cn } from '../lib/cn';
|
|
7
7
|
import { Spinner } from './Spinner';
|
|
@@ -76,7 +76,7 @@ export type ButtonProps = Omit<ComponentProps<'button'>, 'disabled'> & {
|
|
|
76
76
|
shortcut?: string | undefined;
|
|
77
77
|
/** A count at the end (Comments 12). Hidden at zero, 99+ above 99. */
|
|
78
78
|
count?: number | undefined;
|
|
79
|
-
/** Async state: busy
|
|
79
|
+
/** Async state: busy shows a spinner, done confirms in place; the width never changes. See useButtonAction. */
|
|
80
80
|
state?: ButtonState | undefined;
|
|
81
81
|
/** Label shown while state="done". @default the children */
|
|
82
82
|
doneLabel?: ReactNode;
|
|
@@ -119,15 +119,6 @@ export function Button({
|
|
|
119
119
|
ref,
|
|
120
120
|
...rest
|
|
121
121
|
}: ButtonProps) {
|
|
122
|
-
const inner = useRef<HTMLButtonElement | null>(null);
|
|
123
|
-
const [lockedWidth, setLockedWidth] = useState<number | null>(null);
|
|
124
|
-
|
|
125
|
-
// Lock the idle width so busy / done never resize the button.
|
|
126
|
-
useLayoutEffect(() => {
|
|
127
|
-
if (state === 'idle') setLockedWidth(null);
|
|
128
|
-
else if (lockedWidth === null && inner.current) setLockedWidth(inner.current.getBoundingClientRect().width);
|
|
129
|
-
}, [state, lockedWidth]);
|
|
130
|
-
|
|
131
122
|
const classes = cn(button({ variant, size, ground: ground ?? 'auto' }), className);
|
|
132
123
|
if (asChild) {
|
|
133
124
|
return (
|
|
@@ -138,21 +129,18 @@ export function Button({
|
|
|
138
129
|
}
|
|
139
130
|
|
|
140
131
|
const busy = state === 'busy';
|
|
132
|
+
// Busy and done keep the idle content in place (hidden) and draw on top of
|
|
133
|
+
// it, so the button never resizes — also when it first renders busy.
|
|
134
|
+
const overlaid = state !== 'idle';
|
|
141
135
|
const blocked = Boolean(disabledReason) && disabled;
|
|
142
136
|
const shownCount = count === undefined ? null : formatCount(count);
|
|
143
|
-
const setRefs = (el: HTMLButtonElement | null) => {
|
|
144
|
-
inner.current = el;
|
|
145
|
-
if (typeof ref === 'function') ref(el);
|
|
146
|
-
else if (ref) ref.current = el;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
137
|
return (
|
|
150
138
|
<button
|
|
151
139
|
type="button"
|
|
152
140
|
{...rest}
|
|
153
|
-
ref={
|
|
141
|
+
ref={ref}
|
|
154
142
|
className={classes}
|
|
155
|
-
style={
|
|
143
|
+
style={style}
|
|
156
144
|
disabled={disabled && !disabledReason ? true : undefined}
|
|
157
145
|
// Busy is not disabled (spec: "busy and disabled are different states"):
|
|
158
146
|
// it keeps its look; aria-busy says so and repeat clicks are ignored below.
|
|
@@ -167,27 +155,32 @@ export function Button({
|
|
|
167
155
|
onClick?.(e);
|
|
168
156
|
}}
|
|
169
157
|
>
|
|
170
|
-
{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
158
|
+
<span className={cn('contents', overlaid && 'invisible')} aria-hidden={overlaid || undefined} data-button-content="">
|
|
159
|
+
{iconLeft}
|
|
160
|
+
{children}
|
|
161
|
+
{iconRight}
|
|
162
|
+
{shownCount && <span className="font-medium tabular-nums opacity-70">{shownCount}</span>}
|
|
163
|
+
{shortcut && (
|
|
164
|
+
<kbd className="ml-0.5 font-sans text-[12px] font-medium opacity-60" aria-hidden>
|
|
165
|
+
{shortcut}
|
|
166
|
+
</kbd>
|
|
167
|
+
)}
|
|
168
|
+
</span>
|
|
169
|
+
{overlaid && (
|
|
170
|
+
<span className="absolute inset-0 flex items-center justify-center gap-2" data-button-overlay="">
|
|
171
|
+
{busy ? (
|
|
172
|
+
<>
|
|
173
|
+
<Spinner />
|
|
174
|
+
<span className="sr-only">{children}</span>
|
|
175
|
+
</>
|
|
176
|
+
) : (
|
|
177
|
+
<>
|
|
178
|
+
<Check size={14} strokeWidth={2} aria-hidden />
|
|
179
|
+
{doneLabel ?? children}
|
|
180
|
+
</>
|
|
187
181
|
)}
|
|
188
|
-
|
|
182
|
+
</span>
|
|
189
183
|
)}
|
|
190
|
-
{busy && <span className="sr-only">{children}</span>}
|
|
191
184
|
</button>
|
|
192
185
|
);
|
|
193
186
|
}
|
package/src/components/Toast.tsx
CHANGED
|
@@ -91,6 +91,47 @@ const DEFAULT_LABELS: ToastLabels = {
|
|
|
91
91
|
region: 'Notifications',
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
+
const CARD = 'flex w-80 max-w-full items-start gap-3 rounded-[12px] bg-ink px-4 py-3.5 font-sans text-linen ink:border ink:border-inv-rule ink:bg-ink-raised';
|
|
95
|
+
const ACTION =
|
|
96
|
+
'mt-2.5 inline-flex h-8 cursor-pointer items-center rounded-md border border-inv-rule bg-transparent px-3 text-[13px] font-semibold text-linen outline-none hover:border-linen focus-visible:shadow-[0_0_0_3px_var(--ink),0_0_0_5px_var(--yellow)]';
|
|
97
|
+
const CLOSE = 'flex cursor-pointer rounded-xs border-0 bg-transparent p-0.5 text-grey-inverse outline-none hover:text-linen focus-visible:shadow-[0_0_0_2px_var(--yellow)]';
|
|
98
|
+
const statusLabelClass = (status: ToastStatus) => cn('mb-0.5 text-meta font-medium', status === 'attention' ? 'text-yellow-accent' : 'text-grey-inverse');
|
|
99
|
+
|
|
100
|
+
export type ToastCardProps = Omit<ToastOptions, 'duration' | 'action'> & {
|
|
101
|
+
/** A label, or the full action (label + onClick). */
|
|
102
|
+
action?: string | ToastOptions['action'];
|
|
103
|
+
onClose?: (() => void) | undefined;
|
|
104
|
+
labels?: Partial<ToastLabels> | undefined;
|
|
105
|
+
className?: string | undefined;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* ToastCard — one toast drawn in place, not queued: documentation
|
|
110
|
+
* specimens and previews. In the product, call toast() instead.
|
|
111
|
+
*/
|
|
112
|
+
export function ToastCard({ title, description, status = 'neutral', action, onClose, labels, className }: ToastCardProps) {
|
|
113
|
+
const l = { ...DEFAULT_LABELS, ...labels };
|
|
114
|
+
const act = typeof action === 'string' ? { label: action, onClick: () => {} } : action;
|
|
115
|
+
return (
|
|
116
|
+
<div className={cn(CARD, className)}>
|
|
117
|
+
<span aria-hidden className={cn('mt-[5px] size-2 shrink-0 rounded-pill', DOT[status])} />
|
|
118
|
+
<div className="min-w-0 flex-1">
|
|
119
|
+
<div className={statusLabelClass(status)}>{l[status]}</div>
|
|
120
|
+
<div className="text-ui leading-[1.4] font-medium">{title}</div>
|
|
121
|
+
{description && <div className="mt-0.5 text-[13px] leading-normal text-grey-inverse">{description}</div>}
|
|
122
|
+
{act && (
|
|
123
|
+
<button type="button" onClick={act.onClick} className={ACTION}>
|
|
124
|
+
{act.label}
|
|
125
|
+
</button>
|
|
126
|
+
)}
|
|
127
|
+
</div>
|
|
128
|
+
<button type="button" aria-label={l.dismiss} onClick={onClose} className={CLOSE}>
|
|
129
|
+
<X size={14} strokeWidth={2} aria-hidden />
|
|
130
|
+
</button>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
94
135
|
export type ToasterProps = {
|
|
95
136
|
/** Wording of the status labels and controls (e.g. Chinese). */
|
|
96
137
|
labels?: Partial<ToastLabels> | undefined;
|
|
@@ -120,22 +161,18 @@ export function Toaster({ labels, offset = 24 }: ToasterProps) {
|
|
|
120
161
|
}}
|
|
121
162
|
duration={t.duration ?? (t.action ? 8000 : 4000)}
|
|
122
163
|
type={status === 'error' ? 'foreground' : 'background'}
|
|
123
|
-
className={cn(
|
|
124
|
-
'flex w-80 max-w-full items-start gap-3 rounded-[12px] bg-ink px-4 py-3.5 font-sans text-linen',
|
|
125
|
-
'ink:border ink:border-inv-rule ink:bg-ink-raised',
|
|
126
|
-
'data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=end]:hidden',
|
|
127
|
-
)}
|
|
164
|
+
className={cn(CARD, 'data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=end]:hidden')}
|
|
128
165
|
>
|
|
129
166
|
<span aria-hidden className={cn('mt-[5px] size-2 shrink-0 rounded-pill', DOT[status])} />
|
|
130
167
|
<div className="min-w-0 flex-1">
|
|
131
|
-
<div className={
|
|
168
|
+
<div className={statusLabelClass(status)}>{l[status]}</div>
|
|
132
169
|
<ToastPrimitive.Title className="text-ui leading-[1.4] font-medium">{t.title}</ToastPrimitive.Title>
|
|
133
170
|
{t.description && <ToastPrimitive.Description className="mt-0.5 text-[13px] leading-normal text-grey-inverse">{t.description}</ToastPrimitive.Description>}
|
|
134
171
|
{t.action && (
|
|
135
172
|
<ToastPrimitive.Action
|
|
136
173
|
altText={t.action.altText ?? t.action.label}
|
|
137
174
|
onClick={t.action.onClick}
|
|
138
|
-
className=
|
|
175
|
+
className={ACTION}
|
|
139
176
|
>
|
|
140
177
|
{t.action.label}
|
|
141
178
|
</ToastPrimitive.Action>
|
|
@@ -143,7 +180,7 @@ export function Toaster({ labels, offset = 24 }: ToasterProps) {
|
|
|
143
180
|
</div>
|
|
144
181
|
<ToastPrimitive.Close
|
|
145
182
|
aria-label={l.dismiss}
|
|
146
|
-
className=
|
|
183
|
+
className={CLOSE}
|
|
147
184
|
>
|
|
148
185
|
<X size={14} strokeWidth={2} aria-hidden />
|
|
149
186
|
</ToastPrimitive.Close>
|
package/src/index.ts
CHANGED
|
@@ -31,7 +31,7 @@ export { Switch, type SwitchProps } from './components/Switch';
|
|
|
31
31
|
export { Table, type TableColumn, type TableProps, type TableRowBase, type TableSort, type TableSortDirection } from './components/Table';
|
|
32
32
|
export { Tab, TabList, TabPanel, Tabs, type TabItem, type TabListProps, type TabPanelProps, type TabProps, type TabsProps, type TabsVariant } from './components/Tabs';
|
|
33
33
|
export { Textarea, type TextareaProps } from './components/Textarea';
|
|
34
|
-
export { Toaster, toast, type ToasterProps, type ToastLabels, type ToastOptions, type ToastStatus } from './components/Toast';
|
|
34
|
+
export { ToastCard, Toaster, toast, type ToastCardProps, type ToasterProps, type ToastLabels, type ToastOptions, type ToastStatus } from './components/Toast';
|
|
35
35
|
export { Tooltip, TooltipProvider, type TooltipProps } from './components/Tooltip';
|
|
36
36
|
|
|
37
37
|
// Stage 2 — product patterns
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* @cosxai/ui — the design system's Tailwind utilities, without clearing
|
|
2
|
+
* Tailwind's own palette, sizes, radii, shadows, fonts and easings.
|
|
3
|
+
*
|
|
4
|
+
* For an app moving to the kit screen by screen (product-meta during the
|
|
5
|
+
* move): its existing classes keep working, and the kit's are added. Where
|
|
6
|
+
* both define a name (radius, font-sans, ease-in/out), the kit's value wins.
|
|
7
|
+
* New apps import theme.css, which is this plus the reset.
|
|
8
|
+
*/
|
|
9
|
+
/* ink: — styles for ink mode (data-mode="ink" on <html>, or inside
|
|
10
|
+
.ink-mode). The semantic colours switch by themselves; this is for the
|
|
11
|
+
rules that flip on ink (the primary becomes the yellow). */
|
|
12
|
+
@custom-variant ink (&:where([data-mode="ink"], [data-mode="ink"] *, .ink-mode, .ink-mode *));
|
|
13
|
+
|
|
14
|
+
@theme inline {
|
|
15
|
+
|
|
16
|
+
/* Materials — fixed, do not switch with ink mode */
|
|
17
|
+
--color-paper: var(--paper);
|
|
18
|
+
--color-linen: var(--linen);
|
|
19
|
+
--color-sunk-2: var(--sunk-2);
|
|
20
|
+
--color-sunk-3: var(--sunk-3);
|
|
21
|
+
--color-ink: var(--ink);
|
|
22
|
+
--color-ink-raised: var(--ink-raised);
|
|
23
|
+
--color-grey: var(--grey);
|
|
24
|
+
--color-grey-inverse: var(--grey-inverse);
|
|
25
|
+
|
|
26
|
+
/* The yellow — one hue, by area */
|
|
27
|
+
--color-yellow: var(--yellow);
|
|
28
|
+
--color-yellow-accent: var(--yellow-accent);
|
|
29
|
+
--color-yellow-accent-hover: var(--yellow-accent-hover);
|
|
30
|
+
--color-yellow-light: var(--yellow-light);
|
|
31
|
+
--color-yellow-hover: var(--yellow-hover);
|
|
32
|
+
--color-yellow-1: var(--yellow-1);
|
|
33
|
+
--color-yellow-2: var(--yellow-2);
|
|
34
|
+
--color-yellow-3: var(--yellow-3);
|
|
35
|
+
--color-yellow-4: var(--yellow-4);
|
|
36
|
+
--color-yellow-5: var(--yellow-5);
|
|
37
|
+
--color-yellow-wash-12: var(--yellow-12);
|
|
38
|
+
--color-yellow-wash-20: var(--yellow-20);
|
|
39
|
+
--color-yellow-wash-32: var(--yellow-32);
|
|
40
|
+
--color-yellow-wash-50: var(--yellow-50);
|
|
41
|
+
--color-marker: var(--marker);
|
|
42
|
+
|
|
43
|
+
/* Semantic — switch with ink mode. Product code uses these. */
|
|
44
|
+
--color-page: var(--bg-page);
|
|
45
|
+
--color-sunk: var(--bg-sunk);
|
|
46
|
+
--color-well: var(--bg-well);
|
|
47
|
+
--color-chrome: var(--bg-chrome);
|
|
48
|
+
--color-field: var(--bg-field);
|
|
49
|
+
--color-fg: var(--text-primary);
|
|
50
|
+
--color-fg-secondary: var(--text-secondary);
|
|
51
|
+
--color-fg-label: var(--text-label);
|
|
52
|
+
--color-fg-on-yellow-secondary: var(--text-on-yellow-secondary);
|
|
53
|
+
--color-rule: var(--rule);
|
|
54
|
+
--color-rule-soft: var(--rule-soft);
|
|
55
|
+
--color-hover: var(--hover);
|
|
56
|
+
--color-scrim: var(--scrim);
|
|
57
|
+
|
|
58
|
+
/* Workspace brand (brand.css): the COSX yellow unless a customer's
|
|
59
|
+
colour is injected. Selection and grounds use field; dots and
|
|
60
|
+
progress use mark. Never for text. */
|
|
61
|
+
--color-brand-field: var(--brand-field);
|
|
62
|
+
--color-brand-mark: var(--brand-mark);
|
|
63
|
+
|
|
64
|
+
/* On an ink surface inside a paper page */
|
|
65
|
+
--color-inv: var(--inv-bg);
|
|
66
|
+
--color-inv-raised: var(--inv-bg-raised);
|
|
67
|
+
--color-inv-fg: var(--inv-text);
|
|
68
|
+
--color-inv-fg-secondary: var(--inv-text-secondary);
|
|
69
|
+
--color-inv-rule: var(--inv-rule);
|
|
70
|
+
|
|
71
|
+
/* Product status: yellow, ink and one red. Progress is an ink outline and
|
|
72
|
+
complete a grey dot — they take no colour of their own. */
|
|
73
|
+
--color-attention: var(--status-attention);
|
|
74
|
+
--color-attention-wash: var(--status-attention-wash);
|
|
75
|
+
--color-error: var(--status-error);
|
|
76
|
+
--color-error-text: var(--status-error-text);
|
|
77
|
+
--color-error-wash: var(--status-error-wash);
|
|
78
|
+
|
|
79
|
+
--color-transparent: transparent;
|
|
80
|
+
--color-current: currentColor;
|
|
81
|
+
--color-white: #fff;
|
|
82
|
+
|
|
83
|
+
/* Radius ladder — same names and values as 3.0 spacing.css */
|
|
84
|
+
--radius-xs: 4px;
|
|
85
|
+
--radius-sm: 6px;
|
|
86
|
+
--radius-md: 8px;
|
|
87
|
+
--radius-lg: 16px;
|
|
88
|
+
--radius-xl: 24px;
|
|
89
|
+
--radius-pill: 999px;
|
|
90
|
+
|
|
91
|
+
/* One family. Same stacks as fonts.css (the ones in effect): font-sans
|
|
92
|
+
for Latin, font-sans-cjk for Chinese pages (Geist for Latin and
|
|
93
|
+
figures, Noto Sans SC for hanzi). */
|
|
94
|
+
--font-sans: "Geist Variable", "Geist", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
95
|
+
--font-sans-cjk: "Geist Variable", "Geist", "Noto Sans SC Variable", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
96
|
+
|
|
97
|
+
--font-weight-normal: 400;
|
|
98
|
+
--font-weight-medium: 500;
|
|
99
|
+
--font-weight-semibold: 600;
|
|
100
|
+
--font-weight-bold: 700;
|
|
101
|
+
|
|
102
|
+
/* Type scale (typography.css). Product UI body is 14px, content 15px. */
|
|
103
|
+
--text-meta: 12px;
|
|
104
|
+
--text-small: 13.5px;
|
|
105
|
+
--text-ui: 14px;
|
|
106
|
+
--text-body: 15px;
|
|
107
|
+
--text-h3: 18px;
|
|
108
|
+
--text-lede: 20px;
|
|
109
|
+
--text-title: 22px;
|
|
110
|
+
--text-figure: 32px;
|
|
111
|
+
--text-h2: var(--size-h2);
|
|
112
|
+
--text-h1: var(--size-h1);
|
|
113
|
+
--text-display: var(--size-display);
|
|
114
|
+
|
|
115
|
+
--tracking-display: -0.025em;
|
|
116
|
+
--tracking-heading: -0.015em;
|
|
117
|
+
--tracking-figure: -0.03em;
|
|
118
|
+
|
|
119
|
+
/* Motion — flat for state, ease-out for entry; nothing bounces */
|
|
120
|
+
--ease-standard: cubic-bezier(.2,0,.2,1);
|
|
121
|
+
--ease-out: cubic-bezier(.16,1,.3,1);
|
|
122
|
+
--ease-in: cubic-bezier(.4,0,1,1);
|
|
123
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* @cosxai/ui — clears Tailwind's defaults so only the design system's
|
|
2
|
+
* values exist (part of theme.css; see theme-base.css for incremental use). */
|
|
3
|
+
@theme {
|
|
4
|
+
--color-*: initial;
|
|
5
|
+
--radius-*: initial;
|
|
6
|
+
--shadow-*: initial;
|
|
7
|
+
--inset-shadow-*: initial;
|
|
8
|
+
--drop-shadow-*: initial;
|
|
9
|
+
--font-*: initial;
|
|
10
|
+
--ease-*: initial;
|
|
11
|
+
--text-*: initial;
|
|
12
|
+
--font-weight-*: initial;
|
|
13
|
+
--tracking-*: initial;
|
|
14
|
+
}
|
package/src/theme.css
CHANGED
|
@@ -16,128 +16,5 @@
|
|
|
16
16
|
* (theme.test.ts). In particular font sizes avoid --text-primary /
|
|
17
17
|
* --text-secondary / --text-label, which are colours in 3.0.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
rules that flip on ink (the primary becomes the yellow). */
|
|
22
|
-
@custom-variant ink (&:where([data-mode="ink"], [data-mode="ink"] *, .ink-mode, .ink-mode *));
|
|
23
|
-
|
|
24
|
-
@theme inline {
|
|
25
|
-
--color-*: initial;
|
|
26
|
-
--radius-*: initial;
|
|
27
|
-
--shadow-*: initial;
|
|
28
|
-
--inset-shadow-*: initial;
|
|
29
|
-
--drop-shadow-*: initial;
|
|
30
|
-
--font-*: initial;
|
|
31
|
-
--ease-*: initial;
|
|
32
|
-
--text-*: initial;
|
|
33
|
-
--font-weight-*: initial;
|
|
34
|
-
--tracking-*: initial;
|
|
35
|
-
|
|
36
|
-
/* Materials — fixed, do not switch with ink mode */
|
|
37
|
-
--color-paper: var(--paper);
|
|
38
|
-
--color-linen: var(--linen);
|
|
39
|
-
--color-sunk-2: var(--sunk-2);
|
|
40
|
-
--color-sunk-3: var(--sunk-3);
|
|
41
|
-
--color-ink: var(--ink);
|
|
42
|
-
--color-ink-raised: var(--ink-raised);
|
|
43
|
-
--color-grey: var(--grey);
|
|
44
|
-
--color-grey-inverse: var(--grey-inverse);
|
|
45
|
-
|
|
46
|
-
/* The yellow — one hue, by area */
|
|
47
|
-
--color-yellow: var(--yellow);
|
|
48
|
-
--color-yellow-accent: var(--yellow-accent);
|
|
49
|
-
--color-yellow-accent-hover: var(--yellow-accent-hover);
|
|
50
|
-
--color-yellow-light: var(--yellow-light);
|
|
51
|
-
--color-yellow-hover: var(--yellow-hover);
|
|
52
|
-
--color-yellow-1: var(--yellow-1);
|
|
53
|
-
--color-yellow-2: var(--yellow-2);
|
|
54
|
-
--color-yellow-3: var(--yellow-3);
|
|
55
|
-
--color-yellow-4: var(--yellow-4);
|
|
56
|
-
--color-yellow-5: var(--yellow-5);
|
|
57
|
-
--color-yellow-wash-12: var(--yellow-12);
|
|
58
|
-
--color-yellow-wash-20: var(--yellow-20);
|
|
59
|
-
--color-yellow-wash-32: var(--yellow-32);
|
|
60
|
-
--color-yellow-wash-50: var(--yellow-50);
|
|
61
|
-
--color-marker: var(--marker);
|
|
62
|
-
|
|
63
|
-
/* Semantic — switch with ink mode. Product code uses these. */
|
|
64
|
-
--color-page: var(--bg-page);
|
|
65
|
-
--color-sunk: var(--bg-sunk);
|
|
66
|
-
--color-well: var(--bg-well);
|
|
67
|
-
--color-chrome: var(--bg-chrome);
|
|
68
|
-
--color-field: var(--bg-field);
|
|
69
|
-
--color-fg: var(--text-primary);
|
|
70
|
-
--color-fg-secondary: var(--text-secondary);
|
|
71
|
-
--color-fg-label: var(--text-label);
|
|
72
|
-
--color-fg-on-yellow-secondary: var(--text-on-yellow-secondary);
|
|
73
|
-
--color-rule: var(--rule);
|
|
74
|
-
--color-rule-soft: var(--rule-soft);
|
|
75
|
-
--color-hover: var(--hover);
|
|
76
|
-
--color-scrim: var(--scrim);
|
|
77
|
-
|
|
78
|
-
/* Workspace brand (brand.css): the COSX yellow unless a customer's
|
|
79
|
-
colour is injected. Selection and grounds use field; dots and
|
|
80
|
-
progress use mark. Never for text. */
|
|
81
|
-
--color-brand-field: var(--brand-field);
|
|
82
|
-
--color-brand-mark: var(--brand-mark);
|
|
83
|
-
|
|
84
|
-
/* On an ink surface inside a paper page */
|
|
85
|
-
--color-inv: var(--inv-bg);
|
|
86
|
-
--color-inv-raised: var(--inv-bg-raised);
|
|
87
|
-
--color-inv-fg: var(--inv-text);
|
|
88
|
-
--color-inv-fg-secondary: var(--inv-text-secondary);
|
|
89
|
-
--color-inv-rule: var(--inv-rule);
|
|
90
|
-
|
|
91
|
-
/* Product status: yellow, ink and one red. Progress is an ink outline and
|
|
92
|
-
complete a grey dot — they take no colour of their own. */
|
|
93
|
-
--color-attention: var(--status-attention);
|
|
94
|
-
--color-attention-wash: var(--status-attention-wash);
|
|
95
|
-
--color-error: var(--status-error);
|
|
96
|
-
--color-error-text: var(--status-error-text);
|
|
97
|
-
--color-error-wash: var(--status-error-wash);
|
|
98
|
-
|
|
99
|
-
--color-transparent: transparent;
|
|
100
|
-
--color-current: currentColor;
|
|
101
|
-
--color-white: #fff;
|
|
102
|
-
|
|
103
|
-
/* Radius ladder — same names and values as 3.0 spacing.css */
|
|
104
|
-
--radius-xs: 4px;
|
|
105
|
-
--radius-sm: 6px;
|
|
106
|
-
--radius-md: 8px;
|
|
107
|
-
--radius-lg: 16px;
|
|
108
|
-
--radius-xl: 24px;
|
|
109
|
-
--radius-pill: 999px;
|
|
110
|
-
|
|
111
|
-
/* One family. Same stacks as fonts.css (the ones in effect): font-sans
|
|
112
|
-
for Latin, font-sans-cjk for Chinese pages (Geist for Latin and
|
|
113
|
-
figures, Noto Sans SC for hanzi). */
|
|
114
|
-
--font-sans: "Geist Variable", "Geist", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
115
|
-
--font-sans-cjk: "Geist Variable", "Geist", "Noto Sans SC Variable", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
116
|
-
|
|
117
|
-
--font-weight-normal: 400;
|
|
118
|
-
--font-weight-medium: 500;
|
|
119
|
-
--font-weight-semibold: 600;
|
|
120
|
-
--font-weight-bold: 700;
|
|
121
|
-
|
|
122
|
-
/* Type scale (typography.css). Product UI body is 14px, content 15px. */
|
|
123
|
-
--text-meta: 12px;
|
|
124
|
-
--text-small: 13.5px;
|
|
125
|
-
--text-ui: 14px;
|
|
126
|
-
--text-body: 15px;
|
|
127
|
-
--text-h3: 18px;
|
|
128
|
-
--text-lede: 20px;
|
|
129
|
-
--text-title: 22px;
|
|
130
|
-
--text-figure: 32px;
|
|
131
|
-
--text-h2: var(--size-h2);
|
|
132
|
-
--text-h1: var(--size-h1);
|
|
133
|
-
--text-display: var(--size-display);
|
|
134
|
-
|
|
135
|
-
--tracking-display: -0.025em;
|
|
136
|
-
--tracking-heading: -0.015em;
|
|
137
|
-
--tracking-figure: -0.03em;
|
|
138
|
-
|
|
139
|
-
/* Motion — flat for state, ease-out for entry; nothing bounces */
|
|
140
|
-
--ease-standard: cubic-bezier(.2,0,.2,1);
|
|
141
|
-
--ease-out: cubic-bezier(.16,1,.3,1);
|
|
142
|
-
--ease-in: cubic-bezier(.4,0,1,1);
|
|
143
|
-
}
|
|
19
|
+
@import "./theme-reset.css";
|
|
20
|
+
@import "./theme-base.css";
|