@hideyukimori/nene2-ui 0.17.1 → 0.18.1
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 +19 -3
- package/dist/feedback/ToastProvider.js +24 -5
- package/dist/feedback/ToastProvider.js.map +1 -1
- package/dist/feedback/toast-context.d.ts +20 -1
- package/dist/feedback/toast-context.js.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/primitives/Button.js +1 -1
- package/dist/primitives/Button.js.map +1 -1
- package/dist/states/EmptyState.d.ts +14 -1
- package/dist/states/EmptyState.js +3 -3
- package/dist/states/EmptyState.js.map +1 -1
- package/package.json +1 -1
- package/themes/default.css +29 -4
package/README.md
CHANGED
|
@@ -137,12 +137,13 @@ The theme has two layers, and the line between them is the point.
|
|
|
137
137
|
|
|
138
138
|
### ② Slots — 🟢 redefine these
|
|
139
139
|
|
|
140
|
-
Every design value a component
|
|
140
|
+
Every design value a component takes **from the theme** comes from a slot, and slots are named
|
|
141
|
+
per component:
|
|
141
142
|
|
|
142
143
|
```css
|
|
143
144
|
/* your product's theme, loaded after the kit's */
|
|
144
145
|
@theme {
|
|
145
|
-
--spacing-x-slot-
|
|
146
|
+
--spacing-x-slot-modal-pad: var(--spacing-x-lg); /* roomier modals, everywhere */
|
|
146
147
|
--color-x-slot-field-label: var(--color-text-primary); /* darker field labels */
|
|
147
148
|
--radius-x-slot-control: var(--radius-x-md);
|
|
148
149
|
}
|
|
@@ -151,6 +152,18 @@ Every design value a component uses comes from a slot, and slots are named per c
|
|
|
151
152
|
This is where your product decides how it looks. Change a slot and every instance of that
|
|
152
153
|
component follows.
|
|
153
154
|
|
|
155
|
+
🔴 **"From the theme" is the limit of that sentence, and the limit is load-bearing.** The
|
|
156
|
+
**layout components take their spacing from props, not from slots** — `Box` and `Card` (`pad`),
|
|
157
|
+
`Stack` (`gap`), `Section` and `Grid` (both). That is deliberate rather than an omission: layout
|
|
158
|
+
spacing is a decision the *caller* makes per instance, so it is chosen at the call site. Those
|
|
159
|
+
props still pick a **step from the scale** (`pad="lg"`), so a product cannot invent a value here
|
|
160
|
+
either — but **no slot exists for them**.
|
|
161
|
+
|
|
162
|
+
⚠️ **This is the part that bites.** Writing `--spacing-x-slot-card-pad` in your theme does
|
|
163
|
+
nothing at all: **there is no such slot**, and nothing warns you — not an error, not a console
|
|
164
|
+
message, not a failing build. To make every card roomier, pass `pad` where you use `Card`, or
|
|
165
|
+
wrap it once in a component of your own.
|
|
166
|
+
|
|
154
167
|
### ① The scale — 🔒 do not redefine
|
|
155
168
|
|
|
156
169
|
`--spacing-x-3xs` … `--spacing-x-2xl`, `--radius-x-none` … `--radius-x-3xl` plus
|
|
@@ -223,9 +236,12 @@ second only under `@media (pointer: coarse)`.
|
|
|
223
236
|
|
|
224
237
|
### Composing a slot
|
|
225
238
|
|
|
226
|
-
A slot can hold several steps — four-sided padding is just CSS
|
|
239
|
+
A slot can hold several steps — four-sided padding is just CSS. The slot below belongs to a
|
|
240
|
+
component **of your own**, not to the kit (`login-form` is not a kit component); a product
|
|
241
|
+
names slots for its own parts the same way the kit does:
|
|
227
242
|
|
|
228
243
|
```css
|
|
244
|
+
/* in your product, for your own <LoginForm> */
|
|
229
245
|
--spacing-x-slot-login-form-pad: var(--spacing-x-xl) var(--spacing-x-md) var(--spacing-x-lg)
|
|
230
246
|
var(--spacing-x-md);
|
|
231
247
|
```
|
|
@@ -5,8 +5,14 @@ import { CLICKABLE_CLASS } from '../lib/states.js';
|
|
|
5
5
|
import { ToastContext } from './toast-context.js';
|
|
6
6
|
const TONE_CLASS = {
|
|
7
7
|
info: 'bg-x-slot-toast-bg text-x-slot-toast-fg border-x-slot-toast-border',
|
|
8
|
+
success: 'bg-x-slot-toast-bg text-x-slot-toast-success-fg border-x-slot-toast-success-border',
|
|
8
9
|
danger: 'bg-x-slot-toast-bg text-x-slot-toast-danger-fg border-x-slot-toast-danger-border',
|
|
9
10
|
};
|
|
11
|
+
// 🔴 `success` は polite 側。`assertive` は読み上げを中断させるので、成功の報告に使うと
|
|
12
|
+
// 利用者の作業を割り込みで止める。中断してよいのは danger だけ、というのが2リージョンに
|
|
13
|
+
// 分けた元の理由なので、語彙が増えてもその線は動かさない(#457)。
|
|
14
|
+
const POLITE_TONES = ['info', 'success'];
|
|
15
|
+
const ASSERTIVE_TONES = ['danger'];
|
|
10
16
|
/**
|
|
11
17
|
* Hosts the toast queue and the live regions that announce it.
|
|
12
18
|
*
|
|
@@ -34,7 +40,18 @@ export function ToastProvider({ regionLabel, dismissLabel, defaultDurationMs = 5
|
|
|
34
40
|
}, []);
|
|
35
41
|
const show = useCallback((message, options) => {
|
|
36
42
|
const id = `toast-${(nextId.current += 1)}`;
|
|
37
|
-
|
|
43
|
+
const description = options?.description;
|
|
44
|
+
setToasts((current) => [
|
|
45
|
+
...current,
|
|
46
|
+
{
|
|
47
|
+
id,
|
|
48
|
+
message,
|
|
49
|
+
tone: options?.tone ?? 'info',
|
|
50
|
+
// exactOptionalPropertyTypes: 省略と `undefined` を渡すことは別物なので、
|
|
51
|
+
// 渡されなかった場合はキーごと作らない。
|
|
52
|
+
...(description === undefined ? {} : { description }),
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
38
55
|
timers.current.set(id, setTimeout(() => dismiss(id), options?.durationMs ?? defaultDurationMs));
|
|
39
56
|
return id;
|
|
40
57
|
}, [defaultDurationMs, dismiss]);
|
|
@@ -48,9 +65,11 @@ export function ToastProvider({ regionLabel, dismissLabel, defaultDurationMs = 5
|
|
|
48
65
|
};
|
|
49
66
|
}, []);
|
|
50
67
|
const api = useMemo(() => ({ show, dismiss }), [show, dismiss]);
|
|
51
|
-
const region = (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
68
|
+
const region = (tones, live) => (_jsx("div", { "aria-live": live, "aria-label": regionLabel, role: "region", className: "flex flex-col gap-x-slot-toast-gap", children: toasts
|
|
69
|
+
// 複数トーンを1つのリージョンへ。元の配列を filter するので、同じリージョンに
|
|
70
|
+
// 入るトースト同士の**表示順は push された順のまま**になる。
|
|
71
|
+
.filter((toast) => tones.includes(toast.tone))
|
|
72
|
+
.map((toast) => (_jsxs("div", { className: cx('flex items-start gap-x-slot-toast-gap rounded-x-slot-toast border p-x-slot-toast-pad font-sans shadow-x-slot-toast', TONE_CLASS[toast.tone]), children: [toast.description === undefined ? (_jsx("span", { children: toast.message })) : (_jsxs("span", { className: "flex flex-col gap-x-slot-toast-description-gap", children: [_jsx("span", { children: toast.message }), _jsx("span", { className: "text-x-slot-toast-description-fg", children: toast.description })] })), _jsx("button", { type: "button", "aria-label": dismissLabel, onClick: () => dismiss(toast.id), className: cx('rounded-x-slot-toast px-x-slot-toast-dismiss-pad-x', CLICKABLE_CLASS), children: dismissLabel })] }, toast.id))) }));
|
|
73
|
+
return (_jsxs(ToastContext.Provider, { value: api, children: [children, region(POLITE_TONES, 'polite'), region(ASSERTIVE_TONES, 'assertive')] }));
|
|
55
74
|
}
|
|
56
75
|
//# sourceMappingURL=ToastProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToastProvider.js","sourceRoot":"","sources":["../../src/feedback/ToastProvider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC1F,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAoD,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"ToastProvider.js","sourceRoot":"","sources":["../../src/feedback/ToastProvider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 🔴 `success` は 0.17.x まで無く、`info | danger` の2語彙だった。`Badge` と `InlineAlert`
|
|
3
|
+
* は既に `success` を持っており(Badge は neutral|accent|danger|success|warn|info)、
|
|
4
|
+
* **トーストだけ語彙が2つ**という状態は 0.17.0 #422 の「一つの語彙をキット全体で」と
|
|
5
|
+
* 噛み合わない。nene-deal は完了を緑で伝えており、`info` に寄せると保存・移動・削除の
|
|
6
|
+
* 完了が中立色になって、エラーとの差が「赤かどうか」だけになる(#457)。
|
|
7
|
+
*/
|
|
8
|
+
export type ToastTone = 'info' | 'success' | 'danger';
|
|
2
9
|
export interface ToastOptions {
|
|
3
10
|
tone?: ToastTone;
|
|
4
11
|
/** Overrides the provider's default. */
|
|
5
12
|
durationMs?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Localized second line: what the action applied to.
|
|
15
|
+
*
|
|
16
|
+
* 🔴 Not decoration. nene-deal's success toasts carry one at **7 of 7** call sites — the
|
|
17
|
+
* deal that moved, the stage it moved to, the range that was exported. `show(message)`
|
|
18
|
+
* alone drops that text, and joining the two halves is not available to the ship: they are
|
|
19
|
+
* separate catalog keys, so the separator would be a string owned by the ship, against
|
|
20
|
+
* principle 4 (#457).
|
|
21
|
+
*
|
|
22
|
+
* Omit it and the render is what it was before this prop existed.
|
|
23
|
+
*/
|
|
24
|
+
description?: string;
|
|
6
25
|
}
|
|
7
26
|
export interface ToastApi {
|
|
8
27
|
/** Shows a toast and returns its id, so a caller can dismiss it early. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast-context.js","sourceRoot":"","sources":["../../src/feedback/toast-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"toast-context.js","sourceRoot":"","sources":["../../src/feedback/toast-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAmClD,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAkB,IAAI,CAAC,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -39,8 +39,10 @@ export { Pagination } from './data/Pagination.js';
|
|
|
39
39
|
export { tokens } from './theme/tokens.js';
|
|
40
40
|
// Internal helpers, exported so downstream components can compose consistently.
|
|
41
41
|
export { cx } from './lib/cx.js';
|
|
42
|
-
//
|
|
43
|
-
//
|
|
42
|
+
// A control the kit does not ship — one a product writes for itself, or one still waiting for
|
|
43
|
+
// a slot in the kit — can at least carry the same focus and disabled behaviour instead of
|
|
44
|
+
// inventing it. (Written when `Textarea` was the example, with 7 independent implementations
|
|
45
|
+
// across the fleet; `Textarea` ships now, so the example is gone but the reason is not.)
|
|
44
46
|
export { CLICKABLE_CLASS, CONTROL_CLASS, DISABLED_CLASS, FOCUS_CLASS, HOVER_CLASS, } from './lib/states.js';
|
|
45
47
|
// Lets a consumer's build prove the kit is in its Tailwind `@source` (#316).
|
|
46
48
|
export { SOURCE_PROBE_CLASS } from './lib/source-probe.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAmB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAqB,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,IAAI,EAAkB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,IAAI,EAAkB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,KAAK,EAAmB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAElE,SAAS;AACT,OAAO,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAmB,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAiB,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAqB,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AAKxD,QAAQ;AACR,OAAO,EAAE,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAEtE,sFAAsF;AACtF,sDAAsD;AACtD,OAAO,EAAE,YAAY,EAA0B,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAE1E,UAAU;AACV,OAAO,EAAE,KAAK,EAAmB,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AAEpF,WAAW;AACX,OAAO,EAAE,KAAK,EAAmB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAyB,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,aAAa,EAA2B,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,QAAQ,GAIT,MAAM,6BAA6B,CAAC;AAErC,OAAO;AACP,OAAO,EAAE,UAAU,EAAwC,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAwC,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,UAAU,EAAwB,MAAM,sBAAsB,CAAC;AAExE,QAAQ;AACR,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,gFAAgF;AAChF,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAmB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAqB,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,IAAI,EAAkB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,IAAI,EAAkB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,KAAK,EAAmB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAElE,SAAS;AACT,OAAO,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAmB,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAiB,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAqB,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AAKxD,QAAQ;AACR,OAAO,EAAE,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAEtE,sFAAsF;AACtF,sDAAsD;AACtD,OAAO,EAAE,YAAY,EAA0B,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAE1E,UAAU;AACV,OAAO,EAAE,KAAK,EAAmB,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AAEpF,WAAW;AACX,OAAO,EAAE,KAAK,EAAmB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAyB,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,aAAa,EAA2B,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,QAAQ,GAIT,MAAM,6BAA6B,CAAC;AAErC,OAAO;AACP,OAAO,EAAE,UAAU,EAAwC,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAwC,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,UAAU,EAAwB,MAAM,sBAAsB,CAAC;AAExE,QAAQ;AACR,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,gFAAgF;AAChF,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,8FAA8F;AAC9F,0FAA0F;AAC1F,6FAA6F;AAC7F,yFAAyF;AACzF,OAAO,EACL,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,6EAA6E;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { CLICKABLE_CLASS, TOUCH_CLASS } from '../lib/states.js';
|
|
|
4
4
|
const VARIANT_CLASS = {
|
|
5
5
|
primary: 'bg-x-slot-button-primary-bg text-x-slot-button-primary-fg shadow-x-slot-button-primary',
|
|
6
6
|
secondary: 'bg-x-slot-button-secondary-bg text-x-slot-button-secondary-fg border-x-slot-button-secondary-border',
|
|
7
|
-
danger: 'bg-x-slot-button-danger-bg text-x-slot-button-danger-fg',
|
|
7
|
+
danger: 'bg-x-slot-button-danger-bg text-x-slot-button-danger-fg border-x-slot-button-danger-border',
|
|
8
8
|
// No fill and no border: for the third action in a row, where two framed buttons would
|
|
9
9
|
// compete with each other. nene-vault ships this variant already.
|
|
10
10
|
ghost: 'bg-transparent text-x-slot-button-ghost-fg',
|
|
@@ -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;AAchE,MAAM,aAAa,GAAwD;IACzE,OAAO,EAAE,wFAAwF;IACjG,SAAS,EACP,qGAAqG;IACvG,MAAM,
|
|
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;AAchE,MAAM,aAAa,GAAwD;IACzE,OAAO,EAAE,wFAAwF;IACjG,SAAS,EACP,qGAAqG;IACvG,MAAM,EACJ,4FAA4F;IAC9F,uFAAuF;IACvF,kEAAkE;IAClE,KAAK,EAAE,4CAA4C;CACpD,CAAC;AAEF,MAAM,UAAU,GAAqD;IACnE,EAAE,EAAE,uEAAuE;IAC3E,EAAE,EAAE,gFAAgF;CACrF,CAAC;AAEF,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,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,GAAG,IAAI,EACK;IACZ,OAAO,CACL,iBACE,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KAC1E,IAAI,YAEP,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -11,5 +11,18 @@ export interface EmptyStateProps {
|
|
|
11
11
|
align?: 'center' | 'start';
|
|
12
12
|
/** Localized message. The kit never ships strings — see README. */
|
|
13
13
|
message: string;
|
|
14
|
+
/**
|
|
15
|
+
* Localized second line: what the empty area would hold, or how to fill it.
|
|
16
|
+
*
|
|
17
|
+
* 🔴 Not decoration. nene-deal's empty states carry two lines at three of their four call
|
|
18
|
+
* sites ("No deals yet" / "Create one from the board"), and folding them into `message`
|
|
19
|
+
* is not available to it: the two halves are separate catalog keys (`*.empty.title` and
|
|
20
|
+
* `*.empty.description`), so joining them would put the separator — a string — in the
|
|
21
|
+
* ship, against principle 4. Without this prop the second line has nowhere to go and the
|
|
22
|
+
* text is simply dropped (#456).
|
|
23
|
+
*
|
|
24
|
+
* Omit it and the render is byte-for-byte what it was before this prop existed.
|
|
25
|
+
*/
|
|
26
|
+
description?: string;
|
|
14
27
|
}
|
|
15
|
-
export declare function EmptyState({ message, align, className }: EmptyStateProps): import("react").JSX.Element;
|
|
28
|
+
export declare function EmptyState({ message, description, align, className }: EmptyStateProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../lib/cx.js';
|
|
3
|
-
export function EmptyState({ message, align = 'center', className }) {
|
|
4
|
-
return (_jsx("div", { className: cx('py-x-slot-state-pad-y font-sans text-x-slot-empty-state-fg', align === 'center' && 'text-center', className), role: "status", children: message }));
|
|
3
|
+
export function EmptyState({ message, description, align = 'center', className }) {
|
|
4
|
+
return (_jsx("div", { className: cx('py-x-slot-state-pad-y font-sans text-x-slot-empty-state-fg', align === 'center' && 'text-center', className), role: "status", children: description === undefined ? (message) : (_jsxs(_Fragment, { children: [_jsx("p", { children: message }), _jsx("p", { className: "mt-x-slot-empty-state-gap text-x-slot-empty-state-description-fg", children: description })] })) }));
|
|
5
5
|
}
|
|
6
6
|
//# sourceMappingURL=EmptyState.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.js","sourceRoot":"","sources":["../../src/states/EmptyState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"EmptyState.js","sourceRoot":"","sources":["../../src/states/EmptyState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AA6BlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,GAAG,QAAQ,EAAE,SAAS,EAAmB;IAC/F,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,4DAA4D,EAC5D,KAAK,KAAK,QAAQ,IAAI,aAAa,EACnC,SAAS,CACV,EACD,IAAI,EAAC,QAAQ,YAKZ,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC3B,OAAO,CACR,CAAC,CAAC,CAAC,CACF,8BACE,sBAAI,OAAO,GAAK,EAChB,YAAG,SAAS,EAAC,kEAAkE,YAC5E,WAAW,GACV,IACH,CACJ,GACG,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.18.1",
|
|
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
|
@@ -130,10 +130,15 @@
|
|
|
130
130
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
131
131
|
* ② SLOTS — a product may redefine these.
|
|
132
132
|
*
|
|
133
|
-
* Every design value a component
|
|
134
|
-
* back at the scale above. That split is the whole idea: a product decides
|
|
135
|
-
* a part uses**, and cannot invent a step. Change `--spacing-x-slot-
|
|
136
|
-
* `var(--spacing-x-lg)` and
|
|
133
|
+
* Every design value a component takes **from the theme** comes from here, and every slot's
|
|
134
|
+
* default points back at the scale above. That split is the whole idea: a product decides
|
|
135
|
+
* **which step a part uses**, and cannot invent a step. Change `--spacing-x-slot-modal-pad`
|
|
136
|
+
* to `var(--spacing-x-lg)` and every modal gets roomier; you still cannot write `2.25`.
|
|
137
|
+
*
|
|
138
|
+
* 🔴 The layout components (`Box`, `Card`, `Stack`, `Section`, `Grid`) are the exception:
|
|
139
|
+
* their padding and gap come from **props**, not from slots, because the caller decides
|
|
140
|
+
* them per instance. There is no `--spacing-x-slot-card-pad` — setting one does nothing,
|
|
141
|
+
* silently. See README §② (#389).
|
|
137
142
|
*
|
|
138
143
|
* Named per component rather than per role (hide's ruling, 2026-08-23): sharing one slot
|
|
139
144
|
* between `Modal` and `Card` can be arranged later by pointing both at the same value,
|
|
@@ -173,6 +178,8 @@
|
|
|
173
178
|
--spacing-x-slot-detail-row-pad-y: var(--spacing-x-xs);
|
|
174
179
|
--spacing-x-slot-state-pad-y: var(--spacing-x-xl);
|
|
175
180
|
--spacing-x-slot-state-action-pad-y: var(--spacing-x-xs);
|
|
181
|
+
/* Between an EmptyState's two lines (#456). Only read when `description` is passed. */
|
|
182
|
+
--spacing-x-slot-empty-state-gap: var(--spacing-x-3xs);
|
|
176
183
|
--spacing-x-slot-page-header-pad-y: var(--spacing-x-md);
|
|
177
184
|
|
|
178
185
|
--radius-x-slot-button: var(--radius-x-md);
|
|
@@ -273,6 +280,13 @@
|
|
|
273
280
|
--color-x-slot-button-secondary-border: var(--color-border);
|
|
274
281
|
--color-x-slot-button-danger-bg: var(--color-danger);
|
|
275
282
|
--color-x-slot-button-danger-fg: var(--color-on-accent);
|
|
283
|
+
/* 🔴 Defaults to the fill, so a filled danger button looks exactly as it did: the border
|
|
284
|
+
* and the background are the same colour, which is what `border-transparent` over a filled
|
|
285
|
+
* background already rendered. The slot exists for the ships whose danger button is an
|
|
286
|
+
* outline rather than a fill — nene-deal's is `background: transparent` with a tinted
|
|
287
|
+
* border (#455), and it could not express that: the variant emitted no border class at
|
|
288
|
+
* all, so `border-transparent` from BASE_CLASS won and no slot value could reach it. */
|
|
289
|
+
--color-x-slot-button-danger-border: var(--color-danger);
|
|
276
290
|
--color-x-slot-button-ghost-fg: var(--color-text-primary);
|
|
277
291
|
|
|
278
292
|
/* Shared by Input, Select and Textarea — they are one control with three shapes, and a
|
|
@@ -336,6 +350,13 @@
|
|
|
336
350
|
--color-x-slot-toast-border: var(--color-border);
|
|
337
351
|
--color-x-slot-toast-danger-fg: var(--color-danger);
|
|
338
352
|
--color-x-slot-toast-danger-border: var(--color-danger);
|
|
353
|
+
/* `success` tone (#457). Badge and InlineAlert already carry this meaning; the toast is
|
|
354
|
+
* the one surface that had only two. */
|
|
355
|
+
--color-x-slot-toast-success-fg: var(--color-success);
|
|
356
|
+
--color-x-slot-toast-success-border: var(--color-success);
|
|
357
|
+
/* The toast's second line (#457). Only read when `description` is passed. */
|
|
358
|
+
--color-x-slot-toast-description-fg: var(--color-text-muted);
|
|
359
|
+
--spacing-x-slot-toast-description-gap: var(--spacing-x-3xs);
|
|
339
360
|
|
|
340
361
|
--color-x-slot-card-bg: var(--color-surface-raised);
|
|
341
362
|
--color-x-slot-card-border: var(--color-border);
|
|
@@ -361,6 +382,10 @@
|
|
|
361
382
|
--color-x-slot-text-muted-fg: var(--color-text-muted);
|
|
362
383
|
--color-x-slot-spinner-fg: var(--color-text-muted);
|
|
363
384
|
--color-x-slot-empty-state-fg: var(--color-text-muted);
|
|
385
|
+
/* The second line of an EmptyState (#456). Same value as the first by default, so a ship
|
|
386
|
+
* that adopts `description` gets one uniform block until it decides otherwise; a ship that
|
|
387
|
+
* wants the hierarchy overrides one of the two. No existing render reads this. */
|
|
388
|
+
--color-x-slot-empty-state-description-fg: var(--color-text-muted);
|
|
364
389
|
--color-x-slot-error-state-fg: var(--color-danger);
|
|
365
390
|
/* 🔴 The required marker, not the error message — that one is `--color-x-slot-field-error`.
|
|
366
391
|
* Named `-error-fg` when the colour slots were swept in (0.9.0, same day), which reads as
|