@judarn/ui 0.7.7 → 0.8.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 +5 -1
- package/dist/Badge/Badge.d.ts +3 -3
- package/dist/Button/Button.d.ts +2 -2
- package/dist/index.cjs +48 -51
- package/dist/index.mjs +48 -51
- package/dist/sdui/index.cjs +29 -32
- package/dist/sdui/index.mjs +29 -32
- package/dist/sdui/schema.json +2 -3
- package/dist/sdui/serializer.d.ts +2 -2
- package/package.json +1 -1
- package/styles/colors_and_type.css +13 -0
- package/styles/components.css +122 -103
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@judarn/ui`
|
|
2
2
|
|
|
3
3
|
React components and CSS tokens for the Judarn design system, with colors in OKLCh and a fixed 8 px spacing grid.
|
|
4
4
|
|
|
@@ -21,6 +21,10 @@ export function Status() {
|
|
|
21
21
|
|
|
22
22
|
`react` 18 or later is the only peer dependency. The package ships compiled ESM and CommonJS. Other entry points: `@judarn/ui/colors` (CSS custom properties only), `@judarn/ui/theme` and `@judarn/ui/tailwind` (Tailwind v4), and `@judarn/ui/sdui` (server-driven UI).
|
|
23
23
|
|
|
24
|
+
## Class names
|
|
25
|
+
|
|
26
|
+
`@judarn/ui/styles` and `@judarn/ui/components.css` style only `jd-` classes (`jd-btn`, `jd-badge`, `jd-tag`, `jd-card`, `jd-field`, `jd-navbar`, `jd-footer`, `jd-table`, `jd-matrix`, `jd-lockup`), so a project's own `.btn` or `.card` stays its own. Buttons, badges, and tags are set apart by fill, with a transparent border that high-contrast modes turn into an outline.
|
|
27
|
+
|
|
24
28
|
## Accent colors
|
|
25
29
|
|
|
26
30
|
A project that sets its own `--jd-accent` also sets `--jd-accent-ink` to `#000000` or `#ffffff`, whichever stays readable on that fill. Accent buttons and badges read the resolved `--accent-ink`. The `--jd-accent*` hooks have no default, so a value set on `:root` carries into nested scopes.
|
package/dist/Badge/Badge.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import * as React from "react";
|
|
|
2
2
|
|
|
3
3
|
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
4
4
|
children?: React.ReactNode;
|
|
5
|
-
/** @default "
|
|
6
|
-
variant?: "
|
|
7
|
-
/** Optional custom accent color hex or
|
|
5
|
+
/** Neutral is a well fill, accent-tint a light tint of the accent (neutral in dark mode). @default "neutral" */
|
|
6
|
+
variant?: "neutral" | "solid" | "accent" | "accent-tint";
|
|
7
|
+
/** Optional custom accent color (#hex, rgb() or oklch()). The accent variant fills with it and resolves contrasting ink; accent-tint tints with it. */
|
|
8
8
|
accentColor?: string;
|
|
9
9
|
}
|
|
10
10
|
|
package/dist/Button/Button.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as React from "react";
|
|
|
3
3
|
export interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
|
|
4
4
|
children?: React.ReactNode;
|
|
5
5
|
/** Visual style. @default "primary" */
|
|
6
|
-
variant?: "primary" | "
|
|
6
|
+
variant?: "primary" | "secondary" | "ghost" | "accent";
|
|
7
7
|
/** @default "md" */
|
|
8
8
|
size?: "sm" | "md" | "lg";
|
|
9
9
|
/** Stretch to full container width. @default false */
|
|
@@ -14,6 +14,6 @@ export interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonE
|
|
|
14
14
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
/** Judarn button –
|
|
17
|
+
/** Judarn button – set apart by fill alone, with hover inversion. A consumer `className` extends the base classes. */
|
|
18
18
|
export function Button(props: ButtonProps): React.JSX.Element;
|
|
19
19
|
export default Button;
|
package/dist/index.cjs
CHANGED
|
@@ -115,29 +115,27 @@ function getContrastingInk(color) {
|
|
|
115
115
|
const perceptualCrossover = 0.5;
|
|
116
116
|
return lum > perceptualCrossover ? "#000000" : "#ffffff";
|
|
117
117
|
}
|
|
118
|
-
function Badge({ children, variant = "
|
|
118
|
+
function Badge({ children, variant = "neutral", accentColor, style, className, ...rest }) {
|
|
119
119
|
const cls = cx(
|
|
120
|
-
"badge",
|
|
121
|
-
variant === "solid" && "badge--solid",
|
|
122
|
-
variant === "accent" && "badge--accent",
|
|
123
|
-
variant === "accent-
|
|
120
|
+
"jd-badge",
|
|
121
|
+
variant === "solid" && "jd-badge--solid",
|
|
122
|
+
variant === "accent" && "jd-badge--accent",
|
|
123
|
+
variant === "accent-tint" && "jd-badge--accent-tint",
|
|
124
124
|
className
|
|
125
125
|
);
|
|
126
126
|
const inlineStyle = { ...style };
|
|
127
127
|
if (accentColor) {
|
|
128
128
|
if (variant === "accent") {
|
|
129
129
|
inlineStyle.backgroundColor = accentColor;
|
|
130
|
-
inlineStyle.borderColor = accentColor;
|
|
131
130
|
inlineStyle.color = getContrastingInk(accentColor);
|
|
132
|
-
} else if (variant === "accent-
|
|
133
|
-
inlineStyle
|
|
134
|
-
inlineStyle.color = accentColor;
|
|
131
|
+
} else if (variant === "accent-tint") {
|
|
132
|
+
inlineStyle["--jd-badge-accent"] = accentColor;
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
135
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...rest, className: cls, style: Object.keys(inlineStyle).length > 0 ? inlineStyle : void 0, children });
|
|
138
136
|
}
|
|
139
137
|
function Tag({ children, className, ...rest }) {
|
|
140
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...rest, className: cx("tag", className), children });
|
|
138
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...rest, className: cx("jd-tag", className), children });
|
|
141
139
|
}
|
|
142
140
|
var Badge_default = Badge;
|
|
143
141
|
|
|
@@ -155,14 +153,13 @@ function Button({
|
|
|
155
153
|
...rest
|
|
156
154
|
}) {
|
|
157
155
|
const cls = cx(
|
|
158
|
-
"btn",
|
|
159
|
-
variant === "
|
|
160
|
-
variant === "
|
|
161
|
-
variant === "
|
|
162
|
-
|
|
163
|
-
size === "
|
|
164
|
-
|
|
165
|
-
block && "btn--block",
|
|
156
|
+
"jd-btn",
|
|
157
|
+
variant === "secondary" && "jd-btn--secondary",
|
|
158
|
+
variant === "ghost" && "jd-btn--ghost",
|
|
159
|
+
variant === "accent" && "jd-btn--accent",
|
|
160
|
+
size === "sm" && "jd-btn--sm",
|
|
161
|
+
size === "lg" && "jd-btn--lg",
|
|
162
|
+
block && "jd-btn--block",
|
|
166
163
|
className
|
|
167
164
|
);
|
|
168
165
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { ...rest, className: cls, type, disabled, onClick, children });
|
|
@@ -183,12 +180,12 @@ function Card({
|
|
|
183
180
|
className,
|
|
184
181
|
...rest
|
|
185
182
|
}) {
|
|
186
|
-
const cls = cx("card", flat && "card--flat", compact && "card--compact", className);
|
|
183
|
+
const cls = cx("jd-card", flat && "jd-card--flat", compact && "jd-card--compact", className);
|
|
187
184
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ...rest, className: cls, children: [
|
|
188
|
-
media ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "card__media", children: media }) : null,
|
|
189
|
-
eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
190
|
-
title ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "card__title", children: title }) : null,
|
|
191
|
-
children ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "card__body", children }) : null,
|
|
185
|
+
media ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "jd-card__media", children: media }) : null,
|
|
186
|
+
eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("jd-card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
187
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "jd-card__title", children: title }) : null,
|
|
188
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "jd-card__body", children }) : null,
|
|
192
189
|
actions ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: "var(--gap-tight)" }, children: actions }) : null
|
|
193
190
|
] });
|
|
194
191
|
}
|
|
@@ -204,7 +201,7 @@ function DataMatrix({ columns: columns2 = [], rows: rows2 = [], label = "Data Ma
|
|
|
204
201
|
"table",
|
|
205
202
|
{
|
|
206
203
|
...rest,
|
|
207
|
-
className: cx("matrix", className),
|
|
204
|
+
className: cx("jd-matrix", className),
|
|
208
205
|
role: "table",
|
|
209
206
|
"aria-label": label,
|
|
210
207
|
"aria-colcount": totalColumns,
|
|
@@ -275,7 +272,7 @@ var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
|
275
272
|
var headerClass = (c) => [c.numeric && "num", c.casing === "asWritten" && "t-as-written"].filter(Boolean).join(" ") || void 0;
|
|
276
273
|
function DataTable({ columns: columns2 = [], rows: rows2 = [], className, ...rest }) {
|
|
277
274
|
const cols = columns2.map((c) => typeof c === "string" ? { key: c, label: c } : c);
|
|
278
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { ...rest, className: cx("table", className), children: [
|
|
275
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { ...rest, className: cx("jd-table", className), children: [
|
|
279
276
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: cols.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: headerClass(c), children: c.label }, c.key)) }) }),
|
|
280
277
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: rows2.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: cols.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: c.numeric ? "num" : void 0, children: row[c.key] }, c.key)) }, i)) })
|
|
281
278
|
] });
|
|
@@ -285,18 +282,18 @@ var DataTable_default = DataTable;
|
|
|
285
282
|
// src/Footer/Footer.jsx
|
|
286
283
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
287
284
|
function Footer({ brand = "JUDARN", tagline, columns: columns2 = [], headCasing = "uppercase", className, ...rest }) {
|
|
288
|
-
const headClass = headCasing === "asWritten" ? "footer__head t-label t-as-written" : "footer__head t-label";
|
|
289
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("footer", { ...rest, className: cx("footer", className), children: [
|
|
290
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "footer__col", children: [
|
|
291
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "navbar__brand", children: brand }),
|
|
292
|
-
tagline ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "footer__link", style: { marginTop: "8px" }, children: tagline }) : null
|
|
285
|
+
const headClass = headCasing === "asWritten" ? "jd-footer__head t-label t-as-written" : "jd-footer__head t-label";
|
|
286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("footer", { ...rest, className: cx("jd-footer", className), children: [
|
|
287
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "jd-footer__col", children: [
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "jd-navbar__brand", children: brand }),
|
|
289
|
+
tagline ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "jd-footer__link", style: { marginTop: "8px" }, children: tagline }) : null
|
|
293
290
|
] }),
|
|
294
|
-
columns2.map((col) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "footer__col", children: [
|
|
291
|
+
columns2.map((col) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "jd-footer__col", children: [
|
|
295
292
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: headClass, children: col.head }),
|
|
296
293
|
(col.links || []).map((l) => {
|
|
297
294
|
const label = typeof l === "string" ? l : l.label;
|
|
298
295
|
const href = typeof l === "string" ? "#" : l.href || "#";
|
|
299
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { className: "footer__link", href, children: label }, label);
|
|
296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { className: "jd-footer__link", href, children: label }, label);
|
|
300
297
|
})
|
|
301
298
|
] }, col.head))
|
|
302
299
|
] });
|
|
@@ -322,19 +319,19 @@ function LogoLockup({
|
|
|
322
319
|
}) {
|
|
323
320
|
const isIcon = variant === "icon";
|
|
324
321
|
const cls = [
|
|
325
|
-
"lockup",
|
|
326
|
-
variant === "vertical" && "lockup--vertical",
|
|
327
|
-
variant === "reversed" && "lockup--reversed"
|
|
322
|
+
"jd-lockup",
|
|
323
|
+
variant === "vertical" && "jd-lockup--vertical",
|
|
324
|
+
variant === "reversed" && "jd-lockup--reversed"
|
|
328
325
|
].filter(Boolean).join(" ");
|
|
329
326
|
const theMark = mark || /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlaceholderMark, { size: markSize || (variant === "vertical" ? 64 : 48) });
|
|
330
327
|
if (isIcon) {
|
|
331
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lockup__mark", role: "img", "aria-label": name, children: mark || /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlaceholderMark, { size: markSize || 64 }) });
|
|
328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "jd-lockup__mark", role: "img", "aria-label": name, children: mark || /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlaceholderMark, { size: markSize || 64 }) });
|
|
332
329
|
}
|
|
333
330
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cls, role: "img", "aria-label": tagline ? `${name} \u2013 ${tagline}` : name, children: [
|
|
334
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lockup__mark", children: theMark }),
|
|
335
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "lockup__words", children: [
|
|
336
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "lockup__name", children: name }),
|
|
337
|
-
tagline ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: taglineCasing === "asWritten" ? "lockup__tag t-label t-as-written" : "lockup__tag t-label", children: tagline }) : null
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "jd-lockup__mark", children: theMark }),
|
|
332
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "jd-lockup__words", children: [
|
|
333
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "jd-lockup__name", children: name }),
|
|
334
|
+
tagline ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: taglineCasing === "asWritten" ? "jd-lockup__tag t-label t-as-written" : "jd-lockup__tag t-label", children: tagline }) : null
|
|
338
335
|
] })
|
|
339
336
|
] });
|
|
340
337
|
}
|
|
@@ -343,16 +340,16 @@ var LogoLockup_default = LogoLockup;
|
|
|
343
340
|
// src/Navbar/Navbar.jsx
|
|
344
341
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
345
342
|
function Navbar({ brand = "JUDARN", links = [], current, actions, className, ...rest }) {
|
|
346
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("nav", { ...rest, className: cx("navbar", className), children: [
|
|
347
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "navbar__brand", children: brand }),
|
|
348
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("ul", { className: "navbar__links", children: [
|
|
343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("nav", { ...rest, className: cx("jd-navbar", className), children: [
|
|
344
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "jd-navbar__brand", children: brand }),
|
|
345
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("ul", { className: "jd-navbar__links", children: [
|
|
349
346
|
links.map((l) => {
|
|
350
347
|
const label = typeof l === "string" ? l : l.label;
|
|
351
348
|
const href = typeof l === "string" ? "#" : l.href || "#";
|
|
352
349
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
353
350
|
"a",
|
|
354
351
|
{
|
|
355
|
-
className: "navbar__link",
|
|
352
|
+
className: "jd-navbar__link",
|
|
356
353
|
href,
|
|
357
354
|
"aria-current": label === current ? "page" : void 0,
|
|
358
355
|
children: label
|
|
@@ -390,7 +387,7 @@ function TextField({
|
|
|
390
387
|
const common = {
|
|
391
388
|
...rest,
|
|
392
389
|
id: fid,
|
|
393
|
-
className: cx("field__input", className),
|
|
390
|
+
className: cx("jd-field__input", className),
|
|
394
391
|
"aria-invalid": invalid || error ? true : void 0,
|
|
395
392
|
"aria-describedby": describedBy,
|
|
396
393
|
disabled
|
|
@@ -399,11 +396,11 @@ function TextField({
|
|
|
399
396
|
if (as === "textarea") control = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("textarea", { ...common });
|
|
400
397
|
else if (as === "select") control = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("select", { ...common, children });
|
|
401
398
|
else control = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { ...common });
|
|
402
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "field", children: [
|
|
403
|
-
label ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: cx("field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "jd-field", children: [
|
|
400
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: cx("jd-field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
404
401
|
control,
|
|
405
|
-
hint ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "field__hint", id: hintId, children: hint }) : null,
|
|
406
|
-
error ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "field__hint is-error", id: errorId, children: error }) : null
|
|
402
|
+
hint ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "jd-field__hint", id: hintId, children: hint }) : null,
|
|
403
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "jd-field__hint is-error", id: errorId, children: error }) : null
|
|
407
404
|
] });
|
|
408
405
|
}
|
|
409
406
|
var TextField_default = TextField;
|
|
@@ -433,8 +430,8 @@ var VALID_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
433
430
|
"container",
|
|
434
431
|
"text"
|
|
435
432
|
]);
|
|
436
|
-
var BUTTON_VARIANTS = ["primary", "
|
|
437
|
-
var BADGE_VARIANTS = ["
|
|
433
|
+
var BUTTON_VARIANTS = ["primary", "secondary", "ghost", "accent"];
|
|
434
|
+
var BADGE_VARIANTS = ["neutral", "solid", "accent", "accent-tint"];
|
|
438
435
|
var SIZES = ["sm", "md", "lg"];
|
|
439
436
|
var CASINGS = ["uppercase", "asWritten"];
|
|
440
437
|
var VALID_TOKEN_NAMES = /* @__PURE__ */ new Set([
|
package/dist/index.mjs
CHANGED
|
@@ -75,29 +75,27 @@ function getContrastingInk(color) {
|
|
|
75
75
|
const perceptualCrossover = 0.5;
|
|
76
76
|
return lum > perceptualCrossover ? "#000000" : "#ffffff";
|
|
77
77
|
}
|
|
78
|
-
function Badge({ children, variant = "
|
|
78
|
+
function Badge({ children, variant = "neutral", accentColor, style, className, ...rest }) {
|
|
79
79
|
const cls = cx(
|
|
80
|
-
"badge",
|
|
81
|
-
variant === "solid" && "badge--solid",
|
|
82
|
-
variant === "accent" && "badge--accent",
|
|
83
|
-
variant === "accent-
|
|
80
|
+
"jd-badge",
|
|
81
|
+
variant === "solid" && "jd-badge--solid",
|
|
82
|
+
variant === "accent" && "jd-badge--accent",
|
|
83
|
+
variant === "accent-tint" && "jd-badge--accent-tint",
|
|
84
84
|
className
|
|
85
85
|
);
|
|
86
86
|
const inlineStyle = { ...style };
|
|
87
87
|
if (accentColor) {
|
|
88
88
|
if (variant === "accent") {
|
|
89
89
|
inlineStyle.backgroundColor = accentColor;
|
|
90
|
-
inlineStyle.borderColor = accentColor;
|
|
91
90
|
inlineStyle.color = getContrastingInk(accentColor);
|
|
92
|
-
} else if (variant === "accent-
|
|
93
|
-
inlineStyle
|
|
94
|
-
inlineStyle.color = accentColor;
|
|
91
|
+
} else if (variant === "accent-tint") {
|
|
92
|
+
inlineStyle["--jd-badge-accent"] = accentColor;
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
95
|
return /* @__PURE__ */ jsx("span", { ...rest, className: cls, style: Object.keys(inlineStyle).length > 0 ? inlineStyle : void 0, children });
|
|
98
96
|
}
|
|
99
97
|
function Tag({ children, className, ...rest }) {
|
|
100
|
-
return /* @__PURE__ */ jsx("span", { ...rest, className: cx("tag", className), children });
|
|
98
|
+
return /* @__PURE__ */ jsx("span", { ...rest, className: cx("jd-tag", className), children });
|
|
101
99
|
}
|
|
102
100
|
var Badge_default = Badge;
|
|
103
101
|
|
|
@@ -115,14 +113,13 @@ function Button({
|
|
|
115
113
|
...rest
|
|
116
114
|
}) {
|
|
117
115
|
const cls = cx(
|
|
118
|
-
"btn",
|
|
119
|
-
variant === "
|
|
120
|
-
variant === "
|
|
121
|
-
variant === "
|
|
122
|
-
|
|
123
|
-
size === "
|
|
124
|
-
|
|
125
|
-
block && "btn--block",
|
|
116
|
+
"jd-btn",
|
|
117
|
+
variant === "secondary" && "jd-btn--secondary",
|
|
118
|
+
variant === "ghost" && "jd-btn--ghost",
|
|
119
|
+
variant === "accent" && "jd-btn--accent",
|
|
120
|
+
size === "sm" && "jd-btn--sm",
|
|
121
|
+
size === "lg" && "jd-btn--lg",
|
|
122
|
+
block && "jd-btn--block",
|
|
126
123
|
className
|
|
127
124
|
);
|
|
128
125
|
return /* @__PURE__ */ jsx2("button", { ...rest, className: cls, type, disabled, onClick, children });
|
|
@@ -143,12 +140,12 @@ function Card({
|
|
|
143
140
|
className,
|
|
144
141
|
...rest
|
|
145
142
|
}) {
|
|
146
|
-
const cls = cx("card", flat && "card--flat", compact && "card--compact", className);
|
|
143
|
+
const cls = cx("jd-card", flat && "jd-card--flat", compact && "jd-card--compact", className);
|
|
147
144
|
return /* @__PURE__ */ jsxs("div", { ...rest, className: cls, children: [
|
|
148
|
-
media ? /* @__PURE__ */ jsx3("div", { className: "card__media", children: media }) : null,
|
|
149
|
-
eyebrow ? /* @__PURE__ */ jsx3("span", { className: cx("card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
150
|
-
title ? /* @__PURE__ */ jsx3("div", { className: "card__title", children: title }) : null,
|
|
151
|
-
children ? /* @__PURE__ */ jsx3("div", { className: "card__body", children }) : null,
|
|
145
|
+
media ? /* @__PURE__ */ jsx3("div", { className: "jd-card__media", children: media }) : null,
|
|
146
|
+
eyebrow ? /* @__PURE__ */ jsx3("span", { className: cx("jd-card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
147
|
+
title ? /* @__PURE__ */ jsx3("div", { className: "jd-card__title", children: title }) : null,
|
|
148
|
+
children ? /* @__PURE__ */ jsx3("div", { className: "jd-card__body", children }) : null,
|
|
152
149
|
actions ? /* @__PURE__ */ jsx3("div", { style: { display: "flex", gap: "var(--gap-tight)" }, children: actions }) : null
|
|
153
150
|
] });
|
|
154
151
|
}
|
|
@@ -164,7 +161,7 @@ function DataMatrix({ columns: columns2 = [], rows: rows2 = [], label = "Data Ma
|
|
|
164
161
|
"table",
|
|
165
162
|
{
|
|
166
163
|
...rest,
|
|
167
|
-
className: cx("matrix", className),
|
|
164
|
+
className: cx("jd-matrix", className),
|
|
168
165
|
role: "table",
|
|
169
166
|
"aria-label": label,
|
|
170
167
|
"aria-colcount": totalColumns,
|
|
@@ -235,7 +232,7 @@ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
235
232
|
var headerClass = (c) => [c.numeric && "num", c.casing === "asWritten" && "t-as-written"].filter(Boolean).join(" ") || void 0;
|
|
236
233
|
function DataTable({ columns: columns2 = [], rows: rows2 = [], className, ...rest }) {
|
|
237
234
|
const cols = columns2.map((c) => typeof c === "string" ? { key: c, label: c } : c);
|
|
238
|
-
return /* @__PURE__ */ jsxs3("table", { ...rest, className: cx("table", className), children: [
|
|
235
|
+
return /* @__PURE__ */ jsxs3("table", { ...rest, className: cx("jd-table", className), children: [
|
|
239
236
|
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsx5("tr", { children: cols.map((c) => /* @__PURE__ */ jsx5("th", { className: headerClass(c), children: c.label }, c.key)) }) }),
|
|
240
237
|
/* @__PURE__ */ jsx5("tbody", { children: rows2.map((row, i) => /* @__PURE__ */ jsx5("tr", { children: cols.map((c) => /* @__PURE__ */ jsx5("td", { className: c.numeric ? "num" : void 0, children: row[c.key] }, c.key)) }, i)) })
|
|
241
238
|
] });
|
|
@@ -245,18 +242,18 @@ var DataTable_default = DataTable;
|
|
|
245
242
|
// src/Footer/Footer.jsx
|
|
246
243
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
247
244
|
function Footer({ brand = "JUDARN", tagline, columns: columns2 = [], headCasing = "uppercase", className, ...rest }) {
|
|
248
|
-
const headClass = headCasing === "asWritten" ? "footer__head t-label t-as-written" : "footer__head t-label";
|
|
249
|
-
return /* @__PURE__ */ jsxs4("footer", { ...rest, className: cx("footer", className), children: [
|
|
250
|
-
/* @__PURE__ */ jsxs4("div", { className: "footer__col", children: [
|
|
251
|
-
/* @__PURE__ */ jsx6("div", { className: "navbar__brand", children: brand }),
|
|
252
|
-
tagline ? /* @__PURE__ */ jsx6("p", { className: "footer__link", style: { marginTop: "8px" }, children: tagline }) : null
|
|
245
|
+
const headClass = headCasing === "asWritten" ? "jd-footer__head t-label t-as-written" : "jd-footer__head t-label";
|
|
246
|
+
return /* @__PURE__ */ jsxs4("footer", { ...rest, className: cx("jd-footer", className), children: [
|
|
247
|
+
/* @__PURE__ */ jsxs4("div", { className: "jd-footer__col", children: [
|
|
248
|
+
/* @__PURE__ */ jsx6("div", { className: "jd-navbar__brand", children: brand }),
|
|
249
|
+
tagline ? /* @__PURE__ */ jsx6("p", { className: "jd-footer__link", style: { marginTop: "8px" }, children: tagline }) : null
|
|
253
250
|
] }),
|
|
254
|
-
columns2.map((col) => /* @__PURE__ */ jsxs4("div", { className: "footer__col", children: [
|
|
251
|
+
columns2.map((col) => /* @__PURE__ */ jsxs4("div", { className: "jd-footer__col", children: [
|
|
255
252
|
/* @__PURE__ */ jsx6("h2", { className: headClass, children: col.head }),
|
|
256
253
|
(col.links || []).map((l) => {
|
|
257
254
|
const label = typeof l === "string" ? l : l.label;
|
|
258
255
|
const href = typeof l === "string" ? "#" : l.href || "#";
|
|
259
|
-
return /* @__PURE__ */ jsx6("a", { className: "footer__link", href, children: label }, label);
|
|
256
|
+
return /* @__PURE__ */ jsx6("a", { className: "jd-footer__link", href, children: label }, label);
|
|
260
257
|
})
|
|
261
258
|
] }, col.head))
|
|
262
259
|
] });
|
|
@@ -282,19 +279,19 @@ function LogoLockup({
|
|
|
282
279
|
}) {
|
|
283
280
|
const isIcon = variant === "icon";
|
|
284
281
|
const cls = [
|
|
285
|
-
"lockup",
|
|
286
|
-
variant === "vertical" && "lockup--vertical",
|
|
287
|
-
variant === "reversed" && "lockup--reversed"
|
|
282
|
+
"jd-lockup",
|
|
283
|
+
variant === "vertical" && "jd-lockup--vertical",
|
|
284
|
+
variant === "reversed" && "jd-lockup--reversed"
|
|
288
285
|
].filter(Boolean).join(" ");
|
|
289
286
|
const theMark = mark || /* @__PURE__ */ jsx7(PlaceholderMark, { size: markSize || (variant === "vertical" ? 64 : 48) });
|
|
290
287
|
if (isIcon) {
|
|
291
|
-
return /* @__PURE__ */ jsx7("span", { className: "lockup__mark", role: "img", "aria-label": name, children: mark || /* @__PURE__ */ jsx7(PlaceholderMark, { size: markSize || 64 }) });
|
|
288
|
+
return /* @__PURE__ */ jsx7("span", { className: "jd-lockup__mark", role: "img", "aria-label": name, children: mark || /* @__PURE__ */ jsx7(PlaceholderMark, { size: markSize || 64 }) });
|
|
292
289
|
}
|
|
293
290
|
return /* @__PURE__ */ jsxs5("div", { className: cls, role: "img", "aria-label": tagline ? `${name} \u2013 ${tagline}` : name, children: [
|
|
294
|
-
/* @__PURE__ */ jsx7("span", { className: "lockup__mark", children: theMark }),
|
|
295
|
-
/* @__PURE__ */ jsxs5("span", { className: "lockup__words", children: [
|
|
296
|
-
/* @__PURE__ */ jsx7("span", { className: "lockup__name", children: name }),
|
|
297
|
-
tagline ? /* @__PURE__ */ jsx7("span", { className: taglineCasing === "asWritten" ? "lockup__tag t-label t-as-written" : "lockup__tag t-label", children: tagline }) : null
|
|
291
|
+
/* @__PURE__ */ jsx7("span", { className: "jd-lockup__mark", children: theMark }),
|
|
292
|
+
/* @__PURE__ */ jsxs5("span", { className: "jd-lockup__words", children: [
|
|
293
|
+
/* @__PURE__ */ jsx7("span", { className: "jd-lockup__name", children: name }),
|
|
294
|
+
tagline ? /* @__PURE__ */ jsx7("span", { className: taglineCasing === "asWritten" ? "jd-lockup__tag t-label t-as-written" : "jd-lockup__tag t-label", children: tagline }) : null
|
|
298
295
|
] })
|
|
299
296
|
] });
|
|
300
297
|
}
|
|
@@ -303,16 +300,16 @@ var LogoLockup_default = LogoLockup;
|
|
|
303
300
|
// src/Navbar/Navbar.jsx
|
|
304
301
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
305
302
|
function Navbar({ brand = "JUDARN", links = [], current, actions, className, ...rest }) {
|
|
306
|
-
return /* @__PURE__ */ jsxs6("nav", { ...rest, className: cx("navbar", className), children: [
|
|
307
|
-
/* @__PURE__ */ jsx8("div", { className: "navbar__brand", children: brand }),
|
|
308
|
-
/* @__PURE__ */ jsxs6("ul", { className: "navbar__links", children: [
|
|
303
|
+
return /* @__PURE__ */ jsxs6("nav", { ...rest, className: cx("jd-navbar", className), children: [
|
|
304
|
+
/* @__PURE__ */ jsx8("div", { className: "jd-navbar__brand", children: brand }),
|
|
305
|
+
/* @__PURE__ */ jsxs6("ul", { className: "jd-navbar__links", children: [
|
|
309
306
|
links.map((l) => {
|
|
310
307
|
const label = typeof l === "string" ? l : l.label;
|
|
311
308
|
const href = typeof l === "string" ? "#" : l.href || "#";
|
|
312
309
|
return /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8(
|
|
313
310
|
"a",
|
|
314
311
|
{
|
|
315
|
-
className: "navbar__link",
|
|
312
|
+
className: "jd-navbar__link",
|
|
316
313
|
href,
|
|
317
314
|
"aria-current": label === current ? "page" : void 0,
|
|
318
315
|
children: label
|
|
@@ -350,7 +347,7 @@ function TextField({
|
|
|
350
347
|
const common = {
|
|
351
348
|
...rest,
|
|
352
349
|
id: fid,
|
|
353
|
-
className: cx("field__input", className),
|
|
350
|
+
className: cx("jd-field__input", className),
|
|
354
351
|
"aria-invalid": invalid || error ? true : void 0,
|
|
355
352
|
"aria-describedby": describedBy,
|
|
356
353
|
disabled
|
|
@@ -359,11 +356,11 @@ function TextField({
|
|
|
359
356
|
if (as === "textarea") control = /* @__PURE__ */ jsx9("textarea", { ...common });
|
|
360
357
|
else if (as === "select") control = /* @__PURE__ */ jsx9("select", { ...common, children });
|
|
361
358
|
else control = /* @__PURE__ */ jsx9("input", { ...common });
|
|
362
|
-
return /* @__PURE__ */ jsxs7("div", { className: "field", children: [
|
|
363
|
-
label ? /* @__PURE__ */ jsx9("label", { className: cx("field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
359
|
+
return /* @__PURE__ */ jsxs7("div", { className: "jd-field", children: [
|
|
360
|
+
label ? /* @__PURE__ */ jsx9("label", { className: cx("jd-field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
364
361
|
control,
|
|
365
|
-
hint ? /* @__PURE__ */ jsx9("span", { className: "field__hint", id: hintId, children: hint }) : null,
|
|
366
|
-
error ? /* @__PURE__ */ jsx9("span", { className: "field__hint is-error", id: errorId, children: error }) : null
|
|
362
|
+
hint ? /* @__PURE__ */ jsx9("span", { className: "jd-field__hint", id: hintId, children: hint }) : null,
|
|
363
|
+
error ? /* @__PURE__ */ jsx9("span", { className: "jd-field__hint is-error", id: errorId, children: error }) : null
|
|
367
364
|
] });
|
|
368
365
|
}
|
|
369
366
|
var TextField_default = TextField;
|
|
@@ -393,8 +390,8 @@ var VALID_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
393
390
|
"container",
|
|
394
391
|
"text"
|
|
395
392
|
]);
|
|
396
|
-
var BUTTON_VARIANTS = ["primary", "
|
|
397
|
-
var BADGE_VARIANTS = ["
|
|
393
|
+
var BUTTON_VARIANTS = ["primary", "secondary", "ghost", "accent"];
|
|
394
|
+
var BADGE_VARIANTS = ["neutral", "solid", "accent", "accent-tint"];
|
|
398
395
|
var SIZES = ["sm", "md", "lg"];
|
|
399
396
|
var CASINGS = ["uppercase", "asWritten"];
|
|
400
397
|
var VALID_TOKEN_NAMES = /* @__PURE__ */ new Set([
|
package/dist/sdui/index.cjs
CHANGED
|
@@ -61,14 +61,13 @@ function Button({
|
|
|
61
61
|
...rest
|
|
62
62
|
}) {
|
|
63
63
|
const cls = cx(
|
|
64
|
-
"btn",
|
|
65
|
-
variant === "
|
|
66
|
-
variant === "
|
|
67
|
-
variant === "
|
|
68
|
-
|
|
69
|
-
size === "
|
|
70
|
-
|
|
71
|
-
block && "btn--block",
|
|
64
|
+
"jd-btn",
|
|
65
|
+
variant === "secondary" && "jd-btn--secondary",
|
|
66
|
+
variant === "ghost" && "jd-btn--ghost",
|
|
67
|
+
variant === "accent" && "jd-btn--accent",
|
|
68
|
+
size === "sm" && "jd-btn--sm",
|
|
69
|
+
size === "lg" && "jd-btn--lg",
|
|
70
|
+
block && "jd-btn--block",
|
|
72
71
|
className
|
|
73
72
|
);
|
|
74
73
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ...rest, className: cls, type, disabled, onClick, children });
|
|
@@ -140,29 +139,27 @@ function getContrastingInk(color) {
|
|
|
140
139
|
const perceptualCrossover = 0.5;
|
|
141
140
|
return lum > perceptualCrossover ? "#000000" : "#ffffff";
|
|
142
141
|
}
|
|
143
|
-
function Badge({ children, variant = "
|
|
142
|
+
function Badge({ children, variant = "neutral", accentColor, style, className, ...rest }) {
|
|
144
143
|
const cls = cx(
|
|
145
|
-
"badge",
|
|
146
|
-
variant === "solid" && "badge--solid",
|
|
147
|
-
variant === "accent" && "badge--accent",
|
|
148
|
-
variant === "accent-
|
|
144
|
+
"jd-badge",
|
|
145
|
+
variant === "solid" && "jd-badge--solid",
|
|
146
|
+
variant === "accent" && "jd-badge--accent",
|
|
147
|
+
variant === "accent-tint" && "jd-badge--accent-tint",
|
|
149
148
|
className
|
|
150
149
|
);
|
|
151
150
|
const inlineStyle = { ...style };
|
|
152
151
|
if (accentColor) {
|
|
153
152
|
if (variant === "accent") {
|
|
154
153
|
inlineStyle.backgroundColor = accentColor;
|
|
155
|
-
inlineStyle.borderColor = accentColor;
|
|
156
154
|
inlineStyle.color = getContrastingInk(accentColor);
|
|
157
|
-
} else if (variant === "accent-
|
|
158
|
-
inlineStyle
|
|
159
|
-
inlineStyle.color = accentColor;
|
|
155
|
+
} else if (variant === "accent-tint") {
|
|
156
|
+
inlineStyle["--jd-badge-accent"] = accentColor;
|
|
160
157
|
}
|
|
161
158
|
}
|
|
162
159
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { ...rest, className: cls, style: Object.keys(inlineStyle).length > 0 ? inlineStyle : void 0, children });
|
|
163
160
|
}
|
|
164
161
|
function Tag({ children, className, ...rest }) {
|
|
165
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { ...rest, className: cx("tag", className), children });
|
|
162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { ...rest, className: cx("jd-tag", className), children });
|
|
166
163
|
}
|
|
167
164
|
|
|
168
165
|
// src/Card/Card.jsx
|
|
@@ -179,12 +176,12 @@ function Card({
|
|
|
179
176
|
className,
|
|
180
177
|
...rest
|
|
181
178
|
}) {
|
|
182
|
-
const cls = cx("card", flat && "card--flat", compact && "card--compact", className);
|
|
179
|
+
const cls = cx("jd-card", flat && "jd-card--flat", compact && "jd-card--compact", className);
|
|
183
180
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ...rest, className: cls, children: [
|
|
184
|
-
media ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "card__media", children: media }) : null,
|
|
185
|
-
eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
186
|
-
title ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "card__title", children: title }) : null,
|
|
187
|
-
children ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "card__body", children }) : null,
|
|
181
|
+
media ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "jd-card__media", children: media }) : null,
|
|
182
|
+
eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: cx("jd-card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
183
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "jd-card__title", children: title }) : null,
|
|
184
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "jd-card__body", children }) : null,
|
|
188
185
|
actions ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: "var(--gap-tight)" }, children: actions }) : null
|
|
189
186
|
] });
|
|
190
187
|
}
|
|
@@ -199,7 +196,7 @@ function DataMatrix({ columns: columns2 = [], rows: rows2 = [], label = "Data Ma
|
|
|
199
196
|
"table",
|
|
200
197
|
{
|
|
201
198
|
...rest,
|
|
202
|
-
className: cx("matrix", className),
|
|
199
|
+
className: cx("jd-matrix", className),
|
|
203
200
|
role: "table",
|
|
204
201
|
"aria-label": label,
|
|
205
202
|
"aria-colcount": totalColumns,
|
|
@@ -269,7 +266,7 @@ var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
|
269
266
|
var headerClass = (c) => [c.numeric && "num", c.casing === "asWritten" && "t-as-written"].filter(Boolean).join(" ") || void 0;
|
|
270
267
|
function DataTable({ columns: columns2 = [], rows: rows2 = [], className, ...rest }) {
|
|
271
268
|
const cols = columns2.map((c) => typeof c === "string" ? { key: c, label: c } : c);
|
|
272
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { ...rest, className: cx("table", className), children: [
|
|
269
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { ...rest, className: cx("jd-table", className), children: [
|
|
273
270
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: cols.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: headerClass(c), children: c.label }, c.key)) }) }),
|
|
274
271
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: rows2.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: cols.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: c.numeric ? "num" : void 0, children: row[c.key] }, c.key)) }, i)) })
|
|
275
272
|
] });
|
|
@@ -300,7 +297,7 @@ function TextField({
|
|
|
300
297
|
const common = {
|
|
301
298
|
...rest,
|
|
302
299
|
id: fid,
|
|
303
|
-
className: cx("field__input", className),
|
|
300
|
+
className: cx("jd-field__input", className),
|
|
304
301
|
"aria-invalid": invalid || error ? true : void 0,
|
|
305
302
|
"aria-describedby": describedBy,
|
|
306
303
|
disabled
|
|
@@ -309,11 +306,11 @@ function TextField({
|
|
|
309
306
|
if (as === "textarea") control = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("textarea", { ...common });
|
|
310
307
|
else if (as === "select") control = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { ...common, children });
|
|
311
308
|
else control = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { ...common });
|
|
312
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "field", children: [
|
|
313
|
-
label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("label", { className: cx("field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "jd-field", children: [
|
|
310
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("label", { className: cx("jd-field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
314
311
|
control,
|
|
315
|
-
hint ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "field__hint", id: hintId, children: hint }) : null,
|
|
316
|
-
error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "field__hint is-error", id: errorId, children: error }) : null
|
|
312
|
+
hint ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "jd-field__hint", id: hintId, children: hint }) : null,
|
|
313
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "jd-field__hint is-error", id: errorId, children: error }) : null
|
|
317
314
|
] });
|
|
318
315
|
}
|
|
319
316
|
|
|
@@ -329,8 +326,8 @@ var VALID_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
329
326
|
"container",
|
|
330
327
|
"text"
|
|
331
328
|
]);
|
|
332
|
-
var BUTTON_VARIANTS = ["primary", "
|
|
333
|
-
var BADGE_VARIANTS = ["
|
|
329
|
+
var BUTTON_VARIANTS = ["primary", "secondary", "ghost", "accent"];
|
|
330
|
+
var BADGE_VARIANTS = ["neutral", "solid", "accent", "accent-tint"];
|
|
334
331
|
var SIZES = ["sm", "md", "lg"];
|
|
335
332
|
var CASINGS = ["uppercase", "asWritten"];
|
|
336
333
|
var VALID_TOKEN_NAMES = /* @__PURE__ */ new Set([
|
package/dist/sdui/index.mjs
CHANGED
|
@@ -20,14 +20,13 @@ function Button({
|
|
|
20
20
|
...rest
|
|
21
21
|
}) {
|
|
22
22
|
const cls = cx(
|
|
23
|
-
"btn",
|
|
24
|
-
variant === "
|
|
25
|
-
variant === "
|
|
26
|
-
variant === "
|
|
27
|
-
|
|
28
|
-
size === "
|
|
29
|
-
|
|
30
|
-
block && "btn--block",
|
|
23
|
+
"jd-btn",
|
|
24
|
+
variant === "secondary" && "jd-btn--secondary",
|
|
25
|
+
variant === "ghost" && "jd-btn--ghost",
|
|
26
|
+
variant === "accent" && "jd-btn--accent",
|
|
27
|
+
size === "sm" && "jd-btn--sm",
|
|
28
|
+
size === "lg" && "jd-btn--lg",
|
|
29
|
+
block && "jd-btn--block",
|
|
31
30
|
className
|
|
32
31
|
);
|
|
33
32
|
return /* @__PURE__ */ jsx("button", { ...rest, className: cls, type, disabled, onClick, children });
|
|
@@ -99,29 +98,27 @@ function getContrastingInk(color) {
|
|
|
99
98
|
const perceptualCrossover = 0.5;
|
|
100
99
|
return lum > perceptualCrossover ? "#000000" : "#ffffff";
|
|
101
100
|
}
|
|
102
|
-
function Badge({ children, variant = "
|
|
101
|
+
function Badge({ children, variant = "neutral", accentColor, style, className, ...rest }) {
|
|
103
102
|
const cls = cx(
|
|
104
|
-
"badge",
|
|
105
|
-
variant === "solid" && "badge--solid",
|
|
106
|
-
variant === "accent" && "badge--accent",
|
|
107
|
-
variant === "accent-
|
|
103
|
+
"jd-badge",
|
|
104
|
+
variant === "solid" && "jd-badge--solid",
|
|
105
|
+
variant === "accent" && "jd-badge--accent",
|
|
106
|
+
variant === "accent-tint" && "jd-badge--accent-tint",
|
|
108
107
|
className
|
|
109
108
|
);
|
|
110
109
|
const inlineStyle = { ...style };
|
|
111
110
|
if (accentColor) {
|
|
112
111
|
if (variant === "accent") {
|
|
113
112
|
inlineStyle.backgroundColor = accentColor;
|
|
114
|
-
inlineStyle.borderColor = accentColor;
|
|
115
113
|
inlineStyle.color = getContrastingInk(accentColor);
|
|
116
|
-
} else if (variant === "accent-
|
|
117
|
-
inlineStyle
|
|
118
|
-
inlineStyle.color = accentColor;
|
|
114
|
+
} else if (variant === "accent-tint") {
|
|
115
|
+
inlineStyle["--jd-badge-accent"] = accentColor;
|
|
119
116
|
}
|
|
120
117
|
}
|
|
121
118
|
return /* @__PURE__ */ jsx2("span", { ...rest, className: cls, style: Object.keys(inlineStyle).length > 0 ? inlineStyle : void 0, children });
|
|
122
119
|
}
|
|
123
120
|
function Tag({ children, className, ...rest }) {
|
|
124
|
-
return /* @__PURE__ */ jsx2("span", { ...rest, className: cx("tag", className), children });
|
|
121
|
+
return /* @__PURE__ */ jsx2("span", { ...rest, className: cx("jd-tag", className), children });
|
|
125
122
|
}
|
|
126
123
|
|
|
127
124
|
// src/Card/Card.jsx
|
|
@@ -138,12 +135,12 @@ function Card({
|
|
|
138
135
|
className,
|
|
139
136
|
...rest
|
|
140
137
|
}) {
|
|
141
|
-
const cls = cx("card", flat && "card--flat", compact && "card--compact", className);
|
|
138
|
+
const cls = cx("jd-card", flat && "jd-card--flat", compact && "jd-card--compact", className);
|
|
142
139
|
return /* @__PURE__ */ jsxs("div", { ...rest, className: cls, children: [
|
|
143
|
-
media ? /* @__PURE__ */ jsx3("div", { className: "card__media", children: media }) : null,
|
|
144
|
-
eyebrow ? /* @__PURE__ */ jsx3("span", { className: cx("card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
145
|
-
title ? /* @__PURE__ */ jsx3("div", { className: "card__title", children: title }) : null,
|
|
146
|
-
children ? /* @__PURE__ */ jsx3("div", { className: "card__body", children }) : null,
|
|
140
|
+
media ? /* @__PURE__ */ jsx3("div", { className: "jd-card__media", children: media }) : null,
|
|
141
|
+
eyebrow ? /* @__PURE__ */ jsx3("span", { className: cx("jd-card__eyebrow", "t-label", eyebrowCasing === "asWritten" && "t-as-written"), children: eyebrow }) : null,
|
|
142
|
+
title ? /* @__PURE__ */ jsx3("div", { className: "jd-card__title", children: title }) : null,
|
|
143
|
+
children ? /* @__PURE__ */ jsx3("div", { className: "jd-card__body", children }) : null,
|
|
147
144
|
actions ? /* @__PURE__ */ jsx3("div", { style: { display: "flex", gap: "var(--gap-tight)" }, children: actions }) : null
|
|
148
145
|
] });
|
|
149
146
|
}
|
|
@@ -158,7 +155,7 @@ function DataMatrix({ columns: columns2 = [], rows: rows2 = [], label = "Data Ma
|
|
|
158
155
|
"table",
|
|
159
156
|
{
|
|
160
157
|
...rest,
|
|
161
|
-
className: cx("matrix", className),
|
|
158
|
+
className: cx("jd-matrix", className),
|
|
162
159
|
role: "table",
|
|
163
160
|
"aria-label": label,
|
|
164
161
|
"aria-colcount": totalColumns,
|
|
@@ -228,7 +225,7 @@ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
228
225
|
var headerClass = (c) => [c.numeric && "num", c.casing === "asWritten" && "t-as-written"].filter(Boolean).join(" ") || void 0;
|
|
229
226
|
function DataTable({ columns: columns2 = [], rows: rows2 = [], className, ...rest }) {
|
|
230
227
|
const cols = columns2.map((c) => typeof c === "string" ? { key: c, label: c } : c);
|
|
231
|
-
return /* @__PURE__ */ jsxs3("table", { ...rest, className: cx("table", className), children: [
|
|
228
|
+
return /* @__PURE__ */ jsxs3("table", { ...rest, className: cx("jd-table", className), children: [
|
|
232
229
|
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsx5("tr", { children: cols.map((c) => /* @__PURE__ */ jsx5("th", { className: headerClass(c), children: c.label }, c.key)) }) }),
|
|
233
230
|
/* @__PURE__ */ jsx5("tbody", { children: rows2.map((row, i) => /* @__PURE__ */ jsx5("tr", { children: cols.map((c) => /* @__PURE__ */ jsx5("td", { className: c.numeric ? "num" : void 0, children: row[c.key] }, c.key)) }, i)) })
|
|
234
231
|
] });
|
|
@@ -259,7 +256,7 @@ function TextField({
|
|
|
259
256
|
const common = {
|
|
260
257
|
...rest,
|
|
261
258
|
id: fid,
|
|
262
|
-
className: cx("field__input", className),
|
|
259
|
+
className: cx("jd-field__input", className),
|
|
263
260
|
"aria-invalid": invalid || error ? true : void 0,
|
|
264
261
|
"aria-describedby": describedBy,
|
|
265
262
|
disabled
|
|
@@ -268,11 +265,11 @@ function TextField({
|
|
|
268
265
|
if (as === "textarea") control = /* @__PURE__ */ jsx6("textarea", { ...common });
|
|
269
266
|
else if (as === "select") control = /* @__PURE__ */ jsx6("select", { ...common, children });
|
|
270
267
|
else control = /* @__PURE__ */ jsx6("input", { ...common });
|
|
271
|
-
return /* @__PURE__ */ jsxs4("div", { className: "field", children: [
|
|
272
|
-
label ? /* @__PURE__ */ jsx6("label", { className: cx("field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
268
|
+
return /* @__PURE__ */ jsxs4("div", { className: "jd-field", children: [
|
|
269
|
+
label ? /* @__PURE__ */ jsx6("label", { className: cx("jd-field__label", labelCasing === "asWritten" && "t-as-written"), htmlFor: fid, children: label }) : null,
|
|
273
270
|
control,
|
|
274
|
-
hint ? /* @__PURE__ */ jsx6("span", { className: "field__hint", id: hintId, children: hint }) : null,
|
|
275
|
-
error ? /* @__PURE__ */ jsx6("span", { className: "field__hint is-error", id: errorId, children: error }) : null
|
|
271
|
+
hint ? /* @__PURE__ */ jsx6("span", { className: "jd-field__hint", id: hintId, children: hint }) : null,
|
|
272
|
+
error ? /* @__PURE__ */ jsx6("span", { className: "jd-field__hint is-error", id: errorId, children: error }) : null
|
|
276
273
|
] });
|
|
277
274
|
}
|
|
278
275
|
|
|
@@ -288,8 +285,8 @@ var VALID_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
288
285
|
"container",
|
|
289
286
|
"text"
|
|
290
287
|
]);
|
|
291
|
-
var BUTTON_VARIANTS = ["primary", "
|
|
292
|
-
var BADGE_VARIANTS = ["
|
|
288
|
+
var BUTTON_VARIANTS = ["primary", "secondary", "ghost", "accent"];
|
|
289
|
+
var BADGE_VARIANTS = ["neutral", "solid", "accent", "accent-tint"];
|
|
293
290
|
var SIZES = ["sm", "md", "lg"];
|
|
294
291
|
var CASINGS = ["uppercase", "asWritten"];
|
|
295
292
|
var VALID_TOKEN_NAMES = /* @__PURE__ */ new Set([
|
package/dist/sdui/schema.json
CHANGED
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
"type": "string",
|
|
58
58
|
"enum": [
|
|
59
59
|
"primary",
|
|
60
|
-
"outline",
|
|
61
60
|
"secondary",
|
|
62
61
|
"ghost",
|
|
63
62
|
"accent"
|
|
@@ -139,10 +138,10 @@
|
|
|
139
138
|
"variant": {
|
|
140
139
|
"type": "string",
|
|
141
140
|
"enum": [
|
|
142
|
-
"
|
|
141
|
+
"neutral",
|
|
143
142
|
"solid",
|
|
144
143
|
"accent",
|
|
145
|
-
"accent-
|
|
144
|
+
"accent-tint"
|
|
146
145
|
]
|
|
147
146
|
},
|
|
148
147
|
"accentColor": {
|
|
@@ -13,8 +13,8 @@ export type SDUINodeType =
|
|
|
13
13
|
|
|
14
14
|
/** Props accepted per node type. Any other prop is rejected by `validateSDUINode`. */
|
|
15
15
|
export interface SDUIPropsByType {
|
|
16
|
-
button: { variant?: "primary" | "
|
|
17
|
-
badge: { variant?: "
|
|
16
|
+
button: { variant?: "primary" | "secondary" | "ghost" | "accent"; size?: "sm" | "md" | "lg"; block?: boolean; disabled?: boolean; type?: "button" | "submit" | "reset"; token?: string };
|
|
17
|
+
badge: { variant?: "neutral" | "solid" | "accent" | "accent-tint"; accentColor?: string; token?: string };
|
|
18
18
|
tag: { token?: string };
|
|
19
19
|
card: { eyebrow?: string; eyebrowCasing?: "uppercase" | "asWritten"; title?: string; flat?: boolean; compact?: boolean; token?: string };
|
|
20
20
|
"data-matrix": { columns?: SDUIColumn[]; rows?: SDUIRow[]; label?: string; token?: string };
|
package/package.json
CHANGED
|
@@ -332,6 +332,19 @@
|
|
|
332
332
|
letter-spacing: var(--jd-track-body);
|
|
333
333
|
font-feature-settings: normal;
|
|
334
334
|
}
|
|
335
|
+
/* Flow: space between the direct children of a container, from the space tokens. A heading belongs to the text below it. Never combine with gap. */
|
|
336
|
+
.flow {
|
|
337
|
+
display: flow-root;
|
|
338
|
+
}
|
|
339
|
+
.flow > * + * {
|
|
340
|
+
margin-block-start: var(--jd-space-2);
|
|
341
|
+
}
|
|
342
|
+
.flow > * + :is(h1, h2, h3, h4, h5, h6, .t-display, .t-h1, .t-h2, .t-h3, .t-h4) {
|
|
343
|
+
margin-block-start: var(--jd-space-4);
|
|
344
|
+
}
|
|
345
|
+
.flow > :is(h1, h2, h3, h4, h5, h6, .t-display, .t-h1, .t-h2, .t-h3, .t-h4) + * {
|
|
346
|
+
margin-block-start: var(--jd-space-1);
|
|
347
|
+
}
|
|
335
348
|
.t-editorial-nums {
|
|
336
349
|
font-variant-numeric: oldstyle-nums proportional-nums;
|
|
337
350
|
font-feature-settings: "onum" 1, "pnum" 1;
|
package/styles/components.css
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/* =========================================================================
|
|
2
2
|
JUDARN DESIGN SYSTEM
|
|
3
3
|
components.css – component styles (flat, geometric, no decoration)
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Every class carries the jd- prefix, so a project's own .btn or .card never picks these up.
|
|
5
|
+
Controls are set apart by fill alone (DESIGN.md, Surface Hierarchy). Hover inverts the fill,
|
|
6
|
+
press is flat grey. No shadows, no gradients, no radius (unless structurally motivated).
|
|
6
7
|
========================================================================= */
|
|
7
8
|
|
|
8
9
|
/* ---- BUTTON ------------------------------------------------------------ */
|
|
9
|
-
|
|
10
|
+
/* The resting border is transparent: it keeps the control's size, and Windows high-contrast mode
|
|
11
|
+
still draws it. High-contrast modes turn it into an ink-100 outline (end of file). */
|
|
12
|
+
.jd-btn {
|
|
10
13
|
font-family: var(--font-sans);
|
|
11
14
|
font-weight: var(--weight-medium);
|
|
12
15
|
letter-spacing: var(--track-body);
|
|
@@ -16,7 +19,7 @@
|
|
|
16
19
|
align-items: center;
|
|
17
20
|
justify-content: center;
|
|
18
21
|
gap: var(--gap-tight);
|
|
19
|
-
border: var(--rule) solid
|
|
22
|
+
border: var(--rule) solid transparent;
|
|
20
23
|
background: var(--black);
|
|
21
24
|
color: var(--paper);
|
|
22
25
|
cursor: pointer;
|
|
@@ -28,38 +31,35 @@
|
|
|
28
31
|
text-align: center;
|
|
29
32
|
white-space: nowrap;
|
|
30
33
|
}
|
|
31
|
-
.btn:hover { background: var(--
|
|
32
|
-
.btn:active { background: var(--ink-60);
|
|
33
|
-
.btn:focus-visible { outline: var(--rule-bold) solid var(--accent); outline-offset: 2px; }
|
|
34
|
-
|
|
35
|
-
.btn--outline { background: transparent; color: var(--black); border: var(--rule) solid var(--black); }
|
|
36
|
-
.btn--outline:hover { background: var(--black); color: var(--paper); }
|
|
37
|
-
.btn--outline:active { background: var(--ink-60); border-color: var(--ink-60); color: var(--paper); }
|
|
34
|
+
.jd-btn:hover { background: var(--jd-surface-recessed); color: var(--black); } /* invert by fill */
|
|
35
|
+
.jd-btn:active { background: var(--ink-60); color: var(--paper); }
|
|
36
|
+
.jd-btn:focus-visible { outline: var(--rule-bold) solid var(--accent); outline-offset: 2px; }
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
.btn--secondary
|
|
41
|
-
.btn--secondary:
|
|
38
|
+
/* A secondary button is a well like a text field: surfaceRecessed on the page, substrate inside a card. */
|
|
39
|
+
.jd-btn--secondary { background: var(--jd-well, var(--jd-surface-recessed)); color: var(--black); }
|
|
40
|
+
.jd-btn--secondary:hover { background: var(--black); color: var(--paper); }
|
|
41
|
+
.jd-btn--secondary:active { background: var(--ink-60); color: var(--paper); }
|
|
42
42
|
|
|
43
|
-
.btn--ghost { background: transparent; color: var(--black);
|
|
44
|
-
.btn--ghost:hover { background: transparent; color: var(--black); border-bottom-color: var(--black); }
|
|
45
|
-
.btn--ghost:active { background: transparent; color: var(--ink-60); border-bottom-color: var(--ink-60); }
|
|
43
|
+
.jd-btn--ghost { background: transparent; color: var(--black); padding-left: 0; padding-right: 0; }
|
|
44
|
+
.jd-btn--ghost:hover { background: transparent; color: var(--black); border-bottom-color: var(--black); }
|
|
45
|
+
.jd-btn--ghost:active { background: transparent; color: var(--ink-60); border-bottom-color: var(--ink-60); }
|
|
46
46
|
|
|
47
|
-
.btn--accent { background: var(--accent);
|
|
48
|
-
.btn--accent:hover { background: var(--
|
|
49
|
-
.btn--accent:active { filter: none; background: var(--accent); color: var(--accent-ink); }
|
|
47
|
+
.jd-btn--accent { background: var(--accent); color: var(--accent-ink); }
|
|
48
|
+
.jd-btn--accent:hover { background: var(--jd-surface-recessed); color: var(--accent-fg); }
|
|
49
|
+
.jd-btn--accent:active { filter: none; background: var(--accent); color: var(--accent-ink); }
|
|
50
50
|
|
|
51
|
-
.btn--sm { padding: var(--space-1) var(--space-2); font-size: var(--size-small); min-height: var(--space-touch); }
|
|
52
|
-
.btn--lg { padding: var(--space-3) var(--space-4); font-size: var(--size-body-lg); }
|
|
53
|
-
.btn--block { display: flex; width: 100%; }
|
|
51
|
+
.jd-btn--sm { padding: var(--space-1) var(--space-2); font-size: var(--size-small); min-height: var(--space-touch); }
|
|
52
|
+
.jd-btn--lg { padding: var(--space-3) var(--space-4); font-size: var(--size-body-lg); }
|
|
53
|
+
.jd-btn--block { display: flex; width: 100%; }
|
|
54
54
|
|
|
55
|
-
.btn:disabled, .btn[aria-disabled="true"] {
|
|
56
|
-
background: var(--jd-
|
|
55
|
+
.jd-btn:disabled, .jd-btn[aria-disabled="true"] {
|
|
56
|
+
background: var(--jd-well, var(--jd-surface-recessed)); color: var(--ink-30);
|
|
57
57
|
cursor: not-allowed; pointer-events: none;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/* ---- FIELD (text input / textarea / select) --------------------------- */
|
|
61
|
-
.field { display: flex; flex-direction: column; gap: var(--gap-tight); }
|
|
62
|
-
.field__label {
|
|
61
|
+
.jd-field { display: flex; flex-direction: column; gap: var(--gap-tight); }
|
|
62
|
+
.jd-field__label {
|
|
63
63
|
font-family: var(--font-sans);
|
|
64
64
|
font-weight: var(--weight-bold);
|
|
65
65
|
font-size: var(--size-label);
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
/* A field is a well set apart by fill alone (DESIGN.md, Surface Hierarchy): surfaceRecessed on the
|
|
71
71
|
page, substrate inside a card. The resting border is transparent: it keeps the field's size, and
|
|
72
72
|
Windows high-contrast mode still draws it. High-contrast modes turn it into an ink-100 outline. */
|
|
73
|
-
.field__input {
|
|
73
|
+
.jd-field__input {
|
|
74
74
|
font-family: var(--font-sans);
|
|
75
75
|
font-size: var(--size-body);
|
|
76
76
|
color: var(--black);
|
|
@@ -81,23 +81,28 @@
|
|
|
81
81
|
width: 100%;
|
|
82
82
|
transition: border-color 120ms linear, box-shadow 120ms linear;
|
|
83
83
|
}
|
|
84
|
-
.card .field__input { background: var(--paper); }
|
|
84
|
+
.jd-card .jd-field__input { background: var(--paper); }
|
|
85
|
+
@media (prefers-contrast: more) {
|
|
86
|
+
:where(:root:not([data-contrast="normal"])) .jd-field__input { border-color: var(--ink-100); }
|
|
87
|
+
}
|
|
88
|
+
:where([data-contrast="high"]) .jd-field__input { border-color: var(--ink-100); }
|
|
85
89
|
@media (prefers-contrast: more) {
|
|
86
|
-
:where(:root:not([data-contrast="normal"])) .
|
|
87
|
-
}
|
|
88
|
-
:where([data-contrast="high"]) .
|
|
89
|
-
.field__input::placeholder { color: var(--ink-60); }
|
|
90
|
-
.field__input:focus { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
|
91
|
-
.field__input:focus-visible { outline: var(--rule-bold) solid var(--accent); outline-offset: 2px; }
|
|
92
|
-
.field__input:disabled { color: var(--ink-30); cursor: not-allowed; }
|
|
93
|
-
.field__input[aria-invalid="true"], .field__input.is-invalid { border-color: var(--signal-error); box-shadow: 0 0 0 1px var(--signal-error); }
|
|
94
|
-
.field__hint { font-size: var(--size-small); color: var(--ink-60); }
|
|
95
|
-
.field__hint.is-error, .field__hint--error { color: var(--signal-error); font-weight: var(--weight-medium); }
|
|
96
|
-
textarea.field__input { resize: vertical; min-height: var(--space-12); line-height: var(--lh-body); }
|
|
97
|
-
select.field__input { cursor: pointer; } /* native appearance keeps the platform chevron */
|
|
90
|
+
:where(:root:not([data-contrast="normal"])) :is(.jd-btn:not(.jd-btn--ghost), .jd-badge, .jd-tag) { border-color: var(--ink-100); }
|
|
91
|
+
}
|
|
92
|
+
:where([data-contrast="high"]) :is(.jd-btn:not(.jd-btn--ghost), .jd-badge, .jd-tag) { border-color: var(--ink-100); }
|
|
93
|
+
.jd-field__input::placeholder { color: var(--ink-60); }
|
|
94
|
+
.jd-field__input:focus { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
|
95
|
+
.jd-field__input:focus-visible { outline: var(--rule-bold) solid var(--accent); outline-offset: 2px; }
|
|
96
|
+
.jd-field__input:disabled { color: var(--ink-30); cursor: not-allowed; }
|
|
97
|
+
.jd-field__input[aria-invalid="true"], .jd-field__input.is-invalid { border-color: var(--signal-error); box-shadow: 0 0 0 1px var(--signal-error); }
|
|
98
|
+
.jd-field__hint { font-size: var(--size-small); color: var(--ink-60); }
|
|
99
|
+
.jd-field__hint.is-error, .jd-field__hint--error { color: var(--signal-error); font-weight: var(--weight-medium); }
|
|
100
|
+
textarea.jd-field__input { resize: vertical; min-height: var(--space-12); line-height: var(--lh-body); }
|
|
101
|
+
select.jd-field__input { cursor: pointer; } /* native appearance keeps the platform chevron */
|
|
98
102
|
|
|
99
103
|
/* ---- CARD -------------------------------------------------------------- */
|
|
100
|
-
.card {
|
|
104
|
+
.jd-card {
|
|
105
|
+
--jd-well: var(--paper); /* wells inside a card (secondary buttons, neutral badges, tags) fill with substrate */
|
|
101
106
|
background: var(--white);
|
|
102
107
|
border: none;
|
|
103
108
|
border-radius: var(--radius-card);
|
|
@@ -106,97 +111,111 @@ select.field__input { cursor: pointer; } /* native appearance keeps the platform
|
|
|
106
111
|
flex-direction: column;
|
|
107
112
|
gap: var(--gap-normal);
|
|
108
113
|
}
|
|
109
|
-
.card--flat { border: none; padding: 0; border-radius: 0; }
|
|
110
|
-
.card--compact { padding: var(--space-2); }
|
|
111
|
-
.card--field { background: var(--bg2); border: none; }
|
|
112
|
-
.card__eyebrow { color: var(--accent); } /* type comes from t-label */
|
|
113
|
-
.card__title { font-size: var(--size-h4); font-weight: var(--weight-bold); letter-spacing: var(--track-head); }
|
|
114
|
-
.card__body { font-size: var(--size-body); line-height: var(--lh-body); }
|
|
115
|
-
.card__media { aspect-ratio: 3 / 2; background: var(--jd-surface-recessed); border-radius: var(--radius-control); overflow: hidden; }
|
|
114
|
+
.jd-card--flat { border: none; padding: 0; border-radius: 0; }
|
|
115
|
+
.jd-card--compact { padding: var(--space-2); }
|
|
116
|
+
.jd-card--field { background: var(--bg2); border: none; }
|
|
117
|
+
.jd-card__eyebrow { color: var(--accent); } /* type comes from t-label */
|
|
118
|
+
.jd-card__title { font-size: var(--size-h4); font-weight: var(--weight-bold); letter-spacing: var(--track-head); }
|
|
119
|
+
.jd-card__body { font-size: var(--size-body); line-height: var(--lh-body); }
|
|
120
|
+
.jd-card__media { aspect-ratio: 3 / 2; background: var(--jd-surface-recessed); border-radius: var(--radius-control); overflow: hidden; }
|
|
116
121
|
|
|
117
122
|
/* ---- BADGE / TAG ------------------------------------------------------- */
|
|
118
|
-
.
|
|
123
|
+
/* Fill only, like buttons: a transparent resting border, an ink-100 outline in high-contrast modes.
|
|
124
|
+
The neutral badge and the tag are wells: surfaceRecessed on the page, substrate inside a card. */
|
|
125
|
+
.jd-badge {
|
|
119
126
|
display: inline-flex; align-items: center; gap: var(--gap-tight);
|
|
120
127
|
font-family: var(--font-sans); font-weight: var(--weight-bold);
|
|
121
128
|
font-size: var(--size-label); letter-spacing: var(--track-body);
|
|
122
|
-
padding: 4px var(--space-1); border: var(--rule) solid
|
|
123
|
-
background: var(--
|
|
129
|
+
padding: 4px var(--space-1); border: var(--rule) solid transparent;
|
|
130
|
+
background: var(--jd-well, var(--jd-surface-recessed)); color: var(--black);
|
|
131
|
+
border-radius: var(--radius-badge); line-height: 1;
|
|
132
|
+
}
|
|
133
|
+
.jd-badge--solid { background: var(--black); color: var(--paper); }
|
|
134
|
+
.jd-badge--accent { background: var(--accent); color: var(--accent-ink); }
|
|
135
|
+
/* A light tint of the accent (or of --jd-badge-accent) with ink-100 text. Tints belong to light mode,
|
|
136
|
+
so dark mode falls back to the neutral well. */
|
|
137
|
+
.jd-badge--accent-tint {
|
|
138
|
+
background: color-mix(in oklch, var(--jd-badge-accent, var(--accent)) 14%, white);
|
|
139
|
+
color: var(--ink-100);
|
|
140
|
+
}
|
|
141
|
+
@media (prefers-color-scheme: dark) {
|
|
142
|
+
:root:not([data-theme="light"]) .jd-badge--accent-tint { background: var(--jd-well, var(--jd-surface-recessed)); }
|
|
124
143
|
}
|
|
125
|
-
.badge--
|
|
126
|
-
.badge--accent { background: var(--
|
|
127
|
-
.badge--accent-outline { color: var(--accent-fg); border-color: var(--accent-fg); }
|
|
144
|
+
[data-theme="dark"] .jd-badge--accent-tint,
|
|
145
|
+
.palette-dark .jd-badge--accent-tint { background: var(--jd-well, var(--jd-surface-recessed)); }
|
|
128
146
|
|
|
129
|
-
.tag {
|
|
147
|
+
.jd-tag {
|
|
130
148
|
display: inline-flex; align-items: center;
|
|
131
149
|
font-size: var(--size-small); font-weight: var(--weight-medium);
|
|
132
|
-
padding: 4px var(--space-1); border: var(--rule) solid
|
|
133
|
-
background: var(--
|
|
150
|
+
padding: 4px var(--space-1); border: var(--rule) solid transparent;
|
|
151
|
+
background: var(--jd-well, var(--jd-surface-recessed)); color: var(--black);
|
|
152
|
+
border-radius: var(--radius-badge); line-height: 1.2;
|
|
134
153
|
}
|
|
135
154
|
|
|
136
155
|
/* ---- NAVBAR ------------------------------------------------------------ */
|
|
137
|
-
.navbar {
|
|
156
|
+
.jd-navbar {
|
|
138
157
|
display: flex; align-items: center; justify-content: space-between;
|
|
139
158
|
padding: var(--space-2) var(--space-3);
|
|
140
159
|
border-bottom: var(--rule-bold) solid var(--line);
|
|
141
160
|
background: var(--white);
|
|
142
161
|
}
|
|
143
|
-
.navbar__brand { font-weight: var(--weight-bold); font-size: var(--size-h4); letter-spacing: var(--track-head); }
|
|
144
|
-
.navbar__links { display: flex; align-items: center; gap: var(--space-3); list-style: none; margin: 0; padding: 0; }
|
|
145
|
-
.navbar__link {
|
|
162
|
+
.jd-navbar__brand { font-weight: var(--weight-bold); font-size: var(--size-h4); letter-spacing: var(--track-head); }
|
|
163
|
+
.jd-navbar__links { display: flex; align-items: center; gap: var(--space-3); list-style: none; margin: 0; padding: 0; }
|
|
164
|
+
.jd-navbar__link {
|
|
146
165
|
font-size: var(--size-small); font-weight: var(--weight-medium);
|
|
147
166
|
border-bottom: var(--rule-bold) solid transparent;
|
|
148
167
|
padding-bottom: 2px;
|
|
149
168
|
transition: border-color 120ms linear;
|
|
150
169
|
}
|
|
151
|
-
.navbar__link:hover { border-bottom-color: var(--black); }
|
|
152
|
-
.navbar__link[aria-current="page"] { border-bottom-color: var(--accent); }
|
|
170
|
+
.jd-navbar__link:hover { border-bottom-color: var(--black); }
|
|
171
|
+
.jd-navbar__link[aria-current="page"] { border-bottom-color: var(--accent); }
|
|
153
172
|
|
|
154
173
|
/* ---- FOOTER ------------------------------------------------------------ */
|
|
155
|
-
.footer {
|
|
174
|
+
.jd-footer {
|
|
156
175
|
border-top: var(--rule-bold) solid var(--line);
|
|
157
176
|
padding: var(--space-6) var(--space-3) var(--space-3);
|
|
158
177
|
background: var(--white);
|
|
159
178
|
display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--space-4);
|
|
160
179
|
}
|
|
161
|
-
.footer__col { display: flex; flex-direction: column; gap: var(--gap-tight); }
|
|
162
|
-
.footer__head { margin: 0 0 var(--space-1); color: var(--black); } /* type comes from t-label */
|
|
163
|
-
.footer__link { font-size: var(--size-small); color: var(--fg2); }
|
|
164
|
-
.footer__link:hover { color: var(--black); text-decoration: underline; text-underline-offset: 3px; }
|
|
180
|
+
.jd-footer__col { display: flex; flex-direction: column; gap: var(--gap-tight); }
|
|
181
|
+
.jd-footer__head { margin: 0 0 var(--space-1); color: var(--black); } /* type comes from t-label */
|
|
182
|
+
.jd-footer__link { font-size: var(--size-small); color: var(--fg2); }
|
|
183
|
+
.jd-footer__link:hover { color: var(--black); text-decoration: underline; text-underline-offset: 3px; }
|
|
165
184
|
|
|
166
185
|
/* ---- DATA TABLE -------------------------------------------------------- */
|
|
167
|
-
.table { width: 100%; border-collapse: collapse; font-size: var(--size-small); }
|
|
168
|
-
.table th {
|
|
186
|
+
.jd-table { width: 100%; border-collapse: collapse; font-size: var(--size-small); }
|
|
187
|
+
.jd-table th {
|
|
169
188
|
text-align: left; font-weight: var(--weight-bold); font-size: var(--size-label);
|
|
170
189
|
letter-spacing: var(--track-label); text-transform: uppercase;
|
|
171
190
|
padding: var(--space-1) var(--space-2); border-bottom: var(--rule-bold) solid var(--line); color: var(--black);
|
|
172
191
|
}
|
|
173
|
-
.table td { padding: var(--space-2); border-bottom: var(--rule) solid var(--ink-30); color: var(--fg1); }
|
|
174
|
-
.table tbody tr:hover { background: var(--jd-surface-recessed); }
|
|
175
|
-
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
192
|
+
.jd-table td { padding: var(--space-2); border-bottom: var(--rule) solid var(--ink-30); color: var(--fg1); }
|
|
193
|
+
.jd-table tbody tr:hover { background: var(--jd-surface-recessed); }
|
|
194
|
+
.jd-table .num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
176
195
|
|
|
177
196
|
/* As-written casing for a field label or column header that holds a unit, a mixed-case term,
|
|
178
197
|
or more than two words. */
|
|
179
|
-
.field__label.t-as-written,
|
|
180
|
-
.table th.t-as-written,
|
|
181
|
-
.matrix th.t-as-written { text-transform: none; letter-spacing: var(--track-body); }
|
|
198
|
+
.jd-field__label.t-as-written,
|
|
199
|
+
.jd-table th.t-as-written,
|
|
200
|
+
.jd-matrix th.t-as-written { text-transform: none; letter-spacing: var(--track-body); }
|
|
182
201
|
|
|
183
202
|
/* ---- LOGO LOCKUP FRAME ------------------------------------------------- */
|
|
184
|
-
.lockup { display: inline-flex; align-items: center; gap: var(--space-2); }
|
|
185
|
-
.lockup--vertical { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
|
|
186
|
-
.lockup--reversed { background: var(--black); color: var(--paper); padding: var(--space-3); }
|
|
187
|
-
.lockup__mark { display: block; flex: none; }
|
|
188
|
-
.lockup__words { display: flex; flex-direction: column; }
|
|
189
|
-
.lockup__name { font-weight: var(--weight-bold); font-size: var(--size-h4); line-height: 1; letter-spacing: var(--track-head); }
|
|
190
|
-
.lockup__tag { color: var(--fg2); margin-top: 4px; } /* type comes from t-label */
|
|
191
|
-
.lockup--reversed .lockup__tag { color: var(--ink-30); }
|
|
203
|
+
.jd-lockup { display: inline-flex; align-items: center; gap: var(--space-2); }
|
|
204
|
+
.jd-lockup--vertical { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
|
|
205
|
+
.jd-lockup--reversed { background: var(--black); color: var(--paper); padding: var(--space-3); }
|
|
206
|
+
.jd-lockup__mark { display: block; flex: none; }
|
|
207
|
+
.jd-lockup__words { display: flex; flex-direction: column; }
|
|
208
|
+
.jd-lockup__name { font-weight: var(--weight-bold); font-size: var(--size-h4); line-height: 1; letter-spacing: var(--track-head); }
|
|
209
|
+
.jd-lockup__tag { color: var(--fg2); margin-top: 4px; } /* type comes from t-label */
|
|
210
|
+
.jd-lockup--reversed .jd-lockup__tag { color: var(--ink-30); }
|
|
192
211
|
|
|
193
212
|
/* ---- DATA MATRIX ------------------------------------------------------- */
|
|
194
|
-
.matrix {
|
|
213
|
+
.jd-matrix {
|
|
195
214
|
width: 100%;
|
|
196
215
|
border-collapse: collapse;
|
|
197
216
|
font-size: var(--size-small);
|
|
198
217
|
}
|
|
199
|
-
.matrix th {
|
|
218
|
+
.jd-matrix th {
|
|
200
219
|
text-align: left;
|
|
201
220
|
font-weight: var(--weight-bold);
|
|
202
221
|
font-size: var(--size-label);
|
|
@@ -208,44 +227,44 @@ select.field__input { cursor: pointer; } /* native appearance keeps the platform
|
|
|
208
227
|
background: var(--white);
|
|
209
228
|
color: var(--black);
|
|
210
229
|
}
|
|
211
|
-
.matrix th:last-child { border-right: none; }
|
|
212
|
-
.matrix td {
|
|
230
|
+
.jd-matrix th:last-child { border-right: none; }
|
|
231
|
+
.jd-matrix td {
|
|
213
232
|
padding: var(--space-1) var(--space-2);
|
|
214
233
|
border-right: var(--rule) solid var(--ink-30);
|
|
215
234
|
border-bottom: var(--rule) solid var(--ink-30);
|
|
216
235
|
color: var(--fg1);
|
|
217
236
|
}
|
|
218
|
-
.matrix td:last-child { border-right: none; }
|
|
219
|
-
.matrix tbody tr:last-child td { border-bottom: none; }
|
|
220
|
-
.matrix tbody tr:hover td { background: var(--jd-surface-recessed); }
|
|
221
|
-
.matrix .num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
237
|
+
.jd-matrix td:last-child { border-right: none; }
|
|
238
|
+
.jd-matrix tbody tr:last-child td { border-bottom: none; }
|
|
239
|
+
.jd-matrix tbody tr:hover td { background: var(--jd-surface-recessed); }
|
|
240
|
+
.jd-matrix .num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
222
241
|
|
|
223
242
|
/* ---- HIGH CONTRAST RULE SCALING ---------------------------------------- */
|
|
224
243
|
@media (prefers-contrast: more) {
|
|
225
|
-
.matrix th,
|
|
226
|
-
.matrix td {
|
|
244
|
+
.jd-matrix th,
|
|
245
|
+
.jd-matrix td {
|
|
227
246
|
border-right-width: var(--jd-rule-bold);
|
|
228
247
|
border-bottom-width: var(--jd-rule-bold);
|
|
229
248
|
}
|
|
230
|
-
.table th,
|
|
231
|
-
.table td {
|
|
249
|
+
.jd-table th,
|
|
250
|
+
.jd-table td {
|
|
232
251
|
border-bottom-width: var(--jd-rule-bold);
|
|
233
252
|
}
|
|
234
|
-
.field__input {
|
|
253
|
+
.jd-field__input {
|
|
235
254
|
border-width: var(--jd-rule-bold);
|
|
236
255
|
}
|
|
237
256
|
}
|
|
238
257
|
|
|
239
|
-
[data-contrast="high"] .matrix th,
|
|
240
|
-
[data-contrast="high"] .matrix td {
|
|
258
|
+
[data-contrast="high"] .jd-matrix th,
|
|
259
|
+
[data-contrast="high"] .jd-matrix td {
|
|
241
260
|
border-right-width: var(--jd-rule-bold);
|
|
242
261
|
border-bottom-width: var(--jd-rule-bold);
|
|
243
262
|
}
|
|
244
|
-
[data-contrast="high"] .table th,
|
|
245
|
-
[data-contrast="high"] .table td {
|
|
263
|
+
[data-contrast="high"] .jd-table th,
|
|
264
|
+
[data-contrast="high"] .jd-table td {
|
|
246
265
|
border-bottom-width: var(--jd-rule-bold);
|
|
247
266
|
}
|
|
248
|
-
[data-contrast="high"] .field__input {
|
|
267
|
+
[data-contrast="high"] .jd-field__input {
|
|
249
268
|
border-width: var(--jd-rule-bold);
|
|
250
269
|
}
|
|
251
270
|
|