Components/Theming

Theming

Four override layers, from global tokens down to a single component.

Since 0.4.0BETA

This component doc is in progress

This page is still being migrated. Demos and API details may change.

The model

No component hard-codes a color; every visual reads a CSS custom property, so re-theming is a stylesheet change. The four layers run widest first. Pick the narrowest one that solves the problem.

LayerWhere it livesScope
Global tokens:root in base.cssEverything
Theme selectors[data-theme='dark'], [data-tx-contrast='high']A whole mode
BUI tokens--tx-bui-*The AI suite
Component hooks--tx-<component>-*One component, or one subtree

The token inventory is in Design Foundations.

Global tokens

Redefine tokens after importing base.css. Components resolve them at paint time, so an override applies to the whole subtree below it.

EXAMPLE.CSS
@import '@talex-touch/tuffex/base.css';

:root {
  --tx-color-primary: #7c5cff;
  --tx-border-radius-base: 8px;
  --tx-transition-duration: 0.24s;
}

--tx-color-primary-soft and --tx-coloring-border-color are color-mix() expressions on --tx-color-primary, so they follow it. The primary ramp (--tx-color-primary-light-*, --tx-color-primary-dark-2) is fixed hex, and the default focus ring reads from it; override the ramp too when rebranding.

Dark mode

Dark is a selector, not a media query: set data-theme="dark" or the dark class on any ancestor.

EXAMPLE.HTML
<html data-theme="dark">
<!-- or -->
<html class="dark">
  • The two are equivalent, so Tuffex drops into a Tailwind app (.dark) or a data-theme app without an adapter.
  • Set either on a subtree to get a dark island on a light page.

High contrast

A fourth palette that raises text and border contrast in light and dark.

TriggerEffect
html[data-tx-contrast='high'] or html.contrastOn, explicitly
@media (prefers-contrast: more)On, following the OS
html[data-tx-contrast='normal']Opts out of the media query

With data-theme="dark" and either high-contrast trigger, the dark high-contrast palette applies; the two themes don't stack.

AI suite tokens

--tx-bui-* came over with the Beautiful UI components (surface, inset, field, ink, and accent / green / orange / red with matching tints) and has its own dark block under the same [data-theme='dark'] / .dark selectors. Override it when AI surfaces shouldn't inherit your brand hue:

EXAMPLE.CSS
:root {
  --tx-bui-accent: #7c5cff;
  --tx-bui-accent-tint: #f0ecff;
}

Component hooks

--tx-<component>-* restyles one component without touching the global palette. Names are predictable (--tx-collapse-header-bg, --tx-avatar-ring-color, --tx-progress-height), and each has a fallback. They inherit, so setting them on a wrapper themes that subtree only.

EXAMPLE.VUE
<template>
  <section class="settings-panel">
    <TxCollapse v-model="open">
      <TxCollapseItem title="Appearance" name="appearance">…</TxCollapseItem>
    </TxCollapse>
  </section>
</template>

<style scoped>
.settings-panel {
  --tx-collapse-radius: 6px;
  --tx-collapse-header-bg: transparent;
  --tx-collapse-border: rgba(148, 163, 184, 0.24);
}
</style>

Each component page lists the hooks it reads. Use them instead of descendant selectors into component internals: custom properties are the supported surface, class names are not.

Caveats

  • When a component exposes a fill hook, set the token, not background-color: some fills are background-image gradients, and background-color paints behind them.
  • Import base.css exactly once. With two copies, the one that loads last wins, which is rarely the one you edited.

Technologies

  • Tokens and theme selectors: packages/tuffex/packages/components/style/variables.scss.
  • AI suite tokens: packages/tuffex/packages/components/style/bui-tokens.scss.
  • Runtime entry: @talex-touch/tuffex/base.css.