After a custom installation

Theming

Customize the kit’s visual identity without breaking its semantic contract. Tokens control the global theme; Tailwind sources are for structural component changes.

Review custom installation

1. Workflow

Identify the right customization level

tokens.css

Global identity

Colors, typography, radius, shadows, overlays, and scrollbars.

input.css

Components

Dimensions, spacing, density, animations, and .ui-* styles.

tailwind.config.js

Tailwind scale

New utilities, breakpoints, spacing, and theme extensions.

Source of truth: Never edit public/app.css. This file is replaced on every build.
Build loop Bash
# Développement : recompilation continue
npm run dev:css

# Production : CSS minifié
npm run build:css

2. Colors

Change semantic roles

Components use roles such as primary, muted, or destructive, never a hard-coded business color. Keep this principle when changing the palette.

Primary

Secondary

Success

Warning

Danger

Info

Muted

Accent

  • Write colors in HSL without commas or the hsl() function.
  • Always define the role / role-foreground pair.
  • Check light and dark theme contrast separately.
Complete light palette Css
/* assets/css/tokens.css */
:root {
  --background: 42 33% 98%;
  --foreground: 222 47% 11%;
  --card: 0 0% 100%;
  --card-foreground: 222 47% 11%;
  --popover: 0 0% 100%;
  --popover-foreground: 222 47% 11%;

  --primary: 198 89% 32%;
  --primary-foreground: 0 0% 100%;
  --secondary: 198 28% 92%;
  --secondary-foreground: 198 89% 20%;
  --muted: 42 20% 93%;
  --muted-foreground: 220 9% 38%;
  --accent: 198 35% 90%;
  --accent-foreground: 198 89% 20%;

  --destructive: 0 72% 42%;
  --destructive-foreground: 0 0% 100%;
  --success: 142 72% 27%;
  --success-foreground: 0 0% 100%;
  --warning: 38 92% 50%;
  --warning-foreground: 26 83% 14%;
  --info: 217 78% 42%;
  --info-foreground: 0 0% 100%;

  --border: 38 18% 82%;
  --input: 38 18% 82%;
  --ring: 198 89% 32%;
}

3. Typography

Choose and load font families

Public --ui-font-* variables separate the physical loading of fonts from their application in the kit.

Typography tokens Css
/* assets/css/tokens.css */
:root {
  --ui-font-sans: "Public Sans", ui-sans-serif, system-ui, sans-serif;
  --ui-font-mono: "JetBrains Mono", ui-monospace, monospace;
  --ui-font-body: var(--ui-font-sans);
  --ui-font-heading: "Manrope", var(--ui-font-sans);
}

Self-hosted example Css
/* public/fonts/ui-fonts.css */
@font-face {
  font-family: "Public Sans";
  src: url("/fonts/public-sans/PublicSans-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --ui-font-sans: "Public Sans", ui-sans-serif, system-ui, sans-serif;
}

Then load /fonts/ui-fonts.css in the layout, before or after /app.css. Use WOFF2 and font-display: swap.

4. Radius and shadows

Radius and shadows

The --radius token feeds the rounded-lg, rounded-md, and rounded-sm Tailwind variants. The four shadows feed shadow-* classes.

rounded-sm
rounded-md
rounded-lg
Shape tokens Css
/* assets/css/tokens.css */
:root {
  --radius: 0.875rem;
  --shadow-sm: 0 1px 2px rgb(15 23 42 / 0.06);
  --shadow: 0 2px 6px rgb(15 23 42 / 0.10);
  --shadow-md: 0 8px 20px rgb(15 23 42 / 0.12);
  --shadow-lg: 0 18px 40px rgb(15 23 42 / 0.16);
}

5. Components

Adjust density and internal styles

For a targeted change, override canonical .ui-* classes in an @layer components block placed after the kit definitions.

Targeted overrides Css
/* À la fin de assets/css/input.css */
@layer components {
  .ui-btn-md {
    @apply h-10 px-5;
  }

  .ui-card {
    @apply shadow-md;
  }

  .ui-table-compact .ui-td {
    @apply px-3 py-2;
  }
}

Prefer the component’s public parameters first. A CSS override should only change its global appearance, not bypass its API.

6. Tailwind

Extend utilities

Always start from the exported file and add extensions without replacing colors, borderRadius, fontFamily, and boxShadow mappings. Keep content paths too: without them, Tailwind can remove classes used in EJS partials or JavaScript modules from the build.

tailwind.config.js Js
// tailwind.config.js
export default {
  darkMode: 'class',
  content: [
    './src/views/**/*.ejs',
    './public/ui/**/*.js',
    './assets/css/**/*.css',
  ],
  theme: {
    extend: {
      // Conservez ici colors, borderRadius, fontFamily et boxShadow du kit.
      spacing: {
        18: '4.5rem',
      },
      screens: {
        '3xl': '1920px',
      },
    },
  },
};

7. Dark mode

Define a dedicated palette

Dark mode is enabled by the dark class on html. Do not derive the entire dark palette automatically from the light palette: control every surface and foreground.

Dark palette Css
/* assets/css/tokens.css */
.dark {
  --background: 222 47% 7%;
  --foreground: 210 40% 98%;
  --card: 222 47% 9%;
  --card-foreground: 210 40% 98%;
  --popover: 222 47% 10%;
  --popover-foreground: 210 40% 98%;

  --primary: 196 94% 67%;
  --primary-foreground: 222 47% 7%;
  --secondary: 217 33% 17%;
  --secondary-foreground: 210 40% 98%;
  --muted: 217 33% 17%;
  --muted-foreground: 215 20% 68%;
  --accent: 217 33% 20%;
  --accent-foreground: 210 40% 98%;

  --border: 217 33% 20%;
  --input: 217 33% 20%;
  --ring: 196 94% 67%;
}

Prevent theme flash Html
<!-- Dans <head>, avant le rendu de la page -->
<script>
  (function () {
    const stored = localStorage.getItem('ui-theme');
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    if (stored === 'dark' || (!stored && prefersDark)) {
      document.documentElement.classList.add('dark');
    }
  })();
</script>

8. Build and review

Build and review the theme

Production build Bash
npm run build:css

Visual checklist

  • • text and controls have sufficient contrast in light and dark modes
  • • focus is visible with the ring color
  • • success, warning, danger, and info states are legible
  • • borders are visible on cards, tables, and fields
  • • popovers and modals are distinct from the background
  • • fonts load without significant layout shift
  • • components are tested at main breakpoints
  • • no manual change in public/app.css