Arc 瀏覽器:重新想像瀏覽器介面

深入剖析Arc Browser的設計系統:側邊欄導航、Spaces、命令列、Boosts,以及革命性的設計模式。包含CSS、SwiftUI和TypeScript程式碼範例。

4 分鐘閱讀 206 字
Arc 瀏覽器:重新想像瀏覽器介面 screenshot

Arc 瀏覽器:重新想像瀏覽器介面

「瀏覽器現在就是作業系統。那為什麼它看起來還像 2008 年的軟體?」— Josh Miller,The Browser Company

Arc 質疑了每一個瀏覽器的既有假設,從分頁位置到視窗管理。結果是一款感覺更像創意工具而非實用程式的瀏覽器。


核心要點

  1. 垂直側邊欄勝過水平分頁 - 分頁標題保持可讀,而現代寬螢幕顯示器上垂直空間充裕
  2. 空間區隔心智情境 - 工作、個人和專案分頁永不混淆,降低認知負擔
  3. 命令列 > 網址列 - 跨分頁、歷史記錄和操作的通用搜尋,消除了完美整理的需求
  4. 使用者自訂建立忠誠度 - Boosts 讓使用者自行修復惱人的網站,創造個人投入感
  5. 介面份量匹配任務 - Little Arc 證明並非每個任務都需要完整的瀏覽器介面

Arc 為何重要

Arc 證明了即使是最根深蒂固的介面也能被重新想像。Chrome、Firefox、Safari 都遵循數十年前建立的相同基本佈局。Arc 透過將瀏覽器視為工作空間而非視窗管理器,打破了這個框架。

關鍵成就: - 完全消除傳統分頁列 - 讓瀏覽器介面感覺像 macOS 原生應用 - 創造有意義的個人/工作區隔 - 開創瀏覽器層級的網站自訂功能 - 為鍵盤優先導航而設計


核心設計原則

1. 側邊欄革命

Arc 最顯眼的創新:以垂直側邊欄取代水平分頁,依情境而非時序來組織內容。

TRADITIONAL TAB BAR:
┌──────────────────────────────────────────────────────────────┐
│ [←][→][↻] │ Tab 1 │ Tab 2 │ Tab 3 │ Tab 4 │ Tab 5 │ ... │ + │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│                    Page Content                              │
│                                                              │
└──────────────────────────────────────────────────────────────┘
 Problems: Tabs shrink to unreadable, no organization, endless row

ARC'S SIDEBAR MODEL:
┌────────────────┬─────────────────────────────────────────────┐
│  [*] Space     │                                             │
│  ───────────── │                                             │
│  Pinned        │                                             │
│    Gmail       │                                             │
│    Calendar    │          Page Content                       │
│    Notion      │          (full width)                       │
│                │                                             │
│  ───────────── │                                             │
│  Today         │                                             │
│    Tab 1       │                                             │
│    Tab 2       │                                             │
│    Tab 3       │                                             │
│                │                                             │
│  [+ New Tab]   │                                             │
└────────────────┴─────────────────────────────────────────────┘
 Benefits: Readable titles, pinned favorites, organized by purpose

關鍵洞察:水平空間珍貴;垂直空間充裕。使用側邊欄讓分頁標題有呼吸空間。

CSS 模式(可摺疊側邊欄):

.sidebar {
  --sidebar-width: 240px;
  --sidebar-collapsed: 48px;

  width: var(--sidebar-width);
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  transition: width 0.2s ease-out;
}

.sidebar.collapsed {
  width: var(--sidebar-collapsed);
}

.sidebar.collapsed .tab-title {
  opacity: 0;
  pointer-events: none;
}

/* Hover to peek */
.sidebar.collapsed:hover {
  width: var(--sidebar-width);
}

.sidebar.collapsed:hover .tab-title {
  opacity: 1;
  transition: opacity 0.15s ease-in 0.1s; /* Delay for smooth reveal */
}

SwiftUI 模式:

struct SidebarView: View {
    @State private var isCollapsed = false
    @State private var isHovering = false

    private var effectiveWidth: CGFloat {
        isCollapsed && !isHovering ? 48 : 240
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            PinnedSection()
            Divider()
            TodaySection()
            Spacer()
            NewTabButton()
        }
        .frame(width: effectiveWidth)
        .animation(.easeOut(duration: 0.2), value: effectiveWidth)
        .onHover { isHovering = $0 }
    }
}

