Communitygithub.com

Milda 設計系統語言技能

讀取、撰寫、審閱與修復 Milda 設計系統 - `.milda` 檔案 - 並以 Milda 的範式(層級中的 Token、上下文群組、原型、中立平台部件、行為驅動狀態)進行推理。每當使用者提及 Milda、Milda Studio、Milda Playground 或 `.milda` 檔案,要求編寫或修改 Milda 中的設計系統 Token 或元件,或想將 CSS、Figma 或現有元件庫轉譯為 Milda 時使用。

Milda 設計系統語言技能 是什麼?

這是一個專門用於操作 Milda 設計系統的 AI 技能。Milda 是一個附帶圖形化介面的編譯器,其 `.milda` 檔案本身就是設計系統的單一事實來源,包含基礎(Token)、元件、使用規則、文件與資產。React 套件、Figma 元件庫、文件網站以及 AI 可讀的檔案皆由此產生。使用者永遠不應直接編輯輸出,而應修改 `.milda` 檔案後重新產生。此技能專注於語言表面 **0.10** 與前奏曲 **0.0.2**。核心工作流程是「撰寫、檢查、修復」:每次編輯後必須執行 `npx -y -p @mildastudio/milda-lsp milda-check --strict` 來驗證,直到診斷結果顯示 `0 errors, 0 warnings` 為止。該技能強制執行 Milda 的十條關鍵規則,例如:系統是源頭、程式碼是輸出;元件應使用中立的 `kind`(如 `container`、`text`),而非 HTML 標籤;所有值必須透過 Token 名稱引用,不能使用字面值;上下文(如深色模式)透過 `context-group` 處理;狀態來自行為(如 `hovered`、`focus-visible`)。此技能適用於所有支援技能的平台(如 Claude Code、Cursor、Codex 等),能有效協助開發者與設計師以一致、可維護的方式建立與演化設計系統。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mildastudio/milda-skills/tree/main/skills/milda

在你喜歡的 AI 中提問

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

說明文件

Milda

Milda 是一個附帶圖形化介面的設計系統編譯器。一個 .milda 檔案就是設計系統: 基礎(Token)、元件、使用規則、文件與資產。React 套件、Figma 元件庫、 文件網站以及 AI 可讀的檔案都從它產生。你永遠不需要編輯輸出;你只要修改 檔案再重新產生即可。

此技能針對0.10語言表面與0.0.2前奏曲。你撰寫的每個檔案都必須以這兩行開頭。

循環:撰寫、檢查、修復

在讀取器(reader)同意之前,切勿告訴使用者 .milda 檔案是有效的。每次編輯後,執行:

npx -y -p @mildastudio/milda-lsp milda-check --strict path/to/system/

給它目錄,或一次給系統中的所有檔案,因為一個檔案中宣告的 Token 會解析另一個檔案中的參考。 它會輸出 path:line:col severity [code] message,與編輯器擴充功能顯示的診斷訊息相同, 並且在有任何錯誤時(或搭配 --strict 時有任何警告)以非零狀態碼退出。修復它報告的內容並 再次執行,直到它顯示 0 errors, 0 warnings。警告不是雜訊:unknown facet "background" skipped 表示那一行沒有作用。

要向使用者展示結果,位於 https://play.milda.dev 的 Playground 可以即時貼上檔案並渲染,無需帳號。

以 Milda 思考:十條規則

