@godxjp/ui 18.5.0 → 18.6.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/dist/components/charts/compact-bar-trend.d.ts +2 -1
- package/dist/components/charts/index.d.ts +4 -1
- package/dist/components/data-display/data-table.d.ts +25 -4
- package/dist/components/data-display/data-table.js +13 -2
- package/dist/components/data-display/empty-state.js +1 -1
- package/dist/components/data-display/index.d.ts +1 -1
- package/dist/components/data-display/list-row.d.ts +19 -0
- package/dist/components/data-display/list-row.js +2 -0
- package/dist/components/data-display/qr-code.d.ts +1 -1
- package/dist/components/data-display/table.d.ts +47 -2
- package/dist/components/data-display/table.js +29 -4
- package/dist/components/data-entry/command.d.ts +10 -10
- package/dist/components/data-entry/index.d.ts +1 -0
- package/dist/components/data-entry/input-otp.d.ts +1 -0
- package/dist/components/feedback/dialog.d.ts +14 -1
- package/dist/components/feedback/dialog.js +4 -0
- package/dist/components/feedback/index.d.ts +1 -1
- package/dist/components/feedback/index.js +2 -0
- package/dist/components/general/logo.d.ts +7 -1
- package/dist/components/general/logo.js +1 -1
- package/dist/components/layout/app-shell.d.ts +1 -1
- package/dist/components/layout/app-shell.js +55 -46
- package/dist/components/layout/auth-account-summary.d.ts +5 -0
- package/dist/components/layout/auth-account-summary.js +31 -0
- package/dist/components/layout/auth-shell.d.ts +3 -2
- package/dist/components/layout/centered-shell.d.ts +1 -1
- package/dist/components/layout/centered-shell.js +28 -19
- package/dist/components/layout/error-surface.d.ts +35 -0
- package/dist/components/layout/error-surface.js +155 -0
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +4 -0
- package/dist/components/layout/index.d.ts +5 -0
- package/dist/components/layout/index.js +4 -0
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +4 -0
- package/dist/components/navigation/steps.js +38 -19
- package/dist/components/navigation/tabs.js +12 -3
- package/dist/components/ui/avatar.d.ts +2 -1
- package/dist/components/ui/avatar.js +2 -1
- package/dist/components/ui/input-otp.d.ts +4 -1
- package/dist/components/ui/input-otp.js +2 -1
- package/dist/components/ui/toggle-group.d.ts +7 -4
- package/dist/components/ui/toggle-group.js +32 -21
- package/dist/email/brand-mark.d.ts +21 -5
- package/dist/email/brand-mark.js +5 -0
- package/dist/email/color.d.ts +2 -1
- package/dist/email/geometry.d.ts +9 -1
- package/dist/email/geometry.js +1 -0
- package/dist/email/index.d.ts +6 -1
- package/dist/email/index.js +6 -0
- package/dist/email/inline-style.d.ts +7 -5
- package/dist/email/inline-style.js +5 -0
- package/dist/email/tokens.generated.d.ts +40 -20
- package/dist/email/tokens.generated.js +40 -20
- package/dist/email/urgency.d.ts +22 -0
- package/dist/email/urgency.js +14 -0
- package/dist/i18n/messages/en.json +15 -1
- package/dist/i18n/messages/ja.json +15 -1
- package/dist/i18n/messages/vi.json +15 -1
- package/dist/props/components/data-display.prop.d.ts +63 -1
- package/dist/props/components/data-entry.prop.d.ts +6 -0
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/layout.prop.d.ts +191 -4
- package/dist/props/components/navigation.prop.d.ts +5 -1
- package/dist/props/registry.d.ts +145 -4
- package/dist/props/registry.js +189 -5
- package/dist/props/vocabulary/data.prop.d.ts +27 -0
- package/dist/props/vocabulary/index.d.ts +3 -3
- package/dist/props/vocabulary/interaction.prop.d.ts +9 -0
- package/dist/props/vocabulary/layout.prop.d.ts +38 -7
- package/dist/styles/control.css +28 -0
- package/dist/styles/data-display-layout.css +26 -0
- package/dist/styles/layout.css +99 -0
- package/dist/styles/logo-layout.css +42 -9
- package/dist/styles/navigation-layout.css +109 -0
- package/dist/styles/shell-layout.css +302 -0
- package/dist/styles/table-layout.css +164 -1
- package/dist/theme/dxs.canonical.css +5 -4
- package/dist/tokens/axes.css +4 -3
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/components/data-display.css +13 -0
- package/dist/tokens/components/email.css +43 -16
- package/dist/tokens/components/error-surface.css +36 -0
- package/dist/tokens/components/list-row.css +20 -0
- package/dist/tokens/components/logo.css +52 -10
- package/dist/tokens/components/navigation.css +15 -0
- package/dist/tokens/components/shell.css +72 -0
- package/dist/tokens/components/table.css +45 -0
- package/dist/tokens/foundation.css +26 -0
- package/dist/tokens/semantic/layout.css +25 -0
- package/package.json +8 -2
|
@@ -42,8 +42,9 @@ function Tabs({
|
|
|
42
42
|
TabsList,
|
|
43
43
|
{
|
|
44
44
|
"data-slot": "tabs-list",
|
|
45
|
+
variant: variant === "line" ? "line" : "default",
|
|
45
46
|
className: cn(
|
|
46
|
-
variant === "line" && "h-auto w-full justify-start
|
|
47
|
+
variant === "line" && "h-auto w-full justify-start border-b p-0",
|
|
47
48
|
variant === "card" && "w-full justify-start",
|
|
48
49
|
listClassName
|
|
49
50
|
),
|
|
@@ -53,7 +54,9 @@ function Tabs({
|
|
|
53
54
|
value: item.value,
|
|
54
55
|
disabled: item.disabled,
|
|
55
56
|
className: cn(
|
|
56
|
-
|
|
57
|
+
// Geometry only — the active underline is the token-owned `::after` bar the
|
|
58
|
+
// line variant already owns (never a second, hand-rolled border-b indicator).
|
|
59
|
+
variant === "line" && "rounded-none px-4 py-2",
|
|
57
60
|
variant === "card" && "data-[state=active]:shadow-sm"
|
|
58
61
|
),
|
|
59
62
|
children: item.label
|
|
@@ -117,7 +120,13 @@ const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
117
120
|
ref,
|
|
118
121
|
"data-slot": "tabs-trigger",
|
|
119
122
|
className: cn(
|
|
120
|
-
|
|
123
|
+
// The SELECTED-state ring (`ring-1 ring-primary/25`) is scoped to the default/card lists —
|
|
124
|
+
// the `line` variant is underline-only (gh#248) and must NEVER paint a surrounding ring, or
|
|
125
|
+
// it competes with (and at equal specificity overrides) the `:focus-visible` ring. The
|
|
126
|
+
// focus-visible ring/outline below is deliberately left unscoped: every variant keeps a
|
|
127
|
+
// visible keyboard focus indicator (WCAG 2.4.7). The line indicator itself lives in
|
|
128
|
+
// src/styles/navigation-layout.css so it reads the --tabs-indicator-* tokens.
|
|
129
|
+
"text-muted-foreground ring-offset-background hover:text-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-ring/50 data-[state=active]:bg-background data-[state=active]:text-foreground group-data-[variant=default]/tabs-list:data-[state=active]:ring-primary/25 relative inline-flex flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-3 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start group-data-[variant=line]/tabs-list:border-e-0 group-data-[variant=line]/tabs-list:border-b-0 focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=default]/tabs-list:data-[state=active]:ring-1 group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none",
|
|
121
130
|
className
|
|
122
131
|
),
|
|
123
132
|
...props
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
|
-
|
|
3
|
+
import type { AvatarProp } from "../../props/components/data-display.prop.js";
|
|
4
|
+
export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "shape"> & React.RefAttributes<HTMLSpanElement>>;
|
|
4
5
|
export declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
|
|
5
6
|
export declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -3,11 +3,12 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const Avatar = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6
|
+
const Avatar = React.forwardRef(({ className, shape = "circle", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7
7
|
AvatarPrimitive.Root,
|
|
8
8
|
{
|
|
9
9
|
ref,
|
|
10
10
|
"data-slot": "avatar",
|
|
11
|
+
"data-shape": shape === "square" ? "square" : void 0,
|
|
11
12
|
className: cn("ui-avatar", className),
|
|
12
13
|
...props
|
|
13
14
|
}
|
|
@@ -26,7 +26,10 @@ export declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.
|
|
|
26
26
|
render?: never;
|
|
27
27
|
children: React.ReactNode;
|
|
28
28
|
} & React.RefAttributes<HTMLInputElement>, "ref">) & React.RefAttributes<HTMLInputElement>>;
|
|
29
|
-
export
|
|
29
|
+
export type { InputOTPGroupAppearanceProp, InputOTPGroupProp, InputOTPGroupProp as InputOTPGroupProps, } from "../../props/components/data-entry.prop.js";
|
|
30
|
+
export declare const InputOTPGroup: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
31
|
+
appearance?: import("./input-otp.js").InputOTPGroupAppearanceProp;
|
|
32
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
30
33
|
export declare const InputOTPSlot: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
31
34
|
index: number;
|
|
32
35
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -16,11 +16,12 @@ const InputOTP = React.forwardRef(({ className, containerClassName, ...props },
|
|
|
16
16
|
));
|
|
17
17
|
InputOTP.displayName = "InputOTP";
|
|
18
18
|
const InputOTPGroup = React.forwardRef(
|
|
19
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19
|
+
({ appearance = "slots", className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
20
20
|
"div",
|
|
21
21
|
{
|
|
22
22
|
ref,
|
|
23
23
|
"data-slot": "input-otp-group",
|
|
24
|
+
"data-appearance": appearance,
|
|
24
25
|
className: cn("ui-otp-group", className),
|
|
25
26
|
...props
|
|
26
27
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
3
3
|
import { type ToggleProps } from "./toggle.js";
|
|
4
|
+
type ToggleGroupVariant = ToggleProps["variant"];
|
|
5
|
+
type ToggleGroupSize = ToggleProps["size"];
|
|
4
6
|
export declare const ToggleGroup: React.ForwardRefExoticComponent<((Omit<ToggleGroupPrimitive.ToggleGroupSingleProps & React.RefAttributes<HTMLDivElement>, "ref"> | Omit<ToggleGroupPrimitive.ToggleGroupMultipleProps & React.RefAttributes<HTMLDivElement>, "ref">) & {
|
|
5
|
-
variant?:
|
|
6
|
-
size?:
|
|
7
|
+
variant?: ToggleGroupVariant;
|
|
8
|
+
size?: ToggleGroupSize;
|
|
7
9
|
}) & React.RefAttributes<HTMLDivElement>>;
|
|
8
10
|
export declare const ToggleGroupItem: React.ForwardRefExoticComponent<Omit<ToggleGroupPrimitive.ToggleGroupItemProps & React.RefAttributes<HTMLButtonElement>, "ref"> & {
|
|
9
|
-
variant?:
|
|
10
|
-
size?:
|
|
11
|
+
variant?: ToggleGroupVariant;
|
|
12
|
+
size?: ToggleGroupSize;
|
|
11
13
|
} & React.RefAttributes<HTMLButtonElement>>;
|
|
14
|
+
export {};
|
|
@@ -4,28 +4,39 @@ import * as React from "react";
|
|
|
4
4
|
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
6
|
import { toggleVariants } from "./toggle.js";
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
const ToggleGroupContext = React.createContext({});
|
|
8
|
+
const ToggleGroup = React.forwardRef(({ className, variant, size, children, ...props }, ref) => {
|
|
9
|
+
const context = React.useMemo(() => ({ variant, size }), [variant, size]);
|
|
10
|
+
return /* @__PURE__ */ jsx(
|
|
11
|
+
ToggleGroupPrimitive.Root,
|
|
12
|
+
{
|
|
13
|
+
ref,
|
|
14
|
+
"data-slot": "toggle-group",
|
|
15
|
+
"data-variant": variant,
|
|
16
|
+
"data-size": size,
|
|
17
|
+
className: cn("ui-toggle-group", className),
|
|
18
|
+
...props,
|
|
19
|
+
children: /* @__PURE__ */ jsx(ToggleGroupContext.Provider, { value: context, children })
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
});
|
|
19
23
|
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
20
|
-
const ToggleGroupItem = React.forwardRef(({ className, variant, size, ...props }, ref) =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const ToggleGroupItem = React.forwardRef(({ className, variant, size, ...props }, ref) => {
|
|
25
|
+
const context = React.useContext(ToggleGroupContext);
|
|
26
|
+
const resolvedVariant = variant ?? context.variant;
|
|
27
|
+
const resolvedSize = size ?? context.size;
|
|
28
|
+
return /* @__PURE__ */ jsx(
|
|
29
|
+
ToggleGroupPrimitive.Item,
|
|
30
|
+
{
|
|
31
|
+
ref,
|
|
32
|
+
"data-slot": "toggle-group-item",
|
|
33
|
+
"data-variant": resolvedVariant,
|
|
34
|
+
"data-size": resolvedSize,
|
|
35
|
+
className: cn(toggleVariants({ variant: resolvedVariant, size: resolvedSize }), className),
|
|
36
|
+
...props
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
});
|
|
29
40
|
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
30
41
|
export {
|
|
31
42
|
ToggleGroup,
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* The mark is an emerald CAPSULE with an internal light GLYPH bar — the same artwork the React
|
|
5
5
|
* `<Logo mark="godx" />` paints, at the same 32×32 viewBox and the same coordinates (a test asserts
|
|
6
6
|
* the capsule path is byte-identical to the component's, so the two can never diverge). A capsule
|
|
7
|
-
* WITHOUT the internal glyph is the incomplete mark and must not ship.
|
|
7
|
+
* WITHOUT the internal glyph is the incomplete mark and must not ship. The ARTWORK matches the
|
|
8
|
+
* canonical SCR-302 raster exactly; only the rendered BOX is email-specific — the canonical email
|
|
9
|
+
* header sets it at 22px (`--email-mark-width`) beside the "GoDX" wordmark, where the web
|
|
10
|
+
* `<Logo mark="godx" />` box is 32px.
|
|
8
11
|
*
|
|
9
12
|
* Nothing here references an external or relative asset: an email template has no base URL it can
|
|
10
13
|
* trust, remote images are blocked by default in most clients, and a `cid:` attachment needs
|
|
@@ -16,8 +19,10 @@
|
|
|
16
19
|
* Renders everywhere; degrades to a square emerald block with a light bar in Outlook's Word
|
|
17
20
|
* renderer (which drops `border-radius`) — still recognisably the mark, never a broken image.
|
|
18
21
|
*
|
|
19
|
-
* Colours come from `EMAIL_COLORS` (derived from `--
|
|
20
|
-
* `--logo-godx-color`
|
|
22
|
+
* Colours come from `EMAIL_COLORS` (derived from `--brand` / `--brand-foreground`, the roles
|
|
23
|
+
* `--logo-godx-color` points at), so a re-themed identity role re-tints the mark. NOT `--success`:
|
|
24
|
+
* that is the wakatake STATUS green, and binding identity to it rendered the mark ~ΔE76 17 away
|
|
25
|
+
* from the canonical emerald until gh#250 introduced the dedicated `--brand` role.
|
|
21
26
|
*/
|
|
22
27
|
import { type EmailHex } from "./color.js";
|
|
23
28
|
/** A rounded rectangle in the mark's 32×32 coordinate space. */
|
|
@@ -42,9 +47,9 @@ export declare const EMAIL_BRAND_MARK_GLYPH: EmailBrandMarkRect;
|
|
|
42
47
|
export declare function roundedRectPath({ x, y, width, height, radius }: EmailBrandMarkRect): string;
|
|
43
48
|
/** Options for rendering the mark. Every default comes from the token contract. */
|
|
44
49
|
export interface EmailBrandMarkOptions {
|
|
45
|
-
/** Rendered width in px. Default `EMAIL_BRAND_MARK.widthPx` (
|
|
50
|
+
/** Rendered width in px. Default `EMAIL_BRAND_MARK.widthPx` (the canonical 22px header box). */
|
|
46
51
|
width?: number;
|
|
47
|
-
/** Rendered height in px. Default `EMAIL_BRAND_MARK.heightPx` (
|
|
52
|
+
/** Rendered height in px. Default `EMAIL_BRAND_MARK.heightPx` (the canonical 22px header box). */
|
|
48
53
|
height?: number;
|
|
49
54
|
/** Capsule fill. Default `EMAIL_COLORS.brand`. */
|
|
50
55
|
color?: EmailHex;
|
|
@@ -82,6 +87,17 @@ export interface EmailBrandMark {
|
|
|
82
87
|
readonly glyph: EmailBrandMarkRect;
|
|
83
88
|
readonly capsulePath: string;
|
|
84
89
|
readonly glyphPath: string;
|
|
90
|
+
/**
|
|
91
|
+
* Mark ↔ wordmark separation in the canonical header LOCKUP. The mark alone is not the header:
|
|
92
|
+
* the canonical card sets the mark beside a readable "GoDX" wordmark, and the wordmark — not the
|
|
93
|
+
* mark — carries the accessible name (render the mark with `label: ""` in that pairing).
|
|
94
|
+
*/
|
|
95
|
+
readonly gap: string;
|
|
96
|
+
readonly gapPx: number;
|
|
97
|
+
/** Wordmark type size in the lockup. */
|
|
98
|
+
readonly wordmarkFontSize: string;
|
|
99
|
+
readonly wordmarkFontSizePx: number;
|
|
100
|
+
readonly wordmarkFontWeight: number;
|
|
85
101
|
/** Inline `<svg>` — highest fidelity. */
|
|
86
102
|
readonly svg: string;
|
|
87
103
|
/** `data:` URL of the same SVG, for `<img src>`. */
|
package/dist/email/brand-mark.js
CHANGED
|
@@ -67,6 +67,11 @@ const EMAIL_BRAND_MARK = Object.freeze({
|
|
|
67
67
|
glyph: EMAIL_BRAND_MARK_GLYPH,
|
|
68
68
|
capsulePath: CAPSULE_PATH,
|
|
69
69
|
glyphPath: GLYPH_PATH,
|
|
70
|
+
gap: EMAIL_GEOMETRY_SOURCE["--email-mark-gap"],
|
|
71
|
+
gapPx: Number.parseFloat(EMAIL_GEOMETRY_SOURCE["--email-mark-gap"]),
|
|
72
|
+
wordmarkFontSize: EMAIL_GEOMETRY_SOURCE["--email-wordmark-font-size"],
|
|
73
|
+
wordmarkFontSizePx: Number.parseFloat(EMAIL_GEOMETRY_SOURCE["--email-wordmark-font-size"]),
|
|
74
|
+
wordmarkFontWeight: Number.parseFloat(EMAIL_GEOMETRY_SOURCE["--email-wordmark-font-weight"]),
|
|
70
75
|
svg: emailBrandMarkSvg(),
|
|
71
76
|
dataUri: emailBrandMarkDataUri(),
|
|
72
77
|
tableHtml: emailBrandMarkTableHtml()
|
package/dist/email/color.d.ts
CHANGED
|
@@ -41,7 +41,8 @@ export declare function hslToHex(triplet: string): EmailHex;
|
|
|
41
41
|
* | `border` | `--border` | card edge, footer hairline |
|
|
42
42
|
* | `primary` / `primaryForeground`| `--primary` / `--primary-foreground` | the one CTA |
|
|
43
43
|
* | `focus` | `--ring` | focus affordance in webmail panes |
|
|
44
|
-
* | `brand` / `brandForeground` | `--
|
|
44
|
+
* | `brand` / `brandForeground` | `--brand` / `--brand-foreground` | the GoDX capsule + its glyph |
|
|
45
|
+
* | `urgency` / `urgencyForeground`| `--attention` / `--attention-foreground` | action-required accent / solid large label |
|
|
45
46
|
*/
|
|
46
47
|
export declare const EMAIL_COLORS: Readonly<Record<EmailColorToken, EmailHex>>;
|
|
47
48
|
/**
|
package/dist/email/geometry.d.ts
CHANGED
|
@@ -45,8 +45,16 @@ export interface EmailShellTokens {
|
|
|
45
45
|
export declare const EMAIL_SHELL: EmailShellTokens;
|
|
46
46
|
/** Type ramp. Sizes are literal px — no email client resolves the rem scale reliably. */
|
|
47
47
|
export interface EmailTypographyTokens {
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* The canonical DXS stack, M PLUS 2 first. Web-font `@font-face` is unavailable in most clients,
|
|
50
|
+
* so this NAMES the face and degrades: a client with M PLUS 2 installed (or a webmail that
|
|
51
|
+
* already loaded it) renders the canonical face; everything else falls to Hiragino (macOS/iOS) →
|
|
52
|
+
* Yu Gothic (Windows) → Noto Sans JP → Meiryo → the system UI face → Arial → `sans-serif`. Family
|
|
53
|
+
* names are SINGLE-quoted so the value drops straight into a double-quoted `style="…"` attribute.
|
|
54
|
+
*/
|
|
49
55
|
readonly fontFamily: string;
|
|
56
|
+
/** Mono stack for invoice ids, masked card numbers, ISO dates and amounts. */
|
|
57
|
+
readonly monoFontFamily: string;
|
|
50
58
|
readonly bodyFontSize: string;
|
|
51
59
|
readonly bodyFontSizePx: number;
|
|
52
60
|
readonly bodyLineHeight: number;
|
package/dist/email/geometry.js
CHANGED
|
@@ -30,6 +30,7 @@ const EMAIL_SHELL = Object.freeze({
|
|
|
30
30
|
});
|
|
31
31
|
const EMAIL_TYPOGRAPHY = Object.freeze({
|
|
32
32
|
fontFamily: raw("--email-font-family-sans"),
|
|
33
|
+
monoFontFamily: raw("--email-font-family-mono"),
|
|
33
34
|
bodyFontSize: raw("--email-body-font-size"),
|
|
34
35
|
bodyFontSizePx: num("--email-body-font-size"),
|
|
35
36
|
bodyLineHeight: num("--email-body-line-height"),
|
package/dist/email/index.d.ts
CHANGED
|
@@ -23,13 +23,14 @@
|
|
|
23
23
|
* ## Usage
|
|
24
24
|
*
|
|
25
25
|
* ```ts
|
|
26
|
-
* import { EMAIL_COLORS, EMAIL_SHELL, EMAIL_CTA, EMAIL_BRAND_MARK, emailInlineStyle } from "@godxjp/ui/email";
|
|
26
|
+
* import { EMAIL_COLORS, EMAIL_URGENCY, EMAIL_SHELL, EMAIL_CTA, EMAIL_BRAND_MARK, emailInlineStyle } from "@godxjp/ui/email";
|
|
27
27
|
*
|
|
28
28
|
* const card = emailInlineStyle({
|
|
29
29
|
* width: EMAIL_SHELL.width,
|
|
30
30
|
* padding: EMAIL_SHELL.padding,
|
|
31
31
|
* backgroundColor: EMAIL_COLORS.surface,
|
|
32
32
|
* border: `${EMAIL_SHELL.borderWidth} solid ${EMAIL_COLORS.border}`,
|
|
33
|
+
* borderTopColor: EMAIL_URGENCY.accent,
|
|
33
34
|
* borderRadius: EMAIL_SHELL.radius,
|
|
34
35
|
* });
|
|
35
36
|
* ```
|
|
@@ -52,14 +53,18 @@ export { hslToHex, EMAIL_COLORS, EMAIL_COLORS_DARK, type EmailColorToken, type E
|
|
|
52
53
|
export { EMAIL_SHELL, EMAIL_TYPOGRAPHY, EMAIL_CTA, EMAIL_FOOTER, EMAIL_FOCUS, EMAIL_MOBILE, type EmailTokenName, type EmailShellTokens, type EmailTypographyTokens, type EmailCtaTokens, type EmailFooterTokens, type EmailFocusTokens, type EmailMobileTokens, } from "./geometry.js";
|
|
53
54
|
export { EMAIL_BRAND_MARK, EMAIL_BRAND_MARK_VIEWBOX, EMAIL_BRAND_MARK_CAPSULE, EMAIL_BRAND_MARK_GLYPH, emailBrandMarkSvg, emailBrandMarkDataUri, emailBrandMarkTableHtml, roundedRectPath, type EmailBrandMark, type EmailBrandMarkOptions, type EmailBrandMarkRect, } from "./brand-mark.js";
|
|
54
55
|
export { emailInlineStyle, type EmailStyleDeclarations } from "./inline-style.js";
|
|
56
|
+
export { EMAIL_URGENCY, EMAIL_URGENCY_DARK, type EmailUrgencyTokens } from "./urgency.js";
|
|
55
57
|
export { EMAIL_COLOR_SOURCE, EMAIL_COLOR_SOURCE_DARK, EMAIL_GEOMETRY_SOURCE, type EmailColorSource, } from "./tokens.generated.js";
|
|
56
58
|
import { EMAIL_COLORS, EMAIL_COLORS_DARK } from "./color.js";
|
|
57
59
|
import { EMAIL_SHELL, EMAIL_TYPOGRAPHY, EMAIL_CTA, EMAIL_FOOTER, EMAIL_FOCUS, EMAIL_MOBILE } from "./geometry.js";
|
|
58
60
|
import { EMAIL_BRAND_MARK } from "./brand-mark.js";
|
|
61
|
+
import { EMAIL_URGENCY, EMAIL_URGENCY_DARK } from "./urgency.js";
|
|
59
62
|
/** The whole contract in one object — the shape `EMAIL_TOKENS_JSON` serialises. */
|
|
60
63
|
export interface EmailTokens {
|
|
61
64
|
readonly colors: typeof EMAIL_COLORS;
|
|
62
65
|
readonly colorsDark: typeof EMAIL_COLORS_DARK;
|
|
66
|
+
readonly urgency: typeof EMAIL_URGENCY;
|
|
67
|
+
readonly urgencyDark: typeof EMAIL_URGENCY_DARK;
|
|
63
68
|
readonly shell: typeof EMAIL_SHELL;
|
|
64
69
|
readonly typography: typeof EMAIL_TYPOGRAPHY;
|
|
65
70
|
readonly cta: typeof EMAIL_CTA;
|
package/dist/email/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
roundedRectPath
|
|
23
23
|
} from "./brand-mark.js";
|
|
24
24
|
import { emailInlineStyle } from "./inline-style.js";
|
|
25
|
+
import { EMAIL_URGENCY, EMAIL_URGENCY_DARK } from "./urgency.js";
|
|
25
26
|
import {
|
|
26
27
|
EMAIL_COLOR_SOURCE,
|
|
27
28
|
EMAIL_COLOR_SOURCE_DARK,
|
|
@@ -37,9 +38,12 @@ import {
|
|
|
37
38
|
EMAIL_MOBILE as EMAIL_MOBILE2
|
|
38
39
|
} from "./geometry.js";
|
|
39
40
|
import { EMAIL_BRAND_MARK as EMAIL_BRAND_MARK2 } from "./brand-mark.js";
|
|
41
|
+
import { EMAIL_URGENCY as EMAIL_URGENCY2, EMAIL_URGENCY_DARK as EMAIL_URGENCY_DARK2 } from "./urgency.js";
|
|
40
42
|
const EMAIL_TOKENS = Object.freeze({
|
|
41
43
|
colors: EMAIL_COLORS2,
|
|
42
44
|
colorsDark: EMAIL_COLORS_DARK2,
|
|
45
|
+
urgency: EMAIL_URGENCY2,
|
|
46
|
+
urgencyDark: EMAIL_URGENCY_DARK2,
|
|
43
47
|
shell: EMAIL_SHELL2,
|
|
44
48
|
typography: EMAIL_TYPOGRAPHY2,
|
|
45
49
|
cta: EMAIL_CTA2,
|
|
@@ -67,6 +71,8 @@ export {
|
|
|
67
71
|
EMAIL_TOKENS,
|
|
68
72
|
EMAIL_TOKENS_JSON,
|
|
69
73
|
EMAIL_TYPOGRAPHY,
|
|
74
|
+
EMAIL_URGENCY,
|
|
75
|
+
EMAIL_URGENCY_DARK,
|
|
70
76
|
emailBrandMarkDataUri,
|
|
71
77
|
emailBrandMarkSvg,
|
|
72
78
|
emailBrandMarkTableHtml,
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Email clients do not run the cascade: Gmail strips `<style>`, Outlook resolves no custom
|
|
5
5
|
* property, and only the `style=""` attribute on the painting element is universally honoured.
|
|
6
|
-
* `emailInlineStyle` turns a declaration map into that attribute value AND enforces the
|
|
7
|
-
* that silently break templates — no `var()` (nothing resolves it)
|
|
8
|
-
* renderer drops the whole declaration)
|
|
9
|
-
*
|
|
6
|
+
* `emailInlineStyle` turns a declaration map into that attribute value AND enforces the three rules
|
|
7
|
+
* that silently break templates — no `var()` (nothing resolves it), no `calc()` (Outlook's Word
|
|
8
|
+
* renderer drops the whole declaration) and no `"` (it closes the `style="…"` attribute mid-value,
|
|
9
|
+
* which is how a double-quoted font family corrupts a whole tag). Failing loudly at template-build
|
|
10
|
+
* time beats a broken layout discovered in Mailpit.
|
|
10
11
|
*/
|
|
11
12
|
/** A declaration map. Numbers are emitted verbatim (already-unitless values like `font-weight`). */
|
|
12
13
|
export type EmailStyleDeclarations = Record<string, string | number | null | undefined>;
|
|
@@ -20,6 +21,7 @@ export type EmailStyleDeclarations = Record<string, string | number | null | und
|
|
|
20
21
|
*
|
|
21
22
|
* `null` / `undefined` values are dropped, so a conditional declaration needs no branch.
|
|
22
23
|
*
|
|
23
|
-
* @throws if a value contains `var()` or `calc()`
|
|
24
|
+
* @throws if a value contains `var()` or `calc()` (neither survives an email client) or a double
|
|
25
|
+
* quote (it terminates the `style="…"` attribute).
|
|
24
26
|
*/
|
|
25
27
|
export declare function emailInlineStyle(declarations: EmailStyleDeclarations): string;
|
|
@@ -9,6 +9,11 @@ function emailInlineStyle(declarations) {
|
|
|
9
9
|
`emailInlineStyle: "${property}: ${serialised}" uses var()/calc(), which no email client resolves. Pass the literal value from the @godxjp/ui/email token export instead.`
|
|
10
10
|
);
|
|
11
11
|
}
|
|
12
|
+
if (serialised.includes('"')) {
|
|
13
|
+
throw new TypeError(
|
|
14
|
+
`emailInlineStyle: "${property}: ${serialised}" contains a double quote, which terminates the style="\u2026" attribute it is written into. Use single quotes \u2014 a quoted font family from EMAIL_TYPOGRAPHY already ships that way.`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
12
17
|
parts.push(`${kebab(property)}:${serialised}`);
|
|
13
18
|
}
|
|
14
19
|
return parts.join(";");
|
|
@@ -48,11 +48,19 @@ export declare const EMAIL_COLOR_SOURCE: {
|
|
|
48
48
|
readonly hsl: "204 100% 39%";
|
|
49
49
|
};
|
|
50
50
|
readonly brand: {
|
|
51
|
-
readonly cssVar: "--
|
|
52
|
-
readonly hsl: "
|
|
51
|
+
readonly cssVar: "--brand";
|
|
52
|
+
readonly hsl: "160.5 100% 29.6%";
|
|
53
53
|
};
|
|
54
54
|
readonly brandForeground: {
|
|
55
|
-
readonly cssVar: "--
|
|
55
|
+
readonly cssVar: "--brand-foreground";
|
|
56
|
+
readonly hsl: "60 33% 99%";
|
|
57
|
+
};
|
|
58
|
+
readonly urgency: {
|
|
59
|
+
readonly cssVar: "--attention";
|
|
60
|
+
readonly hsl: "25 99% 46%";
|
|
61
|
+
};
|
|
62
|
+
readonly urgencyForeground: {
|
|
63
|
+
readonly cssVar: "--attention-foreground";
|
|
56
64
|
readonly hsl: "60 33% 99%";
|
|
57
65
|
};
|
|
58
66
|
};
|
|
@@ -99,11 +107,19 @@ export declare const EMAIL_COLOR_SOURCE_DARK: {
|
|
|
99
107
|
readonly hsl: "204 90% 60%";
|
|
100
108
|
};
|
|
101
109
|
readonly brand: {
|
|
102
|
-
readonly cssVar: "--
|
|
103
|
-
readonly hsl: "
|
|
110
|
+
readonly cssVar: "--brand";
|
|
111
|
+
readonly hsl: "160.5 100% 36%";
|
|
104
112
|
};
|
|
105
113
|
readonly brandForeground: {
|
|
106
|
-
readonly cssVar: "--
|
|
114
|
+
readonly cssVar: "--brand-foreground";
|
|
115
|
+
readonly hsl: "48 9% 9%";
|
|
116
|
+
};
|
|
117
|
+
readonly urgency: {
|
|
118
|
+
readonly cssVar: "--attention";
|
|
119
|
+
readonly hsl: "25 95% 56%";
|
|
120
|
+
};
|
|
121
|
+
readonly urgencyForeground: {
|
|
122
|
+
readonly cssVar: "--attention-foreground";
|
|
107
123
|
readonly hsl: "48 9% 9%";
|
|
108
124
|
};
|
|
109
125
|
};
|
|
@@ -117,23 +133,27 @@ export declare const EMAIL_GEOMETRY_SOURCE: {
|
|
|
117
133
|
readonly "--email-card-reference-height": "407px";
|
|
118
134
|
readonly "--email-stack-gap": "24px";
|
|
119
135
|
readonly "--email-stack-gap-sm": "12px";
|
|
120
|
-
readonly "--email-mark-width": "
|
|
121
|
-
readonly "--email-mark-height": "
|
|
122
|
-
readonly "--email-
|
|
136
|
+
readonly "--email-mark-width": "22px";
|
|
137
|
+
readonly "--email-mark-height": "22px";
|
|
138
|
+
readonly "--email-mark-gap": "8px";
|
|
139
|
+
readonly "--email-wordmark-font-size": "13px";
|
|
140
|
+
readonly "--email-wordmark-font-weight": "700";
|
|
141
|
+
readonly "--email-font-family-sans": "'M PLUS 2', 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'Yu Gothic Medium', YuGothic, 'Noto Sans JP', Meiryo, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, Arial, sans-serif";
|
|
142
|
+
readonly "--email-font-family-mono": "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
123
143
|
readonly "--email-body-font-size": "14px";
|
|
124
|
-
readonly "--email-body-line-height": "1.
|
|
144
|
+
readonly "--email-body-line-height": "1.9";
|
|
125
145
|
readonly "--email-body-font-weight": "400";
|
|
126
|
-
readonly "--email-heading-font-size": "
|
|
127
|
-
readonly "--email-heading-line-height": "1.
|
|
128
|
-
readonly "--email-heading-font-weight": "
|
|
129
|
-
readonly "--email-cta-height": "
|
|
130
|
-
readonly "--email-cta-line-height": "
|
|
131
|
-
readonly "--email-cta-padding-x": "
|
|
146
|
+
readonly "--email-heading-font-size": "17px";
|
|
147
|
+
readonly "--email-heading-line-height": "1.7";
|
|
148
|
+
readonly "--email-heading-font-weight": "500";
|
|
149
|
+
readonly "--email-cta-height": "36px";
|
|
150
|
+
readonly "--email-cta-line-height": "36px";
|
|
151
|
+
readonly "--email-cta-padding-x": "16px";
|
|
132
152
|
readonly "--email-cta-radius": "6px";
|
|
133
153
|
readonly "--email-cta-font-size": "14px";
|
|
134
|
-
readonly "--email-cta-font-weight": "
|
|
135
|
-
readonly "--email-footer-font-size": "
|
|
136
|
-
readonly "--email-footer-line-height": "1.
|
|
154
|
+
readonly "--email-cta-font-weight": "500";
|
|
155
|
+
readonly "--email-footer-font-size": "11px";
|
|
156
|
+
readonly "--email-footer-line-height": "1.8";
|
|
137
157
|
readonly "--email-footer-link-gap": "12px";
|
|
138
158
|
readonly "--email-footer-padding-top": "20px";
|
|
139
159
|
readonly "--email-footer-border-width": "1px";
|
|
@@ -142,6 +162,6 @@ export declare const EMAIL_GEOMETRY_SOURCE: {
|
|
|
142
162
|
readonly "--email-mobile-width": "100%";
|
|
143
163
|
readonly "--email-mobile-padding": "20px";
|
|
144
164
|
readonly "--email-mobile-page-padding": "12px";
|
|
145
|
-
readonly "--email-mobile-heading-font-size": "
|
|
165
|
+
readonly "--email-mobile-heading-font-size": "16px";
|
|
146
166
|
readonly "--email-mobile-cta-width": "100%";
|
|
147
167
|
};
|
|
@@ -40,11 +40,19 @@ const EMAIL_COLOR_SOURCE = {
|
|
|
40
40
|
"hsl": "204 100% 39%"
|
|
41
41
|
},
|
|
42
42
|
"brand": {
|
|
43
|
-
"cssVar": "--
|
|
44
|
-
"hsl": "
|
|
43
|
+
"cssVar": "--brand",
|
|
44
|
+
"hsl": "160.5 100% 29.6%"
|
|
45
45
|
},
|
|
46
46
|
"brandForeground": {
|
|
47
|
-
"cssVar": "--
|
|
47
|
+
"cssVar": "--brand-foreground",
|
|
48
|
+
"hsl": "60 33% 99%"
|
|
49
|
+
},
|
|
50
|
+
"urgency": {
|
|
51
|
+
"cssVar": "--attention",
|
|
52
|
+
"hsl": "25 99% 46%"
|
|
53
|
+
},
|
|
54
|
+
"urgencyForeground": {
|
|
55
|
+
"cssVar": "--attention-foreground",
|
|
48
56
|
"hsl": "60 33% 99%"
|
|
49
57
|
}
|
|
50
58
|
};
|
|
@@ -90,11 +98,19 @@ const EMAIL_COLOR_SOURCE_DARK = {
|
|
|
90
98
|
"hsl": "204 90% 60%"
|
|
91
99
|
},
|
|
92
100
|
"brand": {
|
|
93
|
-
"cssVar": "--
|
|
94
|
-
"hsl": "
|
|
101
|
+
"cssVar": "--brand",
|
|
102
|
+
"hsl": "160.5 100% 36%"
|
|
95
103
|
},
|
|
96
104
|
"brandForeground": {
|
|
97
|
-
"cssVar": "--
|
|
105
|
+
"cssVar": "--brand-foreground",
|
|
106
|
+
"hsl": "48 9% 9%"
|
|
107
|
+
},
|
|
108
|
+
"urgency": {
|
|
109
|
+
"cssVar": "--attention",
|
|
110
|
+
"hsl": "25 95% 56%"
|
|
111
|
+
},
|
|
112
|
+
"urgencyForeground": {
|
|
113
|
+
"cssVar": "--attention-foreground",
|
|
98
114
|
"hsl": "48 9% 9%"
|
|
99
115
|
}
|
|
100
116
|
};
|
|
@@ -107,23 +123,27 @@ const EMAIL_GEOMETRY_SOURCE = {
|
|
|
107
123
|
"--email-card-reference-height": "407px",
|
|
108
124
|
"--email-stack-gap": "24px",
|
|
109
125
|
"--email-stack-gap-sm": "12px",
|
|
110
|
-
"--email-mark-width": "
|
|
111
|
-
"--email-mark-height": "
|
|
112
|
-
"--email-
|
|
126
|
+
"--email-mark-width": "22px",
|
|
127
|
+
"--email-mark-height": "22px",
|
|
128
|
+
"--email-mark-gap": "8px",
|
|
129
|
+
"--email-wordmark-font-size": "13px",
|
|
130
|
+
"--email-wordmark-font-weight": "700",
|
|
131
|
+
"--email-font-family-sans": "'M PLUS 2', 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'Yu Gothic Medium', YuGothic, 'Noto Sans JP', Meiryo, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, Arial, sans-serif",
|
|
132
|
+
"--email-font-family-mono": "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
113
133
|
"--email-body-font-size": "14px",
|
|
114
|
-
"--email-body-line-height": "1.
|
|
134
|
+
"--email-body-line-height": "1.9",
|
|
115
135
|
"--email-body-font-weight": "400",
|
|
116
|
-
"--email-heading-font-size": "
|
|
117
|
-
"--email-heading-line-height": "1.
|
|
118
|
-
"--email-heading-font-weight": "
|
|
119
|
-
"--email-cta-height": "
|
|
120
|
-
"--email-cta-line-height": "
|
|
121
|
-
"--email-cta-padding-x": "
|
|
136
|
+
"--email-heading-font-size": "17px",
|
|
137
|
+
"--email-heading-line-height": "1.7",
|
|
138
|
+
"--email-heading-font-weight": "500",
|
|
139
|
+
"--email-cta-height": "36px",
|
|
140
|
+
"--email-cta-line-height": "36px",
|
|
141
|
+
"--email-cta-padding-x": "16px",
|
|
122
142
|
"--email-cta-radius": "6px",
|
|
123
143
|
"--email-cta-font-size": "14px",
|
|
124
|
-
"--email-cta-font-weight": "
|
|
125
|
-
"--email-footer-font-size": "
|
|
126
|
-
"--email-footer-line-height": "1.
|
|
144
|
+
"--email-cta-font-weight": "500",
|
|
145
|
+
"--email-footer-font-size": "11px",
|
|
146
|
+
"--email-footer-line-height": "1.8",
|
|
127
147
|
"--email-footer-link-gap": "12px",
|
|
128
148
|
"--email-footer-padding-top": "20px",
|
|
129
149
|
"--email-footer-border-width": "1px",
|
|
@@ -132,7 +152,7 @@ const EMAIL_GEOMETRY_SOURCE = {
|
|
|
132
152
|
"--email-mobile-width": "100%",
|
|
133
153
|
"--email-mobile-padding": "20px",
|
|
134
154
|
"--email-mobile-page-padding": "12px",
|
|
135
|
-
"--email-mobile-heading-font-size": "
|
|
155
|
+
"--email-mobile-heading-font-size": "16px",
|
|
136
156
|
"--email-mobile-cta-width": "100%"
|
|
137
157
|
};
|
|
138
158
|
export {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type EmailHex } from "./color.js";
|
|
2
|
+
/**
|
|
3
|
+
* Semantic action-required styling for transactional email.
|
|
4
|
+
*
|
|
5
|
+
* `accent` is the non-text rail/border color painted on the normal email surface. The solid pair
|
|
6
|
+
* is safe for icons and large or bold labels that satisfy the 3:1 contrast floor; it is not a
|
|
7
|
+
* replacement for normal body copy, which remains `EMAIL_COLORS.foreground` on
|
|
8
|
+
* `EMAIL_COLORS.surface`. This deliberately narrow contract prevents urgency from becoming an
|
|
9
|
+
* undocumented second CTA or a component-local palette.
|
|
10
|
+
*/
|
|
11
|
+
export interface EmailUrgencyTokens {
|
|
12
|
+
/** Non-text action-required rail or border on the standard email surface. */
|
|
13
|
+
readonly accent: EmailHex;
|
|
14
|
+
/** Solid action-required fill for an icon or large/bold label. */
|
|
15
|
+
readonly solidBackground: EmailHex;
|
|
16
|
+
/** Foreground paired only with `solidBackground` under the usage restriction above. */
|
|
17
|
+
readonly solidForeground: EmailHex;
|
|
18
|
+
}
|
|
19
|
+
/** Light-scheme action-required email contract. */
|
|
20
|
+
export declare const EMAIL_URGENCY: Readonly<EmailUrgencyTokens>;
|
|
21
|
+
/** Dark-scheme action-required email contract for clients that honor dark-mode overrides. */
|
|
22
|
+
export declare const EMAIL_URGENCY_DARK: Readonly<EmailUrgencyTokens>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EMAIL_COLORS, EMAIL_COLORS_DARK } from "./color.js";
|
|
2
|
+
function resolveUrgency(colors) {
|
|
3
|
+
return Object.freeze({
|
|
4
|
+
accent: colors.urgency,
|
|
5
|
+
solidBackground: colors.urgency,
|
|
6
|
+
solidForeground: colors.urgencyForeground
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
const EMAIL_URGENCY = resolveUrgency(EMAIL_COLORS);
|
|
10
|
+
const EMAIL_URGENCY_DARK = resolveUrgency(EMAIL_COLORS_DARK);
|
|
11
|
+
export {
|
|
12
|
+
EMAIL_URGENCY,
|
|
13
|
+
EMAIL_URGENCY_DARK
|
|
14
|
+
};
|