Communitygithub.com

askarthemasss/drawn-notebook-ui

一個完整的設計系統與實作指南,用於重現「繪本筆記本」美學——一種安靜、編輯風格、手工打造的 UI 語言。

drawn-notebook-ui 是什麼?

這個技能提供了一個詳盡的設計語言參考,名為「Drawn Notebook」,由 Askar 為其個人作品集所創作。它不僅僅是一個元件庫,而是一套完整的美學哲學,涵蓋了所有設計 Token、元件、動畫和互動模式。文件內容極其詳細,分別針對 Flutter (Dart) 和純網頁 (HTML/CSS/JS) 平台,並同時支援淺色與深色模式。其核心原則包括:沈靜的信心、手繪風格而非擬物化、以章節為單位的敘事性捲動,以及強調緩慢、有意義的動畫來引導使用者。它明確禁止使用常見的 AI 生成設計模式,例如漸層英雄區、霓虹 hover 效果或表情符號裝飾。開發者可以將此技能視為終極參考,在執行任何專案時,只要使用者希望建立或擴展此特定視覺語言,都應依序遵循所有章節,從標記定義開始,並同時確保兩個主題的正確性。

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/askarthemasss/craftsman-skills/tree/HEAD/skills/drawn-notebook-ui

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

drawn-notebook-ui 是做什麼的?


name: drawn-notebook-ui description: > 一個完整的設計系統與實作指南,用於重現「繪本筆記本」美學 (Drawn Notebook) — 一種安靜、編輯風格、手工打造的 UI 語言,最初為 Askar 的個人作品集所創作。詳細涵蓋每個標記、元件、動畫和互動模式,針對 Flutter (Dart) 和純網頁 (HTML/CSS/JS) 兩種平台,並同時支援淺色與深色模式。每當使用者想要在任何情境下建置、改編或擴展此特定視覺語言時,請使用此技能。


概述

Drawn Notebook 不是一個元件庫。它是一種設計語言 — 一個連貫的哲學,服務於每個像素、每條線條粗細、每個間距節奏和每個動畫時序曲線。其指導原則是,介面應該感覺像一本活生生的筆記本:用墨水繪製在奶油色紙上,段落隨著讀者向下捲動而緩慢揭示,像實體旅程一樣橫跨頁面的導航線索。沒有什麼是喧囂的。沒有什麼是為了裝飾而裝飾。UI 透過將每個視覺元素錨定在意義上來贏得它們。

這個技能是一份精確、全面的參考文件。在實作此 UI 時,請依序遵循每個章節。不要跳過標記定義 — 每個間距、顏色和動畫值都是承重的。不要跳過深色模式章節 — 兩個主題都是平等的第一等公民,必須始終同時保持正確。


第 1 節 — 設計理念

1.1 核心原則

沈靜的信心,而非為了極簡而極簡。 設計雖然簡潔,但留下的每個元素都是有意義的。空白空間並非懶惰 — 而是頁面在呼吸。使用者的視線由構圖、重量和動畫引導,而非由色彩飽和度或裝飾性花邊引導。

手繪美學,但非字面上的擬物化。 UI 參考了繪畫的工藝 — 細線條粗細、襯線編輯字體、紙張紋理、以線條畫呈現的 SVG 插圖 — 但它並未假裝自己是紙張。它是一個尊重類比工藝觸感但又不笨拙模仿的數位表面。

每個區塊都是一個章節。 頁面是一個連續的捲動頁面,每個區塊感覺就像翻開筆記本的新一頁。區塊背景在暖色中性色調之間微妙地轉換。一條連續的金色線條(旅程線 SVG)將它們在視覺上縫合在一起。

動畫是敘事,而非娛樂。 動畫揭示內容的方式就像手寫文字 — 從下往上出現、柔和淡入、追蹤 SVG 路徑。持續時間以現代標準來看是慢的(揭示動畫為 1.2 秒至 2 秒)。這是刻意的。速度意味著噪音。緩慢意味著工藝。

