← All Posts

Design Study: How Notion's Block Model Changed Everything

Notion reached 100 million users in 2024 by making a seemingly impossible tradeoff: infinite flexibility without sacrificing usability.[^1]

## Key Takeaways - **Everything is a block** — Notion's atomic unit treats text, images, databases, and embeds identically, enabling drag-and-drop composition. - **Progressive disclosure works** — The "/" menu hides 50+ block types behind a single keystroke, keeping the default interface clean. - **Composability beats features** — Users build workflows the designers never anticipated because blocks combine freely. - **Calm typography lets content shine** — Notion's understated type system (40/30/24/20/16px scale) creates hierarchy without shouting. - **The infinite canvas has no file system** — Pages link to pages, databases contain pages, and the same content appears in multiple views.

Why Does Notion’s Design Matter?

Notion proved that complexity can be composable. Before Notion, productivity tools offered rigid features. You got what the designer imagined. Notion built blocks that users combine in ways no one anticipated—personal wikis, CRMs, habit trackers, recipe databases, company intranets.

The design achievements: - Made databases accessible to non-developers - Created an infinite canvas that feels familiar - Proved flexibility and usability aren’t mutually exclusive - Pioneered collaborative document editing at scale

Ivan Zhao, Notion’s CEO, summarized the philosophy: “We want to make it so that everyone can tailor the software they use, every day, to their exact needs.”


What Is the Block Model and Why Does It Work?

The atomic unit of Notion is the block. Every piece of content—paragraph, heading, image, database, embed—is a block that can be: - Moved — Drag to reorder - Transformed — Turn text into a toggle, callout, or heading - Referenced — Link blocks across pages - Embedded — Nest databases, pages, or external content

TRADITIONAL DOCUMENT:
┌─────────────────────────────────────┐
│ [Fixed header]                      │
│ ─────────────────────────────────   │
│ Paragraph of text that's just text  │
│ and can only be text.               │
│                                     │
│ [Fixed image]                       │
│                                     │
│ Another paragraph, same deal.       │
└─────────────────────────────────────┘

NOTION'S BLOCK MODEL:
┌─────────────────────────────────────┐
│ ⋮⋮ [Heading block - H1]             │  ← Drag to reorder
│ ─────────────────────────────────   │
│ ⋮⋮ [Text block]                     │  ← Turn into toggle, callout, etc.
│     Paragraph that can transform    │
│ ⋮⋮ [Image block]                    │  ← Resize, caption, link
│     [caption]                       │
│ ⋮⋮ [Database block]                 │  ← Full database, inline
│     │ Task │ Status │ Due │         │
│ ⋮⋮ [Text block]                     │
│     Another paragraph               │
└─────────────────────────────────────┘

The genius: every block has the same handle (⋮⋮), the same drag behavior, and can convert to any other block type. Users learn one interaction pattern and apply it everywhere.

CSS Implementation Pattern

.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;
}

/* Universal block spacing */
.block + .block {
  margin-top: var(--space-2);
}

SwiftUI Implementation Pattern

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

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

            // Block content (polymorphic)
            BlockContentView(block: block)
        }
        .onHover { isHovering = $0 }
    }
}

How Does Progressive Disclosure Keep the Interface Clean?

Notion hides complexity until you need it. The default state is a blank page—no toolbar clutter, no feature menus. Power features emerge on demand through keyboard shortcuts.

The “/” Menu Hierarchy:

User types: /
           ↓
┌────────────────────────────────┐
│ BASIC BLOCKS                   │
│  📝 Text                       │
│  📋 Page                       │
│  ☑️  To-do list                │
│  • Bulleted list               │
│                                │
│ DATABASE                       │
│  📊 Table                      │
│  🗂️ Board                      │
│  📅 Calendar                   │
│                                │
│ MEDIA                          │
│  🖼️ Image                      │
│  🎬 Video                      │
│  📎 File                       │
└────────────────────────────────┘

Five Levels of Complexity:

