headless UI 컴포넌트인 melt-ui 와 tailwind 컴포넌트 라이브러리인 daisyUI 를 결합하여 svelte UI 컴포넌트를 작성하는 연습을 합니다. 분량이 많아서 연재로 차근차근 연습합니다.
- melt-ui daisyui 컴포넌트 - 1일차 : checkbox ✔
0. 개요
- 웹프레임워크 및 개발도구
- Bun 1.0.25 + Vite 5.0.3 + SvelteKit 2.0.0
- prettier 3.1.1
- prettier-plugin-svelte 3.1.2
- CSS 유틸리티
- TailwindCSS 3.4.1 (typography) + postcss 8.4.33
- prettier-plugin-tailwindcss 0.5.11
- vite-plugin-tailwind-purgecss 0.1.4
- tailwind-merge 2.1.0
- tailwind-variants
- UI 라이브러리
- fonts : D2Coding, Noto Sans/Serif KR, Noto Color Emoji
- lucide-svelte 0.295.0 (아이콘 1346개, ISC 라이센스)
- daisyui 4.6.0
- melt-ui 0.70.0
- svelte-legos 0.2.2
- 유틸리티
- faker-js 8.3.1
- drizzle-orm 0.29.3
- svelte-persisted-store 0.9.0
0. 프로젝트 생성
SvelteKit 프로젝트 생성
1
2
3
4
5
6
7
8
9
bun create svelte@latest melt-daisy-app
# - Skeleton project
# - Typescript
# - Prettier
cd melt-daisy-app
bun install
bun run dev
tailwind + daisyUI + melt-ui 설정
참고 : 이전 블로그 - Svelte Server Pagination
디렉토리 구조
- src/routes
- +layout.svelte
(base)
- +layout.svelte : header(with menu), main(content)
- components
- +layout.svelte : main(content)
- checkbox
- +page.svelte
1. Tailwind CSS - Grid
2. melt-ui vs daisyUI
컴포넌트 비교 (daisyUI 중심)
구분 | daisyUI | melt-ui | 비교 |
---|---|---|---|
Actions | Button | [✖] | 색상과 스타일, 애니메이션 효과를 포함 |
Dropdown | Dropdown Menu | 스크립트 없어도 사용 가능 | |
Modal | Dialog | showModal() 함수 포함 | |
Swap | [✖] | ||
Data display | Accordion | Accordion | daisyUI 사용 |
Collapse | Collapsible | daisyUI 사용 | |
Avatar | Avatar | daisyUI 사용 (fallback 필요) | |
Badge | Tags Input | ||
Card | [✖] | ||
Carousel | [✖] | auto-play 스크립트 필요 | |
Chat bubble | [✖] | ||
Countdown | [✖] | ||
Diff | [✖] | 두 영역의 겹칩 가로 비율 조정 | |
Kbd | [✖] | 키보드 | |
Stat | [✖] | 대시보드 수치값 | |
Table | [✖] | 출력만 제공 | |
Timeline | [✖] | ||
[✖] | Table Of Contents | 제목 태그를 추출해 트리 출력 | |
Navigation | Breadcrumbs | [✖] | 현재 메뉴 경로 출력 |
Bottom navigation | [✖] | 모바일 하단 메뉴바 | |
Link | [✖] | 헤더 메뉴바에 사용 | |
Menu | Tree, Menubar | 간단한 메뉴는 daisyUI 사용 | |
Navbar | Toolbar | 간단한 메뉴는 daisyUI 사용 | |
Pagination | Pagination | melt-ui 는 페이지 자동 계산 | |
Steps | [✖] | 단계 안내 | |
Tab | Tabs | daisyUI 사용 | |
Feedback | Alert | [✖] | 출력 제어 필요 |
Loading | [✖] | 출력 제어 필요 | |
Progress, Radial progress | Progress | value 제어 필요 | |
Skeleton | [✖] | 출력 제어 필요 (로딩 실패시) | |
Toast | Toast | 출력과 애니메이션 필요 | |
Tooltip | Tooltip | 텍스트 출력만 가능 | |
[✖] | Popover, Context Menu | 특정 위치에 매인 Modal 출력 | |
Data input | Checkbox | Checkbox | daisyUI 사용 |
File Input | [✖] | ||
Radio | Radio Group | name 으로 그룹화 | |
Rating, Range | Slider | value 제어 필요 | |
Select | Select, Combobox | selected 제어 필요 | |
Text input | Label, PIN Input | size 제어 가능, label 별도 | |
Textarea | [✖] | label 예제 포함 | |
Toggle | Toggle, Switch | check 입력 사용 | |
Date input | [✖] | Calendar, Range Calendar | 연월일 계산값을 테이블로 출력하고 event 처리 |
[✖] | Date Field, Date Range Field | 입력 필드 (달력 없음) | |
[✖] | Date Picker, Date Range Picker | 입력 필드 + 달력 포함 | |
Layout | Artboard | [✖] | |
Divider | Separator | ||
Drawer | [✖] | 사이드 출현 메뉴 | |
Footer | [✖] | ||
Hero | [✖] | min-h-(사이즈) 필요 | |
Indicator | [✖] | ||
Join (group items) | Toggle Group | 아이템(버튼)들의 상태값 변경 관리 | |
Mask | [✖] | 테두리 모양 | |
Stack | [✖] | 겹침 상태 (사라질때 애니 필요) |
결론
- Date 관련 컴포넌트는 melt-ui 사용 (선택의 여지가 없고)
- daisyUI 를 사용하는 것이 기본 선택 (writable 함께 사용)
- 코드에서 mediaQuery 제어가 필요하면, svelte-legos 와 svelte-variants 사용
3. checkbox
참고
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script lang="ts">
import { createCheckbox, melt } from '@melt-ui/svelte';
import { Minus } from 'lucide-svelte';
import { writable } from 'svelte/store';
export let label = 'Remember me';
export let checked = writable<boolean | 'indeterminate'>('indeterminate');
const {
elements: { root, input },
helpers: { isIndeterminate }
} = createCheckbox({
checked: checked
});
$: console.log('checked:', $checked, `(${$isIndeterminate})`);
</script>
<div class="form-control flex-row items-center">
<button class="checkbox-secondary checkbox" use:melt={$root} id="checkbox">
{#if $isIndeterminate}
<Minus class="w-5 text-secondary" />
{/if}
<input type="checkbox" use:melt={$input} />
</button>
<label class="label cursor-pointer" for="checkbox">
<span class="label-text">{label}</span>
</label>
</div>
9. Review
- 작성중
끝! 읽어주셔서 감사합니다.