Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x35",
"green" : "0x35",
"red" : "0xC8"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x35",
"green" : "0x35",
"red" : "0xC8"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
16 changes: 15 additions & 1 deletion Projects/DVDesign/SampleApp/Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ struct ContentView: View {
TextFieldPreviewView()
case "DVTextContainer":
TextContainerPreviewView()
case "DVChip":
DVChipPreviewView()
case "DVMultilineTextField":
DVMultilineTextFieldPreviewView()
case "DVDropdown":
DVDropdownPreviewView()
case "DVLabeledField":
DVLabeledFieldPreviewView()
case "DVChipsField":
DVChipsFieldPreviewView()
default:
ComponentPlaceholderView(name: component.name)
}
Expand Down Expand Up @@ -103,7 +113,11 @@ private struct Component: Hashable {
Component(name: "DVRadioButtonGroup"),
Component(name: "DVTextContainer"),
Component(name: "DVTextField"),
Component(name: "DVChip"),
Component(name: "DVMultilineTextField"),
Component(name: "DVDropdown"),
Component(name: "DVLabeledField"),
Component(name: "DVChipsField"),
// Component(name: "DVInputField"),
// Component(name: "DVDropDown"),
]
}
68 changes: 68 additions & 0 deletions Projects/DVDesign/SampleApp/Sources/DVChipPreviewView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright © 2026 Devault. All rights reserved

import SwiftUI
import DVDesign

struct DVChipPreviewView: View {
@State private var chips: [String] = ["GitHub", "NameNameName", "OpenAI"]

var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 32) {
section(title: "기본") {
labeled("단일 chip") {
DVChip("GitHub")
}
labeled("여러 chip (수평 배치)") {
HStack(spacing: 10) {
DVChip("GitHub")
DVChip("OpenAI")
DVChip("Anthropic")
DVChip("LongLongName")
}
}
}

section(title: "인터랙션 — 클릭 시 제거") {
labeled("각 chip 클릭 시 목록에서 제거됨") {
HStack(spacing: 10) {
ForEach(chips, id: \.self) { chip in
DVChip(chip) {
chips.removeAll { $0 == chip }
}
}
}
}
Button("초기화") {
chips = ["GitHub", "NameNameName", "OpenAI"]
}
}
}
.padding(24)
.frame(maxWidth: .infinity, alignment: .leading)
}
.navigationTitle("DVChip")
}

@ViewBuilder
private func section<Content: View>(
title: String,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 16) {
Text(title).font(.title2).fontWeight(.bold)
content()
}
}

@ViewBuilder
private func labeled<Content: View>(
_ caption: String,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 4) {
Text(caption).font(.caption).foregroundStyle(.secondary)
content()
}
}
}
104 changes: 104 additions & 0 deletions Projects/DVDesign/SampleApp/Sources/DVChipsFieldPreviewView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright © 2026 Devault. All rights reserved

import SwiftUI
import DVDesign

struct DVChipsFieldPreviewView: View {
@State private var empty: [String] = []
@State private var emptyInput = ""

@State private var few: [String] = ["GitHub"]
@State private var fewInput = ""

@State private var many: [String] = [
"GitHub", "OpenAI", "Anthropic", "AWS", "Slack", "Notion", "Linear",
"Stripe", "Vercel", "Supabase", "LongLongLongService"
]
@State private var manyInput = ""

@State private var detected: [String] = []
@State private var detectedInput = ""
@State private var lastEvent = "이벤트 없음"

@State private var xs: [String] = ["A", "B"]
@State private var sm: [String] = ["GitHub", "OpenAI"]
@State private var md: [String] = ["Stripe", "Vercel", "Supabase"]
@State private var lg: [String] = ["GitHub", "OpenAI", "Anthropic", "AWS", "Slack", "Notion", "Linear", "Stripe"]
@State private var xsInput = ""
@State private var smInput = ""
@State private var mdInput = ""
@State private var lgInput = ""

var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 32) {
section(title: "기본") {
labeled("Empty — chip 없음") {
DVChipsField("e.g GitHub", chips: empty, input: $emptyInput, size: .sm)
}
labeled("Chip 1개") {
DVChipsField("추가 입력", chips: few, input: $fewInput, size: .sm)
}
labeled("여러 개 — 세로 wrap 확인") {
DVChipsField("추가 입력", chips: many, input: $manyInput, size: .sm)
}
}

section(title: "인터랙션") {
labeled("Chip 클릭 → 텍스트 입력창에 세팅 + 원본은 시각적으로만 숨김. 다른 chip 클릭 시 이전 것 복귀") {
DVChipsField(
"chip 클릭해보기",
chips: ["GitHub", "OpenAI", "Anthropic"],
input: $detectedInput,
size: .sm,
onTap: { chip in lastEvent = "tap — \(chip)" }
)
}
Text("마지막 이벤트: \(lastEvent)")
.font(.caption)
.foregroundStyle(.secondary)
}

section(title: "사이즈 (DVComponentSize 전 케이스)") {
labeled("XS (180pt)") {
DVChipsField("XS", chips: xs, input: $xsInput, size: .xs)
}
labeled("SM (330pt)") {
DVChipsField("SM", chips: sm, input: $smInput, size: .sm)
}
labeled("MD (380pt)") {
DVChipsField("MD", chips: md, input: $mdInput, size: .md)
}
labeled("LG (700pt)") {
DVChipsField("LG", chips: lg, input: $lgInput, size: .lg)
}
}
}
.padding(24)
.frame(maxWidth: .infinity, alignment: .leading)
}
.navigationTitle("DVChipsField")
}