Level Trigger Capability
1 Just type Text block (default)
2 / 50+ block types
3 @ Mentions and page links
4 [[ Inline databases
5 Templates Formulas and automations

New users never see levels 3-5 until they’re ready. Power users access everything in milliseconds.

Implementation Principle

/* Hidden until needed */
.property-options,
.advanced-settings,
.formula-builder {
  display: none;
}

/* Revealed by explicit action */
.block.selected .property-options,
.settings-expanded .advanced-settings,
.formula-mode .formula-builder {
  display: block;
  animation: fadeSlideIn 0.2s ease-out;
}

What Makes the “Infinite Canvas” Feel Natural?

Pages contain pages. Databases contain pages. Pages link everywhere. The workspace has no walls—and no traditional file system.

TRADITIONAL HIERARCHY:
Folders → Documents → Content
   │
   └── Rigid, one location per document

NOTION'S CANVAS:
Everything → Links to → Everything
   │
   └── Page can exist anywhere
   └── Same data, multiple views
   └── Inline or full-page

The key insight: there’s no “file system.” There’s a graph of connected content. A task list can be a page, a database row, an inline embed, or all three simultaneously.

Pattern: Inline vs Full Page

/* Same content, different containers */
.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;
}

/* Content adapts to container */
.database-view {
  display: flex;
  flex-direction: column;
  height: 100%;
}

Why Does Notion’s Typography Feel “Calm”?

Notion’s typography is deliberately understated. It creates hierarchy without competing for attention—letting user content be the star.

HIERARCHY THROUGH SIZE AND WEIGHT:

Page Title         ← 40px, Bold
═══════════════════════════════════════════════

Heading 1          ← 30px, Semibold
───────────────────────────────────────────────

Heading 2          ← 24px, Semibold
. . . . . . . . . . . . . . . . . . . . . . .

Heading 3          ← 20px, Semibold

Body text flows naturally at 16px with         ← 16px, Regular
generous line-height (1.7) and comfortable
measure. Long-form content remains readable.

Typography System

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

  /* Generous line height for readability */
  --line-height-tight: 1.3;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.7;

  /* Neutral, readable font stack */
  --font-family: -apple-system, BlinkMacSystemFont,
    'Segoe UI', 'Roboto', sans-serif;
}

.page-content {
  max-width: 720px;  /* Comfortable reading measure */
  margin: 0 auto;
  font-family: var(--font-family);
  line-height: var(--line-height-relaxed);
}

What Patterns Can You Steal From Notion?

Pattern 1: Slash Commands

Type “/” to reveal contextual actions. Users discover features by typing, not hunting through menus.

interface SlashCommand {
  trigger: string;
  icon: string;
  label: string;
  shortcut?: string;
  action: () => void;
}

const commands: SlashCommand[] = [
  { trigger: 'h1', icon: 'H1', label: 'Heading 1', action: createH1 },
  { trigger: 'bullet', icon: '•', label: 'Bullet list', action: createBullet },
  { trigger: 'todo', icon: '☐', label: 'To-do', action: createTodo },
];

function filterCommands(query: string): SlashCommand[] {
  return commands.filter(cmd =>
    cmd.trigger.includes(query.toLowerCase()) ||
    cmd.label.toLowerCase().includes(query.toLowerCase())
  );
}

Pattern 2: Block Transformation

Any block can become any other block. Text becomes a heading becomes a toggle becomes a callout.

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")
        }
    }
}

Pattern 3: Inline Mentions

”@” to link to anything in the workspace. References become first-class UI elements.

.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;
}

Frequently Asked Questions

What makes Notion's block model different from other editors?

Notion treats every piece of content identically—text, images, databases, and embeds are all "blocks" with the same drag handle, same transformation options, and same nesting capability. Traditional editors treat different content types differently, requiring users to learn multiple interaction patterns. Notion users learn one pattern and apply it everywhere.

How does Notion's "/" menu improve discoverability?

The "/" menu surfaces 50+ block types through a single keystroke with fuzzy search. Users type "/" then a few characters to find what they need. The alternative—toolbar buttons or nested menus—would require hunting through UI chrome. Slack, Linear, and many modern tools have adopted this pattern because it's faster than clicking.

Can I implement Notion-style blocks in my own app?

Yes. The core pattern requires: (1) a unified block interface with consistent handles and drag behavior, (2) a polymorphic content renderer that switches based on block type, and (3) a transformation system that converts between types while preserving content. Libraries like Slate.js, ProseMirror, or Editor.js provide foundations, but Notion's polish comes from years of iteration.

Why does Notion feel "calm" compared to other productivity apps?

Notion hides UI until you need it. The default state is a blank page with minimal chrome. Features reveal through explicit actions (typing "/", clicking "+", hovering for handles) rather than always-visible buttons. Combined with understated typography (system fonts, generous whitespace, muted colors), the interface stays out of the way.

What are the design lessons from Notion for other products?

Five lessons transfer to any product: (1) composability over features—build blocks that combine, not monolithic tools; (2) progressive disclosure—simple by default, powerful on demand; (3) consistent interactions—every element works the same way; (4) calm interface—let content be the focus; (5) infinite flexibility—no artificial constraints on structure.


Quick Summary

Notion’s success comes from treating complexity as composable. The block model creates a single, learnable interaction pattern that scales from simple notes to complex databases. Progressive disclosure keeps the interface calm while hiding tremendous power behind “/” and “@” triggers. For developers building productivity tools, Notion demonstrates that flexibility and usability can coexist—if you’re willing to invest in consistent, well-designed primitives.


References

[^1]: Notion reaches 100 million users. TechCrunch


This post is part of the Design Studies series exploring the design decisions behind exceptional products. See also: Arc Browser, Things 3.

For foundational design principles, see the complete design guide.