Manager — Apple-Style Design
Filozofia projektowania
Manager-Content stosuje filozofie projektowania inspirowana Apple Human Interface Guidelines:
- Czystosc — brak zbednych elementow, kazdy piksel ma swoje uzasadnienie
- Minimalizm — ograniczona paleta kolorow, subtelne cienie zamiast ciezkich ramek
- Fokus na tresci — interfejs schodzi na drugi plan, tresc jest bohaterem
- Przestrzen — generyczny whitespace daje elementom "oddech"
- Konsystencja — te same wzorce powtarzaja sie w calym interfejsie
Whitespace
Generyczny padding i marginesy tworza wrazenie przestronnosci:
| Element | Padding / Margin |
|---|---|
| Strona (main) | px-6 py-8 |
| Karta | p-6 lub p-8 |
| Tabela (komorki) | px-6 py-4 |
| Sekcje miedzy soba | space-y-6 lub space-y-8 |
| Sidebar | px-4 py-6 |
| Formularz (pola) | space-y-5 |
Zasada: Jesli nie wiesz ile dac przestrzeni — daj wiecej.
Typografia
Dwie rodziny fontow tworzace hierarchie wizualna:
| Rola | Font | Klasa CSS | Wagi |
|---|---|---|---|
| Naglowki | Nunito | font-display | 600, 700 |
| Body / UI | Inter | font-sans | 400, 500, 600 |
Konfiguracja Tailwind
js
// tailwind.config.js
module.exports = {
theme: {
fontFamily: {
display: ['Nunito', 'system-ui', 'sans-serif'],
sans: ['Inter', 'system-ui', 'sans-serif'],
},
},
}Skala typograficzna
| Element | Klasy Tailwind |
|---|---|
| H1 (tytul str.) | text-2xl font-display font-bold text-gray-900 |
| H2 (sekcja) | text-xl font-display font-semibold text-gray-900 |
| H3 (karta) | text-lg font-display font-semibold text-gray-800 |
| Body | text-sm font-sans text-gray-700 |
| Label | text-sm font-medium text-gray-700 |
| Caption / Help | text-xs text-gray-500 |
Karty
Karty sa podstawowym kontenerem grupujacym tresc.
html
<!-- Bazowa karta -->
<div class="bg-white rounded-xl border border-gray-100 shadow-sm
hover:shadow-md transition-shadow duration-200">
<div class="p-6">
<h3 class="text-lg font-display font-semibold text-gray-800">
Tytul karty
</h3>
<p class="mt-2 text-sm text-gray-600">
Opis lub zawartosc karty.
</p>
</div>
</div>Warianty kart
html
<!-- Karta z headerem i borderem dolnym -->
<div class="bg-white rounded-xl border border-gray-100 shadow-sm">
<div class="px-6 py-4 border-b border-gray-100">
<h3 class="text-lg font-display font-semibold text-gray-800">Header</h3>
</div>
<div class="p-6">
<!-- tresc -->
</div>
</div>
<!-- Karta z footerem -->
<div class="bg-white rounded-xl border border-gray-100 shadow-sm">
<div class="p-6">
<!-- tresc -->
</div>
<div class="px-6 py-4 bg-gray-50 rounded-b-xl border-t border-gray-100">
<!-- footer / akcje -->
</div>
</div>Tabele
Lekkie, czytelne tabele bez ciezkich ramek:
html
<div class="bg-white rounded-xl border border-gray-100 shadow-sm overflow-hidden">
<table class="w-full">
<thead>
<tr class="border-b border-gray-100">
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Nazwa
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Status
</th>
</tr>
</thead>
<tbody id="table-body" class="divide-y divide-gray-50">
<tr class="hover:bg-gray-50 transition-colors duration-150">
<td class="px-6 py-4 text-sm text-gray-900">
Zadanie matematyczne
</td>
<td class="px-6 py-4">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-700">
Aktywne
</span>
</td>
</tr>
</tbody>
</table>
</div>Zasady tabel
- Brak ciezkich borderow — uzyj
divide-y divide-gray-50miedzy wierszami - Header:
text-xs uppercase tracking-wider text-gray-500 - Hover:
hover:bg-gray-50 transition-colors duration-150 - Padding:
px-6 py-4(generyczny) - Font:
text-smdla zawartosci
Przyciski
Primary (glowna akcja)
html
<button class="inline-flex items-center gap-2 px-4 py-2.5
bg-indigo-600 text-white text-sm font-medium
rounded-lg shadow-sm
hover:bg-indigo-700 active:bg-indigo-800
transition-colors duration-150
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<i data-lucide="plus" class="w-4 h-4"></i>
Dodaj zadanie
</button>Secondary (akcja drugorzedna)
html
<button class="inline-flex items-center gap-2 px-4 py-2.5
bg-white text-gray-700 text-sm font-medium
rounded-lg border border-gray-300 shadow-sm
hover:bg-gray-50 active:bg-gray-100
transition-colors duration-150
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
<i data-lucide="filter" class="w-4 h-4"></i>
Filtruj
</button>Danger (akcja niebezpieczna)
html
<button class="inline-flex items-center gap-2 px-4 py-2.5
bg-white text-red-600 text-sm font-medium
rounded-lg border border-red-200 shadow-sm
hover:bg-red-50 active:bg-red-100
transition-colors duration-150
focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
<i data-lucide="trash-2" class="w-4 h-4"></i>
Usun
</button>Ghost (bezramkowy)
html
<button class="inline-flex items-center gap-2 px-3 py-2
text-gray-500 text-sm font-medium
rounded-lg
hover:bg-gray-100 hover:text-gray-700
transition-colors duration-150">
<i data-lucide="more-horizontal" class="w-4 h-4"></i>
</button>Stat Card (karta statystyk)
html
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-6">
<div class="flex items-center gap-4">
<div class="flex-shrink-0 w-12 h-12 bg-indigo-50 rounded-xl
flex items-center justify-center">
<i data-lucide="zap" class="w-6 h-6 text-indigo-600"></i>
</div>
<div>
<p class="text-sm font-medium text-gray-500">Zebrane XP</p>
<p class="text-2xl font-display font-bold text-gray-900">2,450</p>
</div>
</div>
<div class="mt-4 flex items-center gap-1 text-xs">
<i data-lucide="trending-up" class="w-3.5 h-3.5 text-green-600"></i>
<span class="font-medium text-green-600">+12%</span>
<span class="text-gray-500">vs poprzedni tydzien</span>
</div>
</div>Empty State (pusty stan)
html
<div class="flex flex-col items-center justify-center py-16 px-6">
<div class="w-16 h-16 bg-gray-100 rounded-2xl
flex items-center justify-center mb-4">
<i data-lucide="inbox" class="w-8 h-8 text-gray-400"></i>
</div>
<h3 class="text-lg font-display font-semibold text-gray-800">
Brak zadan
</h3>
<p class="mt-1 text-sm text-gray-500 text-center max-w-sm">
Nie masz jeszcze zadnych zadan. Stworz pierwsze zadanie,
aby rozpoczac przygode edukacyjna.
</p>
<button class="mt-6 inline-flex items-center gap-2 px-4 py-2.5
bg-indigo-600 text-white text-sm font-medium
rounded-lg shadow-sm hover:bg-indigo-700
transition-colors duration-150">
<i data-lucide="plus" class="w-4 h-4"></i>
Stworz zadanie
</button>
</div>Paleta kolorow
Neutralne (tla, tekst, bordery)
| Cel | Kolor | Klasa Tailwind |
|---|---|---|
| Tlo strony | #F9FAFB | bg-gray-50 |
| Tlo karty | #FFFFFF | bg-white |
| Border karty | #F3F4F6 | border-gray-100 |
| Border inputa | #D1D5DB | border-gray-300 |
| Tekst glowny | #111827 | text-gray-900 |
| Tekst drugorzedny | #6B7280 | text-gray-500 |
| Tekst wylaczony | #9CA3AF | text-gray-400 |
| Hover wiersza tabeli | #F9FAFB | bg-gray-50 |
Akcent (primary)
| Cel | Klasa Tailwind |
|---|---|
| Przycisk primary | bg-indigo-600 |
| Przycisk hover | bg-indigo-700 |
| Tlo aktywnego nav | bg-indigo-50 |
| Tekst aktywnego nav | text-indigo-700 |
| Focus ring | ring-indigo-500 |
Statusy
| Status | Tlo | Tekst |
|---|---|---|
| Aktywne | bg-green-50 | text-green-700 |
| Oczekujace | bg-amber-50 | text-amber-700 |
| Odrzucone | bg-red-50 | text-red-700 |
| Szkic | bg-gray-100 | text-gray-600 |
Ikony — Lucide
Uzyj Lucide Icons w rozmiarze 20px z cienkim obrysem:
html
<!-- Domyslna ikona (20px, stroke 1.5) -->
<i data-lucide="home" class="w-5 h-5" style="stroke-width: 1.5"></i>
<!-- Mala ikona (16px) -->
<i data-lucide="chevron-right" class="w-4 h-4"></i>
<!-- Duza ikona (24px, np. w empty state) -->
<i data-lucide="inbox" class="w-6 h-6 text-gray-400"></i>Czesto uzywane ikony
| Ikona | Nazwa Lucide |
|---|---|
| Dashboard | layout-dashboard |
| Content | book-open |
| Worlds | globe |
| Todo | check-square |
| Settings | settings |
| Dodaj | plus |
| Edytuj | pencil |
| Usun | trash-2 |
| Szukaj | search |
| Filtruj | filter |
| Zamknij | x |
| Menu | menu |
Animacje i przejscia
CSS transitions
html
<!-- Subtelne przejscie na hover (cien, kolor) -->
<div class="transition-all duration-200 ease-in-out">
<!-- Przejscie koloru tla -->
<tr class="transition-colors duration-150">
<!-- Przejscie cienia karty -->
<div class="shadow-sm hover:shadow-md transition-shadow duration-200">HTMX swap transitions
css
/* Fade-in dla nowo zaladowanej tresci */
.htmx-swapping {
opacity: 0;
transition: opacity 200ms ease-out;
}
.htmx-settling {
opacity: 1;
transition: opacity 200ms ease-in;
}
/* Klasa dla elementow ladujacych */
.htmx-request .htmx-indicator {
display: inline-flex;
}
.htmx-indicator {
display: none;
}Alpine.js transitions
html
<!-- Slide-in panel -->
<div x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 translate-x-4"
x-transition:enter-end="opacity-100 translate-x-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 translate-x-0"
x-transition:leave-end="opacity-0 translate-x-4">
</div>
<!-- Fade modal backdrop -->
<div x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-black/30 backdrop-blur-sm">
</div>Responsive design
Podejscie desktop-first — Manager jest narzedziem przeznaczonym glownie na desktop:
| Breakpoint | Szerokosc | Zachowanie |
|---|---|---|
| Desktop | >= 1024px | Pelny sidebar + tresc |
| Tablet | 768-1023px | Sidebar kolapsuje do ikon |
| Mobile | < 768px | Sidebar jako hamburger overlay |
html
<!-- Sidebar: pelny na desktop, ikony na tablet, ukryty na mobile -->
<aside class="hidden md:flex md:w-16 lg:w-64 flex-col ...">
<!-- Main content: dostosowuje margines -->
<main class="ml-0 md:ml-16 lg:ml-64 ...">Wzorce formularzy
html
<!-- Pole tekstowe -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">
Tytul zadania
</label>
<input type="text"
class="w-full px-3.5 py-2.5 text-sm text-gray-900
bg-white border border-gray-300 rounded-lg
placeholder:text-gray-400
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500
transition-colors duration-150"
placeholder="Wpisz tytul...">
</div>
<!-- Select -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">
Grupa wiekowa
</label>
<select class="w-full px-3.5 py-2.5 text-sm text-gray-900
bg-white border border-gray-300 rounded-lg
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500
transition-colors duration-150">
<option>Wybierz...</option>
</select>
</div>