RepUI Workbench

Доступные темы

Карточки строятся из manifest и используют presentation metadata темы.

RepUI Core

Default

Официальная тема RepUI с графитовыми поверхностями, нефритовыми взаимодействиями и голубым фокусом.

Mineral Laboratory

Тёплая лабораторная тема с минеральными поверхностями, ирисовыми акцентами и бирюзовым фокусом.

Ocean Deep

Спокойная глубоководная тема с графитово-синими поверхностями, биолюминесцентным фокусом и сдержанными бирюзовыми акцентами.

Theme authoring Folder-based

Как создать новую тему RepUI

Полноценная тема RepUI добавляется отдельной папкой и меняет только токены. Компоненты, layout и runtime при этом остаются общими для всех тем.

Главный принцип Тема определяет визуальный язык через semantic и component tokens, но не переписывает DOM, layout или поведение компонентов.

1. Архитектура темы

Цепочка наследования должна быть одинаковой для каждого компонента.

Raw palette
    ↓
Semantic theme tokens
    ↓
Component token contract
    ↓
Optional theme component overrides
    ↓
Component CSS properties

Например, фон Card проходит путь --rui-core-slate-0--rui-color-surface--rui-card-backgroundbackground .

2. Создайте папку темы

Для примера создадим тему Ocean Studio.

repui/
├── themes/
│   └── ocean/
│       ├── __init__.py
│       └── manifest.py
└── static/repui/theme/ocean/
    ├── palette.css
    ├── light.css
    ├── dark.css
    └── components/
        ├── card.css
        ├── button.css
        └── tooltip.css

Папка components необязательна. Создавайте override-файл только тогда, когда semantic tokens недостаточно.

3. Опишите manifest

Manifest сообщает registry имя темы и список её assets.

THEME = {
    "name": "ocean",
    "title": "Ocean Studio",
    "description": (
        "Calm product theme with deep blue surfaces "
        "and cyan interaction accents."
    ),
    "schemes": ("light", "dark"),
    "styles": (
        "repui/theme/ocean/palette.css",
        "repui/theme/ocean/light.css",
        "repui/theme/ocean/dark.css",
    ),
    "component_styles": {
        "card": (
            "repui/theme/ocean/components/card.css",
        ),
        "button": (
            "repui/theme/ocean/components/button.css",
        ),
        "tooltip": (
            "repui/theme/ocean/components/tooltip.css",
        ),
    },
}
Стабильный идентификатор Значение name используется в settings, template tags, localStorage и data-rui-theme . После публикации его нельзя переименовывать без миграции.

4. Создайте raw palette

Palette содержит только физические цвета. Компоненты её напрямую не используют.

@layer repui.theme {
  [data-rui-theme="ocean"] {
    --rui-ocean-slate-0: oklch(99% 0.005 240);
    --rui-ocean-slate-5: oklch(67% 0.028 240);
    --rui-ocean-slate-9: oklch(19% 0.028 240);

    --rui-ocean-blue-2: oklch(89% 0.055 245);
    --rui-ocean-blue-5: oklch(56% 0.18 245);
    --rui-ocean-blue-7: oklch(42% 0.15 245);

    --rui-ocean-cyan-2: oklch(90% 0.06 195);
    --rui-ocean-cyan-5: oklch(65% 0.13 195);
  }
}

Используйте namespace темы, чтобы raw tokens разных палитр не пересекались.

5. Определите light и dark

Обе схемы реализуют один и тот же semantic contract.

@layer repui.theme {
  [data-rui-theme="ocean"][data-rui-color-scheme="light"] {
    color-scheme: light;

    --rui-color-page: oklch(97% 0.008 240);
    --rui-color-surface: var(--rui-ocean-slate-0);
    --rui-color-surface-raised: white;
    --rui-color-surface-sunken: oklch(94% 0.012 240);

    --rui-color-text: var(--rui-ocean-slate-9);
    --rui-color-text-secondary: oklch(39% 0.032 240);
    --rui-color-text-muted: var(--rui-ocean-slate-5);

    --rui-color-border-subtle: oklch(90% 0.014 240);
    --rui-color-border: oklch(82% 0.022 240);
    --rui-color-border-strong: oklch(65% 0.03 240);

    --rui-color-primary: var(--rui-ocean-blue-5);
    --rui-color-primary-hover: var(--rui-ocean-blue-7);
    --rui-color-primary-soft: var(--rui-ocean-blue-2);
    --rui-color-on-primary: white;

    --rui-color-focus: var(--rui-ocean-cyan-5);
    --rui-color-focus-outer: oklch(70% 0.11 195 / 30%);
  }
}

6. Добавляйте component overrides точечно

Override должен менять component tokens, а не CSS-геометрию компонента.

Правильно
@layer repui.theme {
  [data-rui-theme="ocean"] {
    --rui-card-background:
      var(--rui-color-surface);
    --rui-card-border-color:
      var(--rui-color-border-subtle);
    --rui-card-shadow:
      var(--rui-shadow-xs);
  }
}

7. Подключите тему

Глобально через settings

REPUI = {
    "THEME": "ocean",
}

Явно в шаблоне

{% repui_css card button select theme="ocean" %}

На корневом элементе

<html
  data-rui-theme="ocean"
  data-rui-theme-mode="system"
  data-rui-color-scheme="light"
>

8. Проверьте overlays и portal

Глобальная тема наследуется через document root. Локальная тема требует переноса theme context.

Select
Menu
Tooltip
Popover
Dialog
Autocomplete
Combobox

Для scoped preview OverlayPortal должен определить ближайшие data-rui-theme и data-rui-color-scheme , затем применить их к portal wrapper.

Для глобальной темы дополнительный код не нужен Если атрибуты темы находятся на html , overlay в body продолжит наследовать токены.

9. Проведите визуальный аудит

Проверьте Page, Card, Panel, Typography, InlineCode и Divider в обеих схемах.

10. Добавьте автоматические проверки

def test_theme_manifest_assets_exist():
    theme = get_theme("ocean")

    for asset in theme["styles"]:
        assert static_asset_exists(asset)


def test_theme_declares_both_schemes():
    theme = get_theme("ocean")
    assert set(theme["schemes"]) == {"light", "dark"}


def test_component_overrides_reference_known_components():
    theme = get_theme("ocean")

    for component_name in theme["component_styles"]:
        assert get_component_manifest(component_name)


def test_theme_css_uses_repui_theme_layer():
    for source in theme_css_sources("ocean"):
        assert "@layer repui.theme" in source
        assert "[data-theme=" not in source

Готовность темы

Обязательный контракт

page surface text border primary success warning danger focus inverse surface

Запрещено теме

Менять DOM компонентов

Дублировать runtime

Переопределять display и position

Использовать raw color в component CSS

Смешивать primary и success

Использовать неправильный theme selector

Команда проверки

python manage.py test repui workbench