2. 空間:基於情境的組織

空間區隔工作與個人、專案與專案。每個空間是一個完整的瀏覽器情境,擁有自己的分頁、釘選網站,甚至主題。

SPACE ARCHITECTURE:

┌─────────────────────────────────────────────────────────────┐
│                        Arc Browser                          │
├───────────┬───────────┬───────────┬─────────────────────────┤
│  Work     │  Personal │  Project  │                         │
│  Space    │  Space    │  Space    │    Content Area         │
│  ─────    │  ─────    │  ─────    │                         │
│  • Slack  │  • Gmail  │  • GitHub │                         │
│  • Docs   │  • Reddit │  • Figma  │                         │
│  • Jira   │  • Netflix│  • Notion │                         │
└───────────┴───────────┴───────────┴─────────────────────────┘

Each Space has:
├── Unique pinned tabs
├── Separate "Today" tabs
├── Own color theme/gradient
├── Isolated browsing context
└── Keyboard shortcut (Cmd+1, Cmd+2, etc.)

關鍵洞察:心智情境不應洩漏。工作分頁出現在個人時間會造成認知摩擦。

資料模型:

interface Space {
  id: string;
  name: string;
  icon?: string;
  gradient: {
    from: string;
    to: string;
    angle: number;
  };
  pinnedTabs: Tab[];
  todayTabs: Tab[];
  archivedTabs: Tab[];
  profile?: BrowserProfile; // Different cookies, history, etc.
}

interface Tab {
  id: string;
  url: string;
  title: string;
  favicon?: string;
  isPinned: boolean;
  lastAccessed: Date;
  parentFolderId?: string;
}

SwiftUI 實作:

struct SpaceSwitcher: View {
    @Binding var currentSpace: Space
    let spaces: [Space]

    var body: some View {
        HStack(spacing: 8) {
            ForEach(spaces) { space in
                SpaceButton(
                    space: space,
                    isActive: space.id == currentSpace.id
                ) {
                    withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
                        currentSpace = space
                    }
                }
            }
        }
        .padding(.horizontal, 12)
    }
}

struct SpaceButton: View {
    let space: Space
    let isActive: Bool
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Circle()
                .fill(
                    LinearGradient(
                        colors: [space.gradient.from, space.gradient.to],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
                .frame(width: 24, height: 24)
                .overlay {
                    if isActive {
                        Circle()
                            .strokeBorder(.white, lineWidth: 2)
                    }
                }
        }
        .buttonStyle(.plain)
        .keyboardShortcut(space.keyboardShortcut)
    }
}

3. Command Bar:瀏覽器版的 Spotlight

Arc 的 Command Bar(Cmd+T)不僅僅是網址列,它提供跨分頁、歷史記錄、書籤和操作的通用搜尋功能。

COMMAND BAR 互動:

┌─────────────────────────────────────────────────────────────┐
│  > 搜尋分頁、歷史記錄,或輸入網址...                         │
├─────────────────────────────────────────────────────────────┤
│  開啟的分頁                                                  │
│    [doc] Notion - 專案規劃                    Cmd+1         │
│    [doc] GitHub - Pull Request #123                         │
│                                                             │
│  歷史記錄                                                    │
│    [>] Figma - 設計系統(2 小時前)                          │
│    [>] MDN - CSS Grid 指南(昨天)                           │
│                                                             │
│  操作                                                        │
│    [*] 新增筆記                               Cmd+Shift+N   │
│    [*] 分割視圖                               Cmd+Shift+\   │
│    [*] 複製網址                               Cmd+Shift+C   │
└─────────────────────────────────────────────────────────────┘

關鍵洞察:搜尋應該比整理更快。好的搜尋功能能消除對完美整理的需求。

CSS 模式:

