Motion System: Notion
Category: Productivity / Knowledge Management Unhurried, human motion that respects the rhythm of thought.
Motion Philosophy
Notion is a writing environment before it is a database, a kanban board, or a project manager. Users come to Notion to think, and thinking requires an environment that does not interrupt. Motion in Notion operates at the pace of a person settling into work: not sluggish, but deliberately unhurried. The 200–300ms default range communicates that the interface is responding to the user, not trying to impress them. There is no bounce, no dramatic reveal, no celebratory flourish for opening a page. The product steps back so the user can step forward into their work.
The philosophy is best described as human-paced. Notion's brand identity is defined by its warmth and approachability — handwritten-style typography, generous whitespace, a color palette that feels like a well-lit notebook rather than a corporate dashboard. The motion system extends this identity. Transitions feel like turning a page or opening a notebook rather than navigating a software interface. Side panels slide in the way a drawer opens; pages transition with a sense of physical depth rather than a flat push slide.
Springs are consciously absent from the document editing experience. A bounce or elastic effect in the text editor would be jarring — it would break the mental model of writing in a document and draw the user's attention to the interface rather than the words. The spring restraint is a content-first decision: the document is always more important than the chrome surrounding it. Springs do appear in one limited context — the sidebar expanding and collapsing — because the sidebar is workspace chrome, not content, and its physical feel communicates that the user is adjusting their environment rather than editing their document.
Duration Scale
| Token | Value | Use |
|---|---|---|
| duration-instant | 0ms | Cursor placement, text selection, inline formatting (bold, italic) |
| duration-fast | 150ms | Hover fills, icon state changes, toggle bullets, checkbox checks |
| duration-default | 200ms | Dropdowns, inline menus, slash command palette, small popovers |
| duration-gentle | 250ms | Block drag settle, page icon changes, cover image transitions |
| duration-unhurried | 300ms | Sidebar open/close, database view transitions, full-width modal |
| duration-expressive | 500ms–1000ms | Lottie empty state animations, onboarding illustrations — not used in functional UI |
Easing
| Token | Curve | Use |
|---|---|---|
| ease-out | cubic-bezier(0.16, 1, 0.3, 1) | Primary easing for all entering elements |
| ease-in | cubic-bezier(0.4, 0, 1, 1) | Exiting elements |
| ease-in-out | cubic-bezier(0.45, 0, 0.55, 1) | Repositioning — database rows reordering, block dragging |
| ease-page | cubic-bezier(0.25, 0.46, 0.45, 0.94) | Page transition feel — softer, more organic, like turning a page |
| ease-linear | cubic-bezier(0, 0, 1, 1) | Progress indicators, loading bars |
The primary
ease-outis an aggressive decelerate curve that gives Notion's entering elements a sense of purpose — they arrive decisively but gently. Combined with the longer durations, the result is transitions that feel considered rather than mechanical.
Spring Configs (Framer Motion)
Springs are used only for the sidebar and a handful of workspace-level chrome interactions. Never in the editor.
- Sidebar open/close: stiffness: 260, damping: 28, mass: 1 — slight overshoot, communicates the workspace breathing in and out
- Peek sidebar (hover-to-reveal): stiffness: 300, damping: 32, mass: 0.9 — slightly snappier for the hover-triggered version
- Database row expand (row detail view): stiffness: 240, damping: 30, mass: 1 — gentle, no aggressive bounce
- Inline page reference hover card: stiffness: 400, damping: 38, mass: 0.8 — quick to appear, minimal overshoot
No springs in the block editor. No springs for slash command menu, formatting toolbar, or inline menus. These use CSS transitions exclusively.
Stagger Patterns
- Page tree items (sidebar initial load): 12ms between each item, capped at 12 items — barely perceptible, just enough to prevent simultaneous pop
- Database gallery cards (initial load): 20ms between each card
- Database table rows (initial load): 10ms between each row, capped at 15 rows
- Search results: 15ms between each result
- Template picker cards: 25ms between cards in the template gallery
- Slash command menu items: no stagger — all items appear simultaneously for responsiveness
Stagger is applied only on initial mount. Real-time collaborative changes (another user editing a block, adding a page) appear without stagger.
Enter / Exit Patterns
Fade (tooltips, hover cards, inline mentions)
enter: opacity 0→1, duration: duration-fast (150ms), ease: ease-out
exit: opacity 1→0, duration: duration-fast (150ms), ease: ease-in
Fade + Slide (slash command menu, dropdowns, inline menus)
enter: opacity 0→1, translateY 6px→0, duration: duration-default (200ms), ease: ease-out
exit: opacity 1→0, translateY 0→-3px, duration: duration-fast (150ms), ease: ease-in
Sidebar (left panel)
enter: spring: Sidebar config — translateX from off-screen left, spring feel of opening a drawer
exit: translateX 0→-100%, duration: duration-unhurried (300ms) × 0.75 = 225ms, ease: ease-in
canvas: page content area simultaneously adjusts its left margin, matching the panel motion exactly
Page Transition (clicking an internal link or page in sidebar)
enter: opacity 0→1, translateX 12px→0, duration: duration-gentle (250ms), ease: ease-page
exit: opacity 1→0, translateX 0→-8px, duration: duration-fast (150ms), ease: ease-in
The combination of slight horizontal drift and ease-page produces the page-turn sensation.
Modal (database filter settings, page property panel, full-page popup)
enter: opacity 0→1, scale 0.98→1, translateY 4px→0, duration: duration-unhurried (300ms), ease: ease-out
backdrop: opacity 0→0.4, duration: duration-unhurried (300ms), ease: ease-out
exit: opacity 1→0, duration: duration-default (200ms), ease: ease-in
Block Drag (reordering blocks in the editor)
drag start: dragged block opacity drops to 0.75 at duration-fast (150ms). Other blocks shift positions.
other blocks repositioning: translateY to new position, duration: duration-default (200ms), ease: ease-in-out
drop settle: spring: Database row expand config (stiffness 240, damping 30)
Lottie Empty States (empty databases, empty pages, first-time views)
Lottie JSON animations, 600–1000ms, play once on mount. Static fallback provided for reduced-motion.
Used in: empty database views, empty sidebar, onboarding flow, deleted-page recovery screen.
Never used in: the editor body, inline elements, or any surface where the user is actively working.
Interaction States
- Hover (blocks): Block action handle (drag handle + options) fades in at opacity 0→1 over duration-fast (150ms) ease-out, with a 200ms delay to prevent accidental trigger during reading. Background tint appears at duration-fast (150ms).
- Hover (sidebar items): Background fill at duration-fast (150ms) ease-out. Nested page expand arrow fades in simultaneously.
- Press/Active: Background steps down at 50ms linear. No scale transform on block actions or toolbar buttons.
- Focus (editor): Cursor placement is instant (0ms). Block focus highlight (the subtle left border on focused blocks) appears at duration-fast (150ms) ease-out. Formatting toolbar fades in above selection at duration-default (200ms) ease-out after a 300ms selection-stable delay.
- Checkbox (to-do block): Check icon scales in 0→1 at duration-fast (150ms) ease-out paired with a strikethrough animation on the text — strikethrough width 0→100% at duration-default (200ms) ease-out. Satisfying but not celebratory.
- Toggle block expand: Chevron rotates 0→90deg at duration-fast (150ms) ease-in-out. Content fades in at duration-default (200ms) ease-out with a slight height expansion.
- Loading (initial page load): Skeleton blocks matching approximate layout, shimmer at 1600ms ease-in-out infinite. Blocks replace skeleton one section at a time from top to bottom, fading in at duration-fast (150ms).
- Reduced motion: All transforms removed. Sidebar spring snaps to position. Page transitions become opacity fades at 100ms. Block drag loses animation — items snap to reordered positions. Lottie animations are paused at first frame with static illustration fallbacks. Checkbox strikethrough happens at 0ms.
Rules
- The editor is inviolable. No springs, no bounce, no motion that draws attention to the interface while the user is writing. Block interactions use only opacity and subtle translateY — never scale, rotation, or elastic physics.
- Pacing expresses brand. Notion's default of 200–300ms is intentional. Shortening durations to feel "snappier" would make Notion feel like a task manager or a developer tool, not a thinking environment. The pace is the brand.
- Lottie for delight, CSS for function. Empty states and onboarding use Lottie illustrations for warmth and character. All functional UI uses CSS transitions. The two systems never appear simultaneously in the same viewport area.
- Always implement
prefers-reduced-motion. Transforms disabled, springs snap to position, Lottie paused at frame 0, checkbox strikethrough instant. The writing experience is fully functional — and arguably calmer — without motion.