design/notion

3 min czytania 744 słów
design/notion screenshot

Notion: Rewolucja oparta na blokach

„Chcemy sprawić, by każdy mógł dostosować oprogramowanie, którego używa na co dzień, do swoich dokładnych potrzeb." — Ivan Zhao, CEO Notion

Notion przekształcił oprogramowanie produktywnościowe, czyniąc wszystko blokiem. Ta pozornie prosta abstrakcja stworzyła nieskończoną elastyczność przy zachowaniu użyteczności — wyzwanie projektowe, które większość uważała za niemożliwe.


Dlaczego Notion ma znaczenie

Notion udowodnił, że złożoność może być komponowalna. Zamiast sztywnych funkcji, stworzyli klocki, które użytkownicy łączą w sposoby, których projektanci nigdy nie przewidzieli.

Kluczowe osiągnięcia: - Udostępnienie baz danych osobom niebędącym programistami - Stworzenie nieskończonego płótna, które wydaje się znajome - Udowodnienie, że elastyczność i użyteczność nie są przeciwieństwami - Pionierska współpraca przy edycji dokumentów na dużą skalę


Kluczowe wnioski

  1. Wszystko jest blokiem - Podejście oparte na jednostkach atomowych oznacza, że każdy element treści (tekst, obrazy, bazy danych) zachowuje się identycznie: można go przeciągać, przekształcać, linkować
  2. Stopniowe ujawnianie skaluje złożoność - Polecenia slash ujawniają zaawansowane funkcje tylko gdy są wywołane; początkujący widzą prostotę, eksperci znajdują głębię
  3. Spójność przewyższa spryt - Każdy blok ma ten sam uchwyt, to samo zachowanie przy przeciąganiu i może być przekonwertowany na dowolny inny typ
  4. Nieskończone płótno usuwa ograniczenia - Strony zawierają strony, bazy danych zawierają strony, wszystko łączy się wszędzie — bez sztucznej hierarchii
  5. Spokojna typografia pozwala treści błyszczeć - Stonowany design z hojną interlinią (1.7) i komfortową szerokością czytania (720px) utrzymuje fokus na treści użytkownika

Podstawowe zasady projektowania

1. Wszystko jest blokiem

Jednostką atomową Notion jest blok. Każdy element treści to blok, który można: - Przenosić - Przekształcać - Referencjonować - Osadzać

TRADYCYJNY DOKUMENT:
┌─────────────────────────────────────┐
│ [Stały nagłówek]                    │
│ ─────────────────────────────────   │
│ Akapit tekstu, który jest tylko     │
│ tekstem i może być tylko tekstem.   │
│                                     │
│ [Stały obraz]                       │
│                                     │
│ Kolejny akapit, ta sama historia.   │
└─────────────────────────────────────┘

MODEL BLOKOWY NOTION:
┌─────────────────────────────────────┐
│ ⋮⋮ [Blok nagłówka - H1]             │  ← Przeciągnij by zmienić kolejność
│ ─────────────────────────────────   │
│ ⋮⋮ [Blok tekstu]                    │  ← Zamień na toggle, callout, itp.
│     Akapit, który można przekształcić│
│ ⋮⋮ [Blok obrazu]                    │  ← Zmień rozmiar, podpis, link
│     [podpis]                        │
│ ⋮⋮ [Blok bazy danych]               │  ← Pełna baza danych, inline
│     │ Zadanie │ Status │ Termin │   │
│ ⋮⋮ [Blok tekstu]                    │
│     Kolejny akapit                  │
└─────────────────────────────────────┘

Geniusz: Każdy blok ma ten sam uchwyt (⋮⋮), to samo zachowanie przy przeciąganiu i może być przekonwertowany na dowolny inny typ bloku.

Wzorzec CSS (uchwyt bloku):

.block {
  position: relative;
  padding-left: var(--block-indent);
}

.block-handle {
  position: absolute;
  left: 0;
  opacity: 0;
  transition: opacity 0.15s ease;
  cursor: grab;
}

.block:hover .block-handle,
.block-handle:focus {
  opacity: 1;
}

/* Uniwersalne odstępy między blokami */
.block + .block {
  margin-top: var(--space-2);
}

Wzorzec SwiftUI:

struct BlockView: View {
    @State private var isHovering = false
    let block: Block

    var body: some View {
        HStack(alignment: .top, spacing: 4) {
            // Uniwersalny uchwyt
            Image(systemName: "line.3.horizontal")
                .opacity(isHovering ? 1 : 0)
                .animation(.easeOut(duration: 0.15), value: isHovering)

            // Treść bloku (polimorficzna)
            BlockContentView(block: block)
        }
        .onHover { isHovering = $0 }
    }
}

