Base

base — foundation tokens, mixins & JS utilities

The fundament for every other CzG UI component. Provides design tokens ($cgui-* variables), responsive/utility SCSS mixins, JS helpers, and keyframe animations. Every other component depends on base — install it first.

The naming convention is strict: every variable, mixin, and JS export is prefixed cgui- / $cgui- / cgui so dropping base into an existing project does not collide with your own $color__*, $small, $radius or other legacy names. Override values are exposed via !default flags.

Files

FileContents
_variables.scsscolors, spacing, typography, layout, radii, shadows, transitions, breakpoints, z-index
_mixins.scss15 reusable mixins (media, hover, focus, truncate, ...)
_animations.scssopt-in @keyframes (fade, slide, spin, ...)
_functions.scsssmall SCSS helpers used internally
utils.js$, $$, on, debounce, clamp
outside-click.jsonOutsideClick, offOutsideClick

Install

npx czg-ui add base

In resources/sass/app.scss — order matters, variables first:

@import 'components/base/variables';
@import 'components/base/mixins';
@import 'components/base/animations';   // optional, only if you use keyframes

// AFTER base imports → other components
@import 'components/button';
@import 'components/slider';

JS — only the helpers you need:

import { $, $$, debounce } from './components/base/utils.js';
import { onOutsideClick } from './components/base/outside-click.js';

Customization — override tokens

Every $cgui-* is declared with !default, so override before @import 'components/base/variables':

// resources/sass/app.scss
$cgui-color-primary: #FF6B00;     // brand orange instead of default blue
$cgui-color-brand:   #FF6B00;
$cgui-radius:        2px;          // sharp corners
$cgui-content:       1200px;       // narrower max-width

@import 'components/base/variables';
@import 'components/base/mixins';

Most-overridden tokens

TokenDefault (light)Default (dark)What it controls
$cgui-color-primary#003CFF#5577FFBrand color (buttons, links)
$cgui-color-brand#003CFF#5577FFSame role as primary; usually identical
$cgui-color-secondary#000000#94A3B8Secondary actions
$cgui-radius6pxDefault border-radius for buttons / inputs / cards
$cgui-font-family-basesystem stackBody font
$cgui-content1400pxMax content width (.container)
$cgui-space-base8pxBase unit for the $cgui-space-N scale

Dark mode

base ships with a complete dark theme — flip a single flag before @import:

$cgui-dark-mode: true;

@import 'components/base/variables';
@import 'components/base/mixins';

Every color token then resolves to the dark-friendly value. The registry preview uses this to render every component in both themes, so you can visually compare before integrating.

For an opt-in via prefers-color-scheme, do not use $cgui-dark-mode — the flag is compile-time only. Instead, swap CSS custom properties at runtime, or compile two stylesheets.

Token reference

Colors

// Brand
$cgui-color-primary       $cgui-color-brand        $cgui-color-secondary
$cgui-color-commerce      $cgui-color-discount     $cgui-color-yellow
$cgui-color-red           $cgui-color-green        $cgui-color-blue
$cgui-color-access

// Text
$cgui-color-text          $cgui-color-text-muted   $cgui-color-text-gray
$cgui-color-text-dark     $cgui-color-text-light

// Backgrounds
$cgui-color-bg            $cgui-color-bg-light     $cgui-color-bg-gray
$cgui-color-bg-gray-light $cgui-color-bg-gray-dark $cgui-color-bg-form
$cgui-color-bg-selected   $cgui-color-bg-hover     $cgui-color-bg-dark

// Borders + status
$cgui-color-border        $cgui-color-border-light
$cgui-color-error         $cgui-color-success      $cgui-color-warning

Spacing scale (multiples of $cgui-space-base = 8px)

$cgui-space-0   // 0
$cgui-space-1   // 4
$cgui-space-2   // 8
$cgui-space-3   // 12
$cgui-space-4   // 16
$cgui-space-5   // 24
$cgui-space-6   // 32
$cgui-space-7   // 48
$cgui-space-8   // 64
$cgui-space-9   // 96

Typography

$cgui-font-family-base, -heading, -mono
$cgui-font-size-xs / sm / md / lg / xl / xxl    // 12, 14, 16, 18, 24, 32
$cgui-font-weight-regular / medium / bold        // 400, 500, 700
$cgui-line-height-tight / small / normal / loose // 1.2 / 1.35 / 1.5 / 1.75

Layout & radii

$cgui-content          // 1400  (max-width pro container)
$cgui-content-medium   // 970
$cgui-content-small    // 768
$cgui-content-padding  // 16

$cgui-radius-sm        // 3
$cgui-radius           // 6
$cgui-radius-lg        // 12
$cgui-radius-pill      // 999
$cgui-border-width     // 1

Shadows + transitions

$cgui-shadow-sm / -main / -lg

$cgui-ease         // all 0.15s ease
$cgui-ease-in      // all 0.2s  ease-in
$cgui-ease-out     // all 0.2s  ease-out
$cgui-ease-in-out  // all 0.25s ease-in-out

Breakpoints

