com um clique
style-set-create
새 컴포넌트의 StyleSet을 v2.0.0+ 컨벤션에 맞게 생성
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
새 컴포넌트의 StyleSet을 v2.0.0+ 컨벤션에 맞게 생성
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
Style-Set 코드를 v2.0.0+ 컨벤션에 맞게 리뷰하고 개선 제안
Invoked manually via /write-readme. Generates README.md (English) and README.ko.md (Korean) from Vlossom source code. Supports all document types: components (vs-*), plugins, directives, composables (use*), and utility functions. Do NOT trigger automatically — only run when explicitly called with /write-readme <target>.
Use when vlossom feature/fix/removal work is done and commits are ready, to identify missing documentation files (tests, README, stories, markdown) and amend them back into the appropriate commits via interactive rebase with per-commit user confirmation.
| name | style-set-create |
| description | 새 컴포넌트의 StyleSet을 v2.0.0+ 컨벤션에 맞게 생성 |
새로운 컴포넌트의 StyleSet을 v2.0.0+ 컨벤션 (extends CSSProperties + $ prefix) 으로 설계하고 구현합니다.
VsXxxStyleSet은 CSSProperties를 상속하며, 키는 $ prefix 유무로 구분됩니다.
| 키 형태 | 의미 | 처리 |
|---|---|---|
width, padding, ... (non-$) | 표준 CSS — 컴포넌트 루트에 inline style로 적용 | componentInlineStyle로 자동 수집 |
$X (string/number) | CSS 변수로 노출 | --vs-{kebab-component}-X 로 emit (styleSetVariables) |
$X (object) | 슬롯/요소 스타일 또는 하위 StyleSet | componentStyleSet.$X로 직접 접근 |
import type { CSSProperties } from 'vue';
export interface VsButtonStyleSet extends CSSProperties {
$padding?: string; // CSS 변수: --vs-button-padding
$content?: CSSProperties; // 슬롯
$loading?: VsLoadingStyleSet; // 하위 컴포넌트
}
💡 root는
extends CSSProperties로 이미 노출되므로component?: CSSProperties같은 래퍼 키는 만들지 않습니다.
Vs[ComponentName]이 속성을 외부에서 자주 커스터마이징하나?
├── No → CSS에 하드코딩 (디자인 토큰 우선: var(--vs-comp-bg) 등)
└── Yes → 어떻게 노출할지 결정
├── 임의 CSS로 자유롭게 변경되어도 OK → root CSSProperties (extends 덕분에 자동)
├── .css에서 calc/의사 요소/상태 셀렉터에 쓰임 → $X primitive
├── 특정 슬롯/요소 스타일링 → $X: CSSProperties
└── 하위 Vlossom 컴포넌트 전체 스타일 전파 → $X: VsXxxStyleSet
$X primitive (CSS 변수) 사용 기준 — 4가지 모두 Yes일 때만.css에서 calc(), 의사 요소(::after), 상태 셀렉터에서 실제 사용?위 조건에 해당하지 않으면 root CSSProperties로 충분합니다.
width,height,padding,margin,boxShadow,backgroundColor등은 일반적으로 root에서 받는 것이 자연스럽습니다.
--vs-comp-bg, --vs-comp-font 등 기본 테마 색상은 ColorScheme이 자동 처리합니다. $backgroundColor, $fontColor로 별도 노출하지 마세요. 사용자가 일회성으로 바꿔야 한다면 root CSSProperties (backgroundColor) 로 직접 줄 수 있습니다.
import type { ComponentPublicInstance, CSSProperties } from 'vue';
import type Vs[ComponentName] from './Vs[ComponentName].vue';
// 하위 컴포넌트가 있다면 import
import type { VsChildStyleSet } from '@/components/vs-child/types';
declare module 'vue' {
interface GlobalComponents {
Vs[ComponentName]: typeof Vs[ComponentName];
}
}
export type { Vs[ComponentName] };
export interface Vs[ComponentName]Ref extends ComponentPublicInstance<typeof Vs[ComponentName]> {}
export interface Vs[ComponentName]StyleSet extends CSSProperties {
/** CSS 변수: --vs-[component-kebab]-arrowSize */
$arrowSize?: string;
/** 슬롯/요소 스타일 */
$element?: CSSProperties;
/** 하위 컴포넌트 StyleSet */
$childComponent?: VsChildStyleSet;
}
extends CSSProperties로 root CSS가 자동 노출되므로component?: CSSProperties같은 래퍼 키는 만들지 않습니다.
import { computed, defineComponent, ref, toRefs, type ComputedRef, type Ref } from 'vue';
import { VsComponent } from '@/declaration';
import { useColorScheme, useStyleSet } from '@/composables';
import { getColorSchemeProps, getStyleSetProps } from '@/props';
import { objectUtil } from '@/utils';
import type { Vs[ComponentName]StyleSet } from './types';
const componentName = VsComponent.Vs[ComponentName];
export default defineComponent({
name: componentName,
props: {
...getColorSchemeProps(),
...getStyleSetProps<Vs[ComponentName]StyleSet>(),
// 기타 props
},
setup(props) {
const { colorScheme, styleSet } = toRefs(props);
const { colorSchemeClass } = useColorScheme(componentName, colorScheme);
// 하위 컴포넌트 기본값 (고정값이면 ref 권장, 반응성 필요시 computed)
const baseStyleSet: Ref<Vs[ComponentName]StyleSet> = ref({
$childComponent: {
width: '100%', // 자식의 root CSSProperties
},
});
// props에서 동적 값이 오면 root에 직접 (extends CSSProperties 덕분에 평탄)
const additionalStyleSet = computed<Vs[ComponentName]StyleSet>(() => {
return objectUtil.shake({
height: props.height || undefined,
});
});
const { componentStyleSet, styleSetVariables, componentInlineStyle } =
useStyleSet<Vs[ComponentName]StyleSet>(
componentName,
styleSet,
baseStyleSet, // 3번째: 기본값 (가장 낮은 우선순위)
additionalStyleSet, // 4번째: props 동적 값 (가장 높은 우선순위, 사용자 styleSet도 덮음)
);
return {
colorSchemeClass,
styleSetVariables,
componentInlineStyle,
componentStyleSet,
};
},
});
useStyleSet 인자 규칙| 인자 | 용도 | 반응성 |
|---|---|---|
baseStyleSet (3번째) | 하위 컴포넌트 기본값, 고정 스타일 | ref({}) 권장 (고정값), computed 허용 (반응성 필요시) |
additionalStyleSet (4번째) | props에서 오는 동적 값 (사용자 styleSet보다 우선) | computed (항상) |
⚠️
additionalStyleSet은 사용자styleSet을 덮어쓰므로 신중히 사용하세요. props가 styleSet을 침범하지 않는 게 일반적입니다.
<template>
<div
:class="['vs-[component-kebab]', colorSchemeClass, classObj]"
:style="{ ...styleSetVariables, ...componentInlineStyle }"
>
<!-- 슬롯/요소 -->
<div
class="vs-[component-kebab]-element"
:style="componentStyleSet.$element"
>
<slot name="element" />
</div>
<!-- 하위 컴포넌트 -->
<vs-child-component :style-set="componentStyleSet.$childComponent" />
<slot />
</div>
</template>
핵심 포인트:
{ ...styleSetVariables, ...componentInlineStyle } 두 가지를 spreadcomponentStyleSet.$X (CSSProperties) → :stylecomponentStyleSet.$X (StyleSet) → :style-set$step?: CSSProperties & { $active?: CSSProperties };
computed로 base + 상태 스타일을 머지:
const stepStyle = computed<CSSProperties>(() => ({
...componentStyleSet.value.$step,
...(isActive.value ? componentStyleSet.value.$step?.$active : {}),
}));
.vs-[component-kebab] {
/* CSS 변수 선언 — 인터페이스의 $X primitive에 대응하며 .css에서 실제 사용하는 것만 */
--vs-[component-kebab]-arrowSize: initial;
/* 레이아웃과 기본 스타일은 직접 값 */
display: flex;
flex-direction: column;
/* CSS 변수 사용 (fallback 필수) */
padding-right: var(--vs-[component-kebab]-arrowSize, 1rem);
/* 디자인 토큰 우선 */
background-color: var(--vs-comp-bg);
color: var(--vs-comp-font);
border-radius: calc(var(--vs-radius-ratio) * var(--vs-radius-md));
}
.vs-[component-kebab]-element {
display: flex;
align-items: center;
gap: 0.5rem;
}
/* 상태별 스타일 */
.vs-[component-kebab]:hover {
opacity: 0.9;
}
.vs-[component-kebab].vs-disabled {
opacity: 0.5;
cursor: not-allowed;
}
규칙 요약:
--vs-{component-kebab}-{property} (property는 camelCase 유지)$X primitive ↔ CSS 변수가 1:1로 매칭되고 실제 사용되어야 함var(--vs-comp-bg) 등) 직접 사용Vs[ComponentName]StyleSet인가?extends CSSProperties로 선언되어 있는가?component?: CSSProperties 같은 래퍼 키가 없는가?variables?: { ... } 패턴이 남아있지 않은가?$X primitive는 4가지 기준을 모두 만족하는가?$backgroundColor, $fontColor)을 노출하지 않았는가? (ColorScheme 담당)$step.$active ✅)$content ✅, $expand ❌)$wrapper?: VsInputWrapperStyleSet가 포함되었는가?CSSProperties['objectFit'] & {})useStyleSet에서 componentStyleSet, styleSetVariables, componentInlineStyle 세 가지 모두 destructure했는가?:style에 { ...styleSetVariables, ...componentInlineStyle }을 spread했는가?baseStyleSet이 고정값이면 ref 사용을 검토했는가?componentStyleSet.$X를 :style로 바인딩했는가?componentStyleSet.$X를 :style-set으로 전달했는가?--vs-{component-kebab}-{property} 규칙을 따르는가?$X primitive와 CSS 변수가 1:1 매칭되는가?README.md의 Types 섹션이 새 인터페이스를 그대로 반영하는가?$X, root CSSProperties)을 따르는가?width, padding, boxShadow, backgroundColor → root CSSProperties (extends로 자동)$header, $body, $footer (object)$X primitive로 노출할 만한 속성 없음 (.css에서 calc/의사 요소가 없음)import type { ComponentPublicInstance, CSSProperties } from 'vue';
import type VsCard from './VsCard.vue';
declare module 'vue' {
interface GlobalComponents {
VsCard: typeof VsCard;
}
}
export type { VsCard };
export interface VsCardRef extends ComponentPublicInstance<typeof VsCard> {}
export interface VsCardStyleSet extends CSSProperties {
/** 헤더 영역 */
$header?: CSSProperties;
/** 바디 영역 */
$body?: CSSProperties;
/** 푸터 영역 */
$footer?: CSSProperties;
}
<vs-card
:style-set="{
width: '320px',
padding: '1rem',
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
$header: { fontWeight: 600 },
$footer: { borderTop: '1px solid #eee' },
}"
/>
component?: CSSProperties 같은 래퍼 키 추가 — extends CSSProperties로 이미 노출됨variables?: { ... } 구조 사용 — v2.0.0+ 컨벤션 아님$X (CSS 변수)로 — .css에서 실제 변수로 쓰이는 것만 노출$X: { $Y: { ... } }는 자식 StyleSet이 자체적으로 깊이를 가질 때만 허용$styles, $config, $inner 등 모호한 이름$backgroundColor, $fontColor 등$expand 대신 $content처럼 내용 기반으로root CSSProperties (extends로 자동):
$X primitive (CSS 변수):
.css에서 calc()나 의사 요소(::after)에서 참조해야 함$X object (CSSProperties):
$X (자식 StyleSet):
$loading, $chip, $wrapper)/style-set-create VsCard
대화형으로 요구사항을 파악하고 단계별로 생성합니다.