1. Components
  2. principles

Principles

The decisions that keep JK-UI accessible, familiar, and easy to customize

JK-UI follows one central idea: provide a useful starting point without turning that starting point into a framework you have to fight.
Components are copied into your project, their styles are visible, and the default design language stays close to shadcn. You can adopt JK-UI progressively and change any layer when the product needs it.

Accessibility is structural

Interactive components are built with React Aria Components. Keyboard navigation, focus management, disabled states, selection behavior, labels, and ARIA relationships come from accessible primitives rather than being recreated with visual-only markup.
JK-UI styles React Aria states through Tailwind variants such as fx-selected, fx-open, and fx-invalid. Changing the appearance should not require replacing the accessible behavior.

Use familiar semantic tokens

Application code uses the standard shadcn vocabulary:
<main className="bg-background text-foreground">
  <section className="border border-border bg-card text-card-foreground" />
</main>
The public foundation includes tokens such as background, foreground, primary, muted, accent, destructive, border, input, and ring. JK-UI adds a small number of meaningful roles only where components need a real distinction, for example fg-title, bg-surface, and border-strong.
Aliases that only shorten an existing name are avoided. Use bg-background and text-foreground, not bg-bg and text-fg.

Keep palette values direct

Real light and dark values live directly in your main CSS file. The commonly used semantic colors receive direct values instead of carrying complete 50–950 scales that most applications never consume.
:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.22 0.01 260);
  --primary: oklch(0.52 0.14 215);
  --primary-foreground: oklch(1 0 0);
}
Gray keeps a complete scale because surfaces, dividers, borders, and text often need several neutral levels. Additional shades remain an application decision: add one when the interface actually uses it.

Separate appearance from meaning

variant describes the visual treatment. intent describes the semantic color.
<Button variant="solid" intent="primary">Save</Button>
<Button variant="soft" intent="destructive">Delete</Button>
<Badge variant="soft" intent="success">Published</Badge>
Consumers pass bare intent names such as primary or destructive. Combined names such as btn-solid-primary and ui-soft-success are internal CSS utilities, not component prop values.
The CSS keeps those responsibilities separate:
FileResponsibility
button.cssButton structure, sizes, and visual recipes
ui.cssShared UI recipes such as solid, soft, subtle, and outline
intents.cssColor variables for each supported variant/intent combination
A recipe consumes variables; it does not choose a palette:
@utility btn-solid {
  color: var(--btn-fg);
  background-color: var(--btn-color);
}

@utility btn-solid-primary {
  --btn-color: var(--color-primary);
  --btn-fg: var(--color-primary-foreground);
}
This keeps a new visual treatment independent from a new semantic color.

Ship useful defaults, not every combination

JK-UI intentionally does not expose every possible button intent. Its default button map covers the combinations most interfaces need:
VariantIncluded intents
solidprimary, secondary, accent, neutral, destructive
softprimary, destructive, warning, gray
ghostgray
outlinegray
Shared display components can use the broader UI intent set for badges, alerts, and status surfaces. Button combinations stay deliberately narrower because action hierarchy benefits from restraint.
If a product needs another combination, add its variable utility to intents.css and extend the component's TypeScript map. The defaults demonstrate the extension point without making every project carry every possibility.

Customize at the smallest useful layer

Choose the narrowest change that matches the requirement:
  1. Change semantic values in the main CSS file to recolor the whole product.
  2. Change the component variables in that same file to adjust a shared component decision.
  3. Change or add an intent in intents.css to support a color combination.
  4. Edit the copied component when its API or structure should differ.
  5. Use className for a one-off composition.
This is the practical meaning of being shadcn-friendly: sensible defaults, visible source code, familiar tokens, and no hidden theming system between the application and its CSS.