@orangecheck/design 0.21.0 → 0.23.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 CHANGED
@@ -21,10 +21,14 @@ Canonical design + rollout plan: `~/Projects/ochk/DESIGN-SYSTEM-PLAN.md`.
21
21
 
22
22
  - **Mode** — `light | dark`, owned by `next-themes` via the `.dark` class. Toggle
23
23
  with `<ThemeToggle />`. Unchanged from today.
24
- - **Skin** — a named theme (`orangecheck` default, `midnight`, …), owned by
25
- `<OcThemeProvider>` via the `data-oc-theme` attribute, persisted in the
26
- `oc_skin` cookie at `Domain=.ochk.io` so a choice carries across every family
27
- site. Pick with `<OcThemePicker />`.
24
+ - **Skin** — a named theme, owned by `<OcThemeProvider>` via the `data-oc-theme`
25
+ attribute, persisted in the `oc_skin` cookie at `Domain=.ochk.io` so a choice
26
+ carries across every family site. Pick with `<OcThemePicker />`. Five skins
27
+ ship: **`ember`** — the family **default** (a warm, rounded consumer skin:
28
+ terracotta, 1rem radius, pill buttons, self-hosted Hanken Grotesk; owns the
29
+ bare `:root`/`.dark` base) — plus `orangecheck`, `phosphor`, `lightning`,
30
+ `gold` (the four sharp/flat Bitcoin-ethos alternates, attribute-only arms). A
31
+ skin re-skins color, radius, type, and elevation — not just hue.
28
32
 
29
33
  The two compose: any skin renders in both modes.
30
34
 