2. Stopniowe ujawnianie

Notion ujawnia złożoność tylko wtedy, gdy jest potrzebna. Stan domyślny jest czysty; zaawansowane funkcje pojawiają się na żądanie.

Menu „/":

Użytkownik wpisuje: /
           ↓
┌────────────────────────────────┐
│ PODSTAWOWE BLOKI               │
│  [T] Tekst                     │
│  [P] Strona                    │
│  [x] Lista zadań               │
│   *  Lista punktowana          │
│                                │
│ BAZA DANYCH                    │
│  [=] Tabela                    │
│  [#] Tablica                   │
│  [D] Kalendarz                 │
│                                │
│ MEDIA                          │
│  [I] Obraz                     │
│  [V] Wideo                     │
│  [@] Plik                      │
└────────────────────────────────┘

Progresywna złożoność:

Poziom 1: Po prostu pisz (blok tekstowy)
Poziom 2: „/" dla typów bloków
Poziom 3: „@" dla wzmianek i linków
Poziom 4: „[" dla baz danych inline
Poziom 5: Szablony i formuły

Zasada implementacji:

/* Ukryte dopóki nie potrzebne */
.property-options,
.advanced-settings,
.formula-builder {
  display: none;
}

/* Ujawniane przez jawną akcję */
.block.selected .property-options,
.settings-expanded .advanced-settings,
.formula-mode .formula-builder {
  display: block;
  animation: fadeSlideIn 0.2s ease-out;
}

3. Nieskończone płótno

Strony zawierają strony. Bazy danych zawierają strony. Strony linkują wszędzie. Przestrzeń robocza nie ma ścian.

TRADYCYJNA HIERARCHIA:
Foldery → Dokumenty → Treść
   │
   └── Sztywna, jedna lokalizacja na dokument

PŁÓTNO NOTION:
Wszystko → Linkuje do → Wszystkiego
   │
   └── Strona może istnieć wszędzie
   └── Te same dane, wiele widoków
   └── Inline lub pełna strona

Kluczowy wniosek: Nie ma „systemu plików". Jest graf połączonej treści.

Wzorzec - Inline vs pełna strona:

/* Ta sama treść, różne kontenery */
.database-inline {
  max-height: 400px;
  overflow-y: auto;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
}

.database-fullpage {
  height: 100%;
  border: none;
}

/* Treść dostosowuje się do kontenera */
.database-view {
  display: flex;
  flex-direction: column;
  height: 100%;
}

4. Spokojna typografia

Typografia Notion jest celowo stonowana. Pozwala treści błyszczeć.

HIERARCHIA PRZEZ ROZMIAR I GRUBOŚĆ:

Tytuł strony        ← 40px, Bold, mało osobowości
═══════════════════════════════════════════════

Nagłówek 1          ← 30px, Semibold
───────────────────────────────────────────────

Nagłówek 2          ← 24px, Semibold
. . . . . . . . . . . . . . . . . . . . . . .

Nagłówek 3          ← 20px, Semibold

Tekst główny płynie naturalnie przy 16px       ← 16px, Regular
z hojną interlinią (1.7) i komfortową
szerokością. Długie treści pozostają czytelne.

System typograficzny:

:root {
  /* Skala inspirowana Notion */
  --font-title: 40px;
  --font-h1: 30px;
  --font-h2: 24px;
  --font-h3: 20px;
  --font-body: 16px;
  --font-small: 14px;

  /* Hojna interlinia dla czytelności */
  --line-height-tight: 1.3;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.7;

  /* Neutralny, czytelny stos fontów */
  --font-family: -apple-system, BlinkMacSystemFont,
    'Segoe UI', 'Roboto', sans-serif;
}

.page-content {
  max-width: 720px;  /* Komfortowa szerokość czytania */
  margin: 0 auto;
  font-family: var(--font-family);
  line-height: var(--line-height-relaxed);
}

Wzorce do przeniesienia

Wzorzec 1: Polecenia slash

Mechanizm: Wpisz „/" aby ujawnić akcje kontekstowe.

// Rejestr poleceń slash
interface SlashCommand {
  trigger: string;
  icon: string;
  label: string;
  shortcut?: string;
  action: () => void;
}

const commands: SlashCommand[] = [
  { trigger: 'h1', icon: 'H1', label: 'Nagłówek 1', action: createH1 },
  { trigger: 'bullet', icon: '•', label: 'Lista punktowana', action: createBullet },
  { trigger: 'todo', icon: '☐', label: 'Zadanie', action: createTodo },
];

// Filtruj gdy użytkownik pisze
function filterCommands(query: string): SlashCommand[] {
  return commands.filter(cmd =>
    cmd.trigger.includes(query.toLowerCase()) ||
    cmd.label.toLowerCase().includes(query.toLowerCase())
  );
}

Wzorzec 2: Transformacja bloków

Mechanizm: Każdy blok może stać się dowolnym innym blokiem.

enum BlockType: CaseIterable {
    case text, heading1, heading2, heading3
    case bulletList, numberedList, toggleList, todo
    case quote, callout, divider
    case image, video, embed

    var icon: String {
        switch self {
        case .text: return "text.alignleft"
        case .heading1: return "textformat.size.larger"
        // ...
        }
    }
}

struct BlockTransformMenu: View {
    let currentBlock: Block
    let onTransform: (BlockType) -> Void

    var body: some View {
        Menu {
            ForEach(BlockType.allCases, id: \.self) { type in
                Button {
                    onTransform(type)
                } label: {
                    Label(type.label, systemImage: type.icon)
                }
            }
        } label: {
            Image(systemName: "arrow.triangle.turn.up.right.circle")
        }
    }
}

Wzorzec 3: Wzmianki inline

Mechanizm: „@" aby linkować do czegokolwiek w przestrzeni roboczej.

.mention {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  background: var(--bg-mention);
  border-radius: var(--radius-sm);
  color: var(--text-link);
  text-decoration: none;
  cursor: pointer;
}

.mention:hover {
  background: var(--bg-mention-hover);
}

.mention-icon {
  width: 16px;
  height: 16px;
}

Lekcje projektowania

  1. Komponowalność ponad funkcje: Buduj bloki, które się łączą, nie monolityczne narzędzia
  2. Stopniowe ujawnianie: Proste domyślnie, potężne na żądanie
  3. Spójne interakcje: Każdy blok działa tak samo
  4. Spokojny interfejs: Niech treść będzie w centrum uwagi, nie dekoracje
  5. Nieskończona elastyczność: Brak sztucznych ograniczeń struktury

Często zadawane pytania

Czym jest architektura blokowa Notion?

Każdy element treści w Notion to „blok" — tekst, obrazy, bazy danych, osadzenia, a nawet same strony. Każdy blok ma identyczne zachowanie: uchwyt do przeciągania, możliwość transformacji w inne typy bloków i spójne odstępy. To podejście atomowe oznacza, że użytkownicy uczą się jednego wzorca interakcji, który stosuje się wszędzie.

Jak działa system poleceń slash w Notion?

Wpisanie „/" otwiera kontekstowe menu wszystkich dostępnych typów bloków. Menu filtruje się gdy użytkownik pisze (np. „/todo" pokazuje listę zadań). Ten wzorzec łączy odkrywalność (zobacz wszystkie opcje) z szybkością (zaawansowani użytkownicy wpisują skróty bezpośrednio). Polecenie slash stało się standardem branżowym.

Czym jest stopniowe ujawnianie i jak Notion je wykorzystuje?

Stopniowe ujawnianie oznacza ujawnianie złożoności tylko wtedy, gdy jest potrzebna. W Notion Poziom 1 to po prostu pisanie (tworzy blok tekstowy), Poziom 2 to „/" dla typów bloków, Poziom 3 to „@" dla wzmianek, Poziom 4 to „[" dla baz danych, a Poziom 5 to szablony i formuły. Początkujący nigdy nie widzą przytłaczających opcji.

Czym nieskończone płótno Notion różni się od tradycyjnej struktury dokumentów?

Tradycyjne aplikacje używają hierarchii folderów, gdzie każdy dokument istnieje w jednej lokalizacji. Notion traktuje treść jako graf: strony zawierają strony, bazy danych zawierają strony i wszystko może linkować do wszystkiego. Ta sama baza danych może pojawiać się inline na wielu stronach, a strony nie mają ustalonej „lokalizacji" w systemie plików.

Dlaczego Notion używa tak stonowanej typografii?

Spokojna typografia Notion (fonty systemowe, 16px tekst główny, interlinia 1.7, max-width 720px) celowo unika osobowości. Użytkownicy tworzą bardzo różne treści — notatki ze spotkań, wiki, trackery projektów — więc interfejs musi być neutralnym płótnem, na którym każdy typ treści czuje się naturalnie.


Zasoby

  • Strona internetowa: notion.so
  • Blog o designie: Kulisy decyzji projektowych Notion
  • Galeria szablonów: Wzorce i przypadki użycia ze społeczności
  • Dokumentacja API: Budowanie z modelem blokowym Notion