Skip to content

Semantic Colors

Raw token values like --color-primary-600 are implementation details. Semantic aliases give your components meaning-based names that survive theme switches.

The Pattern

Import a theme's tokens, then create semantic aliases in :root:

css
@import "@syncupsuite/themes/swiss-international/tokens.css";

:root {
  --app-background: var(--color-neutral-50);
  --app-text: var(--color-neutral-900);
  --app-text-muted: var(--color-neutral-600);
  --app-border: var(--color-neutral-200);
  --app-accent: var(--color-primary-600);
  --app-accent-hover: var(--color-primary-700);
  --app-success: var(--color-semantic-success);
  --app-warning: var(--color-semantic-warning);
  --app-error: var(--color-semantic-error);
}

Your components reference --app-accent, not --color-primary-600. When you switch from Swiss International to Art Deco, only the token import changes — your components stay the same.

With Tailwind v4

Register semantic aliases in the @theme block so Tailwind generates utility classes:

css
@import "tailwindcss";
@import "@syncupsuite/themes/swiss-international/tokens.css";

:root {
  --app-bg: var(--color-neutral-50);
  --app-fg: var(--color-neutral-900);
  --app-accent: var(--color-primary-600);
}

@theme {
  --color-app-bg: var(--app-bg);
  --color-app-fg: var(--app-fg);
  --color-app-accent: var(--app-accent);
}

Use in markup:

html
<div class="bg-app-bg text-app-fg">
  <a class="text-app-accent hover:underline">Link</a>
</div>

Theme Switching

Scope token imports to support multiple themes:

css
@import "@syncupsuite/themes/swiss-international/tokens.css";

[data-theme="nihon-traditional"] {
  @import "@syncupsuite/themes/nihon-traditional/tokens.css";
}

Or load dynamically:

ts
async function loadTheme(slug: string) {
  const link = document.createElement("link");
  link.rel = "stylesheet";
  link.href = `/@syncupsuite/themes/${slug}/tokens.css`;
  document.head.appendChild(link);
  document.documentElement.dataset.theme = slug;
}

Dark Mode

Tokens are theme-scoped, not mode-scoped. Create a second set of semantic aliases for dark mode:

css
@media (prefers-color-scheme: dark) {
  :root {
    --app-background: var(--color-neutral-900);
    --app-text: var(--color-neutral-50);
    --app-text-muted: var(--color-neutral-400);
    --app-border: var(--color-neutral-700);
  }
}

Platform Convention

SyncupSuite platform projects use the su-* namespace:

css
:root {
  --su-background: var(--color-neutral-50);
  --su-text-primary: var(--color-neutral-900);
  --su-text-secondary: var(--color-neutral-600);
  --su-border: var(--color-neutral-200);
  --su-accent: var(--color-primary-600);
}

The su-* prefix is reserved for SyncupSuite platform properties. Your project can use any namespace.

Released under the MIT License.