避免 AI 生成的垃圾模式。 以下模式被明確禁止:帶有紫色到粉紅色漸層的英雄背景、具有相同高度和相同圓角的卡片網格、發出霓虹光的懸停狀態、大多數元素上過大的圓角(> 14px)、帶有百分比數字的顏色編碼技能條、帶有項目符號和粗體日期的時間線,以及任何將表情符號用作裝飾的行為。


第 2 節 — 設計標記

2.1 色彩調色盤 — 淺色模式(日光筆記本)

淺色模式中的每種顏色都是源自紙張、奶油色和天然墨水的暖色中性色。只有一個重點色系列:金色/陶土色,範圍從柔和的琥珀色到暖磚色。

/* 淺色模式(應用於 :root) */
--cream:       #F7F5F0;   /* 頁面背景 — 主要表面 */
--sage:        #EEF3ED;   /* 關於區塊背景 — 最淺的灰綠色 */
--parchment:   #F1ECE3;   /* 經歷 + 履歷區塊背景 */
--warm-white:  #FAF8F5;   /* 技能區塊背景 — 最淺的表面 */
--linen:       #F3EFE8;   /* 專案區塊背景 */
--sage-tint:   #EFF3EE;   /* 學習區塊背景 */
--charcoal:    #1A1A1A;   /* 主要文字,SVG 線條,邊框 */
--soft-black:  #2C2C2C;   /* 次要文字,強標籤 */
--warm-grey:   #8A8580;   /* 淡化標籤,時間戳,說明文字 */
--light-grey:  #C5BFB8;   /* 捲動提示,裝飾性分隔線 */
--terracotta:  #B87A5A;   /* 懸停狀態,項目符號,活動路徑點 */
--indigo:      #6B6EA0;   /* 保留 — 未在主要模式中使用 */
--gold:        #C4956A;   /* 主要重點色 — 旅程線,技能圖示,標籤 */
--gold-dim:    rgba(196, 149, 106, 0.3);  /* 淡金色用於陰影,邊框 */
--blush:       #F0EBE5;   /* 懸停狀態下的標籤/徽章背景 */
--sage-dark:   #8B9E8B;   /* 區塊邊框分隔線色調 */

2.2 色彩調色盤 — 深色模式(夜間筆記本)

深色模式不是簡單的反色。背景從暖奶油色轉變為深暖黑色 — 一種幾乎像墨水漬的質感。重點色稍微變亮以維持在深色背景上的可讀性。

/* 深色模式(應用於 :root[data-theme="dark"]) */
--cream:       #141210;   /* 頁面背景 — 深暖黑色 */
--sage:        #171816;   /* 關於區塊背景 */
--parchment:   #1A1815;   /* 經歷 + 履歷背景 */
--warm-white:  #1E1B18;   /* 技能區塊背景 */
--linen:       #181614;   /* 專案區塊背景 */
--sage-tint:   #161815;   /* 學習區塊背景 */
--charcoal:    #EDE8E1;   /* 主要文字 — 暖米白色 */
--soft-black:  #D8D2C8;   /* 次要文字 */
--warm-grey:   #9E978F;   /* 淡化標籤 */
--light-grey:  #38342E;   /* 裝飾性分隔線 */
--terracotta:  #D98A62;   /* 懸停重點色 — 比淺色模式稍亮 */
--indigo:      #8C8FB8;
--gold:        #D4A373;   /* 主要重點色 — 比淺色模式稍暖 */
--gold-dim:    rgba(212, 163, 115, 0.3);
--blush:       #241E1A;
--sage-dark:   #9EAF9E;

