mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-27 18:57:09 +00:00
feat(appearance): add Calm/Signature visual style, readability mode, and chart palette (#1407)
* feat(appearance): add Calm/Signature visual style, readability mode, and chart palette Turn the "too intense / italic headers hurt / the security graph fights my eyes" feedback into a token-driven Visual style with Calm as the new default and Signature one click back to the prior look. - Heading family routes through a `.font-heading` utility driven by `--font-heading`/`--heading-style`: operational headings render upright in the interface face under Calm and italic Instrument Serif under Signature. Base rule sets family + style only, so each call site keeps its own weight/tracking and Signature stays a true no-op; the Calm lift is a `[data-headings="clean"]` descendant rule. Brand lockup, empty-state heroes, and onboarding stay serif. - Severity charts resolve through `--sev-*` tokens with Muted, Heat, and Signature palettes; FindingsByType routes its series through the severity ramp plus a neutral so no brand-cyan sits next to rose. The risk trend flattens its gradient under Muted/Heat/reduced and keeps the gradient under Signature. - Appearance settings gain Visual style cards, a Security visualization palette, a Readability master toggle, a Motion & effects group, and a "Reset to default" button (restores the Calm axes, disabled while readability is on). Contrast moves under Readability and Ambient glow under Motion & effects. A card is selected only while the stored sub-axes match its preset, so a custom combination de-selects both. - The topbar Theme quick-switch swaps the interface/data font pickers for a Visual style switch and a Readability toggle (text size kept); its footer Settings link jumps straight to Appearance. - Readability is a sticky master that forces the calm resolution and a contrast lift at apply time without mutating the stored sub-axes. - New users default to Calm; any pre-existing persisted appearance state keeps the Signature look. The pre-paint script mirrors the store. - SegmentedControl gains a `disabled` prop and a nullable value (no active segment for a custom combination, with a roving-tabindex keyboard anchor). Adds unit/component coverage for the store, migration, chart shape logic, the disabled control, the reset/de-selection, and the quick-switch. * fix(appearance): migrate Blueprint serif headings and surface readability locks - Migrate the two operational Blueprint headings (catalog tile name, drift-policy option title) from font-serif italic to the .font-heading utility; the first pass only covered font-display, so Calm still left these italic. font-serif and font-display both resolve to the same display face, so this is the same fix. - Lock the Visual style cards under Readability (parity with the topbar switch and the on-screen guidance to turn Readability off to choose a style by hand). - Lock the Border brightness slider under Readability and show its forced +0.03 readout, since Readability overrides the stored value; dragging it previously appeared to do nothing. - Correct the Appearance docs sentence for the topbar quick switch (it listed fonts; the quick switch now carries visual style, readability, and text size).
This commit is contained in:
@@ -206,7 +206,7 @@ function StackReadinessCard({
|
||||
<span className="font-mono text-[10px] uppercase tracking-[0.22em] text-stat-subtitle/80">
|
||||
Stack
|
||||
</span>
|
||||
<span className="font-display italic text-2xl leading-tight tracking-tight text-stat-value truncate">
|
||||
<span className="font-heading text-2xl leading-tight tracking-tight text-stat-value truncate">
|
||||
{stack}
|
||||
</span>
|
||||
</div>
|
||||
@@ -334,7 +334,7 @@ function ReadinessHero({
|
||||
<span className="font-mono text-[10px] uppercase tracking-[0.22em] text-brand">
|
||||
Fleet readiness
|
||||
</span>
|
||||
<span className="font-display italic text-3xl leading-tight tracking-tight text-stat-value">
|
||||
<span className="font-heading text-3xl leading-tight tracking-tight text-stat-value">
|
||||
{headline}
|
||||
</span>
|
||||
{total > 0 && (
|
||||
@@ -389,7 +389,7 @@ function NodeGroupSection({
|
||||
<section className="flex flex-col gap-4">
|
||||
<div className="flex items-baseline gap-3 border-b border-card-border/60 pb-2">
|
||||
<TypeIcon className="h-4 w-4 text-stat-subtitle self-center" strokeWidth={1.5} aria-hidden="true" />
|
||||
<span className="font-display italic text-xl leading-tight tracking-tight text-stat-value truncate">
|
||||
<span className="font-heading text-xl leading-tight tracking-tight text-stat-value truncate">
|
||||
{group.nodeName}
|
||||
</span>
|
||||
<Badge variant="outline" className="text-[10px] px-1.5 py-0 h-4 shrink-0 self-center">
|
||||
@@ -428,7 +428,7 @@ export function MobileReadinessCard({ card, onApply }: { card: StackCard; onAppl
|
||||
<div className="flex items-start justify-between gap-[10px]">
|
||||
<div className="min-w-0 flex-1">
|
||||
<Kicker>stack</Kicker>
|
||||
<div className="mt-px truncate font-display italic text-[23px] leading-[26px] text-stat-value">{stack}</div>
|
||||
<div className="mt-px truncate font-heading text-[23px] leading-[26px] text-stat-value">{stack}</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1.5">
|
||||
{!autoUpdateEnabled && (
|
||||
@@ -483,7 +483,7 @@ function MobileNodeSection({ group, onApply }: { group: NodeGroup; onApply: (sta
|
||||
return (
|
||||
<section>
|
||||
<div className="mb-[13px] flex items-baseline gap-2 border-b border-hairline pb-2">
|
||||
<span className="truncate font-display italic text-[19px] leading-tight text-stat-value">{group.nodeName}</span>
|
||||
<span className="truncate font-heading text-[19px] leading-tight text-stat-value">{group.nodeName}</span>
|
||||
<span className="shrink-0 rounded-[5px] border border-card-border px-1.5 py-px font-mono text-[10px] uppercase tracking-[0.1em] text-stat-subtitle">{group.nodeType}</span>
|
||||
<span className="shrink-0 font-mono text-[11px] text-stat-icon">{group.cards.length} {group.cards.length === 1 ? 'stack' : 'stacks'}</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user