diff --git a/AGENTS.md b/AGENTS.md index 5f5632b9..36387bc2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -135,6 +135,23 @@ Some complex components may also contain `components/`, `utils.ts`, `intl.ts` or - Only use CSS features supported by the project's [browserslist](package.json) targets. - Mostly plain CSS. Mixins are used for typography and text ellipsis (`packages/components/src/styles/mixins.css`). +### Component CSS Variables + +Private `---*` variables define defaults. +Public `--kbq--*` variables are override points. + +```css +/* Flag.module.css */ +.base { + --flag-border-radius: 0; + + border-radius: var(--kbq-flag-border-radius, var(--flag-border-radius)); +} +``` + +- Never define public variables in component CSS. +- Public variables inherit, allowing parents to style nested components. + ### Prop System - Prefer standard ARIA attributes and existing prop names to keep component APIs consistent and familiar. diff --git a/packages/components/src/components/Flag/Flag.mdx b/packages/components/src/components/Flag/Flag.mdx index 4d7a4220..63cafd62 100644 --- a/packages/components/src/components/Flag/Flag.mdx +++ b/packages/components/src/components/Flag/Flag.mdx @@ -121,10 +121,10 @@ and add a shadow/gradient in your own styles. Everything visual that isn't a discrete state is an overridable CSS variable: -| Variable | Default | Purpose | -| ----------------------------- | --------------------------------------- | ----------------------------------------------------- | -| `--kbq-flag-size` | `1em` | Flag height (also settable via the `size` prop). | -| `--kbq-flag-aspect-ratio` | `3 / 2` | Box ratio (also settable via the `aspectRatio` prop). | -| `--kbq-flag-border-radius` | `0` | Corner radius (rounded / stylized look). | -| `--kbq-flag-shadow-color` | `var(--kbq-line-contrast-fade)` | Inset hairline color; theme-adaptive. | -| `--kbq-flag-empty-background` | `var(--kbq-states-background-disabled)` | Placeholder fill. | +| Variable | Purpose | +| ----------------------------- | ----------------------------------------------------- | +| `--kbq-flag-size` | Flag height (also settable via the `size` prop). | +| `--kbq-flag-aspect-ratio` | Box ratio (also settable via the `aspectRatio` prop). | +| `--kbq-flag-border-radius` | Corner radius (rounded / stylized look). | +| `--kbq-flag-shadow-color` | Inset hairline color; theme-adaptive. | +| `--kbq-flag-empty-background` | Placeholder fill. | diff --git a/packages/components/src/components/Flag/Flag.module.css b/packages/components/src/components/Flag/Flag.module.css index 5663403e..dbfd2c9d 100644 --- a/packages/components/src/components/Flag/Flag.module.css +++ b/packages/components/src/components/Flag/Flag.module.css @@ -1,17 +1,17 @@ .base { - /* Public, overridable knobs (see the component docs). */ - --kbq-flag-aspect-ratio: 3 / 2; - --kbq-flag-border-radius: 0; - --kbq-flag-shadow-color: var(--kbq-line-contrast-fade); - --kbq-flag-empty-background: var(--kbq-states-background-disabled); + --flag-size: 1em; + --flag-aspect-ratio: 3 / 2; + --flag-border-radius: 0; + --flag-shadow-color: var(--kbq-line-contrast-fade); + --flag-empty-background: var(--kbq-states-background-disabled); display: inline-block; position: relative; overflow: hidden; vertical-align: middle; - block-size: var(--kbq-flag-size, 1em); - aspect-ratio: var(--kbq-flag-aspect-ratio); - border-radius: var(--kbq-flag-border-radius); + block-size: var(--kbq-flag-size, var(--flag-size)); + aspect-ratio: var(--kbq-flag-aspect-ratio, var(--flag-aspect-ratio)); + border-radius: var(--kbq-flag-border-radius, var(--flag-border-radius)); } /* The projected flag graphic fills the box (descendant selector supports wrapped graphics). */ @@ -28,7 +28,7 @@ position: absolute; inset: 0; border-radius: inherit; - border: 1px solid var(--kbq-flag-shadow-color); + border: 1px solid var(--kbq-flag-shadow-color, var(--flag-shadow-color)); pointer-events: none; } @@ -43,5 +43,8 @@ /* No projected graphic → neutral placeholder (e.g. unknown/invalid country). */ .base:empty { - background-color: var(--kbq-flag-empty-background); + background-color: var( + --kbq-flag-empty-background, + var(--flag-empty-background) + ); } diff --git a/packages/components/src/components/Sidebar/Sidebar.mdx b/packages/components/src/components/Sidebar/Sidebar.mdx index 244df0cf..60f881c1 100644 --- a/packages/components/src/components/Sidebar/Sidebar.mdx +++ b/packages/components/src/components/Sidebar/Sidebar.mdx @@ -90,9 +90,11 @@ A Sidebar has no ARIA role by default: ## CSS variables -| Variable | Default | Purpose | -| ------------------------------ | ------- | ---------------------------------------------------------- | -| `--kbq-sidebar-size` | `240px` | Inline size while open (also settable via `size`). | -| `--kbq-sidebar-closed-size` | `32px` | Inline size while closed (also settable via `closedSize`). | -| `--kbq-sidebar-open-duration` | `200ms` | Duration of the expand animation. | -| `--kbq-sidebar-close-duration` | `100ms` | Duration of the collapse animation. | +These optional variables override the component's internal values. + +| Variable | Purpose | +| ------------------------------ | ---------------------------------------------------------- | +| `--kbq-sidebar-size` | Inline size while open (also settable via `size`). | +| `--kbq-sidebar-closed-size` | Inline size while closed (also settable via `closedSize`). | +| `--kbq-sidebar-open-duration` | Duration of the expand animation. | +| `--kbq-sidebar-close-duration` | Duration of the collapse animation. | diff --git a/packages/components/src/components/Sidebar/Sidebar.module.css b/packages/components/src/components/Sidebar/Sidebar.module.css index 73f5f7b1..56f777fc 100644 --- a/packages/components/src/components/Sidebar/Sidebar.module.css +++ b/packages/components/src/components/Sidebar/Sidebar.module.css @@ -1,8 +1,8 @@ .base { - --kbq-sidebar-size: 240px; - --kbq-sidebar-closed-size: 32px; - --kbq-sidebar-open-duration: 200ms; - --kbq-sidebar-close-duration: 100ms; + --sidebar-size: 240px; + --sidebar-closed-size: 32px; + --sidebar-open-duration: 200ms; + --sidebar-close-duration: 100ms; display: flex; overflow: hidden; @@ -10,7 +10,10 @@ block-size: 100%; interpolate-size: allow-keywords; /* Kept for future intrinsic-size transition support. */ transition: inline-size var(--kbq-transition-slow); - transition-duration: var(--kbq-sidebar-close-duration); + transition-duration: var( + --kbq-sidebar-close-duration, + var(--sidebar-close-duration) + ); } .base[data-placement='end'] { @@ -19,15 +22,18 @@ /* animation */ .base[data-transition='entering'] { - transition-duration: var(--kbq-sidebar-open-duration); + transition-duration: var( + --kbq-sidebar-open-duration, + var(--sidebar-open-duration) + ); } .base[data-transition='entering'], .base[data-transition='entered'] { - inline-size: var(--kbq-sidebar-size); + inline-size: var(--kbq-sidebar-size, var(--sidebar-size)); } .base[data-transition='exiting'], .base[data-transition='exited'] { - inline-size: var(--kbq-sidebar-closed-size); + inline-size: var(--kbq-sidebar-closed-size, var(--sidebar-closed-size)); }