@@ -65,15 +69,32 @@ Header (gate the picker behind a flag during staged rollout):
65
69
  ```
66
70
 
67
71
  Fonts are still loaded by the app via `next/font` into `--font-sans-display`
68
- and `--font-mono-display`, exactly as before.
72
+ and `--font-mono-display`, exactly as before — the default skins defer to them.
73
+ A skin may instead **self-host its own font in-package**: `ember` ships Hanken
74
+ Grotesk as a variable woff2 under `src/styles/fonts/`, declared in
75
+ `src/styles/fonts.css` (imported first by `styles.css`). Tailwind v4 (Lightning
76
+ CSS) rebases the relative `url()` on `@import`, so the woff2 emits through every
77
+ consumer's build with **zero per-site `next/font` wiring**; the browser only
78
+ fetches it when ember is the active skin.
69
79
 
70
80
  ## Adding a skin
71
81
 
72
82
  1. Add `src/styles/themes/<id>.css` declaring the full token set for both modes
73
- (under `[data-oc-theme='<id>']` and `[data-oc-theme='<id>'].dark`).
83
+ (under `[data-oc-theme='<id>']` and `[data-oc-theme='<id>'].dark`). Scope every
84
+ selector to the two `[data-oc-theme='<id>']` arms — never touch bare `:root`/
85
+ `.dark`, or you re-skin the default.
74
86
  2. `@import` it from `src/styles/themes.css`.
75
- 3. Add a row to `OC_THEMES` in `src/tokens/themes.ts`.
76
- 4. Publish. Every site picks it up on the next Renovate bump — no per-site edits.
87
+ 3. Add a row to `OC_THEMES` in `src/tokens/themes.ts` (this auto-populates the
88
+ appearance menu, picker, Storybook toolbar, and favicon recolor).
89
+ 4. Add the id to the hardcoded `SKINS` arrays in `scripts/verify-themes.mjs` +
90
+ `scripts/verify-contrast.mjs`, then `yarn verify` (asserts the skin is
91
+ distinct and AA-clean in both modes).
92
+ 5. (Optional) self-host a font: see the Hanken Grotesk note above.
93
+ 6. Publish. Every site picks it up on the next Renovate bump — no per-site edits.
94
+
95
+ A skin is **opt-in** by default — shipping one makes it a picker option, not the
96
+ default. Changing `DEFAULT_OC_THEME` (family-wide) or a per-site
97
+ `<OcThemeProvider defaultSkin>` is a separate, deliberate flip.
77
98
 
78
99
  ## Build
79
100
 
@@ -1,4 +1,4 @@
1
- export { AccentList, AccentListItem, AccentListProps, AccentNote, AccentNoteProps, BrandBand, Callout, CalloutProps, CalloutTone, CheckList, CheckListProps, ComparisonRow, ComparisonTable, ComparisonTableProps, DataRow, DataRowProps, DefinitionItem, DefinitionList, DefinitionListProps, EmailCapture, EmailCaptureProps, EmptyState, EmptyStateCta, EmptyStateProps, Faq, FaqItem, FaqProps, FeatureCard, FeatureCardProps, HelpHint, HelpHintProps, MarketingHeading, MarketingHeadingProps, NumberedStep, NumberedStepProps, Section, SectionHeader, SectionHeaderProps, SectionProps, StatCard, StatCardProps, StatGrid, StatGridProps, StatItem, StatTile, Step, StepList, StepListProps, TwoToneHeading, TwoToneHeadingProps, VerifiedChip, VerifiedChipProps } from './composites.mjs';
1
+ export { AccentList, AccentListItem, AccentListProps, AccentNote, AccentNoteProps, BrandBand, Callout, CalloutProps, CalloutTone, CheckList, CheckListProps, ComparisonRow, ComparisonTable, ComparisonTableProps, DataRow, DataRowProps, DefinitionItem, DefinitionList, DefinitionListProps, EmailCapture, EmailCaptureProps, EmptyState, EmptyStateCta, EmptyStateProps, Faq, FaqItem, FaqProps, FeatureCard, FeatureCardProps, HelpHint, HelpHintProps, MarketingHeading, MarketingHeadingProps, NumberedStep, NumberedStepProps, Panel, PanelProps, Section, SectionHeader, SectionHeaderProps, SectionProps, StatCard, StatCardProps, StatGrid, StatGridProps, StatItem, StatTile, Step, StepList, StepListProps, TwoToneHeading, TwoToneHeadingProps, VerifiedChip, VerifiedChipProps } from './composites.mjs';
2
2
  export { AppShell, AppShellProps, EcosystemSlug, EcosystemSwitcher, EcosystemSwitcherProps, FAMILY_PROPERTIES, FamilyCategory, FamilyProperty, LayoutSubHeader, LayoutSubHeaderProps, LayoutSubHeaderTag, OcAccountMenu, OcAccountMenuBuildInfo, OcAccountMenuItem, OcAccountMenuProps, OcAccountMenuSession, OcAccountMenuView, OcAccountMenuViewProps, OcAppBar, OcAppBarProps, OcDashboardHub, OcDashboardHubProps, OcDashboardShell, OcDashboardShellProps, OcDashboardTool, OcLogoDropdown, OcLogoDropdownProps, OcPrimaryNav, OcPrimaryNavLink, OcPrimaryNavProps, SITE_STATE_LABEL, SiteState, findFamilyProperty } from './chrome.mjs';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
@@ -1,4 +1,4 @@
1
- export { AccentList, AccentListItem, AccentListProps, AccentNote, AccentNoteProps, BrandBand, Callout, CalloutProps, CalloutTone, CheckList, CheckListProps, ComparisonRow, ComparisonTable, ComparisonTableProps, DataRow, DataRowProps, DefinitionItem, DefinitionList, DefinitionListProps, EmailCapture, EmailCaptureProps, EmptyState, EmptyStateCta, EmptyStateProps, Faq, FaqItem, FaqProps, FeatureCard, FeatureCardProps, HelpHint, HelpHintProps, MarketingHeading, MarketingHeadingProps, NumberedStep, NumberedStepProps, Section, SectionHeader, SectionHeaderProps, SectionProps, StatCard, StatCardProps, StatGrid, StatGridProps, StatItem, StatTile, Step, StepList, StepListProps, TwoToneHeading, TwoToneHeadingProps, VerifiedChip, VerifiedChipProps } from './composites.js';
1
+ export { AccentList, AccentListItem, AccentListProps, AccentNote, AccentNoteProps, BrandBand, Callout, CalloutProps, CalloutTone, CheckList, CheckListProps, ComparisonRow, ComparisonTable, ComparisonTableProps, DataRow, DataRowProps, DefinitionItem, DefinitionList, DefinitionListProps, EmailCapture, EmailCaptureProps, EmptyState, EmptyStateCta, EmptyStateProps, Faq, FaqItem, FaqProps, FeatureCard, FeatureCardProps, HelpHint, HelpHintProps, MarketingHeading, MarketingHeadingProps, NumberedStep, NumberedStepProps, Panel, PanelProps, Section, SectionHeader, SectionHeaderProps, SectionProps, StatCard, StatCardProps, StatGrid, StatGridProps, StatItem, StatTile, Step, StepList, StepListProps, TwoToneHeading, TwoToneHeadingProps, VerifiedChip, VerifiedChipProps } from './composites.js';
2
2
  export { AppShell, AppShellProps, EcosystemSlug, EcosystemSwitcher, EcosystemSwitcherProps, FAMILY_PROPERTIES, FamilyCategory, FamilyProperty, LayoutSubHeader, LayoutSubHeaderProps, LayoutSubHeaderTag, OcAccountMenu, OcAccountMenuBuildInfo, OcAccountMenuItem, OcAccountMenuProps, OcAccountMenuSession, OcAccountMenuView, OcAccountMenuViewProps, OcAppBar, OcAppBarProps, OcDashboardHub, OcDashboardHubProps, OcDashboardShell, OcDashboardShellProps, OcDashboardTool, OcLogoDropdown, OcLogoDropdownProps, OcPrimaryNav, OcPrimaryNavLink, OcPrimaryNavProps, SITE_STATE_LABEL, SiteState, findFamilyProperty } from './chrome.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
@@ -179,11 +179,11 @@ var COL_CLASS = {
179
179
  4: "md:grid-cols-2 lg:grid-cols-4"
180
180
  };
181
181
  function StatGrid({ items, columns = 3, className = "" }) {
182
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `bg-border grid gap-px border ${COL_CLASS[columns]} ${className}`, children: items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsx(Tile, { item: it }, `${it.label}-${i}`)) });
182
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `oc-stat-grid bg-border grid gap-px border ${COL_CLASS[columns]} ${className}`, children: items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsx(Tile, { item: it }, `${it.label}-${i}`)) });
183
183
  }
184
184
  function Tile({ item }) {
185
185
  const tone = item.tone ?? (item.accent ? "primary" : "default");
186
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background p-5", children: [
186
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oc-stat-tile bg-background p-5", children: [
187
187
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 font-mono text-[10px] tracking-widest uppercase", children: item.label }),
188
188
  /* @__PURE__ */ jsxRuntime.jsx(
189
189
  "div",
@@ -236,7 +236,7 @@ function StatBlock({ label, value, sub, delta, tone = "default", className }) {
236
236
  ] });
237
237
  }
238
238
  function StatCard({ pad = "default", className, ...stat }) {
239
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border bg-card", pad === "sm" ? "p-3 md:p-4" : "p-5", className), children: /* @__PURE__ */ jsxRuntime.jsx(StatBlock, { ...stat }) });
239
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("oc-stat-card border bg-card", pad === "sm" ? "p-3 md:p-4" : "p-5", className), children: /* @__PURE__ */ jsxRuntime.jsx(StatBlock, { ...stat }) });
240
240
  }
241
241
  var FRAME = {
242
242
  info: "border-primary/30 bg-primary/5",
@@ -273,7 +273,7 @@ function DefinitionList({ items, className }) {
273
273
  "dl",
274
274
  {
275
275
  className: cn(
276
- "grid gap-x-5 gap-y-2 text-sm sm:grid-cols-[auto_1fr] sm:items-baseline",
276
+ "oc-deflist grid gap-x-5 gap-y-2 text-sm sm:grid-cols-[auto_1fr] sm:items-baseline",
277
277
  className
278
278
  ),
279
279
  children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(React2.Fragment, { children: [
@@ -289,7 +289,7 @@ function DataRow({ children, meta, action, as, className }) {
289
289
  Tag,
290
290
  {
291
291
  className: cn(
292
- "flex flex-col gap-1 py-3 sm:flex-row sm:items-baseline sm:justify-between sm:gap-4",
292
+ "oc-data-row flex flex-col gap-1 py-3 sm:flex-row sm:items-baseline sm:justify-between sm:gap-4",
293
293
  className
294
294
  ),
295
295
  children: [
@@ -302,6 +302,19 @@ function DataRow({ children, meta, action, as, className }) {
302
302
  }
303
303
  );
304
304
  }
305
+ function Panel({ label, title, action, flush, className, children }) {
306
+ const hasHeader = label || title || action;
307
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cn("oc-panel py-8", !flush && "border-t", className), children: [
308
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
309
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
310
+ label && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary mb-1", children: label }),
311
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-display text-lg font-bold tracking-tight", children: title })
312
+ ] }),
313
+ action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: action })
314
+ ] }),
315
+ children
316
+ ] });
317
+ }
305
318
  function TwoToneHeading({
306
319
  lead,
307
320
  muted,
@@ -311,7 +324,7 @@ function TwoToneHeading({
311
324
  }) {
312
325
  const Tag = as ?? "h2";
313
326
  const leadColor = tone === "onBrand" ? "text-primary-foreground" : "text-foreground";
314
- const mutedColor = tone === "onBrand" ? "text-primary-foreground/60" : "text-foreground/40";
327
+ const mutedColor = tone === "onBrand" ? "text-primary-foreground/75" : "text-foreground/40";
315
328
  return /* @__PURE__ */ jsxRuntime.jsxs(
316
329
  Tag,
317
330
  {
@@ -3000,6 +3013,7 @@ exports.OcDashboardHub = OcDashboardHub;
3000
3013
  exports.OcDashboardShell = OcDashboardShell;
3001
3014
  exports.OcLogoDropdown = OcLogoDropdown;
3002
3015
  exports.OcPrimaryNav = OcPrimaryNav;
3016
+ exports.Panel = Panel;
3003
3017
  exports.SITE_STATE_LABEL = SITE_STATE_LABEL;
3004
3018
  exports.Section = Section;
3005
3019
  exports.SectionHeader = SectionHeader;