Communitygithub.com

Milda

Milda 디자인 시스템(.milda 파일)을 읽고, 쓰고, 검토하고, 수정하며, Milda의 패러다임(계층 속 토큰, 컨텍스트 그룹, 아키타입, 플랫폼 중립 파트, 동작에서 비롯된 상태)으로 추론합니다. 사용자가 Milda, Milda Studio, Milda 플레이그라운드 또는 .milda 파일을 언급하거나, Milda에서 디자인 시스템의 토큰이나 컴포넌트를 작성/변경하거나, CSS, Figma 또는 기존 컴포넌트 라이브러리를 Milda로 변환하려 할 때 사용하세요.

Milda란 무엇인가요?

Milda는 디자인 시스템을 위한 GUI 기반 컴파일러입니다. `.milda` 파일 자체가 곧 디자인 시스템으로, 파운데이션(토큰), 컴포넌트, 사용 규칙, 문서, 에셋을 포함하며, 여기서 React 패키지, Figma 라이브러리, 문서 사이트, 에이전트가 읽을 수 있는 파일이 생성됩니다. 이 스킬은 언어 표면 0.10과 프렐류드 0.0.2를 대상으로 하며, Milda의 고유한 패러다임(계층화된 토큰, 컨텍스트 그룹, 아키타입, 플랫폼 중립 파트, 동작에서 비롯된 상태)에 따라 작성 및 검증을 돕습니다. 사용자가 Milda Studio, Milda 플레이그라운드, `.milda` 파일을 언급하거나, CSS나 Figma, 기존 컴포넌트 라이브러리를 Milda로 변환하려 할 때 활성화됩니다. 주요 작업은 `milda-check --strict`로 파일을 검증하고, Milda 구문 규칙(예: CSS 속성 대신 Milda 파셋 사용, 플랫폼 용어 배제)을 적용하며, 오류와 경고가 0이 될 때까지 수정하는 루프를 수행합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mildastudio/milda-skills/tree/main/skills/milda

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

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 구문으로 작성할 때 발생합니다. 이 규칙들은 구문이 표현하고자 하는 바입니다.

  1. 시스템이 소스이며, 코드는 출력물입니다. 플랫폼과 관련된 모든 것은 생성 시간에 결정되므로, 파일에는 CSS 속성, 태그, 프레임워크의 이벤트 이름, 의사 클래스가 절대 포함되지 않습니다.
  2. 무엇으로 만들어졌는지가 아니라 무엇인지 말하세요. 파트는 중립적인 종류(container, text, input, icon, control, ...)를 가지며, div나 button이 아닙니다. 각 대상은 자체 요소를 선택합니다.
  3. 값에는 이름이 있고, 이름에는 계층이 있습니다. 컴포넌트는 리터럴로 칠하지 않습니다. 파셋은 토큰을 가리키며, Semantic 계층은 리터럴의 Base 계층을 별칭합니다. 리스타일은 파운데이션의 변경입니다.
  4. 컨텍스트는 차원이지 복사본이 아닙니다. 다크 모드, 밀도, 브랜드: 각각은 context-group이며, 토큰은 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), 토큰은 경로(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 "주요 액션입니다." {
  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 / 아키타입의 루트
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(...), 토큰 내부에서만 사용
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없음: 파트 순서, 컨테이너, 하나의 박스만 있음

파트의 파셋, 상태 및 조건

  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를 출력합니다.

관련 스킬