Auto Foreground
weekendsuperhero-io-sistine/auto-foregroundUnverifiedComponent
Sets --foreground / --muted-foreground from an OKLCH ramp so text contrast tracks light/dark automatically. Configure declaratively via props (palette, start, ramp) or a persisted config; re-applies on theme change.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/Weekendsuperhero-io/sistine/main/auto-foreground.jsonSource
1"use client";23import * as React from "react";4import {5 formatOklch,6 glassSolidSurface,7 HARMONIC_OFFSETS,8 type HarmonicName,9 harmonicHue,10 pickInBand,11 READABLE_USAGE,12 readableForeground,13 type ThemeForegroundOptions,14 themeForeground,15} from "@/lib/oklch-utils";1617const FG_STORAGE_KEY = "sistine-fg";18const RAMP_KEY = "sistine-ramp";19const FG_EVENT = "sistine-fg";2021// Dev instrumentation: set localStorage["sistine-fg-debug"] = "1" (then reload) to log each update()'s22// wall-time and how far it nudges --foreground off the CSS baseline (the "marginal bump"). Off by default.23const fgDebug = () => {24 try {25 return typeof localStorage !== "undefined" && localStorage.getItem("sistine-fg-debug") === "1";26 } catch {27 return false;28 }29};3031export type FgPalette = ThemeForegroundOptions["palette"];32export interface FgConfig {33 palette: FgPalette;34 /** Icon foreground hue for `--foreground-ui`: a number (0–360) pins a hue; a harmonic name35 * ("complement" | "triad-1" | "split-2" | … — a color-wheel relationship rotated off --harmony-h,36 * tracked live); null → icons follow the theme/text color. Always contrast-solved (APCA/ARC). */37 iconHue: number | HarmonicName | null;38 /** Heading/large-text hue for `--foreground-soft` — same semantics as iconHue (number pins, a harmonic39 * name rotates off the theme live, null → follow the chosen palette ramp). */40 softHue: number | HarmonicName | null;41 /** Fine/small-text hue for `--foreground-strong` — same semantics (null → follow the palette ramp). */42 strongHue: number | HarmonicName | null;43}44/** The /colors ramp generator's base color + step count, shared with the foreground. */45export interface RampConfig {46 l: number;47 c: number;48 h: number;49 count: number;50}5152const FG_PALETTES: FgPalette[] = [53 "tonal",54 "lightness",55 "hue",56 "chroma",57];58const DEFAULT_FG: FgConfig = {59 palette: "lightness", // linear ramp — holds the theme's chroma, so high-contrast text reads as a soft tinted white, not gray60 iconHue: null,61 softHue: null,62 strongHue: null,63};64const DEFAULT_RAMP: RampConfig = {65 l: 60,66 c: 0.15,67 h: 255,68 count: 12, // finest ramp (12 steps/side) — the most cohesive foreground set in practice69};7071/** Normalize a stored hue choice: a harmonic relationship name, a pinned number, else null. */72const hueChoice = (v: unknown): number | HarmonicName | null =>73// … truncated
What it pulls in
Other registry items
Files it writes
More from weekendsuperhero-io/sistine
All 71 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | weekendsuperhero-io/sistine | Components | Unverified | 5 deps · 4 files | |
| Alertalert | weekendsuperhero-io/sistine | Components | Unverified | 3 deps · 4 files | |
| Alert Dialogalert-dialog | weekendsuperhero-io/sistine | Components | Unverified | 4 deps · 4 files | |
| Avataravatar | weekendsuperhero-io/sistine | Components | Unverified | 4 deps · 4 files | |
| Badgebadge | weekendsuperhero-io/sistine | Components | Unverified | 4 deps · 4 files | |
| Breadcrumbbreadcrumb | weekendsuperhero-io/sistine | Components | Unverified | 5 deps · 4 files | |
| Buttonbutton | weekendsuperhero-io/sistine | Components | Unverified | 4 deps · 4 files | |
| Button Groupbutton-group | weekendsuperhero-io/sistine | Components | Unverified | 4 deps · 4 files |