$cgui-bp-min     // 320
$cgui-bp-tiny    // 480
$cgui-bp-small   // 640
$cgui-bp-medium  // 960
$cgui-bp-large   // 1280
$cgui-bp-xlarge  // 1700
$cgui-bp-max     // 1920

Z-index layers

$cgui-z-base      //    1
$cgui-z-dropdown  //  100
$cgui-z-sticky    //  500
$cgui-z-overlay   //  900
$cgui-z-modal     // 1000
$cgui-z-toast     // 2000
$cgui-z-tooltip   // 3000

Mixin reference

cgui-media($breakpoint, $direction: up)

Responsive media query. $breakpoint accepts a name (tiny, small, medium, large, xlarge, max) or any custom px value. $direction: up (default, min-width), down (max-width), only (within a 320px window).

.btn {
    padding: 8px 16px;

    @include cgui-media(medium) {        // ≥ 960px
        padding: 12px 24px;
    }

    @include cgui-media(900px, down) {   // ≤ 899px (custom)
        width: 100%;
    }
}

cgui-hover()

Wraps :hover and :focus-visible in @media (hover: hover) so it does not fire on touch devices (avoids the iOS "stuck hover" bug after tap).

.btn {
    background: $cgui-color-primary;

    @include cgui-hover() {
        background: $cgui-color-brand;
    }
}

cgui-focus-visible($color: $cgui-color-primary, $offset: 2px)

Removes the default outline on :focus but restores a visible 2px outline on :focus-visible (keyboard-only).

a       { @include cgui-focus-visible(); }
.btn    { @include cgui-focus-visible(#f00, 4px); }

cgui-visually-hidden()

Hides an element visually while keeping it for screen readers (sr-only).

.skip-link { @include cgui-visually-hidden(); }

cgui-truncate($lines: 1)

Single-line ellipsis or multi-line -webkit-line-clamp.

.product__title       { @include cgui-truncate(); }     // 1 line
.product__description { @include cgui-truncate(3); }    // 3 lines

cgui-pseudo($display: block, $position: absolute, $cgui-content: '')

Boilerplate for ::before / ::after.

.tag::before {
    @include cgui-pseudo();
    inset: 0;
    background: rgba(0,0,0,0.5);
}

cgui-container($max-width: $cgui-content, $padding: $cgui-content-padding)

Centered max-width container with horizontal padding.

.section__inner { @include cgui-container(); }
.narrow         { @include cgui-container(800px); }

Other mixins

MixinUse
cgui-reset-list()Strip <ul> margin/padding/bullets
cgui-reset-button()Strip native <button> styles
cgui-aspect-ratio($w, $h)Wrapper around aspect-ratio property
cgui-scrollbar-thin($thumb, $track)Slim styled scrollbar (Firefox + WebKit)
cgui-stretched-link()Whole-card clickable area via absolute pseudo
`cgui-center-absolute($axis: both \x \y)`Center an absolute element
cgui-surface($padding, $radius, $shadow)Card surface (bg + border + shadow + padding)

JS — utils.js

Five micro-utilities, no dependencies. Tree-shakable.

import { $, $$, on, debounce, clamp } from './components/base/utils.js';

// $(selector, root?)         — querySelector with optional root
const dropdown = $('.dropdown');

// $$(selector, root?)        — querySelectorAll → Array
const tabs = $$('.tab');

// on(el, event, handler, opts?) — addEventListener; returns unsubscribe
const off = on(window, 'scroll', () => console.log('scrolled'));
off();   // remove later

// debounce(fn, wait = 100)   — coalesce burst calls
window.addEventListener('resize', debounce(onResize, 200));

// clamp(n, min, max)         — restrict number to range
clamp(150, 0, 100);   // → 100

JS — outside-click.js

Closes popovers / dropdowns / modals when the user clicks outside the component. Used by dropdown, modal, popover.

import { onOutsideClick, offOutsideClick } from './components/base/outside-click.js';

const dropdown = document.querySelector('.dropdown');

const off = onOutsideClick(dropdown, () => {
    dropdown.classList.remove('is-open');
});

// Manually unsubscribe:
off();
// or by element reference:
offOutsideClick(dropdown);

The listener is registered on the next animation frame to avoid catching the same click that opened the component.

Animations (opt-in)

_animations.scss defines @keyframes only — no rules of its own. Import adds a few hundred bytes; skip it if you do not use any.

@import 'components/base/animations';

.toast { animation: cgui-fade-in 0.2s ease; }
.spinner { animation: cgui-spin 1s linear infinite; }

When NOT to use

  • Tiny project, no other CzG components — copy the 1-2 utilities you

need manually instead of pulling the whole foundation

  • You already have an established design system (Tailwind config,

custom token set) — adopting base would force a parallel system and cost more than it saves

Compatibility note

Earlier base versions shipped legacy aliases ($color__primary, $small, $radius...) for drop-in to old projects. The current version no longer ships them — every component uses $cgui-* exclusively. If you migrate from an old base, search-replace $color__$cgui-color-, $small$cgui-bp-small, etc.

Live preview

ui.czechgroup.cz/component/base — full source files, override examples, dark mode toggle.

Další kategorie