/* 表面標記 */
--card-glass:         rgba(30, 27, 24, 0.72);
--card-glass-hover:   rgba(42, 38, 34, 0.95);
--card-item-bg:       rgba(24, 21, 19, 0.78);
--card-item-hover:    rgba(38, 34, 30, 0.96);
--card-border:        rgba(212, 163, 115, 0.22);
--card-border-hover:  rgba(212, 163, 115, 0.48);
--card-shadow:        0 4px 16px rgba(0, 0, 0, 0.25);
--card-shadow-hover:  0 6px 20px rgba(0, 0, 0, 0.45);
--card-inset:         inset 0 1px 0 rgba(255, 255, 255, 0.05);
--card-inset-hover:   inset 0 1px 0 rgba(255, 255, 255, 0.08);
--badge-bg:           rgba(24, 21, 19, 0.88);
--grain-opacity:      0.022;    /* 深色模式中較低以避免混濁 */

2.3 色彩調色盤 — 淺色模式表面標記

/* 淺色模式表面標記 */
--card-glass:         rgba(255, 255, 255, 0.65);
--card-glass-hover:   #ffffff;
--card-item-bg:       rgba(247, 245, 240, 0.8);
--card-item-hover:    rgba(255, 255, 255, 0.98);
--card-border:        rgba(196, 149, 106, 0.22);
--card-border-hover:  rgba(196, 149, 106, 0.45);
--card-shadow:        0 4px 16px rgba(26, 26, 26, 0.04);
--card-shadow-hover:  0 6px 20px rgba(196, 149, 106, 0.12);
--card-inset:         inset 0 1px 0 rgba(255, 255, 255, 0.9);
--card-inset-hover:   inset 0 1px 0 rgba(255, 255, 255, 0.95);
--badge-bg:           rgba(247, 245, 240, 0.82);
--grain-opacity:      0.035;

2.4 主題切換 — 無閃爍實作

主題檢測必須在頁面渲染前同步執行於 <head> 中,以防止錯誤主題閃爍 (FOUT)。這是一個關鍵的實作需求:

<head>
  <!-- 必須是 <head> 中的第一個 script,在任何樣式表連結之前 -->
  <script>
    (function () {
      try {
        var stored = localStorage.getItem('color-scheme');
        var prefersDark = window.matchMedia &&
          window.matchMedia('(prefers-color-scheme: dark)').matches;
        var theme = (stored === 'dark' || (!stored && prefersDark)) ? 'dark' : 'light';
        document.documentElement.setAttribute('data-theme', theme);
        var meta = document.querySelector('meta[name="color-scheme"]');
        if (meta && (stored === 'dark' || stored === 'light')) meta.content = stored;
        var themeColor = document.querySelector('meta[name="theme-color"]');
        if (themeColor) themeColor.content = theme === 'dark' ? '#141210' : '#F8F4F0';
      } catch (e) {}
    })();
  </script>
</head>

在 Flutter/Dart 中,使用 ThemeMode.system 作為預設值,並透過 SharedPreferences 進行持久化覆寫。鍵為 color-scheme,值為 'dark' 或 'light'。

2.5 字體標記

--font-serif: 'Cormorant Garamond', 'Georgia', serif;
--font-sans:  'Inter', 'Helvetica Neue', sans-serif;

Cormorant Garamond 對此設計的編輯語調是不可妥協的。它載入了 300, 400, 500, 600 粗細,並包含 300 和 400 粗細的斜體變體。它用於所有標題、區塊標題、英雄名稱、標籤、側欄標籤、路徑點訊息,以及任何需要「書寫」質感的地方。它絕不能在 600 粗細以上使用 — 這不是一個粗體字體。

Inter 是功能性輔助字體。它用於說明文字、技能標籤、時間戳、大寫引言,以及密集資訊上下文中的正文。僅載入 300, 400, 500 粗細。

/* Google Fonts 導入 */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&family=Inter:wght@300;400;500&display=swap');

2.6 間距標記

所有間距均使用 clamp() 實現流體排版。請勿對區塊內距或內容寬度限制使用硬編碼的像素值。

--section-pad:   clamp(80px, 12vh, 160px);  /* 主要區塊的垂直內距 */
--content-max:   800px;                      /* 窄版散文列 */
--content-wide:  1100px;                     /* 用於網格的寬版面 */
--side-pad:      clamp(24px, 5vw, 80px);     /* 頁面水平邊距 */

2.7 動畫標記