.command-bar {
  --bar-width: min(600px, 90vw);

  position: fixed;
  top: 20%;
  left: 50%;
  transform: translateX(-50%);
  width: var(--bar-width);
  background: var(--surface-elevated);
  border-radius: var(--radius-lg);
  box-shadow:
    0 4px 24px rgba(0, 0, 0, 0.2),
    0 0 0 1px rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.command-input {
  width: 100%;
  padding: 16px 20px;
  font-size: 18px;
  background: transparent;
  border: none;
  color: var(--text-primary);
}

.command-results {
  max-height: 400px;
  overflow-y: auto;
  border-top: 1px solid var(--border-subtle);
}

.command-result {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 20px;
  cursor: pointer;
}

.command-result:hover,
.command-result.selected {
  background: var(--surface-hover);
}

.command-result-shortcut {
  margin-left: auto;
  font-size: 12px;
  color: var(--text-secondary);
  font-family: var(--font-mono);
}

4. Boosts:使用者層級的自訂功能

Boosts 讓使用者能夠將自訂 CSS 和 JavaScript 注入任何網站:打造個人化的深色模式、簡化的介面,或增強的功能。

BOOST 概念:

未使用 Boost:                    使用 Boost 後:
┌─────────────────────┐          ┌─────────────────────┐
│ [頁首]              │          │                     │
│ [導覽列]            │          │                     │
│ [側邊欄] [內容]     │    →     │     [內容]          │
│ [頁尾]              │          │     (簡潔、專注)     │
│ [Cookie 橫幅]       │          │                     │
└─────────────────────┘          └─────────────────────┘

使用者自訂 CSS:
- 隱藏干擾元素
- 更改顏色/字型
- 提升可讀性

關鍵洞察:每個使用者都有每天造訪、但希望能有不同運作方式的網站。賦予他們掌控權。

實作模式:

interface Boost {
  id: string;
  name: string;
  domain: string; // "github.com" or "*.google.com"
  enabled: boolean;
  css?: string;
  js?: string;
  createdAt: Date;
}

// Example Boost: Clean YouTube
const youtubeBoost: Boost = {
  id: 'youtube-clean',
  name: 'Clean YouTube',
  domain: 'youtube.com',
  enabled: true,
  css: `
    /* Hide recommendations */
    #secondary,
    ytd-browse[page-subtype="home"] ytd-rich-grid-renderer {
      display: none !important;
    }

    /* Hide comments */
    #comments {
      display: none !important;
    }

    /* Expand video */
    #primary {
      max-width: 100% !important;
    }
  `
};

SwiftUI Boost 編輯器:

struct BoostEditor: View {
    @Binding var boost: Boost
    @State private var activeTab: BoostTab = .css

    enum BoostTab: String, CaseIterable {
        case css = "CSS"
        case javascript = "JavaScript"
    }

    var body: some View {
        VStack(spacing: 0) {
            // Domain selector
            HStack {
                Image(systemName: "globe")
                TextField("Domain (e.g., github.com)", text: $boost.domain)
                    .textFieldStyle(.plain)
            }
            .padding()
            .background(.ultraThinMaterial)

            // Tab selector
            Picker("", selection: $activeTab) {
                ForEach(BoostTab.allCases, id: \.self) { tab in
                    Text(tab.rawValue).tag(tab)
                }
            }
            .pickerStyle(.segmented)
            .padding()

            // Code editor
            CodeEditor(
                text: activeTab == .css ? $boost.css : $boost.js,
                language: activeTab == .css ? .css : .javascript
            )
        }
    }
}

5. Little Arc:極簡設計哲學

Little Arc 是一個獨立的極簡視窗,專為快速任務設計:單一分頁、無介面裝飾、零干擾。

FULL ARC:                         LITTLE ARC:
┌────────┬────────────────┐      ┌────────────────────────┐
│Sidebar │                │      │ ← google.com/search... │
│        │    Content     │      ├────────────────────────┤
│        │                │      │                        │
│        │                │  →   │    Search Results      │
│        │                │      │    (just the content)  │
└────────┴────────────────┘      └────────────────────────┘

使用情境:
- 快速搜尋
- 查看單一資訊
- 開啟來自其他應用程式的連結

關鍵洞察:並非每項任務都需要完整的瀏覽器。讓介面與任務的重要程度相匹配。

CSS 模式(極簡介面框架):

.mini-browser {
  --chrome-height: 36px;

  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.mini-chrome {
  height: var(--chrome-height);
  display: flex;
  align-items: center;
  padding: 0 12px;
  background: var(--surface-1);
  gap: 8px;
}

.mini-url-bar {
  flex: 1;
  padding: 4px 8px;
  font-size: 13px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
}

.mini-content {
  height: calc(100% - var(--chrome-height));
}

可遷移的設計模式

模式 1:暫時性 vs. 持久性

Arc 的「Today」區段會在 12 小時後自動歸檔分頁。持久性項目必須明確釘選。

interface EphemeralityConfig {
  defaultLifetime: number; // milliseconds
  onExpire: 'archive' | 'close' | 'prompt';
  exceptions: string[]; // domains that never expire
}

function shouldArchive(tab: Tab, config: EphemeralityConfig): boolean {
  const age = Date.now() - tab.lastAccessed.getTime();
  if (config.exceptions.includes(new URL(tab.url).hostname)) {
    return false;
  }
  return age > config.defaultLifetime;
}

模式 2:分割視圖

並排瀏覽,無需管理多個視窗。

struct SplitView: View {
    @State private var splitRatio: CGFloat = 0.5
    let leftTab: Tab
    let rightTab: Tab

    var body: some View {
        GeometryReader { geometry in
            HStack(spacing: 1) {
                WebView(tab: leftTab)
                    .frame(width: geometry.size.width * splitRatio)

                // Draggable divider
                Rectangle()
                    .fill(.quaternary)
                    .frame(width: 4)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                let newRatio = value.location.x / geometry.size.width
                                splitRatio = max(0.2, min(0.8, newRatio))
                            }
                    )

                WebView(tab: rightTab)
            }
        }
    }
}