@ViewBuilder
private func section<Content: View>(
title: String,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 16) {
Text(title).font(.title2).fontWeight(.bold)
content()
}
}

@ViewBuilder
private func labeled<Content: View>(
_ caption: String,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 4) {
Text(caption).font(.caption).foregroundStyle(.secondary)
content()
}
}
}
104 changes: 104 additions & 0 deletions Projects/DVDesign/SampleApp/Sources/DVDropdownPreviewView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright © 2026 Devault. All rights reserved

import SwiftUI
import DVDesign

struct DVDropdownPreviewView: View {
@State private var project: String? = nil
@State private var env: String? = "Staging"
@State private var xs: String? = nil
@State private var md: String? = nil
@State private var lg: String? = nil

private let projects = ["CheerLot", "DrinkiG", "LongLongNameExample"]

var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 32) {
section(title: "기본") {
labeled("Placeholder — 아직 선택 안 함") {
DVDropdown(project ?? "Select Project", size: .sm) {
ForEach(projects, id: \.self) { name in
Button(name) { project = name }
}
Divider()
Button {
// add new project
} label: {
Label("Add New Project", systemImage: "plus")
}
}
}
labeled("Selected — 값 있음") {
DVDropdown(env ?? "Select Env", size: .sm) {
Button("Dev") { env = "Dev" }
Button("Staging") { env = "Staging" }
Button("Prod") { env = "Prod" }
}
}
}

section(title: "사이즈 (DVComponentSize 전 케이스)") {
labeled("XS (180pt)") {
DVDropdown(xs ?? "XS", size: .xs) {
Button("Option 1") { xs = "Option 1" }
Button("Option 2") { xs = "Option 2" }
}
}
labeled("SM (330pt)") {
DVDropdown(project ?? "Select Project", size: .sm) {
ForEach(projects, id: \.self) { name in
Button(name) { project = name }
}
}
}
labeled("MD (380pt)") {
DVDropdown(md ?? "Select Region", size: .md) {
Button("us-east-1") { md = "us-east-1" }
Button("ap-northeast-2") { md = "ap-northeast-2" }
}
}
labeled("LG (700pt)") {
DVDropdown(lg ?? "Select Very Long Value", size: .lg) {
Button("A") { lg = "Option A" }
Button("B") { lg = "Option B" }
}
}
}

section(title: "긴 텍스트 truncation") {
labeled("SM 사이즈 + 긴 프로젝트명 → 뒤가 잘림 (tail truncation)") {
DVDropdown("SuperLongProjectNameThatExceedsWidth", size: .sm) {
Button("A") {}
}
}
}
}
.padding(24)
.frame(maxWidth: .infinity, alignment: .leading)
}
.navigationTitle("DVDropdown")
}

@ViewBuilder
private func section<Content: View>(
title: String,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 16) {
Text(title).font(.title2).fontWeight(.bold)
content()
}
}

@ViewBuilder
private func labeled<Content: View>(
_ caption: String,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 4) {
Text(caption).font(.caption).foregroundStyle(.secondary)
content()
}
}
}
Loading