atomsystem 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,12 @@
1
1
  'use client';
2
2
 
3
3
  import React, { useState } from 'react';
4
- import { Check, X, Sparkles, Zap, Shield, Building2 } from 'lucide-react';
4
+ import { Card, Button, Badge } from '@/components/ui';
5
+ import {
6
+ Check,
7
+ X,
8
+ Sparkles,
9
+ } from 'lucide-react';
5
10
 
6
11
  interface PricingTier {
7
12
  id: string;
@@ -11,7 +16,6 @@ interface PricingTier {
11
16
  description: string;
12
17
  monthlyPrice: number;
13
18
  annualPrice: number;
14
- icon: 'zap' | 'sparkles' | 'building';
15
19
  features: { text: string; included: boolean }[];
16
20
  ctaText: string;
17
21
  }
@@ -20,191 +24,134 @@ const TIERS: PricingTier[] = [
20
24
  {
21
25
  id: 'starter',
22
26
  name: 'Starter',
23
- description: '개인 개발자 및 소규모 사이드 프로젝트를 위한 무료 스타터 팩',
27
+ description: '개인 개발자 및 오픈소스 프로젝트를 위한 플랜.',
24
28
  monthlyPrice: 0,
25
29
  annualPrice: 0,
26
- icon: 'zap',
27
30
  ctaText: '무료로 시작하기',
28
31
  features: [
29
32
  { text: '최대 3개 프로젝트 연동', included: true },
30
- { text: '기본 W3C DTCG 토큰 명세 제공', included: true },
31
- { text: 'Tailwind v4 CSS 자동 컴파일', included: true },
32
- { text: '커스텀 브랜드 테마 에디터', included: false },
33
- { text: '우선순위 기술 지원 SLA', included: false },
34
- { text: 'SSO 단일 로그인 및 감사 로그', included: false },
33
+ { text: 'W3C DTCG 표준 토큰 규격', included: true },
34
+ { text: 'Tailwind v4 CSS 즉시 컴파일', included: true },
35
+ { text: '실시간 커스텀 테마 에디터', included: false },
36
+ { text: '우선 기술 지원 SLA', included: false },
35
37
  ],
36
38
  },
37
39
  {
38
40
  id: 'pro',
39
41
  name: 'Pro',
40
42
  isPopular: true,
41
- badge: '가장 인기 있는 플랜',
42
- description: '성장하는 스타트업 및 디자인 시스템 팀을 위한 전문 도구 모음',
43
- monthlyPrice: 29,
44
- annualPrice: 22,
45
- icon: 'sparkles',
43
+ badge: '추천 플랜',
44
+ description: '디자인 시스템 확장을 준비하는 프로덕트 팀.',
45
+ monthlyPrice: 29000,
46
+ annualPrice: 22000,
46
47
  ctaText: '14일 무료 체험 시작',
47
48
  features: [
48
49
  { text: '무제한 프로젝트 & 토큰 세트', included: true },
49
- { text: '고급 실시간 차트 & 블록 전체 제공', included: true },
50
- { text: 'Tailwind v4 / CSS / React 원클릭 내보내기', included: true },
51
- { text: '커스텀 브랜드 테마 에디터 및 프리셋', included: true },
52
- { text: '영업일 24시간 내 기술 지원 SLA', included: true },
53
- { text: 'SSO 단일 로그인 및 감사 로그', included: false },
50
+ { text: 'W3C DTCG 표준 토큰 규격', included: true },
51
+ { text: 'Tailwind v4 CSS 즉시 컴파일', included: true },
52
+ { text: '실시간 커스텀 테마 에디터', included: true },
53
+ { text: 'Git 저장소 실시간 동기화', included: true },
54
54
  ],
55
55
  },
56
56
  {
57
57
  id: 'enterprise',
58
58
  name: 'Enterprise',
59
- description: '엔터프라이즈 보안, 규정 준수, 대규모 팀을 위한 맞춤형 인프라',
60
- monthlyPrice: 99,
61
- annualPrice: 79,
62
- icon: 'building',
63
- ctaText: '영업팀 문의하기',
59
+ description: '엄격한 보안과 거버넌스가 필요한 엔터프라이즈.',
60
+ monthlyPrice: 99000,
61
+ annualPrice: 79000,
62
+ ctaText: '영업팀 문의',
64
63
  features: [
65
- { text: '모든 Pro 기능 무제한 포함', included: true },
66
- { text: '전담 솔루션 아키텍트 지원', included: true },
67
- { text: '온프레미스 / VPC 프라이빗 배포', included: true },
68
- { text: '99.99% 시스템 가동률 SLA 보증', included: true },
69
- { text: 'SSO (SAML, Okta) & 상세 감사 로그', included: true },
70
- { text: '맞춤형 계약 및 보안성 심사 지원', included: true },
64
+ { text: '무제한 프로젝트 & 전용 빌드 코어', included: true },
65
+ { text: 'W3C DTCG 표준 토큰 규격', included: true },
66
+ { text: 'Tailwind v4 CSS 즉시 컴파일', included: true },
67
+ { text: '실시간 커스텀 테마 에디터', included: true },
68
+ { text: 'SSO, 감사 로그 & 99.99% SLA', included: true },
71
69
  ],
72
70
  },
73
71
  ];
74
72
 
75
73
  export function PricingPlanBlock() {
76
- const [isAnnual, setIsAnnual] = useState<boolean>(true);
77
- const [selectedPlan, setSelectedPlan] = useState<string>('pro');
78
-
79
- const getTierIcon = (icon: PricingTier['icon']) => {
80
- switch (icon) {
81
- case 'zap':
82
- return <Zap className="w-5 h-5 text-blue-500" />;
83
- case 'sparkles':
84
- return <Sparkles className="w-5 h-5 text-amber-500" />;
85
- case 'building':
86
- return <Building2 className="w-5 h-5 text-purple-500" />;
87
- }
88
- };
74
+ const [billingCycle, setBillingCycle] = useState<'monthly' | 'annual'>('annual');
89
75
 
90
76
  return (
91
- <div className="w-full bg-(--bg-primary) rounded-2xl border border-(--border-subtle) shadow-sm p-5 sm:p-8 transition-colors">
92
- {/* Header & Billing Toggle */}
93
- <div className="text-center max-w-2xl mx-auto mb-10">
94
- <span className="text-xs font-semibold text-(--accent-primary) uppercase tracking-wider">
95
- 투명하고 예측 가능한 요금제
96
- </span>
97
- <h3 className="text-2xl sm:text-3xl font-extrabold text-(--text-primary) tracking-tight mt-1 mb-3">
98
- 팀의 규모에 꼭 맞는 유연한 플랜
99
- </h3>
100
- <p className="text-xs sm:text-sm text-(--text-secondary) leading-relaxed">
101
- 숨겨진 비용 없이 언제든 플랜을 변경하거나 해지할 수 있습니다. 연간 결제 시 20%의 추가 할인이 적용됩니다.
102
- </p>
77
+ <Card className="p-5 sm:p-6 transition-colors">
78
+ {/* 1. Header & Billing Toggle (Using Button & Badge Component) */}
79
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
80
+ <div>
81
+ <h3 className="text-base font-semibold text-(--text-primary)">
82
+ 요금제 플랜 선택
83
+ </h3>
84
+ <p className="text-xs text-(--text-secondary) mt-0.5">
85
+ 팀의 규모와 워크플로우에 맞는 플랜을 선택하세요.
86
+ </p>
87
+ </div>
103
88
 
104
- {/* Toggle Switch */}
105
- <div className="inline-flex items-center gap-3 p-1 rounded-full bg-(--bg-secondary) border border-(--border-subtle) mt-6">
106
- <button
107
- onClick={() => setIsAnnual(false)}
108
- className={`px-4 py-1.5 rounded-full text-xs font-semibold transition-all ${
109
- !isAnnual
110
- ? 'bg-(--bg-primary) text-(--text-primary) shadow-xs'
111
- : 'text-(--text-secondary) hover:text-(--text-primary)'
112
- }`}
89
+ {/* Billing Switch composed with Button components */}
90
+ <div className="flex items-center gap-1 p-0.5 rounded-(--radius-sm) bg-(--bg-secondary) border border-(--border-subtle) text-xs self-start sm:self-auto">
91
+ <Button
92
+ size="sm"
93
+ variant={billingCycle === 'monthly' ? 'primary' : 'ghost'}
94
+ onClick={() => setBillingCycle('monthly')}
95
+ className="text-xs py-1 px-3 h-auto"
113
96
  >
114
97
  월간 결제
115
- </button>
116
- <button
117
- onClick={() => setIsAnnual(true)}
118
- className={`flex items-center gap-1.5 px-4 py-1.5 rounded-full text-xs font-semibold transition-all ${
119
- isAnnual
120
- ? 'bg-(--accent-primary) text-white shadow-xs'
121
- : 'text-(--text-secondary) hover:text-(--text-primary)'
122
- }`}
98
+ </Button>
99
+ <Button
100
+ size="sm"
101
+ variant={billingCycle === 'annual' ? 'primary' : 'ghost'}
102
+ onClick={() => setBillingCycle('annual')}
103
+ className="text-xs py-1 px-3 h-auto flex items-center gap-1"
123
104
  >
124
105
  <span>연간 결제</span>
125
- <span
126
- className={`text-[10px] px-1.5 py-0.2 rounded-full font-bold ${
127
- isAnnual ? 'bg-white/20 text-white' : 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400'
128
- }`}
129
- >
130
- 20% OFF
131
- </span>
132
- </button>
106
+ <Badge variant="success" className="text-xs px-1.5 py-0 font-bold">
107
+ -20%
108
+ </Badge>
109
+ </Button>
133
110
  </div>
134
111
  </div>
135
112
 
136
- {/* 3-Column Pricing Grid */}
137
- <div className="grid grid-cols-1 md:grid-cols-3 gap-6 items-stretch">
113
+ {/* 2. Three Column Pricing Cards composed with Card & Button */}
114
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
138
115
  {TIERS.map((tier) => {
139
- const isSelected = selectedPlan === tier.id;
140
- const price = isAnnual ? tier.annualPrice : tier.monthlyPrice;
141
-
116
+ const price = billingCycle === 'annual' ? tier.annualPrice : tier.monthlyPrice;
142
117
  return (
143
- <div
118
+ <Card
144
119
  key={tier.id}
145
- onClick={() => setSelectedPlan(tier.id)}
146
- className={`relative flex flex-col justify-between rounded-2xl p-6 transition-all duration-200 cursor-pointer ${
120
+ className={`p-5 flex flex-col justify-between transition-colors bg-(--bg-primary) ${
147
121
  tier.isPopular
148
- ? 'border-2 border-(--accent-primary) bg-(--bg-secondary)/40 shadow-md ring-4 ring-(--accent-primary)/10'
149
- : 'border border-(--border-strong) bg-(--bg-primary) hover:border-(--accent-primary)/50 shadow-xs'
122
+ ? 'border-(--text-primary)'
123
+ : 'border-(--border-subtle)'
150
124
  }`}
151
125
  >
152
- {/* Popular Badge */}
153
- {tier.badge && (
154
- <div className="absolute -top-3.5 left-1/2 -translate-x-1/2 px-3 py-1 rounded-full text-[11px] font-bold bg-(--accent-primary) text-white shadow-sm flex items-center gap-1">
155
- <Sparkles className="w-3 h-3" />
156
- <span>{tier.badge}</span>
157
- </div>
158
- )}
159
-
160
126
  <div>
161
- {/* Tier Title & Icon */}
162
- <div className="flex items-center justify-between mb-4">
163
- <div className="p-2.5 rounded-xl bg-(--bg-secondary) border border-(--border-subtle)">
164
- {getTierIcon(tier.icon)}
165
- </div>
166
- {isSelected && (
167
- <span className="text-[11px] font-bold px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-600 dark:text-emerald-400">
168
- 선택됨
169
- </span>
127
+ <div className="flex items-center justify-between mb-2">
128
+ <h4 className="font-semibold text-sm text-(--text-primary)">{tier.name}</h4>
129
+ {tier.badge && (
130
+ <Badge variant="primary" className="text-xs">
131
+ {tier.badge}
132
+ </Badge>
170
133
  )}
171
134
  </div>
172
-
173
- <h4 className="text-lg font-bold text-(--text-primary)">{tier.name}</h4>
174
- <p className="text-xs text-(--text-secondary) mt-1 min-h-[32px] leading-relaxed">
135
+ <p className="text-xs text-(--text-secondary) mb-4 leading-relaxed">
175
136
  {tier.description}
176
137
  </p>
177
138
 
178
- {/* Price Display */}
179
- <div className="my-6 pb-6 border-b border-(--border-subtle)">
180
- <div className="flex items-baseline gap-1">
181
- <span className="text-3xl sm:text-4xl font-black text-(--text-primary)">
182
- \${price}
183
- </span>
184
- <span className="text-xs text-(--text-muted)">/월 (계정당)</span>
185
- </div>
186
- <div className="text-[11px] text-(--text-muted) mt-1">
187
- {isAnnual ? '연간 일괄 결제 기준' : '매월 자동 갱신'}
188
- </div>
139
+ <div className="flex items-baseline gap-1 mb-5">
140
+ <span className="text-2xl font-bold tracking-tight text-(--text-primary)">
141
+ ₩{price.toLocaleString()}
142
+ </span>
143
+ <span className="text-xs text-(--text-secondary)">/월</span>
189
144
  </div>
190
145
 
191
- {/* Feature Checklist */}
192
- <div className="space-y-3 mb-6">
193
- <div className="text-[11px] font-semibold text-(--text-muted) uppercase tracking-wider">
194
- 포함된 핵심 기능
195
- </div>
146
+ <div className="space-y-2.5 pt-4 border-t border-(--border-subtle) text-xs">
196
147
  {tier.features.map((feat, idx) => (
197
- <div key={idx} className="flex items-center gap-2.5 text-xs">
148
+ <div key={idx} className="flex items-center gap-2">
198
149
  {feat.included ? (
199
- <div className="w-4 h-4 rounded-full bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 flex items-center justify-center shrink-0">
200
- <Check className="w-2.5 h-2.5 stroke-[3]" />
201
- </div>
150
+ <Check className="w-3.5 h-3.5 text-emerald-600 dark:text-emerald-400 shrink-0" />
202
151
  ) : (
203
- <div className="w-4 h-4 rounded-full bg-(--bg-secondary) text-(--text-muted) flex items-center justify-center shrink-0">
204
- <X className="w-2.5 h-2.5" />
205
- </div>
152
+ <X className="w-3.5 h-3.5 text-(--text-muted) shrink-0 opacity-40" />
206
153
  )}
207
- <span className={feat.included ? 'text-(--text-primary)' : 'text-(--text-muted) line-through'}>
154
+ <span className={feat.included ? 'text-(--text-primary)' : 'text-(--text-muted) line-through opacity-60'}>
208
155
  {feat.text}
209
156
  </span>
210
157
  </div>
@@ -212,20 +159,17 @@ export function PricingPlanBlock() {
212
159
  </div>
213
160
  </div>
214
161
 
215
- {/* Action CTA */}
216
- <button
217
- className={`w-full py-2.5 rounded-xl font-bold text-xs tracking-wide transition-all shadow-xs ${
218
- tier.isPopular
219
- ? 'bg-(--accent-primary) hover:bg-(--accent-hover) text-white'
220
- : 'bg-(--bg-secondary) hover:bg-(--border-strong) text-(--text-primary) border border-(--border-subtle)'
221
- }`}
162
+ <Button
163
+ variant={tier.isPopular ? 'primary' : 'secondary'}
164
+ size="md"
165
+ className="w-full mt-6 text-xs"
222
166
  >
223
167
  {tier.ctaText}
224
- </button>
225
- </div>
168
+ </Button>
169
+ </Card>
226
170
  );
227
171
  })}
228
172
  </div>
229
- </div>
173
+ </Card>
230
174
  );
231
175
  }