模式 3:漸層識別

每個 Space 都有獨特的漸層色彩,提供即時的視覺識別。

.space-gradient {
  --gradient-work: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  --gradient-personal: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  --gradient-project: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}

.space-indicator {
  width: 100%;
  height: 4px;
  background: var(--current-gradient);
}

.space-badge {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--current-gradient);
  display: flex;
  align-items: center;
  justify-content: center;
}

設計啟示

  1. 挑戰既有假設:分頁列並非神聖不可侵犯;沒有什麼是
  2. 情境分離:不同任務值得擁有不同的環境
  3. 鍵盤優先:進階使用者無需滑鼠即可導航
  4. 漸進式複雜度:預設簡單,需要時才展現強大功能
  5. 使用者自訂:讓人們能夠打造屬於自己的軟體
  6. 適當的份量:介面複雜度應與任務複雜度相匹配

常見問題

為什麼 Arc 使用垂直側邊欄而非水平分頁?

當你開啟大量頁面時,水平分頁會縮小到無法閱讀的寬度。垂直側邊欄利用現代寬螢幕顯示器上充裕的螢幕高度,讓分頁標題完整可見。側邊欄還能實現釘選區塊和資料夾等組織功能,這些在水平排列下效果不佳。

Arc Spaces 與瀏覽器設定檔有何不同?

Spaces 比完整的瀏覽器設定檔更為輕量。設定檔會建立完全獨立的瀏覽器實例(不同的 cookies、歷史記錄、擴充功能),而 Spaces 則共享你的瀏覽器設定,僅依情境組織分頁。你可以用快捷鍵即時切換 Spaces,而切換設定檔則需要重新啟動或開啟新視窗。

Arc「今日」區塊中的分頁會怎樣?

「今日」區塊中的分頁在閒置 12 小時後會自動封存。它們不會被刪除,而是移至可搜尋的封存區。這既防止了分頁囤積,又保持內容可恢復。釘選的分頁永遠不會自動封存。

我可以在自己的應用程式中使用 Arc 的設計模式嗎?

可以。本文記錄的模式(可摺疊側邊欄、命令面板、Spaces 架構、Boost 系統)都是可轉移的概念。程式碼範例展示了 CSS、SwiftUI 和 TypeScript 的實作方式,你可以加以調整。側邊欄和命令列模式特別適合任何內容密集型應用程式。

Arc 的 Command Bar 相較傳統網址列有何改進?

傳統網址列搜尋歷史記錄並建議網址。Arc 的 Command Bar 則從單一輸入框搜尋已開啟的分頁、歷史記錄、書籤和可用操作。你可以找到某個開啟的分頁、執行命令或導航到新位置,無需切換情境或記住東西放在哪裡。


參考資料