大多數錯誤來自於用 Milda 的語法撰寫 CSS、DOM 樹或 React 元件。這些規則 正是該語法存在的目的。

  1. 系統是源頭;程式碼是輸出。 所有與平台相關的決策都在產生時決定, 因此檔案中永遠不會包含 CSS 屬性、標籤、框架的事件名稱或 pseudo-class。
  2. 說出一件事物是什麼,而非它由什麼組成。 部件有中立的_種類_(container、 text、input、icon、control...),永遠不會是 div 或 button。每個目標平台會選擇自己的元素。
  3. 值有名稱,名稱有層級。 元件永遠不會使用字面值著色。facet 指向一個 Token;Semantic 層級 為字面值的 Base 層級設定別名。重新設計風格就是修改基礎。
  4. 上下文是一個維度,不是一個副本。 深色模式、密度、品牌:各自是一個 context-group,一個 Token 透過 alias by Group { ... } 針對每個上下文給出答案。由上下文群組型別化的 prop(variant) 在每個實例中使用相同機制。
  5. 狀態來自行為。 hovered、pressed、focus-visible、disabled、open、 selected 由原型的行為發出。使用 state hovered { } 來設定它們的樣式,永遠不要使用任何 與指標或平台相關的詞語。列表是封閉的(reference/vocabulary.md),讀取器會對任何其他詞語發出警告: state hover 會被報告並提示它可能想拼寫的是哪個詞。
  6. 合約就是識別。 props 和 events 是消費者編寫程式碼時所依賴的內容,也是版本差異比較的對象。 根據意義命名(variant、checkedChange),而不是根據平台。
  7. 從既有的內容建構。 從前奏曲中的一個 archetype 開始建立元件:它帶來了合約形狀、 必需的部件和行為(鍵盤、ARIA、焦點)。使用 instance 部件將較大的元件 從較小的元件組合而成。
  8. 每個參考都使用名稱。 部件使用點分隔路徑(Header.Title),Token 使用路徑 (space.sm 代表 space/sm),元件使用識別符。沒有 id。註解 (#) 是唯一 不會在往返過程中保留的東西。
  9. 透過接縫擴展,永遠不要修補輸出。 當詞彙無法表達某些內容時,使用 slot、每個目標的選項, 或最終手段是使用標記了目標的 foreign 內容。永遠不要建議編輯產生的程式碼。
  10. 說出它應該如何使用。 將介面約束(required、required when、 one-of)放在 props 中,將組合規則(rule ... { never X within Y })放在頂層, 每個都帶有原因。

一個檔案,從上到下

milda 0.10
prelude 0.0.2

meta { name "Acme" }

context-group ColorScheme { Light Dark }

foundations {
  layer Base {
    token violet/600 : color = hex(7c3aed)
    token white : color = hex(ffffff)
    token gray/900 : color = hex(0f172a)
  }
  layer Semantic {
    token accent : color = alias by ColorScheme { default -> violet.600 }
    token on-accent : color = alias by ColorScheme { default -> white; Dark -> gray.900 }
    token space/sm : spacing = 8px
    token radius/sm : radius = 6px
  }
}

component Button "The primary action." {
  archetype Button

  props {
    label : string = "Get started"
  }

  events {
    click
  }

  part Button: container {
    emits { click on activate }
    layout { stack row; gap space.sm; align center }
    fill accent
    ink on-accent
    corner radius.sm
    inset space.sm
    state focus-visible {
      ring accent
    }
  }

  part label: text {
    content bind label
  }
}

順序:header、meta、context-group、group(元件庫章節)、foundations、type、 component、rule,然後是 example、assets、icons、docs。根部件以元件命名; 其他部件由原型的解剖結構命名(label、icon、control...)或由你使用點分隔路徑嵌套命名。

從 CSS 和 React 到 Milda

你習慣寫的Milda 的說法
<div>, <span>, <button>part X: container / text / 原型的根部件
backgroundfill
colorink
padding, padding-inline-startinset, inset.inline-start
margin無:使用父層的 gap、對齊或 bleed
border, border-radiusborder <color> <width>, corner
box-shadow, outline (焦點)elevation, ring
font-size + line-height, font-weighttext <typography or font-size token>, weight
display: flex; flex-direction: rowlayout { stack row }
justify-content, align-items, flex: 1distribute, align, size fill
position: absolutelayout { stack layers } + 子層上使用 position overlay
:hover, :focus-visible, :disabledstate hovered { }, state focus-visible { }, ...
.btn--secondary, [data-variant]when variant = Secondary { }
.card:hover .icon在圖示部件上使用 when ancestor Card hovered { }
@media (prefers-color-scheme: dark)context-group ColorScheme + alias by ColorScheme
--space-sm: 8px / var(--space-sm)token space/sm : spacing = 8px / space.sm
#7c3aed, oklch(...)hex(7c3aed), oklch(...),僅在 Token 內部使用
color-mix(), calc()compute <token> in oklch { darken 10% }
onClick propevents { click } + emits { click on activate }
{children}在容納它們的部件上使用 slot of content default
{cond && <X/>}在部件上使用 present when <prop>
z-index, text-align, box-sizing無:部件順序、容器,只有一個盒子

部件上的 Facet、狀態與條件

  part Panel: container {
    layout { stack column; gap space.sm; size fill fit }
    fill surface
    ink text
    border line hairline
    corner radius.sm
    inset space.sm space.md
    when tone = danger {
      border danger hairline
    }
    state hovered {
      fill surface-raised
    }
    state hovered when tone = danger {
      fill danger-subtle
    }
  }

facet 的值首先解析為 Token;只有在沒有 Token 聲明該詞的情況下,才會接受單純的字面值 (opacity 50、inset 0)。優先使用 Token。when 作用於 props,state 作用於行為狀態, 兩者可以組合。

Props、事件與約束

  archetype TextField

  props {
    label : string required "欄位詢問的內容,也是它的可訪問名稱。"
    value : string
    invalid : boolean = false
    error : string required when invalid "在無效時顯示在控制項下方。"
    size : enum(sm, md) = md
    tone : context Tone = Neutral
  }

  events {
    valueChange
  }

型別:string、number、boolean、enum(a, b)、context <Group>、array<T>、你自己定義的 type。 尾隨的字串是 prop 的文件。one-of a, b / any-of / exclusive 約束一組 prop。

下一步

  • reference/syntax.md:每條陳述式都附帶經過驗證的範例(Token 和值、佈局、插槽、實例、行為、規則、文件、資產、圖示)。
  • reference/vocabulary.md:從語言套件產生。讀取器接受的每種 Token 型別、部件種類、facet、狀態、佈局詞彙和字面值函式。 對某個詞有疑問時,請查閱此處而不是亂猜。
  • reference/archetypes.md:從前奏曲產生。每個原型及其合約、解剖結構(哪些部件是必需的)和行為。
  • examples/acme.milda:一個完整、乾淨的系統,可以從中複製模式。
  • 規範文件:https://github.com/mildastudio/milda-lang/tree/main/spec(`FORMAT.md` 說明檔案保證了什麼,GRAMMAR.ebnf 說明語法,PRELUDE.md 說明原型)。
  • 對於已發布的設計系統,Milda MCP 伺服器會以精確的元件和 Token 回應;請參閱 https://milda.dev/mcp。

完成之前

  • 檔案標頭必須是 milda 0.10 和 prelude 0.0.2。
  • 元件中不能有任何字面顏色、長度或字型;每個值都必須是 Token 參考。
  • 任何地方都不能出現平台相關詞語:沒有標籤、CSS 屬性、pseudo-class 或框架事件名稱。
  • 除非是純粹由實例組合而成,否則每個元件都必須從一個原型開始。
  • 在整個系統上執行 milda-check --strict 必須顯示 0 errors, 0 warnings。

相關技能