Milda
Mildaは、デザインシステムのためのGUI付きコンパイラです。.milda ファイルこそがデザインシステムです:
ファンデーション(トークン)、コンポーネント、使用ルール、ドキュメント、アセット。Reactパッケージ、Figmaライブラリ、
ドキュメントサイト、エージェント可読ファイルはそこから生成されます。出力を編集することは決してありません。ファイルを変更して再生成します。
このスキルは、プレリュード 0.0.2 を伴う言語サーフェス 0.10 をターゲットにしています。あなたが作成するすべてのファイルは、そのヘッダーから始まります。
ループ:書く、チェックする、修正する
リーダーが同意するまで、.milda ファイルが有効であるとユーザーに伝えないでください。編集後は毎回、以下を実行してください:
npx -y -p @mildastudio/milda-lsp milda-check --strict path/to/system/
これにシステムのディレクトリ、またはシステムのすべてのファイルを一緒に渡します。なぜなら、あるファイルで宣言されたトークンが別のファイルの参照を解決するためです。path:line:col severity [code] message の形式で出力され、これはエディター拡張機能が表示するのと同じ診断メッセージです。エラーがあれば非ゼロで終了します(--strict の場合は、警告でも同様です)。報告された内容を修正し、0 errors, 0 warnings と表示されるまで再実行してください。警告は無視してはいけません:unknown facet "background" skipped は、その行が何も実行しなかったことを意味します。
ユーザーに結果を表示するには、https://play.milda.dev のプレイグラウンドでファイルを貼り付けてライブレンダリングできます。アカウントは不要です。
Mildaで考える:10のルール
ほとんどの間違いは、CSS、DOMツリー、ReactコンポーネントをMildaの構文で書こうとすることから生じます。これらのルールは、その構文が表現するために存在するものです。
- システムがソースであり、コードは出力です。 プラットフォームに関連するものはすべて生成時に決定されるため、ファイルにはCSSプロパティ、タグ、フレームワークのイベント名、擬似クラスは決して含まれません。
- 何が何でできているかではなく、何であるかを述べます。 パーツは中立的な種類(
container、text、input、icon、control、...)を持ち、divやbuttonを使うことはありません。各ターゲットは独自の要素を選択します。 - 値には名前があり、名前にはレイヤーがあります。 コンポーネントがリテラルで描画することはありません。ファセットはトークンを指します。
SemanticレイヤーはリテラルのBaseレイヤーをエイリアスします。再スタイルはファンデーションの変更です。 - コンテキストはディメンションであり、コピーではありません。 ダークモード、密度、ブランド:それぞれが
context-groupであり、トークンはコンテキストごとにalias by Group { ... }で応答します。コンテキストグループによって型付けされるprop(variant)は、インスタンスごとに同じメカニズムを使用します。 - 状態はビヘイビアから生じます。
hovered、pressed、focus-visible、disabled、open、selectedはアーキタイプのビヘイビアによって生成されます。state hovered { }でスタイル設定し、ポインターやプラットフォーム固有のものは決して使わないでください。リストは閉じており(reference/vocabulary.md)、リーダーは他の単語に対して警告を報告します:state hoverは、意図されたスペルと共に報告されます。 - 契約がアイデンティティです。
propsとeventsは、コンシューマーがコードで扱う対象であり、バージョン管理で差分をとる対象です。プラットフォームではなく、意味に基づいて名前を付けます(variant、checkedChange)。 - 既存のものから構築します。 プレリュードの
archetypeからコンポーネントを開始します:契約の形状、必要なパーツ、ビヘイビア(キーボード、ARIA、フォーカス)をもたらします。instanceパーツを使って、より小さなコンポーネントからより大きなコンポーネントを構成します。 - すべての参照は名前で行います。 パーツはドット区切りパス(
Header.Title)、トークンはパス(space.smでspace/sm)、コンポーネントは識別子で参照します。IDはありません。コメント(#)のみがラウンドトリップ後も保持されません。 - 継ぎ目を通じて拡張し、出力にパッチを当てることはしません。 語彙で表現できない場合は、
slot、ターゲットごとのオプション、または最後の手段として、ターゲットでタグ付けされたforeignコンテンツを使用します。生成されたコードを編集することを提案しないでください。 - どのように使用されることを意図しているかを述べます。 インターフェース制約(
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 "主要なアクション。" {
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
}
}
順序:ヘッダー、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 / アーキタイプのルート |
background | fill |
color | ink |
padding, padding-inline-start | inset, inset.inline-start |
margin | なし:親の gap、配置、または bleed |
border, border-radius | border <color> <width>, corner |
box-shadow, outline (フォーカス) | elevation, ring |
font-size + line-height, font-weight | text <typography or font-size token>, weight |
display: flex; flex-direction: row | layout { stack row } |
justify-content, align-items, flex: 1 | distribute, align, size fill |
position: absolute | layout { stack layers } + 子に position overlay |
:hover, :focus-visible, :disabled | state 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(...)、トークン内のみ |
color-mix(), calc() | compute <token> in oklch { darken 10% } |
onClick プロパティ | events { click } + emits { click on activate } |
{children} | それらを保持するパーツに slot of content default |
{cond && <X/>} | パーツに present when <prop> |
z-index, text-align, box-sizing | なし:パーツ順序、コンテナー、ボックスは1つ |
パーツ上のファセット、状態、条件
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
}
}
ファセットの値は最初にトークンとして解決されます。単独のリテラルは、その単語をトークンが主張しない場合にのみ受け入れられます(opacity 50、inset 0)。トークンを優先してください。when はプロパティにキーを置き、state はビヘイビア状態にキーを置き、両者は組み合わせられます。
プロパティ、イベント、制約
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。末尾の文字列はプロパティのドキュメントです。one-of a, b / any-of / exclusive はプロパティのグループを制約します。
次に参照すべき場所
- reference/syntax.md: すべてのステートメントと確認済みの例(トークンと値、レイアウト、スロット、インスタンス、ビヘイビア、ルール、ドキュメント、アセット、アイコン)。
- reference/vocabulary.md: 言語パッケージから生成されます。リーダーが受け入れるすべてのトークンタイプ、パーツの種類、ファセット、状態、レイアウトワード、リテラル関数。単語に迷ったら、推測せずにこちらを参照してください。
- reference/archetypes.md: プレリュードから生成されます。各アーキタイプの契約、構造(必須のパーツ)、ビヘイビア。
- examples/acme.milda: パターンをコピーするための、完全でクリーンなシステム。
- 規範的な仕様: https://github.com/mildastudio/milda-lang/tree/main/spec(`FORMAT.md` はファイルの約束事、
GRAMMAR.ebnfは構文、PRELUDE.mdはアーキタイプについて)。 - すでに公開されているデザインシステムについては、Milda MCPサーバーが正確なコンポーネントとトークンで応答します。https://milda.dev/mcp を参照してください。
終了前に確認すること
- ヘッダーに
milda 0.10とprelude 0.0.2が含まれていること。 - コンポーネント内にリテラルの色、長さ、フォントがないこと。すべての値はトークン参照であること。
- プラットフォーム用語(タグ、CSSプロパティ、擬似クラス、フレームワークのイベント名)がどこにも使われていないこと。
- すべてのコンポーネントがアーキタイプから始まっているか、インスタンスの純粋な構成であること。
- システム全体に対して
milda-check --strictが0 errors, 0 warningsを出力すること。