Linear:软件设计的新标准
Linear如何成为现代软件的设计标准:键盘优先UX、乐观UI、命令面板和深色模式。包含CSS和TypeScript实现模式。
Linear:软件设计的新标准
"软件应该有明确的主张,并且快速响应。" — Karri Saarinen,Linear CEO
Linear 是一款重新定义了现代软件体验的项目管理工具。它由前 Uber 和 Airbnb 的设计师于 2019 年创立,证明了 B2B 软件不必丑陋或迟缓。
为什么 Linear 如此重要
Linear 是对臃肿、委员会式设计的企业软件的一次设计宣言。它展示了当设计师为设计师打造产品时会发生什么。
核心成就: - 让企业软件拥有消费级软件的体验 - 证明了键盘优先的界面也可以很美 - 展示了性能本身就是一项功能 - 为 SaaS 产品质量树立了新标杆
核心要点
- 速度是功能,不只是指标 - Linear 对亚 100 毫秒交互的执着追求证明,感知性能能够触发情感共鸣
- 键盘优先意味着专业用户获益 - 命令面板(Cmd+K)和助记快捷键(S 代表 Status,P 代表 Priority)让专家用户如虎添翼,同时不阻碍新手入门
- 信息密度胜过留白 - 用更少的界面元素展示更多数据;通过悬停显示细节,而非隐藏在点击之后
- 深色模式作为主要体验 - 以深色模式为主的设计创造高端美感,并减少专业用户的眼睛疲劳
- 乐观更新消除等待 - 先在本地更新,后台同步,只在真正出错时才显示错误
核心设计原则
1. 速度即功能
Linear 对速度有着近乎偏执的追求。每一次交互都感觉瞬间完成。
实现方式: - 乐观 UI 更新(假设成功,失败时回滚) - 本地优先架构 - 激进的缓存策略 - 最少的网络请求
实现思路:
// Optimistic update pattern
function updateIssue(id: string, changes: Partial<Issue>) {
// 1. Update local state immediately
localStore.update(id, changes)
// 2. Show success state
ui.showSaved()
// 3. Sync with server in background
api.updateIssue(id, changes).catch(() => {
// 4. Rollback only on failure
localStore.rollback(id)
ui.showError()
})
}
设计应用: - 加载状态应尽可能不可见 - 只在必要时使用骨架屏 - 永远不要阻止用户进行下一步操作
2. 键盘优先,鼠标友好
Linear 为专业用户设计,但对新手同样友好。
命令面板(Cmd+K): - 所有操作的统一入口 - 对所有内容进行模糊搜索 - 键盘快捷键可被发现 - 无需离开键盘
┌────────────────────────────────────────────────────────────┐
│ Cmd+K │
├────────────────────────────────────────────────────────────┤
│ > Search issues, projects, or commands... │
│ │
│ Recent │
│ ├─ FE-123 Fix navigation animation Cmd+O │
│ ├─ BE-456 API rate limiting Cmd+O │
│ └─ Create new issue C │
│ │
│ Commands │
│ ├─ Change status S │
│ ├─ Assign issue A │
│ └─ Set priority P │
│ │
└────────────────────────────────────────────────────────────┘
实现原则: - 每个操作都有键盘快捷键 - 快捷键采用助记设计(S 代表 Status,P 代表 Priority) - 鼠标操作完美支持。键盘操作更快 - 帮助始终只需一键之遥
3. 恰到好处的信息密度
Linear 展示大量信息却不显得杂乱。
如何平衡密度:
CLUTTERED (typical enterprise):
┌────────────────────────────────────────────────────────────┐
│ [ ] * FE-123 | Fix bug | John | High | In Progress | 2d │
│ Tags: frontend, urgent, sprint-12, reviewed │
│ Created: Jan 1 | Updated: Jan 5 | Due: Jan 10 │
│ Comments: 5 | Attachments: 2 | Subtasks: 3/5 │
├────────────────────────────────────────────────────────────┤
│ [ ] * FE-124 | Another bug | Jane | Medium | Todo | 1d │
│ ... (repeating all metadata) │
└────────────────────────────────────────────────────────────┘
LINEAR'S APPROACH:
┌────────────────────────────────────────────────────────────┐
│ [x] FE-123 Fix navigation animation bug ^ John ** │
│ [ ] FE-124 Update user profile endpoint Jane * │
│ [x] FE-125 Add dark mode toggle ^ Alex ***│
└────────────────────────────────────────────────────────────┘
^ ^
Priority Assignee Estimate
(caret) (name) (dots)
设计原则: - 在每个层级只展示必要的信息 - 用图标和符号替代文字标签 - 悬停/选中时显示详情 - 按需渐进披露
4. 一致的视觉语言
Linear 的设计系统严谨且一致。
色彩系统:
/* Linear-inspired semantic colors */
:root {
/* Status colors - highly saturated, distinct */
--status-backlog: #6B7280; /* Gray - not started */
--status-todo: #3B82F6; /* Blue - ready */
--status-progress: #F59E0B; /* Amber - in work */
--status-done: #10B981; /* Green - complete */
--status-cancelled: #EF4444; /* Red - cancelled */
/* Priority - consistent hue shift */
--priority-urgent: #EF4444; /* Red */
--priority-high: #F97316; /* Orange */
--priority-medium: #EAB308; /* Yellow */
--priority-low: #6B7280; /* Gray */
--priority-none: #374151; /* Dark gray */
/* Surface hierarchy */
--bg-primary: #0D0D0D; /* Main background */
--bg-elevated: #141414; /* Cards, panels */
--bg-hover: #1F1F1F; /* Hover states */
--bg-active: #292929; /* Active/selected */
}
字体排版:
/* Linear uses Inter for everything */
:root {
--font-family: 'Inter', -apple-system, sans-serif;
/* Tight scale, high readability */
--text-xs: 11px; /* Metadata */
--text-sm: 12px; /* Secondary */
--text-base: 13px; /* Body (smaller than typical) */
--text-lg: 14px; /* Emphasis */
--text-xl: 16px; /* Headings */
--text-2xl: 20px; /* Page titles */
}
5. 默认深色模式
Linear 选择深色模式作为主要体验。
为什么这样做有效: - 减少专业用户的眼睛疲劳(长时间工作) - 营造高端、专注的美感 - 让状态颜色更加醒目 - 与开发工具的美学风格保持一致
实现方式:
/* Dark-first design */
:root {
color-scheme: dark;
--text-primary: rgba(255, 255, 255, 0.95);
--text-secondary: rgba(255, 255, 255, 0.65);
--text-tertiary: rgba(255, 255, 255, 0.45);
--border-default: rgba(255, 255, 255, 0.08);
--border-hover: rgba(255, 255, 255, 0.12);
}
/* Light mode as override */
[data-theme="light"] {
--text-primary: rgba(0, 0, 0, 0.90);
--text-secondary: rgba(0, 0, 0, 0.60);
/* ... */
}
6. 令人愉悦的微交互
Linear 中的每一个交互都经过精心考量。
示例: - 问题卡片在悬停时会轻微上浮 - 状态变化有细腻的颜色过渡 - 拖放操作具有流畅的物理动效 - 复选框点击时有令人满意的反馈
动画原则:
/* Linear's motion */
:root {
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--duration-fast: 100ms; /* Micro feedback */
--duration-normal: 150ms; /* Standard transitions */
--duration-slow: 250ms; /* Page transitions */
}
.issue-card {
transition:
transform var(--duration-fast) var(--ease-out),
box-shadow var(--duration-normal) var(--ease-out);
}
.issue-card:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
值得学习的设计模式
命令面板
Linear 的 Cmd+K 如今已成为现代软件的标配模式。
实现指南:
<!-- Command palette structure -->
<dialog class="command-palette" aria-label="Command menu">
<header>
<input
type="text"
placeholder="Search issues or commands..."
aria-describedby="command-hint"
/>
</header>
<nav aria-label="Command results">
<section aria-label="Recent">
<h3>Recent</h3>
<ul role="listbox">
<li role="option" tabindex="0">
<span class="issue-id">FE-123</span>
<span class="issue-title">Fix bug</span>
<kbd>Cmd+O</kbd>
</li>
</ul>
</section>
<section aria-label="Commands">
<h3>Commands</h3>
<!-- ... -->
</section>
</nav>
</dialog>
上下文菜单
右键菜单精准展示你所需要的选项。
Right-click on issue:
┌────────────────────────────────┐
│ Open issue Cmd+O │
│ Open in new tab Cmd+Shft+O │
├────────────────────────────────┤
│ Set status S │
│ Set priority P │
│ Assign A │
├────────────────────────────────┤
│ Copy link Cmd+C │
│ Copy ID │
├────────────────────────────────┤
│ Delete Backspace│
└────────────────────────────────┘
行内编辑
无需弹出模态框即可编辑。
BEFORE (click to edit):
┌────────────────────────────────────────┐
│ Fix navigation bug [Edit] │
└────────────────────────────────────────┘
AFTER (inline edit on click):
┌────────────────────────────────────────┐
│ Fix navigation bug| │ ← Cursor appears
│ ────────────────── │ in place
└────────────────────────────────────────┘
从 Linear 借鉴什么
适用于任何软件项目
- 速度不可妥协 - 同时优化感知性能和实际性能
- 随处可用的快捷键 - 但不强制要求使用
- 命令面板 - 统一的功能入口
- 做好深色模式 - 不能是事后补救
- 信息密度 - 用更少的空间展示更多内容
- 一致的设计语言 - 每个元素都有关联感
具体技巧
| 技巧 | 如何应用 |
|---|---|
| 乐观 UI | 先在本地更新,后台同步 |
| 模糊搜索 | 使用 Fuse.js 或类似库实现命令面板 |
| 助记快捷键 | S 代表 Status,P 代表 Priority,A 代表 Assign |
| 微妙的层次感 | 悬停时上浮 1-2px,而非夸张的阴影 |
| 语义化颜色 | 一致的状态/优先级颜色体系 |
| 紧凑的排版 | 13px 正文字号,密集但可读 |
Linear 团队的重要观点
"我们把速度视为一项功能。如果某个操作需要 300ms,用户就会觉得出了问题。"
"每一个像素都应该是有意为之。如果你无法解释某个元素为什么存在,就把它删掉。"
"键盘优先不意味着只能用键盘。它意味着尊重高级用户。"
常见问题
是什么让 Linear 比其他项目管理工具更快?
Linear 使用乐观 UI 更新、本地优先架构和积极的缓存策略。当你更改问题状态时,UI 会立即更新,同步则在后台进行。大多数交互感觉是即时的,因为 Linear 假设操作会成功,只在真正出错时才显示错误,而不是阻塞等待网络请求。
Linear 的命令面板(Cmd+K)是如何工作的?
命令面板是一个统一入口,使用模糊搜索覆盖问题、项目和命令。它支持助记快捷键(S 代表 Status,P 代表 Priority,A 代表 Assign),用户可以通过面板发现这些快捷键,然后直接使用而无需再打开面板。这为用户创造了一条从新手到高级用户的渐进学习路径。
Linear 为什么选择深色模式作为默认?
Linear 的设计面向那些在应用中长时间工作的高级用户。深色模式可以减轻眼睛疲劳,创造出区别于典型企业软件的高端美感,并让状态颜色更加鲜明。浅色模式作为可选项存在,但深色模式才是主要的设计目标。
Linear 如何在保持高信息密度的同时不显得杂乱?
Linear 使用符号和图标替代文字标签,在列表层级只显示必要的元数据,在悬停或选中时才展示详情。排版比例比常规更紧凑(13px 正文字号),一致的间距创造出视觉节奏而不浪费空白。
Linear 的快捷键设计理念是什么?
Linear 中的每个操作都有对应的快捷键,而且快捷键都是助记式的(易于记忆)。命令面板会在每个操作旁边显示对应的快捷键来教会用户。这意味着鼠标用户完全可以正常使用,但键盘用户可以工作得更快。设计理念是"键盘优先,鼠标友好"。
资源
- 官网: linear.app
- 更新日志: Linear 的更新日志本身设计得也很精美
- 博客: 团队发布的工程和设计文章
- Twitter: @linear 获取设计更新