--ease-out:     cubic-bezier(0.25, 0.46, 0.45, 0.94);  /* 一般的 easing-out */
--ease-smooth:  cubic-bezier(0.4, 0, 0.2, 1);           /* 類 Material 平滑 */
--duration-slow: 1.2s;   /* 揭示動畫 */
--duration-med:  0.8s;   /* 中等過渡 */
--duration-fast: 0.4s;   /* 快速微互動 */

第 3 節 — 全域基礎

3.1 CSS 重置與基礎

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background-color: var(--cream);
  color: var(--charcoal);
  font-family: var(--font-sans);
  font-weight: 300;
  line-height: 1.7;
  overflow-x: hidden;
  position: relative;
}

3.2 文字選取

選取反白是柔和的金色洗滌 — 它反映了重點色調色盤,而不會過於強烈:

::selection {
  background: rgba(196, 149, 106, 0.2);
  color: var(--charcoal);
}
::-moz-selection {
  background: rgba(196, 149, 106, 0.2);
  color: var(--charcoal);
}

3.3 SVG 線條適應

所有內聯 SVG 都使用淺色模式調色盤的硬編碼十六進制線條顏色(#1A1A1A、#2C2C2C)。若要將它們適應深色模式而無需修改 SVG 標記,請使用 CSS 屬性選擇器覆寫:

svg [stroke="#1A1A1A"], svg [stroke="#1a1a1a"] { stroke: var(--charcoal); }
svg [fill="#1A1A1A"],   svg [fill="#1a1a1a"]   { fill:   var(--charcoal); }
svg [stroke="#2C2C2C"], svg [stroke="#2c2c2c"] { stroke: var(--soft-black); }
svg [fill="#2C2C2C"],   svg [fill="#2c2c2c"]   { fill:   var(--soft-black); }
svg text[fill="#1A1A1A"]                        { fill:   var(--charcoal); }
svg text[fill="#8A8580"]                        { fill:   var(--warm-grey); }

SVG 中的金色重點色 (#C4956A) 特意不被覆寫。 金色重點色在兩個主題中都是固定的參考顏色;在深色模式中,標記 --gold 會變亮為 #D4A373,但內聯 SVG 金色不需要重新映射,因為它與深色背景的對比度仍然可以接受。

3.4 平滑主題過渡

對每個在主題間變更的表面套用協調的過渡。這可以防止突兀的顏色跳躍:

body, section,
.about, .experience, .resume-section, .skills, .projects, .learning, .closing,
.exp-card, .exp-item, .skill-cell, .compact-card, .compact-card__icon,
.about__point, .about__visual-card, .about__chip, .closing__link,
.journey-waypoint__message, .rail-node__label, .resume-modal__panel,
.resume-modal__header {
  transition:
    background-color 0.35s var(--ease-out),
    color 0.35s var(--ease-out),
    border-color 0.35s var(--ease-out);
}

/* 始終尊重使用者動作偏好 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; }
}

第 4 節 — 紙張紋理疊加層

一個微妙的紙張紋理圖層會作為整個視口固定的疊加層套用。它位於 z-index: 9999 — 在所有元素之上 — 但 pointer-events: none 確保它永遠不會攔截互動。

.grain-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: var(--grain-opacity, 0.035);
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 200px 200px;
  transform: translateZ(0);
  will-change: transform;
  transition: opacity 0.35s var(--ease-out);
}

/* 在深色模式中,螢幕混合模式能更自然地呈現紋理 */
:root[data-theme="dark"] .grain-overlay {
  mix-blend-mode: screen;
}

在 Flutter 中: 在元件樹頂部使用一個帶有基於 shader 噪點模式的 CustomPaint widget 來重現此效果,或將紋理作為 ~3% 透明度的 PNG 資產烘焙,並在深色模式中使用 BlendMode.screen。


第 5 節 — 主題切換(天體切換器)

主題切換按鈕是一個位於右上角固定定位的小藥丸按鈕。它

…

[此處內容因原文截斷而省略]

相關技能