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이 아닌 종료 코드로 종료됩니다. 보고된 내용을 수정하고 0 errors, 0 warnings가 나올 때까지 다시 실행하세요. 경고는 무시할 수 없습니다: unknown facet "background" skipped는 해당 줄이 아무 효과도 없었음을 의미합니다.
사용자에게 결과를 보여주려면 https://play.milda.dev 플레이그라운드에서 파일을 붙여넣어 실시간으로 렌더링할 수 있으며, 계정이 필요 없습니다.
Milda로 생각하기: 열 가지 규칙
대부분의 실수는 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-groups, groups (라이브러리 섹션), foundations, types, components, rules, 그 다음 examples, 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 prop | events { click } + emits { click on activate } |
{children} | 해당 파트에 slot of content default |
{cond && <X/>} | 해당 파트에 present when <prop> |
z-index, text-align, box-sizing | 없음: 파트 순서, 컨테이너, 하나의 박스만 있음 |
파트의 파셋, 상태 및 조건
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은 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>, 사용자 정의 types. 뒤따르는 문자열은 prop의 문서입니다. one-of a, b / any-of / exclusive는 prop 그룹을 제한합니다.
다음을 참고하세요
- 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를 출력합니다.