Skip to content

Design Systemy

Wprowadzenie

Lumos Islands ma dwa odseparowane design systemy — po jednym dla każdej aplikacji. Oba dzielą wspólne tokeny brand (kolory, typografia), ale mają niezależne komponenty dostosowane do swojego kontekstu (mobile vs web).

Wspólne Tokeny Brand

Kolory

TokenWartośćZastosowanie
brand-primary#6366F1 (Indigo 500)Główne akcje, linki, ikony
brand-secondary#8B5CF6 (Violet 500)Akcenty, wyróżnienia
brand-accent#F59E0B (Amber 500)XP, nagrody, odznaki
success#10B981 (Emerald 500)Ukończone, poprawne
warning#F59E0B (Amber 500)Ostrzeżenia, deadline
error#EF4444 (Red 500)Błędy, niepoprawne
surface#FFFFFF / #1F2937Tło kart (light/dark)
background#F9FAFB / #111827Tło strony (light/dark)

Typografia

TokenWartośćZastosowanie
font-displayNunitoNagłówki, tytuły
font-bodyInterTekst body, opisy
font-monoJetBrains MonoKod, dane techniczne

Spacing

Skala oparta na wielokrotnościach 4px:

TokenWartość
space-14px
space-28px
space-312px
space-416px
space-624px
space-832px
space-1248px
space-1664px

Border Radius

TokenWartośćZastosowanie
radius-sm4pxMałe elementy (badge, chip)
radius-md8pxPrzyciski, inputy
radius-lg12pxKarty
radius-xl16pxModale, panele
radius-full9999pxAwatary, kółka

Flutter App — Design System

Narzędzie: Widgetbook

Widgetbook to storybook dla Flutter — pozwala przeglądać, testować i dokumentować widgety w izolacji.

app/widgetbook/
└── lib/
    ├── main.dart                  # Entry point Widgetbook
    ├── components/
    │   ├── buttons.dart           # Warianty przycisków
    │   ├── cards.dart             # Karty zadań, lokacji
    │   ├── inputs.dart            # Pola formularzy
    │   ├── navigation.dart        # Bottom bar, app bar
    │   └── badges.dart            # Odznaki, XP badge
    └── tokens/
        ├── colors.dart            # Paleta kolorów
        ├── typography.dart        # Style tekstowe
        └── spacing.dart           # Spacing preview

Uruchomienie Widgetbook

bash
cd app
flutter run -t widgetbook/lib/main.dart

Tokeny w Dart

dart
class AppColors {
  static const primary = Color(0xFF6366F1);
  static const secondary = Color(0xFF8B5CF6);
  static const accent = Color(0xFFF59E0B);
  static const success = Color(0xFF10B981);
  static const warning = Color(0xFFF59E0B);
  static const error = Color(0xFFEF4444);
}

class AppTypography {
  static const displayLarge = TextStyle(
    fontFamily: 'Nunito',
    fontSize: 32,
    fontWeight: FontWeight.bold,
  );
  static const bodyMedium = TextStyle(
    fontFamily: 'Inter',
    fontSize: 14,
    fontWeight: FontWeight.normal,
  );
}

class AppSpacing {
  static const s1 = 4.0;
  static const s2 = 8.0;
  static const s3 = 12.0;
  static const s4 = 16.0;
  static const s6 = 24.0;
  static const s8 = 32.0;
}

Kluczowe Komponenty Flutter

KomponentOpisWarianty
LumosButtonPrzyciskprimary, secondary, outline, text
TaskCardKafel zadania (Netflix-style)video, quiz, audio, game, creative
LocationPinPin na mapielocked, unlocked, completed
XpBadgeBadge z XPsmall, large
AvatarWidgetAwatar dzieckaeditable, display
TodoItemElement todo listypending, done, overdue
NavBarDolna nawigacjaglobe, cosmos, spaceship, profile

Theming

dart
final lightTheme = ThemeData(
  colorScheme: ColorScheme.light(
    primary: AppColors.primary,
    secondary: AppColors.secondary,
    surface: Colors.white,
    background: Color(0xFFF9FAFB),
  ),
  fontFamily: 'Inter',
  textTheme: TextTheme(
    displayLarge: AppTypography.displayLarge,
    bodyMedium: AppTypography.bodyMedium,
  ),
);

