@godxjp/ui 16.6.0 → 16.7.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/dist/components/data-display/badge.d.ts +6 -1
- package/dist/components/data-display/badge.js +2 -0
- package/dist/components/data-entry/date-range-picker.js +1 -1
- package/dist/components/data-entry/input.d.ts +12 -0
- package/dist/components/data-entry/input.js +18 -3
- package/dist/components/data-entry/month-picker.js +1 -1
- package/dist/components/data-entry/month-range-picker.js +1 -1
- package/dist/components/general/button.js +3 -2
- package/dist/components/general/typography.d.ts +1 -0
- package/dist/components/general/typography.js +2 -1
- package/dist/lib/control-styles.d.ts +8 -3
- package/dist/lib/control-styles.js +5 -3
- package/dist/props/components/data-display.prop.d.ts +2 -1
- package/dist/props/components/data-entry.prop.d.ts +4 -0
- package/dist/props/components/general.prop.d.ts +2 -0
- package/dist/styles/control.css +8 -2
- package/dist/styles/index.css +2 -1
- package/dist/styles/layout.css +10 -0
- package/dist/styles/text-layout.css +9 -4
- package/dist/tokens/components/control.css +11 -0
- package/dist/tokens/foundation.css +17 -0
- package/package.json +1 -1
|
@@ -2,7 +2,12 @@ import * as React from "react";
|
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
import type { ShapeProp, ToneProp } from "../../props/vocabulary";
|
|
4
4
|
export type BadgeVariant = "default" | "secondary" | "outline" | "dashed";
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Badge tones extend the shared status `ToneProp` with a brand `primary` tone — a SOFT brand pill
|
|
7
|
+
* (tinted fill + brand text), the dashboard "role pill" pattern. The status tones stay status-only;
|
|
8
|
+
* for a SOLID brand fill use `variant="default"`.
|
|
9
|
+
*/
|
|
10
|
+
export type BadgeTone = ToneProp | "primary";
|
|
6
11
|
declare const badgeVariants: (props?: ({
|
|
7
12
|
variant?: "default" | "outline" | "dashed" | "secondary" | null | undefined;
|
|
8
13
|
shape?: "default" | "pill" | "sharp" | null | undefined;
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
toneInfoClass,
|
|
18
18
|
toneMutedClass,
|
|
19
19
|
toneNeutralClass,
|
|
20
|
+
tonePrimaryClass,
|
|
20
21
|
toneSuccessClass,
|
|
21
22
|
toneWarningClass
|
|
22
23
|
} from "../../lib/control-styles";
|
|
@@ -65,6 +66,7 @@ const badgeVariants = cva(
|
|
|
65
66
|
);
|
|
66
67
|
const badgeToneClass = {
|
|
67
68
|
default: void 0,
|
|
69
|
+
primary: cn("border-transparent", tonePrimaryClass),
|
|
68
70
|
success: cn("border-transparent", toneSuccessClass),
|
|
69
71
|
warning: cn("border-transparent", toneWarningClass),
|
|
70
72
|
destructive: cn("border-transparent", toneDestructiveClass),
|
|
@@ -72,7 +72,7 @@ function DateRangePicker({
|
|
|
72
72
|
className: cn(
|
|
73
73
|
// One input-styled shell for the whole range — mirrors Input's control
|
|
74
74
|
// tokens (border/radius/ring) so it reads as a single form field.
|
|
75
|
-
"ui-control border-input bg-background flex w-full min-w-0 items-center gap-2 rounded-
|
|
75
|
+
"ui-control border-input bg-background flex w-full min-w-0 items-center gap-2 rounded-[var(--control-radius)] transition-[color,box-shadow] outline-none",
|
|
76
76
|
"focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]",
|
|
77
77
|
open && "border-ring ring-ring/50 ring-[3px]",
|
|
78
78
|
disabled && "pointer-events-none cursor-not-allowed opacity-50",
|
|
@@ -4,6 +4,12 @@ export type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
|
4
4
|
allowClear?: boolean;
|
|
5
5
|
/** Called after the field is cleared via the inline ✕. */
|
|
6
6
|
onClear?: () => void;
|
|
7
|
+
/**
|
|
8
|
+
* A leading affordance pinned inside the start of the field — e.g. a mail or
|
|
9
|
+
* search icon (the common auth/search pattern). Decorative by default; the
|
|
10
|
+
* input keeps the keyboard focus. Pairs with `trailingIcon`/`allowClear`.
|
|
11
|
+
*/
|
|
12
|
+
leadingIcon?: React.ReactNode;
|
|
7
13
|
/**
|
|
8
14
|
* A trailing affordance pinned inside the field — e.g. a calendar / clock popover
|
|
9
15
|
* trigger button. ONE trailing icon shows at a time: when `allowClear` and the field
|
|
@@ -16,6 +22,12 @@ export declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttri
|
|
|
16
22
|
allowClear?: boolean;
|
|
17
23
|
/** Called after the field is cleared via the inline ✕. */
|
|
18
24
|
onClear?: () => void;
|
|
25
|
+
/**
|
|
26
|
+
* A leading affordance pinned inside the start of the field — e.g. a mail or
|
|
27
|
+
* search icon (the common auth/search pattern). Decorative by default; the
|
|
28
|
+
* input keeps the keyboard focus. Pairs with `trailingIcon`/`allowClear`.
|
|
29
|
+
*/
|
|
30
|
+
leadingIcon?: React.ReactNode;
|
|
19
31
|
/**
|
|
20
32
|
* A trailing affordance pinned inside the field — e.g. a calendar / clock popover
|
|
21
33
|
* trigger button. ONE trailing icon shows at a time: when `allowClear` and the field
|
|
@@ -4,7 +4,7 @@ import { X } from "lucide-react";
|
|
|
4
4
|
import { useTranslation } from "../../i18n/use-translation";
|
|
5
5
|
import { cn } from "../../lib/utils";
|
|
6
6
|
const inputBaseClass = [
|
|
7
|
-
"ui-control border-input bg-background w-full min-w-0 rounded-
|
|
7
|
+
"ui-control border-input bg-background w-full min-w-0 rounded-[var(--control-radius)] transition-[color,box-shadow] outline-none",
|
|
8
8
|
"selection:bg-primary selection:text-primary-foreground",
|
|
9
9
|
"file:text-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium",
|
|
10
10
|
"placeholder:text-muted-foreground",
|
|
@@ -18,6 +18,7 @@ const Input = React.forwardRef(
|
|
|
18
18
|
type,
|
|
19
19
|
allowClear = false,
|
|
20
20
|
onClear,
|
|
21
|
+
leadingIcon,
|
|
21
22
|
trailingIcon,
|
|
22
23
|
value,
|
|
23
24
|
defaultValue,
|
|
@@ -58,7 +59,7 @@ const Input = React.forwardRef(
|
|
|
58
59
|
setHasText(false);
|
|
59
60
|
onClear?.();
|
|
60
61
|
};
|
|
61
|
-
if (!allowClear && trailingIcon == null) {
|
|
62
|
+
if (!allowClear && trailingIcon == null && leadingIcon == null) {
|
|
62
63
|
return /* @__PURE__ */ jsx(
|
|
63
64
|
"input",
|
|
64
65
|
{
|
|
@@ -86,6 +87,15 @@ const Input = React.forwardRef(
|
|
|
86
87
|
}
|
|
87
88
|
) : trailingIcon;
|
|
88
89
|
return /* @__PURE__ */ jsxs("span", { "data-slot": "input-affix-wrapper", className: "relative inline-flex w-full items-center", children: [
|
|
90
|
+
leadingIcon != null ? /* @__PURE__ */ jsx(
|
|
91
|
+
"span",
|
|
92
|
+
{
|
|
93
|
+
"data-slot": "input-leading",
|
|
94
|
+
"aria-hidden": "true",
|
|
95
|
+
className: "text-muted-foreground pointer-events-none absolute inset-y-0 start-2 inline-flex items-center",
|
|
96
|
+
children: leadingIcon
|
|
97
|
+
}
|
|
98
|
+
) : null,
|
|
89
99
|
/* @__PURE__ */ jsx(
|
|
90
100
|
"input",
|
|
91
101
|
{
|
|
@@ -95,7 +105,12 @@ const Input = React.forwardRef(
|
|
|
95
105
|
value,
|
|
96
106
|
defaultValue,
|
|
97
107
|
onChange: handleChange,
|
|
98
|
-
className: cn(
|
|
108
|
+
className: cn(
|
|
109
|
+
inputBaseClass,
|
|
110
|
+
leadingIcon != null && "ps-9",
|
|
111
|
+
(showClear || trailingIcon != null) && "pe-9",
|
|
112
|
+
className
|
|
113
|
+
),
|
|
99
114
|
...props
|
|
100
115
|
}
|
|
101
116
|
),
|
|
@@ -57,7 +57,7 @@ function MonthPicker({
|
|
|
57
57
|
"div",
|
|
58
58
|
{
|
|
59
59
|
className: cn(
|
|
60
|
-
"ui-control border-input bg-background flex w-full min-w-0 items-center gap-2 rounded-
|
|
60
|
+
"ui-control border-input bg-background flex w-full min-w-0 items-center gap-2 rounded-[var(--control-radius)] transition-[color,box-shadow] outline-none",
|
|
61
61
|
"focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]",
|
|
62
62
|
open && "border-ring ring-ring/50 ring-[3px]",
|
|
63
63
|
disabled && "pointer-events-none cursor-not-allowed opacity-50",
|
|
@@ -100,7 +100,7 @@ function MonthRangePicker({
|
|
|
100
100
|
"div",
|
|
101
101
|
{
|
|
102
102
|
className: cn(
|
|
103
|
-
"ui-control border-input bg-background flex w-full min-w-0 items-center gap-2 rounded-
|
|
103
|
+
"ui-control border-input bg-background flex w-full min-w-0 items-center gap-2 rounded-[var(--control-radius)] transition-[color,box-shadow] outline-none",
|
|
104
104
|
"focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]",
|
|
105
105
|
open && "border-ring ring-ring/50 ring-[3px]",
|
|
106
106
|
disabled && "pointer-events-none cursor-not-allowed opacity-50",
|
|
@@ -37,9 +37,10 @@ const buttonVariants = cva("ui-button", {
|
|
|
37
37
|
"icon-lg": "size-[calc(var(--control-height)+0.25rem)]"
|
|
38
38
|
},
|
|
39
39
|
// Single source of corner radius (deterministic — no competing rounded-* utility): default uses
|
|
40
|
-
// the
|
|
40
|
+
// the dedicated --button-radius token (themeable independently of --control-radius, issue #124),
|
|
41
|
+
// pill is fully rounded, sharp is square.
|
|
41
42
|
shape: {
|
|
42
|
-
default: "rounded-
|
|
43
|
+
default: "rounded-[var(--button-radius)]",
|
|
43
44
|
pill: "rounded-[var(--radius-pill)]",
|
|
44
45
|
sharp: "rounded-[var(--radius-sharp)]"
|
|
45
46
|
}
|
|
@@ -27,4 +27,5 @@ export declare const Heading: React.ForwardRefExoticComponent<Omit<React.HTMLAtt
|
|
|
27
27
|
tone?: import("../../props").TextToneProp;
|
|
28
28
|
align?: import("../../props").TextAlignProp;
|
|
29
29
|
truncate?: boolean;
|
|
30
|
+
weight?: import("../../props").FontWeightProp;
|
|
30
31
|
} & React.RefAttributes<HTMLHeadingElement>>;
|
|
@@ -28,12 +28,13 @@ const Text = React.forwardRef(
|
|
|
28
28
|
);
|
|
29
29
|
Text.displayName = "Text";
|
|
30
30
|
const Heading = React.forwardRef(
|
|
31
|
-
({ level = 2, as, tone = "default", align, truncate, className, ...props }, ref) => React.createElement(as ?? `h${level}`, {
|
|
31
|
+
({ level = 2, as, tone = "default", align, truncate, weight = "medium", className, ...props }, ref) => React.createElement(as ?? `h${level}`, {
|
|
32
32
|
ref,
|
|
33
33
|
"data-slot": "heading",
|
|
34
34
|
"data-level": level,
|
|
35
35
|
"data-tone": tone,
|
|
36
36
|
"data-align": align,
|
|
37
|
+
"data-weight": weight,
|
|
37
38
|
"data-truncate": truncate ? "" : void 0,
|
|
38
39
|
className: cn("ui-heading", className),
|
|
39
40
|
...props
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Shared control sizing — reads `--control-height`, `--font-size-*` from density / theme. */
|
|
2
|
-
export declare const controlFieldClass = "ui-control w-full rounded-
|
|
3
|
-
export declare const controlMultilineClass = "ui-control-multiline w-full rounded-
|
|
2
|
+
export declare const controlFieldClass = "ui-control w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
|
|
3
|
+
export declare const controlMultilineClass = "ui-control-multiline w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
|
|
4
4
|
/**
|
|
5
5
|
* Open-state ring for popup-style triggers (Select / Cascader / TreeSelect / SearchSelect).
|
|
6
6
|
* Radix moves focus INTO the popup on open, so the trigger loses `:focus-visible` and — without
|
|
@@ -9,7 +9,7 @@ export declare const controlMultilineClass = "ui-control-multiline w-full rounde
|
|
|
9
9
|
* `focus-visible:ring-*` on any trigger that toggles `data-state="open"`.
|
|
10
10
|
*/
|
|
11
11
|
export declare const controlOpenRingClass = "data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px]";
|
|
12
|
-
export declare const controlTriggerClass = "ui-control flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-
|
|
12
|
+
export declare const controlTriggerClass = "ui-control flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-[var(--control-radius)] border border-input bg-background shadow-sm transition-[color,box-shadow] focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1";
|
|
13
13
|
export declare const controlIconClass = "size-[length:var(--control-height)] shrink-0";
|
|
14
14
|
export declare const controlIconSmClass = "size-[calc(var(--control-height)-0.5rem)] shrink-0";
|
|
15
15
|
/** Leading/affix icon inside an input row (search, command) — sized to `--control-icon-size`. */
|
|
@@ -23,6 +23,11 @@ export declare const tableCellPaddingClass = "py-[length:var(--table-cell-paddin
|
|
|
23
23
|
export declare const toneSuccessClass = "border-success/30 bg-success/10 text-success-strong";
|
|
24
24
|
export declare const toneWarningClass = "border-warning/30 bg-warning/10 text-warning-strong";
|
|
25
25
|
export declare const toneInfoClass = "border-info/30 bg-info/10 text-info-strong";
|
|
26
|
+
/** Soft BRAND pill — a tinted primary tone (border/fill keep the brand role; the TEXT uses the
|
|
27
|
+
* AA-strong brand colour `text-primary-strong`, darker than the fill, so a small brand label clears
|
|
28
|
+
* WCAG AA on the soft tint — `text-primary` alone is only 4.04:1 in light). For a SOLID brand fill
|
|
29
|
+
* use the Badge `default` variant instead. */
|
|
30
|
+
export declare const tonePrimaryClass = "border-primary/30 bg-primary/10 text-primary-strong";
|
|
26
31
|
export declare const toneDestructiveClass = "border-destructive/30 bg-destructive/10 text-error-strong";
|
|
27
32
|
export declare const toneMutedClass = "border-border bg-muted text-muted-foreground";
|
|
28
33
|
export declare const toneNeutralClass = "border-border bg-muted text-muted-foreground";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const controlFieldClass = "ui-control w-full rounded-
|
|
2
|
-
const controlMultilineClass = "ui-control-multiline w-full rounded-
|
|
1
|
+
const controlFieldClass = "ui-control w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
|
|
2
|
+
const controlMultilineClass = "ui-control-multiline w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
|
|
3
3
|
const controlOpenRingClass = "data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px]";
|
|
4
|
-
const controlTriggerClass = "ui-control flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-
|
|
4
|
+
const controlTriggerClass = "ui-control flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-[var(--control-radius)] border border-input bg-background shadow-sm transition-[color,box-shadow] focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1";
|
|
5
5
|
const controlIconClass = "size-[length:var(--control-height)] shrink-0";
|
|
6
6
|
const controlIconSmClass = "size-[calc(var(--control-height)-0.5rem)] shrink-0";
|
|
7
7
|
const controlIconLeadingClass = "size-[length:var(--control-icon-size)] shrink-0";
|
|
@@ -11,6 +11,7 @@ const tableCellPaddingClass = "py-[length:var(--table-cell-padding-y)]";
|
|
|
11
11
|
const toneSuccessClass = "border-success/30 bg-success/10 text-success-strong";
|
|
12
12
|
const toneWarningClass = "border-warning/30 bg-warning/10 text-warning-strong";
|
|
13
13
|
const toneInfoClass = "border-info/30 bg-info/10 text-info-strong";
|
|
14
|
+
const tonePrimaryClass = "border-primary/30 bg-primary/10 text-primary-strong";
|
|
14
15
|
const toneDestructiveClass = "border-destructive/30 bg-destructive/10 text-error-strong";
|
|
15
16
|
const toneMutedClass = "border-border bg-muted text-muted-foreground";
|
|
16
17
|
const toneNeutralClass = "border-border bg-muted text-muted-foreground";
|
|
@@ -29,6 +30,7 @@ export {
|
|
|
29
30
|
toneInfoClass,
|
|
30
31
|
toneMutedClass,
|
|
31
32
|
toneNeutralClass,
|
|
33
|
+
tonePrimaryClass,
|
|
32
34
|
toneSuccessClass,
|
|
33
35
|
toneWarningClass
|
|
34
36
|
};
|
|
@@ -23,7 +23,8 @@ export type DescriptionsItemProp = {
|
|
|
23
23
|
/** @see Badge */
|
|
24
24
|
export type BadgeProp = {
|
|
25
25
|
variant?: "default" | "secondary" | "outline";
|
|
26
|
-
tone
|
|
26
|
+
/** Status tones plus a brand `primary` tone (soft brand pill); solid brand = `variant="default"`. */
|
|
27
|
+
tone?: ToneProp | "primary";
|
|
27
28
|
status?: string;
|
|
28
29
|
icon?: React.ComponentType<{
|
|
29
30
|
className?: string;
|
|
@@ -15,6 +15,10 @@ export type InputProp = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
|
15
15
|
allowClear?: boolean;
|
|
16
16
|
/** Called after the field is cleared via the inline ✕. */
|
|
17
17
|
onClear?: () => void;
|
|
18
|
+
/** A leading affordance pinned inside the start of the field (e.g. a mail/lock icon). */
|
|
19
|
+
leadingIcon?: React.ReactNode;
|
|
20
|
+
/** A trailing affordance pinned inside the end of the field (replaced by the clear ✕ when `allowClear` + value). */
|
|
21
|
+
trailingIcon?: React.ReactNode;
|
|
18
22
|
};
|
|
19
23
|
/** @see Textarea */
|
|
20
24
|
export type TextareaProp = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
@@ -28,6 +28,8 @@ export type HeadingProp = Omit<React.HTMLAttributes<HTMLHeadingElement>, "color"
|
|
|
28
28
|
tone?: TextToneProp;
|
|
29
29
|
align?: TextAlignProp;
|
|
30
30
|
truncate?: boolean;
|
|
31
|
+
/** Weight (system canon: 400 · 500 · 700). Default `medium` — set `bold` for an emphasised title. */
|
|
32
|
+
weight?: FontWeightProp;
|
|
31
33
|
};
|
|
32
34
|
/** @see Button */
|
|
33
35
|
export type ButtonProp = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
package/dist/styles/control.css
CHANGED
|
@@ -202,13 +202,19 @@
|
|
|
202
202
|
height: var(--control-height);
|
|
203
203
|
padding-inline-start: var(--control-padding-x);
|
|
204
204
|
padding-inline-end: var(--control-padding-x);
|
|
205
|
-
font-size: var(--font-size
|
|
205
|
+
font-size: var(--control-font-size);
|
|
206
|
+
border-width: var(--control-border-width);
|
|
207
|
+
border-style: solid;
|
|
208
|
+
box-shadow: var(--control-shadow);
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
.ui-control-multiline {
|
|
209
212
|
min-height: calc(var(--control-height) * 2.75);
|
|
210
213
|
padding: var(--space-2) var(--control-padding-x);
|
|
211
|
-
font-size: var(--font-size
|
|
214
|
+
font-size: var(--control-font-size);
|
|
215
|
+
border-width: var(--control-border-width);
|
|
216
|
+
border-style: solid;
|
|
217
|
+
box-shadow: var(--control-shadow);
|
|
212
218
|
}
|
|
213
219
|
|
|
214
220
|
.ui-table-row {
|
package/dist/styles/index.css
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
@source inline("rounded-{xs,xl,2xl}");
|
|
43
43
|
@source inline("text-2xs");
|
|
44
44
|
@source inline("text-{3xl,4xl,5xl}");
|
|
45
|
-
@source inline("text-{success,warning,info,error}-strong");
|
|
45
|
+
@source inline("text-{primary,success,warning,info,error}-strong");
|
|
46
46
|
/* `.js` matters: the published package ships only compiled JS under dist (no
|
|
47
47
|
* .tsx sources), and this file is copied verbatim into dist/styles — without
|
|
48
48
|
* it Tailwind finds no component classes in consumers (unstyled popovers and
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
--color-attention-foreground: hsl(var(--attention-foreground));
|
|
104
104
|
/* AA-strong status TEXT colours (text-{success,warning,info,error}-strong) — darker than the
|
|
105
105
|
* fills so small coloured labels clear WCAG AA on white; flip light on the dark theme. */
|
|
106
|
+
--color-primary-strong: hsl(var(--text-primary));
|
|
106
107
|
--color-success-strong: hsl(var(--text-success));
|
|
107
108
|
--color-warning-strong: hsl(var(--text-warning));
|
|
108
109
|
--color-info-strong: hsl(var(--text-info));
|
package/dist/styles/layout.css
CHANGED
|
@@ -23,6 +23,16 @@
|
|
|
23
23
|
overflow: hidden;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/* Decorative brand SPOTLIGHT backdrop — the token-driven radial halo behind a hero / auth card,
|
|
27
|
+
* replacing a hand-authored `radial-gradient(... hsl(var(--primary)/.18) ...)`. Apply to an
|
|
28
|
+
* `aria-hidden` layer (e.g. an absolutely-positioned full-bleed div behind the card). All geometry
|
|
29
|
+
* and tint come from the `--brand-glow*` tokens, so a theme retints/repositions it with no markup
|
|
30
|
+
* change. `pointer-events:none` keeps the backdrop from stealing clicks from the card above it. */
|
|
31
|
+
.ui-brand-glow {
|
|
32
|
+
background-image: var(--brand-glow);
|
|
33
|
+
pointer-events: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
.ui-flex,
|
|
27
37
|
.ui-stack-xs {
|
|
28
38
|
display: flex;
|
|
@@ -33,14 +33,19 @@
|
|
|
33
33
|
font-size: var(--font-size-2xl);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/* Weight — the dxs-kintai canon (400 body · 500 heading/label · 700 emphasis). No 600.
|
|
37
|
-
|
|
36
|
+
/* Weight — the dxs-kintai canon (400 body · 500 heading/label · 700 emphasis). No 600.
|
|
37
|
+
* Shared by text + heading; the two-attribute heading selectors outrank the base heading
|
|
38
|
+
* rule below, so `<Heading weight="bold">` renders a semantic, emphasised title. */
|
|
39
|
+
[data-slot="text"][data-weight="regular"],
|
|
40
|
+
[data-slot="heading"][data-weight="regular"] {
|
|
38
41
|
font-weight: var(--font-weight-normal);
|
|
39
42
|
}
|
|
40
|
-
[data-slot="text"][data-weight="medium"]
|
|
43
|
+
[data-slot="text"][data-weight="medium"],
|
|
44
|
+
[data-slot="heading"][data-weight="medium"] {
|
|
41
45
|
font-weight: var(--font-weight-medium);
|
|
42
46
|
}
|
|
43
|
-
[data-slot="text"][data-weight="bold"]
|
|
47
|
+
[data-slot="text"][data-weight="bold"],
|
|
48
|
+
[data-slot="heading"][data-weight="bold"] {
|
|
44
49
|
font-weight: var(--font-weight-bold);
|
|
45
50
|
}
|
|
46
51
|
|
|
@@ -18,6 +18,17 @@
|
|
|
18
18
|
--control-gap: var(--space-inline-sm);
|
|
19
19
|
--control-gap-sm: var(--space-inline-xs);
|
|
20
20
|
--control-radius: var(--radius);
|
|
21
|
+
/* Button corner radius — defaults to the button's historical `rounded-md` so nothing
|
|
22
|
+
* changes by default, but is its OWN knob so a service theme can retune the button
|
|
23
|
+
* radius INDEPENDENTLY of input/control radius (issue #124). */
|
|
24
|
+
--button-radius: var(--radius-md);
|
|
25
|
+
/* Control surface knobs — font-size, border width and resting shadow of every
|
|
26
|
+
* `.ui-control` (input / picker trigger). Tokenised so a service theme tunes them
|
|
27
|
+
* once instead of each component hard-coding Tailwind utilities. Defaults preserve
|
|
28
|
+
* the historical look (font-size-base, 1px border, shadow-xs). */
|
|
29
|
+
--control-font-size: var(--font-size-base);
|
|
30
|
+
--control-border-width: 1px;
|
|
31
|
+
--control-shadow: var(--shadow-xs);
|
|
21
32
|
--control-icon-size: calc(1rem * var(--scaling));
|
|
22
33
|
--control-icon-size-sm: calc(0.875rem * var(--scaling));
|
|
23
34
|
--control-focus-ring-width: var(--focus-ring-width);
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
/* Status TEXT colours — darker than the fill roles so small coloured text (a StatCard delta, an
|
|
41
41
|
* outline status badge label) clears WCAG AA 4.5:1 on white. The fill roles (--success/--warning/
|
|
42
42
|
* --info) stay the brighter wa-iro for badges/bars; only TEXT reads these via text-*-strong. */
|
|
43
|
+
--text-primary: 204 100% 30%; /* deep brand blue — AA brand text on the soft primary tint */
|
|
43
44
|
--text-success: 152 84% 22%; /* deep 若竹 — AA green text on white */
|
|
44
45
|
--text-warning: 36 100% 28%; /* dark 山吹 amber — yellow can never pass as text */
|
|
45
46
|
--text-info: 221 70% 38%; /* deep 群青 — AA blue text on white */
|
|
@@ -107,6 +108,21 @@
|
|
|
107
108
|
* — the CTA then carries a brand glow with no component change. */
|
|
108
109
|
--shadow-glow: 0 0 0 0 transparent;
|
|
109
110
|
|
|
111
|
+
/* Brand SPOTLIGHT — a decorative radial brand halo for hero / auth backdrops (the `.ui-brand-glow`
|
|
112
|
+
* utility paints this as a background-image on an aria-hidden layer). Every knob is a token, so a
|
|
113
|
+
* service retints (`--brand-glow-color`), softens (`--brand-glow-alpha`), resizes
|
|
114
|
+
* (`--brand-glow-size`) or repositions (`--brand-glow-position`) the halo with no markup change;
|
|
115
|
+
* override the whole `--brand-glow` for a bespoke gradient. Default: a soft primary glow up top. */
|
|
116
|
+
--brand-glow-color: var(--primary);
|
|
117
|
+
--brand-glow-alpha: 0.18;
|
|
118
|
+
--brand-glow-size: 60% 50%;
|
|
119
|
+
--brand-glow-position: 50% 0%;
|
|
120
|
+
--brand-glow: radial-gradient(
|
|
121
|
+
ellipse var(--brand-glow-size) at var(--brand-glow-position),
|
|
122
|
+
hsl(var(--brand-glow-color) / var(--brand-glow-alpha)),
|
|
123
|
+
transparent 70%
|
|
124
|
+
);
|
|
125
|
+
|
|
110
126
|
/* FOCUS RING — the two global knobs for the keyboard-focus affordance (WCAG 2.4.7 / 2.4.11).
|
|
111
127
|
* `--focus-ring-color` is the themeable hue (HSL components, defaults to --ring) and
|
|
112
128
|
* `--focus-ring-width` the standard thickness; override either ONCE — even scoped under a
|
|
@@ -345,6 +361,7 @@
|
|
|
345
361
|
--text-link: 204 90% 66%;
|
|
346
362
|
--text-brand: 204 90% 66%;
|
|
347
363
|
/* Status text on the dark spine reads LIGHT (AA on dark surfaces). */
|
|
364
|
+
--text-primary: 204 90% 64%; /* lifted brand blue — AA on the dark primary tint */
|
|
348
365
|
--text-success: 146 55% 64%;
|
|
349
366
|
--text-warning: 44 95% 62%;
|
|
350
367
|
--text-info: 221 70% 72%;
|