테마 사용자 정의
lh-ui-plus는 완전한 CSS 변수 테마 시스템을 제공하여, 국풍 테마 색상, 다크 모드, 문양 배경, 런타임 전환 등 다양한 사용자 정의 기능을 지원합니다.
색상을 시각적으로 조정하고 scss를 바로 내보내고 싶다면 테마 스튜디오를 참고하세요.
국풍 테마 색상 체계
컴포넌트 라이브러리는 전통 수묵 단청에서 디자인 영감을 얻어, 8가지 국풍 색상 테마를 정의합니다:
| 색상 | 의미 | 주요 색상 | hover | 적용 |
|---|---|---|---|---|
| 靛蓝 (쪽빛) | 청화자기의 푸름 | #2B4C7C | #3D649E | 주요 버튼, 링크, 포커스 상태 |
| 松花绿 (송화록) | 대나무 그림자의 푸르름 | #5B8C5A | #6FA36E | 성공 상태 |
| 藤黄 (등황) | 단풍잎의 금빛 | #C4A35A | #D4B76F | 경고 상태 |
| 朱砂 (위험) | 도장의 주홍색 | #B23A3A | #C45050 | 위험/오류 상태 (--lh-danger-*) |
| 黛色 (짙은 먹색) | 수묵의 옅은 채색 | #7A7A7A | #8F8F8F | 정보 상태 |
| 金色 (금색) | 화려한 옛 정취 | #B8860B | #D4A843 | 장식 포인트 (--lh-gold-*) |
| 朱砂红 (강조) | 진사가 붉은 쪽으로 치우친 강조 변형 | #C43A31 | #E85D4A | 강조 색상 (--lh-vermilion-*) |
| 玉色 (옥색) | 싱그러운 대나무의 청아함 | #5B8C5A | #7AAE7A | 성공/장식 (松花绿와 동일한 값) |
각 색상은 일반적으로 4개의 계층 (주요 색상/hover/active/light 배경색)을 포함하며, 주요 색상과 금색은 추가로 lighter 테두리색 (*-color-border)을 제공하여 다양한 상황에서 적절한 대비를 보장합니다.
CSS 변수 테마 시스템
모든 테마 색상은 CSS 사용자 속성 (--lh-*)으로 구현되며, 총 88+개 변수가 다음 카테고리를 다룹니다:
색상 변수
| 변수 접두사 | 설명 | 예시 |
|---|---|---|
--lh-primary-color | 주요 색상 기본값 | #2B4C7C |
--lh-primary-color-hover | 주요 색상 hover 상태 | #3D649E |
--lh-primary-color-active | 주요 색상 active 상태 | #1F3A5F |
--lh-primary-color-bg | 주요 색상의 옅은 배경 | #E8EDF3 |
--lh-success-color | 성공 색상 | #5B8C5A |
--lh-warning-color | 경고 색상 | #C4A35A |
--lh-danger-color | 위험 색상 | #B23A3A |
--lh-info-color | 정보 색상 | #7A7A7A |
텍스트 변수
| 변수명 | 설명 | 기본값 |
|---|---|---|
--lh-text-primary | 주요 텍스트 | #2C2C2C |
--lh-text-regular | 일반 텍스트 | #5A5A5A |
--lh-text-secondary | 보조 텍스트 | #8A8A8A |
--lh-text-placeholder | 플레이스홀더 | #B0B0B0 |
--lh-text-disabled | 비활성화 텍스트 | #C8C8C8 |
테두리 변수
| 변수명 | 설명 | 기본값 |
|---|---|---|
--lh-border-color-base | 기본 테두리 | #D8D3CC |
--lh-border-color-light | 가벼운 테두리 | #E5E0D8 |
--lh-border-radius-base | 기본 모서리 둥글기 | 2px |
--lh-border-radius-round | 캡슐형 모서리 둥글기 | 20px |
배경 변수
| 변수명 | 설명 | 기본값 |
|---|---|---|
--lh-bg-color | 컴포넌트 배경 | #FAF6F0 (화선지색) |
--lh-bg-color-page | 페이지 배경 | #F5F0EB |
--lh-bg-color-overlay | 오버레이 배경 | rgba(26, 26, 26, 0.4) |
그림자 변수
| 변수명 | 설명 |
|---|---|
--lh-box-shadow-base | 기본 그림자 |
--lh-box-shadow-light | 가벼운 그림자 |
--lh-box-shadow-lighter | 아주 가벼운 그림자 |
글꼴 변수
| 변수명 | 설명 | 기본값 |
|---|---|---|
--lh-font-family | 글꼴 패밀리 | Noto Serif SC, STSong, SimSun... |
--lh-font-size-base | 기본 글자 크기 | 14px |
--lh-font-size-small | 작은 글자 크기 | 13px |
--lh-font-weight-primary | 일반 글꼴 두께 | 400 |
--lh-font-line-height-primary | 줄 높이 | 1.8 |
간격 변수
| 변수명 | 값 | 용도 |
|---|---|---|
--lh-spacing-xs | 4px | 아주 작은 간격 |
--lh-spacing-sm | 8px | 작은 간격 |
--lh-spacing-md | 12px | 중간 간격 |
--lh-spacing-base | 16px | 기본 간격 |
--lh-spacing-lg | 20px | 큰 간격 |
--lh-spacing-xl | 24px | 아주 큰 간격 |
Z-Index 변수
| 변수명 | 값 | 용도 |
|---|---|---|
--lh-z-index-dropdown | 1000 | 드롭다운 메뉴 |
--lh-z-index-modal | 1050 | 모달 |
--lh-z-index-tooltip | 2000 | 툴팁 |
트랜지션 변수
| 변수명 | 값 | 설명 |
|---|---|---|
--lh-transition-duration-fast | 0.25s | 빠른 트랜지션 |
--lh-transition-duration-base | 0.3s | 기본 트랜지션 |
--lh-transition-duration-slow | 0.4s | 느린 트랜지션 |
다크 테마
컴포넌트 라이브러리는 다크 테마 스타일을 내장하며, 모든 CSS 변수는 다크 모드에서 자동으로 적응된 값으로 전환됩니다.
방법 1: useLhTheme 컴포저블 사용
Composition API
<script setup lang="ts">
import { useLhTheme } from '@lh-ui/vue3'
const { theme, toggleTheme, setTheme } = useLhTheme()
</script>
<template>
<div>
<LhButton @click="toggleTheme">
{{ theme === 'dark' ? '라이트로 전환' : '다크로 전환' }}
</LhButton>
<LhButton @click="() => setTheme('light')">라이트</LhButton>
<LhButton @click="() => setTheme('dark')">다크</LhButton>
</div>
</template>Options API
<script>
import { useLhTheme } from '@lh-ui/vue3'
export default {
setup() {
const { theme, toggleTheme, setTheme } = useLhTheme()
return { theme, toggleTheme, setTheme }
},
}
</script>
<template>
<div>
<LhButton @click="toggleTheme">
{{ theme === 'dark' ? '라이트로 전환' : '다크로 전환' }}
</LhButton>
</div>
</template>
useLhTheme는 테마 상태를localStorage(key:lh-ui-theme)에 자동으로 저장하여, 페이지를 새로고침해도 테마가 유지됩니다.
방법 2: HTML 속성 전환
루트 요소에 data-theme="dark"를 설정하면 다크 모드가 전역으로 활성화됩니다:
<!DOCTYPE html>
<html lang="ko-KR" data-theme="dark">
<!-- ... -->
</html>사용자 정의 테마 색상 (青花瓷 / 松花绿 / 朱砂红)
내장된 라이트/다크 테마 외에, 컴포넌트 라이브러리는 themeVars를 통해 임의의 색상 조합을 사용자 정의하여 개인화된 테마를 구현할 수 있습니다. (青花瓷 (청화자기) / 松花绿 (송화록) / 朱砂红 (진사홍))
아래 예시는 수동으로 사용자 정의 변수를 작성하는 시연이며, 설명을 위해 값을 조정했으므로 사전 정의된 테마의 동일한 이름의 내장 프리셋 (
cerblue/songhua/zhusha)과 완전히 같지는 않습니다. 내장 프리셋을 직접 사용하려면useLhPresetTheme또는getThemeVars(name)을 사용하세요.
青花瓷 (청화자기) 테마
짙은 쪽빛을 주요 색상으로 하며, 전통 청화자기에서 영감을 받았습니다.
Composition API
<script setup lang="ts">
const cerblueTheme = {
'primary-color': '#2B4C7C',
'primary-color-hover': '#3D649E',
'primary-color-active': '#1F3A5F',
'primary-color-bg': '#E8EDF3',
'bg-color': '#F0F4F8',
'border-color-base': '#C8D6E5',
}
</script>
<template>
<LhConfigProvider :theme-vars="cerblueTheme">
<LhButton type="primary">청화자기 버튼</LhButton>
<LhInput placeholder="청화자기 입력 상자" />
</LhConfigProvider>
</template>Options API
<script>
import { LhConfigProvider, LhButton, LhInput } from '@lh-ui/vue3'
export default {
components: { LhConfigProvider, LhButton, LhInput },
data() {
return {
cerblueTheme: {
'primary-color': '#2B4C7C',
'primary-color-hover': '#3D649E',
'primary-color-bg': '#E8EDF3',
'bg-color': '#F0F4F8',
},
}
},
}
</script>
<template>
<LhConfigProvider :theme-vars="cerblueTheme">
<LhButton type="primary">청화자기 버튼</LhButton>
</LhConfigProvider>
</template>松花绿 (송화록) 테마
대나무 초록을 포인트로 삼아, 청량하고 자연스러운 분위기를 연출합니다.
<script setup lang="ts">
const bambooTheme = {
'primary-color': '#5B8C5A',
'primary-color-hover': '#6FA36E',
'primary-color-bg': '#EDF5EC',
'success-color': '#5B8C5A',
'bg-color': '#F6FAF5',
}
</script>
<template>
<LhConfigProvider :theme-vars="bambooTheme">
<LhButton type="primary">대숲 오솔길</LhButton>
<LhTag type="success">새 잎</LhTag>
</LhConfigProvider>
</template>朱砂红 (진사홍) 테마
도장의 주홍색을 주조로 하여, 우아하고 화려한 분위기를 돋보이게 합니다.
<script setup lang="ts">
const vermilionTheme = {
'primary-color': '#C43A31',
'primary-color-hover': '#E85D4A',
'primary-color-bg': '#FDF0EE',
'bg-color': '#FFFBF9',
'border-color-base': '#F0D5CF',
}
</script>
<template>
<LhConfigProvider :theme-vars="vermilionTheme">
<LhButton type="primary">주홍 증서</LhButton>
</LhConfigProvider>
</template>문양 배경 시스템
컴포넌트 라이브러리는 국풍 시적인 문양 배경 시스템을 제공하여, 6가지 프리셋 문양을 지원하고 patternComponents 허용 목록으로 적용 범위를 정밀하게 제어할 수 있습니다.
프리셋 문양
| 문양명 | CSS 변수 | 설명 |
|---|---|---|
| 柳叶 (버들잎) | var(--lh-pattern-willow) | 가늘고 긴 버들잎, 적당한 밀도 |
| 祥云 (상서로운 구름) | var(--lh-pattern-cloud) | 펼쳐진 상서로운 구름, 유려하게 흐름 |
| 水波 (물결) | var(--lh-pattern-water) | 미세하게 움직이는 잔물결, 겹겹이 쌓임 |
| 雪花 (눈꽃) | var(--lh-pattern-snow) | 육각 눈꽃, 가지가 갈라짐 |
| 梅花 (매화) | var(--lh-pattern-plum) | 다섯 잎이 펼쳐지고, 꽃밥이 또렷함 |
| 竹叶 (대나무잎) | var(--lh-pattern-bamboo) | 바늘잎 형태의 대나무잎, 어우러짐 |
전역 문양 구성
Composition API
<script setup lang="ts">
const config = {
themeVars: {
'bg-pattern': 'var(--lh-pattern-cloud)',
'bg-pattern-opacity': '0.15',
},
patternComponents: ['button', 'input'] as const,
}
</script>
<template>
<LhConfigProvider
:theme-vars="config.themeVars"
:pattern-components="config.patternComponents"
>
<!-- 버튼과 입력 상자에 문양이 적용되고, Dialog에는 적용되지 않습니다 -->
<LhButton>문양 버튼</LhButton>
<LhInput placeholder="문양 입력 상자" />
</LhConfigProvider>
</template>Options API
<script>
export default {
data() {
return {
config: {
themeVars: {
'bg-pattern': 'var(--lh-pattern-cloud)',
'bg-pattern-opacity': '0.15',
},
patternComponents: ['button', 'input'],
},
}
},
}
</script>
<template>
<LhConfigProvider
:theme-vars="config.themeVars"
:pattern-components="config.patternComponents"
>
<LhButton>문양 버튼</LhButton>
</LhConfigProvider>
</template>문양 변수 참고
| 변수명 | 설명 | 기본값 |
|---|---|---|
--lh-bg-pattern | 문양 배경 URL | none |
--lh-bg-pattern-repeat | 바둑판 배열 모드 | repeat |
--lh-bg-pattern-size | 문양 크기 | 40px |
--lh-bg-pattern-opacity | 문양 불투명도 | 0.15 |
--lh-bg-pattern-color | 문양 색상 | var(--lh-decoration-color, rgba(184, 134, 11, 0.12)) |
--lh-bg-pattern-blend | 혼합 모드 | soft-light |
전체 구성 예시
다음은 ConfigProvider의 전체 구성 사용법을 보여주며, 테마, 언어, 크기, 문양 등 모든 기능을 통합합니다.
Composition API
<script setup lang="ts">
import { zhCN } from '@lh-ui/vue3'
const configProvider = {
size: 'medium' as const,
locale: zhCN,
themeVars: {
'primary-color': '#2B4C7C',
'bg-pattern': 'var(--lh-pattern-cloud)',
'bg-pattern-opacity': '0.15',
},
patternComponents: ['button', 'input', 'dialog'],
}
</script>
<template>
<LhConfigProvider
:size="configProvider.size"
:locale="configProvider.locale"
:theme-vars="configProvider.themeVars"
:pattern-components="configProvider.patternComponents"
>
<slot />
</LhConfigProvider>
</template>Options API
<script>
import { zhCN } from '@lh-ui/vue3'
export default {
data() {
return {
configProvider: {
size: 'medium',
locale: zhCN,
themeVars: {
'primary-color': '#2B4C7C',
'bg-pattern': 'var(--lh-pattern-cloud)',
},
patternComponents: ['button', 'input', 'dialog'],
},
}
},
}
</script>
<template>
<LhConfigProvider
:size="configProvider.size"
:locale="configProvider.locale"
:theme-vars="configProvider.themeVars"
:pattern-components="configProvider.patternComponents"
>
<slot />
</LhConfigProvider>
</template>테마 변수 우선순위
컴포넌트가 최종적으로 사용하는 CSS 변수는 다음 우선순위로 병합됩니다 (후자가 전자를 덮어씁니다):
- ConfigProvider 전역
themeVars(가장 낮은 우선순위) - ConfigProvider의 컴포넌트별
componentTheme[컴포넌트명] - 컴포넌트 자체의
themeVarsprop - 컴포넌트 자체의
bgPatternprop (가장 높은 우선순위)
bg-pattern 변수의 경우 추가로 patternComponents 허용 목록의 제어를 받습니다: 허용 목록에 있는 컴포넌트만 전역으로 구성된 bg-pattern을 적용합니다.
sx 빠른 레이아웃
sx 속성은 선언적인 인라인 레이아웃 방식을 제공하여, CSS를 작성하지 않고도 컴포넌트의 간격과 크기를 설정할 수 있습니다. 현재 다음 컴포넌트에서 지원합니다: Button, Input, Dialog, Tooltip, Alert, Card, Empty, Breadcrumb, Pagination, Steps, Tabs, Skeleton.
원리
sx는 8px 기준 그리드를 사용하며, 숫자에 8을 곱해 실제 픽셀 값을 얻습니다. 예를 들어 mt: 2는 marginTop: 16px와 동일합니다.
지원 속성
간격
| 속성 | 설명 | 예시 | 동등한 CSS |
|---|---|---|---|
m | 네 면 바깥쪽 간격 | m: 2 | margin: 16px |
mx | 수평 바깥쪽 간격 | mx: 1 | marginLeft: 8px; marginRight: 8px |
my | 수직 바깥쪽 간격 | my: 1 | marginTop: 8px; marginBottom: 8px |
mt, mr, mb, ml | 한쪽 방향 바깥쪽 간격 | mt: 2 | marginTop: 16px |
p | 네 면 안쪽 간격 | p: 3 | padding: 24px |
px | 수평 안쪽 간격 | px: 2 | paddingLeft: 16px; paddingRight: 16px |
py | 수직 안쪽 간격 | py: 1 | paddingTop: 8px; paddingBottom: 8px |
pt, pr, pb, pl | 한쪽 방향 안쪽 간격 | pt: 2 | paddingTop: 16px |
크기
| 속성 | 설명 | 예시 |
|---|---|---|
w | 너비 (숫자는 px, 문자열은 값 그 자체) | w: 200 또는 w: '100%' |
h | 높이 | h: 100 또는 h: 'auto' |
Flex 레이아웃
| 속성 | 설명 | 예시 |
|---|---|---|
display | 표시 유형 | display: 'flex' |
flex | flex 약식 표기 | flex: '1 1 0%' |
flexDirection | 주축 방향 | flexDirection: 'column' |
alignItems | 교차축 정렬 | alignItems: 'center' |
justifyContent | 주축 정렬 | justifyContent: 'flex-end' |
사용 예시
<script setup lang="ts">
import { ref } from 'vue'
const visible = ref(false)
</script>
<template>
<!-- 버튼 간격 -->
<LhButton type="primary" :sx="{ mt: 2, mx: 1 }">간격이 있는 버튼</LhButton>
<!-- 입력 상자 바깥쪽 간격 -->
<LhInput placeholder="입력 상자 상하 간격" :sx="{ my: 1 }" />
<!-- Dialog 너비: sx는 w/h와 간격류 속성만 지원 -->
<LhDialog v-model="visible" title="예시" :sx="{ w: 480 }">
<p>고정 너비의 대화상자</p>
</LhDialog>
</template><script>
export default {
data() {
return { visible: false }
},
}
</script>
<template>
<LhButton type="primary" :sx="{ mt: 2, mx: 1 }">간격이 있는 버튼</LhButton>
</template>