final darkTheme = ThemeData(
  colorScheme: ColorScheme.dark(
    primary: AppColors.primary,
    secondary: AppColors.secondary,
    surface: Color(0xFF1F2937),
    background: Color(0xFF111827),
  ),
  fontFamily: 'Inter',
);

Manager-Content — Design System

Narzędzie: Dedykowana Strona Komponentów

Manager-content ma wbudowaną stronę /design-system dostępną w trybie development, prezentującą wszystkie komponenty UI.

Tokeny w TailwindCSS

js
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          primary: '#6366F1',
          secondary: '#8B5CF6',
          accent: '#F59E0B',
        },
        success: '#10B981',
        warning: '#F59E0B',
        error: '#EF4444',
      },
      fontFamily: {
        display: ['Nunito', 'sans-serif'],
        body: ['Inter', 'sans-serif'],
        mono: ['JetBrains Mono', 'monospace'],
      },
      borderRadius: {
        sm: '4px',
        md: '8px',
        lg: '12px',
        xl: '16px',
      },
    },
  },
}

Komponenty Go Templates

Komponenty UI jako szablony Go, wywoływane przez :

html
<!-- components/button.html -->
{{ define "button" }}
<button
  class="inline-flex items-center px-4 py-2 rounded-md font-medium
         bg-brand-primary text-white hover:bg-indigo-600
         transition-colors duration-150"
  {{ if .HxGet }}hx-get="{{ .HxGet }}"{{ end }}
  {{ if .HxTarget }}hx-target="{{ .HxTarget }}"{{ end }}
>
  {{ .Label }}
</button>
{{ end }}
html
<!-- components/card.html -->
{{ define "card" }}
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
  {{ if .Title }}
  <h3 class="text-lg font-display font-semibold text-gray-900 mb-2">
    {{ .Title }}
  </h3>
  {{ end }}
  <div class="text-gray-600 font-body">
    {{ .Content }}
  </div>
</div>
{{ end }}

Kluczowe Komponenty Manager-Content

KomponentOpisPlik
buttonPrzycisk (primary, secondary, danger)button.html
cardKarta z tytułem i treściącard.html
modalOkno modalne (Alpine.js)modal.html
form-fieldPole formularza z labelem i błędemform-field.html
task-cardKafel zadania z miniaturątask-card.html
todo-itemElement todo listytodo-item.html
stat-cardKarta statystyki (dashboard)stat-card.html
dropdownMenu rozwijane (Alpine.js)dropdown.html

Interaktywność HTMX

html
<!-- Dynamiczna lista zadań -->
<div id="task-list"
     hx-get="/content/tasks"
     hx-trigger="load"
     hx-swap="innerHTML">
  <p>Ładowanie zadań...</p>
</div>

<!-- Usuwanie zadania z animacją -->
<div id="task-{{ .ID }}" class="task-card">
  <button hx-delete="/content/tasks/{{ .ID }}"
          hx-target="#task-{{ .ID }}"
          hx-swap="outerHTML swap:0.3s"
          hx-confirm="Usunąć to zadanie?">
    Usuń
  </button>
</div>

Zasady Projektowe

1. Spójność wizualna

Obie aplikacje wyglądają jak część tego samego ekosystemu dzięki wspólnym tokenom brand (kolory, fonty, spacing).

2. Kontekst użycia

  • Flutter App — mobile-first, dotykowy UI, animacje, duże hittable areas
  • Manager-Content — desktop-first, formularze, tabele, gęstszy layout

3. Dostępność

  • Kontrast kolorów zgodny z WCAG AA
  • Focus states na wszystkich interaktywnych elementach
  • Semantyczny HTML w manager-content
  • Semantyczne widgety w Flutter (Semantics widget)

4. Dark Mode

Obie aplikacje wspierają dark mode:

  • Flutter: ThemeData light/dark z automatycznym przełączaniem
  • Manager-content: TailwindCSS dark: variant + prefers-color-scheme

5. Responsive

  • Flutter: adaptacyjne layouty (phone, tablet)
  • Manager-content: responsive breakpoints TailwindCSS (sm, md, lg, xl)

Lumos Islands v2 - Dokumentacja Projektowa