@hideyukimori/nene2-ui 0.19.0 → 0.20.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/README.md +10 -0
- package/dist/data/Pagination.js +2 -2
- package/dist/data/Pagination.js.map +1 -1
- package/dist/feedback/Badge.d.ts +32 -1
- package/dist/feedback/Badge.js +18 -3
- package/dist/feedback/Badge.js.map +1 -1
- package/dist/layout/PageHeader.d.ts +19 -1
- package/dist/layout/PageHeader.js +3 -2
- package/dist/layout/PageHeader.js.map +1 -1
- package/dist/overlay/ConfirmDialog.js +1 -1
- package/dist/overlay/ConfirmDialog.js.map +1 -1
- package/dist/primitives/Button.d.ts +33 -2
- package/dist/primitives/Button.js +77 -12
- package/dist/primitives/Button.js.map +1 -1
- package/dist/states/ErrorState.js +1 -1
- package/dist/states/ErrorState.js.map +1 -1
- package/package.json +1 -1
- package/themes/default.css +70 -16
package/README.md
CHANGED
|
@@ -35,6 +35,16 @@ bound. Providing the parts scales with the number of screens, which is finite.**
|
|
|
35
35
|
cannot express it, add a variant — for everyone. _This is the principle that matters:_ the
|
|
36
36
|
13,021 style violations the fleet is currently remediating exist because values could be
|
|
37
37
|
written inline. Make them unwritable and there is nothing to inspect.
|
|
38
|
+
|
|
39
|
+
🔴 **But "add a variant" is the wrong move when the axis is wrong** (#487). `Button` carried
|
|
40
|
+
one closed enum that mixed *shape* with *colour* — `primary | secondary | danger | ghost` —
|
|
41
|
+
so "the ghost shape in the danger colour" was not sayable. Five ships each invented a
|
|
42
|
+
private name for that one cell and no two agreed (`ghost-danger`, `danger-ghost`,
|
|
43
|
+
`link-danger`, `danger-outline`, and nene-deal reached it through slots). Enumerating four
|
|
44
|
+
more values would have left `4 shapes × 4 tones = 16` names to chase. 0.20.0 splits the
|
|
45
|
+
axis instead: `variant` is the shape, `tone` is the colour. **Before adding a value, check
|
|
46
|
+
whether what is missing is a value or an axis** — a value that ships keep spelling with a
|
|
47
|
+
hyphen in the middle is usually two axes wearing one name.
|
|
38
48
|
4. **No strings.** The kit ships no user-visible text. `Spinner` takes `label`, `ErrorState` takes
|
|
39
49
|
`retryLabel`. Localisation stays with the product (`@hideyukimori/nene2-i18n`), so a wording
|
|
40
50
|
change never becomes a kit release.
|
package/dist/data/Pagination.js
CHANGED
|
@@ -28,9 +28,9 @@ export function Pagination(props) {
|
|
|
28
28
|
const atEnd = props.page === undefined ? !props.canNext : props.page >= props.pageCount;
|
|
29
29
|
const goPrev = () => props.page === undefined ? props.onPrev() : props.onPageChange(props.page - 1);
|
|
30
30
|
const goNext = () => props.page === undefined ? props.onNext() : props.onPageChange(props.page + 1);
|
|
31
|
-
const prev = (_jsx(Button, { variant: "
|
|
31
|
+
const prev = (_jsx(Button, { variant: "outline", tone: "neutral", size: size, disabled: atStart, onClick: goPrev, "aria-label": previousLabel, children: previousLabel }, "prev"));
|
|
32
32
|
const current = (_jsx("span", { "aria-current": "page", className: "font-sans text-x-slot-pagination-fg", children: status }, "status"));
|
|
33
|
-
const next = (_jsx(Button, { variant: "
|
|
33
|
+
const next = (_jsx(Button, { variant: "outline", tone: "neutral", size: size, disabled: atEnd, onClick: goNext, "aria-label": nextLabel, children: nextLabel }, "next"));
|
|
34
34
|
const order = statusPlacement === 'start'
|
|
35
35
|
? [current, prev, next]
|
|
36
36
|
: statusPlacement === 'end'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.js","sourceRoot":"","sources":["../../src/data/Pagination.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAiElC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,MAAM,EACJ,KAAK,EACL,aAAa,EACb,SAAS,EACT,MAAM,EACN,SAAS,EACT,IAAI,GAAG,IAAI,EACX,aAAa,EACb,eAAe,GAAG,QAAQ,GAC3B,GAAG,KAAK,CAAC;IAEV,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC;IAExF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAEjF,MAAM,IAAI,GAAG,CACX,KAAC,MAAM,IAEL,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"Pagination.js","sourceRoot":"","sources":["../../src/data/Pagination.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAiElC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,MAAM,EACJ,KAAK,EACL,aAAa,EACb,SAAS,EACT,MAAM,EACN,SAAS,EACT,IAAI,GAAG,IAAI,EACX,aAAa,EACb,eAAe,GAAG,QAAQ,GAC3B,GAAG,KAAK,CAAC;IAEV,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC;IAExF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAEjF,MAAM,IAAI,GAAG,CACX,KAAC,MAAM,IAEL,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,SAAS,EACd,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,MAAM,gBACH,aAAa,YAExB,aAAa,IARV,MAAM,CASH,CACV,CAAC;IACF,MAAM,OAAO,GAAG,CACd,+BAAgC,MAAM,EAAC,SAAS,EAAC,qCAAqC,YACnF,MAAM,IADC,QAAQ,CAEX,CACR,CAAC;IACF,MAAM,IAAI,GAAG,CACX,KAAC,MAAM,IAEL,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,SAAS,EACd,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,KAAK,EACf,OAAO,EAAE,MAAM,gBACH,SAAS,YAEpB,SAAS,IARN,MAAM,CASH,CACV,CAAC;IACF,MAAM,KAAK,GACT,eAAe,KAAK,OAAO;QACzB,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;QACvB,CAAC,CAAC,eAAe,KAAK,KAAK;YACzB,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC;YACvB,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAE9B,OAAO,CACL,4BAAiB,KAAK,EAAE,SAAS,EAAE,SAAS,YAC1C,KAAC,KAAK,IACJ,SAAS,EAAC,YAAY,EACtB,GAAG,EAAC,KAAK,EACT,KAAK,EAAC,QAAQ;YACd,6EAA6E;YAC7E,SAAS,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,IAAI,sCAAsC,CAAC,YAE9E,KAAK,GACA,GACJ,CACP,CAAC;AACJ,CAAC"}
|
package/dist/feedback/Badge.d.ts
CHANGED
|
@@ -10,6 +10,22 @@ export interface BadgeProps {
|
|
|
10
10
|
* badge as it does in an alert (0.17.0, #422).
|
|
11
11
|
*/
|
|
12
12
|
tone?: 'neutral' | 'accent' | 'danger' | 'success' | 'warn' | 'info';
|
|
13
|
+
/**
|
|
14
|
+
* Draw a small filled circle before the label.
|
|
15
|
+
*
|
|
16
|
+
* 🔴 It takes its colour from `currentColor`, so there is no dot colour slot and there
|
|
17
|
+
* must not be one: the dot is the tone, shown small. A slot would let a product set a
|
|
18
|
+
* badge whose dot disagrees with its own text, and it would have to be redefined for
|
|
19
|
+
* every tone — six values to keep in step with six that already exist (the
|
|
20
|
+
* redefine-the-default shape nene-vault retired in #481).
|
|
21
|
+
*
|
|
22
|
+
* Whether a badge has one is a per-call-site decision, not a theme value: nene-clear
|
|
23
|
+
* renders dotted and undotted badges **on the same screen** (`DunningPage` marks overdue
|
|
24
|
+
* with a dot and paused without one), so it cannot be a slot. Hence a prop.
|
|
25
|
+
*
|
|
26
|
+
* Omit it and the render is byte-for-byte what it was before this prop existed.
|
|
27
|
+
*/
|
|
28
|
+
dot?: boolean;
|
|
13
29
|
/** Composed after the kit's own classes (design principle 2). */
|
|
14
30
|
className?: string;
|
|
15
31
|
children: ReactNode;
|
|
@@ -21,4 +37,19 @@ export interface BadgeProps {
|
|
|
21
37
|
* `<Badge color="red">` becomes a lie the moment the theme changes, and there is no way to
|
|
22
38
|
* find every such lie afterwards except by reading every screen.
|
|
23
39
|
*/
|
|
24
|
-
|
|
40
|
+
/**
|
|
41
|
+
* 🔴 `whitespace-nowrap` is load-bearing (#477). A badge is a label, not body copy — but the
|
|
42
|
+
* kit had no opinion on wrapping, so in a narrow flex row the label wrapped. In CJK that is
|
|
43
|
+
* not a word-boundary break: 「あなた」 came apart into three stacked characters and the badge
|
|
44
|
+
* grew from 26.5px tall to 43px (measured, nene-deal /users at 375px).
|
|
45
|
+
*
|
|
46
|
+
* Two holes were open at once — the label could *wrap* (`white-space: normal`) and the badge
|
|
47
|
+
* could *shrink* (`flex-shrink: 1`) — and either one alone produces the failure. `shrink-0`
|
|
48
|
+
* would close it too, but only while the badge is a flex item: measured in a 50px block
|
|
49
|
+
* container, `shrink-0` still wrapped (50 × 43) while `nowrap` did not (51 × 26.5). `nowrap`
|
|
50
|
+
* also stops the shrink, because a flex item's automatic minimum size is its min-content
|
|
51
|
+
* width and nowrap makes that the whole label. One class, both holes, any context.
|
|
52
|
+
*
|
|
53
|
+
* A badge that already fits is unchanged (35.88 × 26.5 before and after, measured).
|
|
54
|
+
*/
|
|
55
|
+
export declare function Badge({ tone, dot, className, children }: BadgeProps): import("react").JSX.Element;
|
package/dist/feedback/Badge.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../lib/cx.js';
|
|
3
3
|
const TONE_CLASS = {
|
|
4
4
|
neutral: 'bg-x-slot-badge-neutral-bg text-x-slot-badge-neutral-fg border-x-slot-badge-neutral-border',
|
|
@@ -15,7 +15,22 @@ const TONE_CLASS = {
|
|
|
15
15
|
* `<Badge color="red">` becomes a lie the moment the theme changes, and there is no way to
|
|
16
16
|
* find every such lie afterwards except by reading every screen.
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 🔴 `whitespace-nowrap` is load-bearing (#477). A badge is a label, not body copy — but the
|
|
20
|
+
* kit had no opinion on wrapping, so in a narrow flex row the label wrapped. In CJK that is
|
|
21
|
+
* not a word-boundary break: 「あなた」 came apart into three stacked characters and the badge
|
|
22
|
+
* grew from 26.5px tall to 43px (measured, nene-deal /users at 375px).
|
|
23
|
+
*
|
|
24
|
+
* Two holes were open at once — the label could *wrap* (`white-space: normal`) and the badge
|
|
25
|
+
* could *shrink* (`flex-shrink: 1`) — and either one alone produces the failure. `shrink-0`
|
|
26
|
+
* would close it too, but only while the badge is a flex item: measured in a 50px block
|
|
27
|
+
* container, `shrink-0` still wrapped (50 × 43) while `nowrap` did not (51 × 26.5). `nowrap`
|
|
28
|
+
* also stops the shrink, because a flex item's automatic minimum size is its min-content
|
|
29
|
+
* width and nowrap makes that the whole label. One class, both holes, any context.
|
|
30
|
+
*
|
|
31
|
+
* A badge that already fits is unchanged (35.88 × 26.5 before and after, measured).
|
|
32
|
+
*/
|
|
33
|
+
export function Badge({ tone = 'neutral', dot = false, className, children }) {
|
|
34
|
+
return (_jsxs("span", { className: cx('inline-flex items-center whitespace-nowrap gap-x-slot-badge-gap rounded-x-slot-badge border px-x-slot-badge-pad-x py-x-slot-badge-pad-y font-sans text-x-slot-badge font-x-slot-badge', TONE_CLASS[tone], className), children: [dot && (_jsx("span", { "aria-hidden": "true", className: "size-x-slot-badge-dot shrink-0 rounded-full bg-current" })), children] }));
|
|
20
35
|
}
|
|
21
36
|
//# sourceMappingURL=Badge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../src/feedback/Badge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../src/feedback/Badge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAkClC,MAAM,UAAU,GAAoD;IAClE,OAAO,EACL,4FAA4F;IAC9F,MAAM,EAAE,yFAAyF;IACjG,MAAM,EAAE,yFAAyF;IACjG,OAAO,EACL,4FAA4F;IAC9F,IAAI,EAAE,mFAAmF;IACzF,IAAI,EAAE,mFAAmF;CAC1F,CAAC;AAEF;;;;;;GAMG;AACH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,GAAG,SAAS,EAAE,GAAG,GAAG,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAc;IACtF,OAAO,CACL,gBACE,SAAS,EAAE,EAAE,CACX,uLAAuL,EACvL,UAAU,CAAC,IAAI,CAAC,EAChB,SAAS,CACV,aAQA,GAAG,IAAI,CACN,8BACc,MAAM,EAClB,SAAS,EAAC,wDAAwD,GAClE,CACH,EACA,QAAQ,IACJ,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -4,6 +4,24 @@ export interface PageHeaderProps {
|
|
|
4
4
|
className?: string;
|
|
5
5
|
/** Localized page title. */
|
|
6
6
|
title: string;
|
|
7
|
+
/**
|
|
8
|
+
* Localized one-line description of the page, under the title.
|
|
9
|
+
*
|
|
10
|
+
* 🔴 Not decoration. nene-clear carries one on **every one of its ten pages** — the prop
|
|
11
|
+
* is `sub` there and the value is always a catalog key (`t('dunning.subtitle')`,
|
|
12
|
+
* `t('audit.subtitle')`, …), so folding it into `title` is not available to it: the two
|
|
13
|
+
* halves are separate keys, and joining them would put the separator — a string — in the
|
|
14
|
+
* ship, against principle 4. `PageHeader` takes no `children` either, so without this prop
|
|
15
|
+
* the line has nowhere to go and ten pages lose their description (#492).
|
|
16
|
+
*
|
|
17
|
+
* Omit it and the render is byte-for-byte what it was before this prop existed.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ Its size is not a slot, on purpose. The title has no size slot either — an `<h1>`
|
|
20
|
+
* reset by Preflight inherits the body size — so adding one here alone would let a product
|
|
21
|
+
* scale the description while its title stayed put. Products that need a type scale of
|
|
22
|
+
* their own are blocked on the same missing thing, and it is one gap, not two.
|
|
23
|
+
*/
|
|
24
|
+
description?: string;
|
|
7
25
|
actions?: ReactNode;
|
|
8
26
|
}
|
|
9
|
-
export declare function PageHeader({ title, actions, className }: PageHeaderProps): import("react").JSX.Element;
|
|
27
|
+
export declare function PageHeader({ title, description, actions, className }: PageHeaderProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../lib/cx.js';
|
|
3
|
-
export function PageHeader({ title, actions, className }) {
|
|
4
|
-
|
|
3
|
+
export function PageHeader({ title, description, actions, className }) {
|
|
4
|
+
const heading = (_jsx("h1", { className: "font-sans font-x-slot-page-header text-x-slot-page-header-fg", children: title }));
|
|
5
|
+
return (_jsxs("header", { className: cx('flex items-center justify-between py-x-slot-page-header-pad-y', className), children: [description === undefined ? (heading) : (_jsxs("div", { children: [heading, _jsx("p", { className: "mt-x-slot-page-header-gap font-sans text-x-slot-page-header-description-fg", children: description })] })), actions] }));
|
|
5
6
|
}
|
|
6
7
|
//# sourceMappingURL=PageHeader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/layout/PageHeader.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/layout/PageHeader.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AA4BlC,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAmB;IACpF,MAAM,OAAO,GAAG,CACd,aAAI,SAAS,EAAC,8DAA8D,YAAE,KAAK,GAAM,CAC1F,CAAC;IAEF,OAAO,CACL,kBACE,SAAS,EAAE,EAAE,CAAC,+DAA+D,EAAE,SAAS,CAAC,aAMxF,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC3B,OAAO,CACR,CAAC,CAAC,CAAC,CACF,0BACG,OAAO,EACR,YAAG,SAAS,EAAC,4EAA4E,YACtF,WAAW,GACV,IACA,CACP,EACA,OAAO,IACD,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -12,6 +12,6 @@ import { Modal } from './Modal.js';
|
|
|
12
12
|
* kind of detail that differs between five independent implementations.
|
|
13
13
|
*/
|
|
14
14
|
export function ConfirmDialog({ open, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, tone = 'default', }) {
|
|
15
|
-
return (_jsx(Modal, { open: open, onClose: onCancel, title: title, children: _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { children: message }), _jsxs(Stack, { direction: "horizontal", gap: "2xs", justify: "end", children: [_jsx(Button, { variant: "
|
|
15
|
+
return (_jsx(Modal, { open: open, onClose: onCancel, title: title, children: _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { children: message }), _jsxs(Stack, { direction: "horizontal", gap: "2xs", justify: "end", children: [_jsx(Button, { variant: "outline", tone: "neutral", onClick: onCancel, children: cancelLabel }), _jsx(Button, { tone: tone === 'danger' ? 'danger' : 'accent', onClick: onConfirm, children: confirmLabel })] })] }) }));
|
|
16
16
|
}
|
|
17
17
|
//# sourceMappingURL=ConfirmDialog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmDialog.js","sourceRoot":"","sources":["../../src/overlay/ConfirmDialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAkBnC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,IAAI,GAAG,SAAS,GACG;IACnB,OAAO,CACL,KAAC,KAAK,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,YAChD,MAAC,KAAK,IAAC,GAAG,EAAC,IAAI,aACb,KAAC,IAAI,cAAE,OAAO,GAAQ,EACtB,MAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,GAAG,EAAC,KAAK,EAAC,OAAO,EAAC,KAAK,aACnD,KAAC,MAAM,IAAC,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.js","sourceRoot":"","sources":["../../src/overlay/ConfirmDialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAkBnC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,IAAI,GAAG,SAAS,GACG;IACnB,OAAO,CACL,KAAC,KAAK,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,YAChD,MAAC,KAAK,IAAC,GAAG,EAAC,IAAI,aACb,KAAC,IAAI,cAAE,OAAO,GAAQ,EACtB,MAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,GAAG,EAAC,KAAK,EAAC,OAAO,EAAC,KAAK,aACnD,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,SAAS,EAAC,OAAO,EAAE,QAAQ,YACvD,WAAW,GACL,EAIT,KAAC,MAAM,IAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,YACtE,YAAY,GACN,IACH,IACF,GACF,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* The shape: which properties get painted. Not which colour they get painted in.
|
|
5
|
+
*
|
|
6
|
+
* 🔴 This used to be one closed enum that mixed shape and colour
|
|
7
|
+
* (`primary | secondary | danger | ghost`), so "the ghost shape in the danger colour" was
|
|
8
|
+
* not expressible. Five ships each invented their own name for that one missing cell, and
|
|
9
|
+
* no two agreed: nene-clear `ghost-danger`, nene-field `danger-ghost` (the same thing,
|
|
10
|
+
* written backwards), nene-profile `link-danger`, nene-origin `danger-outline`, and
|
|
11
|
+
* nene-deal reached the same place through slots instead — it set
|
|
12
|
+
* `--color-x-slot-button-danger-bg: transparent` and turned the filled danger into an
|
|
13
|
+
* outlined one (#455). One need, five workarounds, because the API could not say it.
|
|
14
|
+
*
|
|
15
|
+
* 🔴 `bare`, not `ghost`. The old name meant "no fill, no border" here, but nene-clear's
|
|
16
|
+
* `.btn-ghost` has both a background and a border — it is this kit's `outline`. The word is
|
|
17
|
+
* split across the industry too (Bootstrap's ghost is an outline, Material's is a text
|
|
18
|
+
* button), so a ship reading `ghost` cannot know which one it got. Renaming costs nothing:
|
|
19
|
+
* neither consuming ship uses it (nene-vault 0, nene-deal 0, measured 2026-08-27).
|
|
20
|
+
*/
|
|
21
|
+
variant?: 'solid' | 'outline' | 'bare' | 'link';
|
|
22
|
+
/**
|
|
23
|
+
* The colour: what the shape means. Not how loud it is.
|
|
24
|
+
*
|
|
25
|
+
* 🔴 The same six words `Badge` has carried since 0.17.0, in the same order, painted from
|
|
26
|
+
* the same shape of slot. A tone means one thing across the kit or it means nothing.
|
|
27
|
+
*
|
|
28
|
+
* 🔴 The default is `accent`, not `neutral`. What 0.19.x called `primary` was never a tone
|
|
29
|
+
* — it was "the accent-coloured filled button", so `<Button>` keeps rendering exactly that.
|
|
30
|
+
* `neutral` is the quiet grey step, which is what `Badge` has always meant by the word.
|
|
31
|
+
* Reading `neutral` as "the ordinary action" is how this kit ended up with two vocabularies
|
|
32
|
+
* in the first place.
|
|
33
|
+
*/
|
|
34
|
+
tone?: 'neutral' | 'accent' | 'danger' | 'success' | 'warn' | 'info';
|
|
4
35
|
/**
|
|
5
36
|
* Two sizes, not a length. `sm` for dense rows and toolbars.
|
|
6
37
|
*
|
|
@@ -10,4 +41,4 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
10
41
|
size?: 'md' | 'sm';
|
|
11
42
|
children: ReactNode;
|
|
12
43
|
}
|
|
13
|
-
export declare function Button({ variant, size, children, type, className, ...rest }: ButtonProps): import("react").JSX.Element;
|
|
44
|
+
export declare function Button({ variant, tone, size, children, type, className, ...rest }: ButtonProps): import("react").JSX.Element;
|
|
@@ -1,18 +1,82 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../lib/cx.js';
|
|
3
3
|
import { CLICKABLE_CLASS, TOUCH_CLASS } from '../lib/states.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Shape × tone, written out.
|
|
6
|
+
*
|
|
7
|
+
* 🔴 Sixteen literal strings and no interpolation, because Tailwind reads the source as text.
|
|
8
|
+
* `` `bg-x-slot-button-${tone}-bg` `` produces the right class at runtime and no CSS for it at
|
|
9
|
+
* build time — the generator never sees the string, so the rule is never emitted. The kit has
|
|
10
|
+
* to spell every combination it supports.
|
|
11
|
+
*
|
|
12
|
+
* 🔴 `solid` paints `-bg` + `-fg`; every other shape paints `-ink`. They are separate slots
|
|
13
|
+
* because they are separate colours: on a filled danger button the text is the on-accent
|
|
14
|
+
* colour, and on an outlined one it is the danger colour itself. Deriving one from the other
|
|
15
|
+
* would have made the outlined button's label white on white.
|
|
16
|
+
*
|
|
17
|
+
* 🔴 `outline`'s background is a single slot that does not vary with tone. nene-clear's
|
|
18
|
+
* outlined danger sits on the plain surface (`background: var(--surface)`) and only reaches
|
|
19
|
+
* for a tinted one on hover; painting the rest a tone-tinted colour would be louder than what
|
|
20
|
+
* any ship draws today.
|
|
21
|
+
*/
|
|
22
|
+
const SHAPE_TONE_CLASS = {
|
|
23
|
+
solid: {
|
|
24
|
+
neutral: 'bg-x-slot-button-neutral-bg text-x-slot-button-neutral-fg shadow-x-slot-button-solid',
|
|
25
|
+
accent: 'bg-x-slot-button-accent-bg text-x-slot-button-accent-fg shadow-x-slot-button-solid',
|
|
26
|
+
danger: 'bg-x-slot-button-danger-bg text-x-slot-button-danger-fg shadow-x-slot-button-solid',
|
|
27
|
+
success: 'bg-x-slot-button-success-bg text-x-slot-button-success-fg shadow-x-slot-button-solid',
|
|
28
|
+
warn: 'bg-x-slot-button-warn-bg text-x-slot-button-warn-fg shadow-x-slot-button-solid',
|
|
29
|
+
info: 'bg-x-slot-button-info-bg text-x-slot-button-info-fg shadow-x-slot-button-solid',
|
|
30
|
+
},
|
|
31
|
+
outline: {
|
|
32
|
+
neutral: 'bg-x-slot-button-outline-bg text-x-slot-button-neutral-ink border-x-slot-button-neutral-border',
|
|
33
|
+
accent: 'bg-x-slot-button-outline-bg text-x-slot-button-accent-ink border-x-slot-button-accent-border',
|
|
34
|
+
danger: 'bg-x-slot-button-outline-bg text-x-slot-button-danger-ink border-x-slot-button-danger-border',
|
|
35
|
+
success: 'bg-x-slot-button-outline-bg text-x-slot-button-success-ink border-x-slot-button-success-border',
|
|
36
|
+
warn: 'bg-x-slot-button-outline-bg text-x-slot-button-warn-ink border-x-slot-button-warn-border',
|
|
37
|
+
info: 'bg-x-slot-button-outline-bg text-x-slot-button-info-ink border-x-slot-button-info-border',
|
|
38
|
+
},
|
|
39
|
+
bare: {
|
|
40
|
+
neutral: 'bg-transparent text-x-slot-button-neutral-ink',
|
|
41
|
+
accent: 'bg-transparent text-x-slot-button-accent-ink',
|
|
42
|
+
danger: 'bg-transparent text-x-slot-button-danger-ink',
|
|
43
|
+
success: 'bg-transparent text-x-slot-button-success-ink',
|
|
44
|
+
warn: 'bg-transparent text-x-slot-button-warn-ink',
|
|
45
|
+
info: 'bg-transparent text-x-slot-button-info-ink',
|
|
46
|
+
},
|
|
47
|
+
link: {
|
|
48
|
+
neutral: 'bg-transparent text-x-slot-button-neutral-ink underline-offset-4 hover:underline',
|
|
49
|
+
accent: 'bg-transparent text-x-slot-button-accent-ink underline-offset-4 hover:underline',
|
|
50
|
+
danger: 'bg-transparent text-x-slot-button-danger-ink underline-offset-4 hover:underline',
|
|
51
|
+
success: 'bg-transparent text-x-slot-button-success-ink underline-offset-4 hover:underline',
|
|
52
|
+
warn: 'bg-transparent text-x-slot-button-warn-ink underline-offset-4 hover:underline',
|
|
53
|
+
info: 'bg-transparent text-x-slot-button-info-ink underline-offset-4 hover:underline',
|
|
54
|
+
},
|
|
11
55
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
56
|
+
/**
|
|
57
|
+
* 🔴 Padding and type size are separate because `link` takes one and not the other.
|
|
58
|
+
*
|
|
59
|
+
* A link-shaped button is a run of text inside a sentence or a table cell; padding would push
|
|
60
|
+
* it off the line it belongs to. nene-clear's `.btn-link` sets `padding: 0` and
|
|
61
|
+
* nene-profile's renders through a `linkbtn` class that does the same. The type size still
|
|
62
|
+
* applies — it is the same two sizes as every other button.
|
|
63
|
+
*/
|
|
64
|
+
const PAD_CLASS = {
|
|
65
|
+
md: 'px-x-slot-button-pad-x py-x-slot-button-pad-y',
|
|
66
|
+
sm: 'px-x-slot-button-sm-pad-x py-x-slot-button-sm-pad-y',
|
|
15
67
|
};
|
|
68
|
+
const TEXT_CLASS = {
|
|
69
|
+
md: 'text-x-slot-button-size',
|
|
70
|
+
sm: 'text-x-slot-button-sm-size',
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* `link` drops the box the other three shapes share.
|
|
74
|
+
*
|
|
75
|
+
* 🔴 `border-0` rather than leaving the transparent border in place: the border is there so a
|
|
76
|
+
* bordered button matches an unbordered one in height, and a link has no height to match.
|
|
77
|
+
* `rounded-none` for the same reason — there is no box to round.
|
|
78
|
+
*/
|
|
79
|
+
const LINK_UNBOX = 'border-0 rounded-none';
|
|
16
80
|
// 🔴 `inline-flex`, so the button places what is inside it. A `<button>` is `inline-block`
|
|
17
81
|
// by default, which leaves an icon and its label on a shared baseline rather than centred —
|
|
18
82
|
// visible as a half-pixel of drift on every icon button, and invisible in a diff. The kit
|
|
@@ -43,7 +107,8 @@ const SIZE_CLASS = {
|
|
|
43
107
|
// leaves anything already smaller alone.
|
|
44
108
|
const SVG_BOUND = '[&_svg]:max-h-x-slot-button-icon [&_svg]:max-w-x-slot-button-icon';
|
|
45
109
|
const BASE_CLASS = `rounded-x-slot-button border border-transparent inline-flex items-center justify-center gap-x-slot-button-gap font-sans font-x-slot-button ${SVG_BOUND} ${TOUCH_CLASS} ${CLICKABLE_CLASS}`;
|
|
46
|
-
export function Button({ variant = '
|
|
47
|
-
|
|
110
|
+
export function Button({ variant = 'solid', tone = 'accent', size = 'md', children, type = 'button', className, ...rest }) {
|
|
111
|
+
const isLink = variant === 'link';
|
|
112
|
+
return (_jsx("button", { type: type, className: cx(BASE_CLASS, isLink ? LINK_UNBOX : PAD_CLASS[size], TEXT_CLASS[size], SHAPE_TONE_CLASS[variant][tone], className), ...rest, children: children }));
|
|
48
113
|
}
|
|
49
114
|
//# sourceMappingURL=Button.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/primitives/Button.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/primitives/Button.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA6ChE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,gBAAgB,GAGlB;IACF,KAAK,EAAE;QACL,OAAO,EAAE,sFAAsF;QAC/F,MAAM,EAAE,oFAAoF;QAC5F,MAAM,EAAE,oFAAoF;QAC5F,OAAO,EAAE,sFAAsF;QAC/F,IAAI,EAAE,gFAAgF;QACtF,IAAI,EAAE,gFAAgF;KACvF;IACD,OAAO,EAAE;QACP,OAAO,EACL,gGAAgG;QAClG,MAAM,EACJ,8FAA8F;QAChG,MAAM,EACJ,8FAA8F;QAChG,OAAO,EACL,gGAAgG;QAClG,IAAI,EAAE,0FAA0F;QAChG,IAAI,EAAE,0FAA0F;KACjG;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,+CAA+C;QACxD,MAAM,EAAE,8CAA8C;QACtD,MAAM,EAAE,8CAA8C;QACtD,OAAO,EAAE,+CAA+C;QACxD,IAAI,EAAE,4CAA4C;QAClD,IAAI,EAAE,4CAA4C;KACnD;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,kFAAkF;QAC3F,MAAM,EAAE,iFAAiF;QACzF,MAAM,EAAE,iFAAiF;QACzF,OAAO,EAAE,kFAAkF;QAC3F,IAAI,EAAE,+EAA+E;QACrF,IAAI,EAAE,+EAA+E;KACtF;CACF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,SAAS,GAAqD;IAClE,EAAE,EAAE,+CAA+C;IACnD,EAAE,EAAE,qDAAqD;CAC1D,CAAC;AAEF,MAAM,UAAU,GAAqD;IACnE,EAAE,EAAE,yBAAyB;IAC7B,EAAE,EAAE,4BAA4B;CACjC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,uBAAuB,CAAC;AAE3C,2FAA2F;AAC3F,4FAA4F;AAC5F,0FAA0F;AAC1F,wFAAwF;AACxF,6FAA6F;AAC7F,yFAAyF;AACzF,kCAAkC;AAClC,EAAE;AACF,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,0FAA0F;AAC1F,EAAE;AACF,wFAAwF;AACxF,uFAAuF;AACvF,0FAA0F;AAC1F,6FAA6F;AAC7F,mDAAmD;AACnD,2FAA2F;AAC3F,6FAA6F;AAC7F,4FAA4F;AAC5F,yDAAyD;AACzD,EAAE;AACF,2FAA2F;AAC3F,0FAA0F;AAC1F,yFAAyF;AACzF,yFAAyF;AACzF,yCAAyC;AACzC,MAAM,SAAS,GAAG,mEAAmE,CAAC;AAEtF,MAAM,UAAU,GAAG,8IAA8I,SAAS,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;AAE/M,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,GAAG,OAAO,EACjB,IAAI,GAAG,QAAQ,EACf,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,GAAG,IAAI,EACK;IACZ,MAAM,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC;IAClC,OAAO,CACL,iBACE,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CACX,UAAU,EACV,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EACrC,UAAU,CAAC,IAAI,CAAC,EAChB,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAC/B,SAAS,CACV,KACG,IAAI,YAEP,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button } from '../primitives/Button.js';
|
|
3
3
|
import { cx } from '../lib/cx.js';
|
|
4
4
|
export function ErrorState({ message, retryLabel, onRetry, className }) {
|
|
5
|
-
return (_jsxs("div", { className: cx('py-x-slot-state-pad-y', className), role: "alert", children: [_jsx("p", { className: "font-sans text-x-slot-error-state-fg", children: message }), _jsx("div", { className: "py-x-slot-state-action-pad-y", children: _jsx(Button, { variant: "
|
|
5
|
+
return (_jsxs("div", { className: cx('py-x-slot-state-pad-y', className), role: "alert", children: [_jsx("p", { className: "font-sans text-x-slot-error-state-fg", children: message }), _jsx("div", { className: "py-x-slot-state-action-pad-y", children: _jsx(Button, { variant: "outline", tone: "neutral", onClick: onRetry, children: retryLabel }) })] }));
|
|
6
6
|
}
|
|
7
7
|
//# sourceMappingURL=ErrorState.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorState.js","sourceRoot":"","sources":["../../src/states/ErrorState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAYlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAmB;IACrF,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,EAAE,IAAI,EAAC,OAAO,aAClE,YAAG,SAAS,EAAC,sCAAsC,YAAE,OAAO,GAAK,EACjE,cAAK,SAAS,EAAC,8BAA8B,YAC3C,KAAC,MAAM,IAAC,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"ErrorState.js","sourceRoot":"","sources":["../../src/states/ErrorState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAYlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAmB;IACrF,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,EAAE,IAAI,EAAC,OAAO,aAClE,YAAG,SAAS,EAAC,sCAAsC,YAAE,OAAO,GAAK,EACjE,cAAK,SAAS,EAAC,8BAA8B,YAC3C,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,SAAS,EAAC,OAAO,EAAE,OAAO,YACtD,UAAU,GACJ,GACL,IACF,CACP,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hideyukimori/nene2-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "NeNe fleet shared React UI kit — token-driven primitives on Tailwind v4 @theme. Components carry no design of their own; themes do.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/themes/default.css
CHANGED
|
@@ -42,6 +42,11 @@
|
|
|
42
42
|
--color-warn-soft: oklch(95% 0.035 80);
|
|
43
43
|
--color-on-warn: oklch(21% 0.04 75);
|
|
44
44
|
--color-danger-soft: oklch(95% 0.03 30);
|
|
45
|
+
/* 🔴 契約キーだが値が無かった2つ(#487 で必要になったので与える)。
|
|
46
|
+
* `on-danger` は 0.19.x が danger の塗りに使っていた `on-accent` と同値=描画は不変。
|
|
47
|
+
* `accent-soft` は他の *-soft(95% / chroma ~0.03 / 同 hue)と同じ作り方。 */
|
|
48
|
+
--color-on-danger: oklch(99% 0 0);
|
|
49
|
+
--color-accent-soft: oklch(95% 0.03 250);
|
|
45
50
|
|
|
46
51
|
/* 🔴 Six more contract colours, added in 0.17.0 for `Badge` (#422). Five ships carry a
|
|
47
52
|
* success tone and a warning tone in their own badge (clear / field / invoice / origin /
|
|
@@ -170,6 +175,7 @@
|
|
|
170
175
|
* nene-deal — were already correcting that independently, so the painting this replaces
|
|
171
176
|
* is one no consumer used. */
|
|
172
177
|
--spacing-x-slot-badge-gap: var(--spacing-x-3xs);
|
|
178
|
+
--spacing-x-slot-badge-dot: var(--spacing-x-3xs);
|
|
173
179
|
--spacing-x-slot-switch-pad-x: var(--spacing-x-2xs);
|
|
174
180
|
--spacing-x-slot-switch-pad-y: var(--spacing-x-3xs);
|
|
175
181
|
--spacing-x-slot-alert-pad: var(--spacing-x-2xs);
|
|
@@ -187,6 +193,7 @@
|
|
|
187
193
|
/* Between an EmptyState's two lines (#456). Only read when `description` is passed. */
|
|
188
194
|
--spacing-x-slot-empty-state-gap: var(--spacing-x-3xs);
|
|
189
195
|
--spacing-x-slot-page-header-pad-y: var(--spacing-x-md);
|
|
196
|
+
--spacing-x-slot-page-header-gap: var(--spacing-x-3xs);
|
|
190
197
|
|
|
191
198
|
--radius-x-slot-button: var(--radius-x-md);
|
|
192
199
|
--radius-x-slot-control: var(--radius-x-md);
|
|
@@ -283,22 +290,65 @@
|
|
|
283
290
|
* there is now an opening. */
|
|
284
291
|
--color-x-slot-focus-ring: var(--color-text-primary);
|
|
285
292
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
293
|
+
/* Button: shape × tone (#487).
|
|
294
|
+
*
|
|
295
|
+
* 🔴 The six tones are `Badge`'s six, in `Badge`'s order, read through the same shape of
|
|
296
|
+
* slot. That was the whole argument for splitting the axis — if the words do not line up,
|
|
297
|
+
* the kit still has two vocabularies and has only moved where they disagree.
|
|
298
|
+
*
|
|
299
|
+
* 🔴 `-fg` reads the contract's own `on-<tone>`, not `on-accent` for everything. The
|
|
300
|
+
* contract has carried `on-warn` since it was frozen (2026-07-14) and it is a dark brown,
|
|
301
|
+
* because `--color-warn` is mid-luminance and white on it measures 3.48:1 — below AA.
|
|
302
|
+
* With `on-warn` it is 4.97:1. The first draft of this PR painted every tone's label with
|
|
303
|
+
* `on-accent` and shipped that 3.48:1; the contract had already solved it.
|
|
304
|
+
*
|
|
305
|
+
* 🔴 The default tone is `accent`, so `<Button>` is still the accent-coloured filled
|
|
306
|
+
* button 0.19.x called `primary`. `neutral` is the quiet grey step.
|
|
307
|
+
*
|
|
308
|
+
* Four colours per tone, none derivable from the others:
|
|
309
|
+
* -bg the fill, painted by `solid` only
|
|
310
|
+
* -fg what sits on that fill (the contract's `on-<tone>`)
|
|
311
|
+
* -ink the tone itself, painted by `outline` / `bare` / `link`
|
|
312
|
+
* -border the outline's frame — the *-soft step, not the tone
|
|
313
|
+
*
|
|
314
|
+
* 🔴 `-border` is the soft step. nene-clear draws its outlined danger with a frame far
|
|
315
|
+
* lighter than the label (`--bad-line` #e3bcbc against `--bad` #9c2c2c). Using the tone for
|
|
316
|
+
* both makes every outlined button louder than any ship draws today.
|
|
317
|
+
*
|
|
318
|
+
* 🔴 Renaming a slot fails SILENTLY. A ship that redefined `primary-* / secondary-* /
|
|
319
|
+
* danger-border / ghost-fg` sees no error — the property stops being read and the kit
|
|
320
|
+
* default paints instead. Both consuming ships redefined some (nene-deal 4, nene-vault 3,
|
|
321
|
+
* measured 2026-08-27), so the migration note carries the mapping. */
|
|
322
|
+
--color-x-slot-button-outline-bg: var(--color-surface-raised);
|
|
323
|
+
--color-x-slot-button-neutral-bg: var(--color-border);
|
|
324
|
+
--color-x-slot-button-neutral-fg: var(--color-text-primary);
|
|
325
|
+
--color-x-slot-button-neutral-ink: var(--color-text-primary);
|
|
326
|
+
--color-x-slot-button-neutral-border: var(--color-border);
|
|
327
|
+
--color-x-slot-button-accent-bg: var(--color-accent);
|
|
328
|
+
--color-x-slot-button-accent-fg: var(--color-on-accent);
|
|
329
|
+
--color-x-slot-button-accent-ink: var(--color-accent);
|
|
330
|
+
--color-x-slot-button-accent-border: var(--color-accent-soft);
|
|
291
331
|
--color-x-slot-button-danger-bg: var(--color-danger);
|
|
292
|
-
--color-x-slot-button-danger-fg: var(--color-on-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
--color-x-slot-button-
|
|
300
|
-
--color-x-slot-button-
|
|
301
|
-
|
|
332
|
+
--color-x-slot-button-danger-fg: var(--color-on-danger);
|
|
333
|
+
--color-x-slot-button-danger-ink: var(--color-danger);
|
|
334
|
+
--color-x-slot-button-danger-border: var(--color-danger-soft);
|
|
335
|
+
--color-x-slot-button-success-bg: var(--color-success);
|
|
336
|
+
--color-x-slot-button-success-fg: var(--color-on-success);
|
|
337
|
+
--color-x-slot-button-success-ink: var(--color-success);
|
|
338
|
+
--color-x-slot-button-success-border: var(--color-success-soft);
|
|
339
|
+
--color-x-slot-button-warn-bg: var(--color-warn);
|
|
340
|
+
--color-x-slot-button-warn-fg: var(--color-on-warn);
|
|
341
|
+
/* 🔴 warn の ink だけ tone 本体色ではない。`--color-warn` は中間輝度で、白地に置くと
|
|
342
|
+
* 3.58:1 ——AA を割る(他の tone は本体色のままで 4.7〜5.5 通る)。契約の `--color-on-warn`
|
|
343
|
+
* は 16:1 で、**InlineAlert が既に「白地に載る warn の字」として使っている**
|
|
344
|
+
* (`--color-x-slot-alert-warn-fg`)。同じ用途に同じトークンを充てるのは揃える方向であって、
|
|
345
|
+
* 例外ではない。⇒ 契約の値は1つも変えずに済む(Badge も InlineAlert も動かない)。 */
|
|
346
|
+
--color-x-slot-button-warn-ink: var(--color-on-warn);
|
|
347
|
+
--color-x-slot-button-warn-border: var(--color-warn-soft);
|
|
348
|
+
--color-x-slot-button-info-bg: var(--color-info);
|
|
349
|
+
--color-x-slot-button-info-fg: var(--color-on-info);
|
|
350
|
+
--color-x-slot-button-info-ink: var(--color-info);
|
|
351
|
+
--color-x-slot-button-info-border: var(--color-info-soft);
|
|
302
352
|
/* Shared by Input, Select and Textarea — they are one control with three shapes, and a
|
|
303
353
|
* product that darkens one and not the others has a bug, not a design. */
|
|
304
354
|
--color-x-slot-control-fg: var(--color-text-primary);
|
|
@@ -388,6 +438,7 @@
|
|
|
388
438
|
|
|
389
439
|
--color-x-slot-pagination-fg: var(--color-text-muted);
|
|
390
440
|
--color-x-slot-page-header-fg: var(--color-text-primary);
|
|
441
|
+
--color-x-slot-page-header-description-fg: var(--color-text-muted);
|
|
391
442
|
--color-x-slot-text-fg: var(--color-text-primary);
|
|
392
443
|
--color-x-slot-text-muted-fg: var(--color-text-muted);
|
|
393
444
|
--color-x-slot-spinner-fg: var(--color-text-muted);
|
|
@@ -492,7 +543,10 @@
|
|
|
492
543
|
* `Card` and `Toast` wrote `shadow-sm`, so theirs point at the scale. A default that is
|
|
493
544
|
* anything other than the current rendering changes how every product already looks —
|
|
494
545
|
* and "the default is harmless" only holds while the default is that copy. */
|
|
495
|
-
|
|
546
|
+
/* 🔴 Renamed from `--shadow-x-slot-button-primary` (#487): the shadow belongs to the
|
|
547
|
+
* filled shape, not to one colour. nene-vault redefines this one (`var(--shadow-sm)`) and
|
|
548
|
+
* must rename it — see the migration note. */
|
|
549
|
+
--shadow-x-slot-button-solid: none;
|
|
496
550
|
--shadow-x-slot-card-raised: var(--shadow-sm);
|
|
497
551
|
--shadow-x-slot-toast: var(--shadow-sm);
|
|
498
552
|
|