rechta-ds 0.0.0

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.
Files changed (58) hide show
  1. package/.changeset/config.json +11 -0
  2. package/.github/workflows/release.yml +53 -0
  3. package/.github/workflows/storybook.yml +34 -0
  4. package/.storybook/main.ts +17 -0
  5. package/.storybook/preview.ts +35 -0
  6. package/CHANGELOG.md +65 -0
  7. package/CONTRIBUTING.md +106 -0
  8. package/README.md +206 -0
  9. package/package.json +30 -0
  10. package/packages/tokens/build.js +357 -0
  11. package/packages/tokens/package.json +44 -0
  12. package/packages/tokens/src/tokens.json +1538 -0
  13. package/packages/ui/.storybook/main.ts +17 -0
  14. package/packages/ui/.storybook/preview.tsx +37 -0
  15. package/packages/ui/package.json +109 -0
  16. package/packages/ui/postcss.config.js +6 -0
  17. package/packages/ui/src/components/atoms/Avatar.tsx +139 -0
  18. package/packages/ui/src/components/atoms/Badge.tsx +62 -0
  19. package/packages/ui/src/components/atoms/Button.tsx +125 -0
  20. package/packages/ui/src/components/atoms/Input.tsx +116 -0
  21. package/packages/ui/src/components/atoms/Misc.tsx +128 -0
  22. package/packages/ui/src/components/atoms/Toggle.tsx +191 -0
  23. package/packages/ui/src/components/atoms/Typography.tsx +178 -0
  24. package/packages/ui/src/components/atoms/index.ts +7 -0
  25. package/packages/ui/src/components/charts/Charts.tsx +380 -0
  26. package/packages/ui/src/components/charts/DataTable.tsx +222 -0
  27. package/packages/ui/src/components/charts/index.ts +19 -0
  28. package/packages/ui/src/components/molecules/Accordion.tsx +93 -0
  29. package/packages/ui/src/components/molecules/Card.tsx +100 -0
  30. package/packages/ui/src/components/molecules/PricingCard.tsx +196 -0
  31. package/packages/ui/src/components/molecules/TestimonialCard.tsx +85 -0
  32. package/packages/ui/src/components/molecules/Tooltip.tsx +71 -0
  33. package/packages/ui/src/components/molecules/index.ts +5 -0
  34. package/packages/ui/src/components/organisms/FeatureTabs.tsx +196 -0
  35. package/packages/ui/src/components/organisms/LogoMarquee.tsx +119 -0
  36. package/packages/ui/src/components/organisms/Navbar.tsx +194 -0
  37. package/packages/ui/src/components/organisms/index.ts +3 -0
  38. package/packages/ui/src/index.ts +15 -0
  39. package/packages/ui/src/lib/utils.ts +12 -0
  40. package/packages/ui/src/stories/atoms/Avatar.stories.tsx +49 -0
  41. package/packages/ui/src/stories/atoms/Badge.stories.tsx +68 -0
  42. package/packages/ui/src/stories/atoms/Button.stories.tsx +98 -0
  43. package/packages/ui/src/stories/atoms/Input.stories.tsx +66 -0
  44. package/packages/ui/src/stories/atoms/Toggle.stories.tsx +36 -0
  45. package/packages/ui/src/stories/molecules/Accordion.stories.tsx +47 -0
  46. package/packages/ui/src/stories/molecules/Card.stories.tsx +84 -0
  47. package/packages/ui/src/stories/molecules/PricingCard.stories.tsx +62 -0
  48. package/packages/ui/src/stories/molecules/TestimonialCard.stories.tsx +52 -0
  49. package/packages/ui/src/stories/molecules/Tooltip.stories.tsx +66 -0
  50. package/packages/ui/src/stories/organisms/LogoMarquee.stories.tsx +33 -0
  51. package/packages/ui/src/stories/organisms/Navbar.stories.tsx +37 -0
  52. package/packages/ui/src/styles/globals.css +220 -0
  53. package/packages/ui/tailwind.config.ts +68 -0
  54. package/packages/ui/tsconfig.json +23 -0
  55. package/packages/ui/tsup.config.ts +24 -0
  56. package/packages/ui/vite.config.ts +17 -0
  57. package/pnpm-workspace.yaml +2 -0
  58. package/turbo.json +33 -0
@@ -0,0 +1,128 @@
1
+ import * as React from 'react';
2
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
3
+ import { cn } from '../../lib/utils';
4
+
5
+ // ─── Separator / Divider ─────────────────────────────────────────────────────
6
+ export interface SeparatorProps
7
+ extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> {
8
+ label?: string;
9
+ variant?: 'default' | 'subtle' | 'strong' | 'brand' | 'dashed';
10
+ }
11
+
12
+ const Separator = React.forwardRef<
13
+ React.ElementRef<typeof SeparatorPrimitive.Root>,
14
+ SeparatorProps
15
+ >(({ className, label, variant = 'default', orientation = 'horizontal', decorative = true, ...props }, ref) => {
16
+ const lineClass = {
17
+ default: 'bg-border',
18
+ subtle: 'bg-border-subtle',
19
+ strong: 'bg-border-strong',
20
+ brand: 'bg-brand-500/30',
21
+ dashed: 'border-t border-dashed border-border bg-transparent',
22
+ }[variant];
23
+
24
+ if (label) {
25
+ return (
26
+ <div className={cn('flex items-center gap-4', className)}>
27
+ <div className={cn('flex-1 h-px', lineClass)} />
28
+ <span className="text-xs font-mono text-text-tertiary tracking-wider uppercase whitespace-nowrap">
29
+ {label}
30
+ </span>
31
+ <div className={cn('flex-1 h-px', lineClass)} />
32
+ </div>
33
+ );
34
+ }
35
+
36
+ return (
37
+ <SeparatorPrimitive.Root
38
+ ref={ref}
39
+ decorative={decorative}
40
+ orientation={orientation}
41
+ className={cn(
42
+ 'shrink-0',
43
+ orientation === 'horizontal' ? 'h-px w-full' : 'h-full w-px',
44
+ lineClass,
45
+ className
46
+ )}
47
+ {...props}
48
+ />
49
+ );
50
+ });
51
+ Separator.displayName = 'Separator';
52
+
53
+ // ─── Icon wrapper ─────────────────────────────────────────────────────────────
54
+ export interface IconProps extends React.HTMLAttributes<HTMLSpanElement> {
55
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
56
+ color?: 'default' | 'brand' | 'accent' | 'muted' | 'error' | 'success' | 'warning';
57
+ children: React.ReactNode;
58
+ }
59
+
60
+ const sizeClasses = {
61
+ xs: '[&_svg]:size-3',
62
+ sm: '[&_svg]:size-3.5',
63
+ md: '[&_svg]:size-4',
64
+ lg: '[&_svg]:size-5',
65
+ xl: '[&_svg]:size-6',
66
+ };
67
+
68
+ const colorClasses = {
69
+ default: 'text-text-secondary',
70
+ brand: 'text-brand-400',
71
+ accent: 'text-accent-400',
72
+ muted: 'text-text-tertiary',
73
+ error: 'text-red-400',
74
+ success: 'text-brand-400',
75
+ warning: 'text-amber-400',
76
+ };
77
+
78
+ const Icon: React.FC<IconProps> = ({ size = 'md', color = 'default', className, children, ...props }) => (
79
+ <span
80
+ className={cn(
81
+ 'inline-flex items-center justify-center shrink-0',
82
+ sizeClasses[size],
83
+ colorClasses[color],
84
+ className
85
+ )}
86
+ {...props}
87
+ >
88
+ {children}
89
+ </span>
90
+ );
91
+
92
+ // ─── Star Rating ──────────────────────────────────────────────────────────────
93
+ export interface StarRatingProps {
94
+ value: number;
95
+ max?: number;
96
+ size?: 'sm' | 'md' | 'lg';
97
+ showValue?: boolean;
98
+ className?: string;
99
+ }
100
+
101
+ const StarRating: React.FC<StarRatingProps> = ({ value, max = 5, size = 'md', showValue, className }) => {
102
+ const starSize = { sm: 'size-3', md: 'size-4', lg: 'size-5' }[size];
103
+
104
+ return (
105
+ <div className={cn('inline-flex items-center gap-1.5', className)}>
106
+ <div className="flex items-center gap-0.5">
107
+ {Array.from({ length: max }).map((_, i) => (
108
+ <svg
109
+ key={i}
110
+ viewBox="0 0 20 20"
111
+ fill="currentColor"
112
+ className={cn(
113
+ starSize,
114
+ i < Math.floor(value) ? 'text-amber-400' : 'text-border-strong'
115
+ )}
116
+ >
117
+ <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
118
+ </svg>
119
+ ))}
120
+ </div>
121
+ {showValue && (
122
+ <span className="text-sm font-mono font-medium text-text-primary">{value.toFixed(1)}</span>
123
+ )}
124
+ </div>
125
+ );
126
+ };
127
+
128
+ export { Separator, Icon, StarRating };
@@ -0,0 +1,191 @@
1
+ import * as React from 'react';
2
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
3
+ import { cn } from '../../lib/utils';
4
+
5
+ // ─── Switch ───────────────────────────────────────────────────────────────────
6
+ export interface SwitchProps
7
+ extends React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> {
8
+ size?: 'sm' | 'md' | 'lg';
9
+ label?: string;
10
+ description?: string;
11
+ }
12
+
13
+ const Switch = React.forwardRef<
14
+ React.ElementRef<typeof SwitchPrimitive.Root>,
15
+ SwitchProps
16
+ >(({ className, size = 'md', label, description, id, ...props }, ref) => {
17
+ const sizeClasses = {
18
+ sm: { root: 'h-4 w-7', thumb: 'size-3 data-[state=checked]:translate-x-3' },
19
+ md: { root: 'h-5 w-9', thumb: 'size-4 data-[state=checked]:translate-x-4' },
20
+ lg: { root: 'h-6 w-11', thumb: 'size-5 data-[state=checked]:translate-x-5' },
21
+ }[size];
22
+
23
+ const switchEl = (
24
+ <SwitchPrimitive.Root
25
+ ref={ref}
26
+ id={id}
27
+ className={cn(
28
+ 'peer inline-flex shrink-0 cursor-pointer items-center rounded-full border border-border',
29
+ 'bg-surface transition-all duration-200',
30
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-base',
31
+ 'disabled:cursor-not-allowed disabled:opacity-50',
32
+ 'data-[state=checked]:bg-brand-500 data-[state=checked]:border-brand-500',
33
+ 'hover:border-border-strong data-[state=checked]:hover:bg-brand-400',
34
+ sizeClasses.root,
35
+ className
36
+ )}
37
+ {...props}
38
+ >
39
+ <SwitchPrimitive.Thumb
40
+ className={cn(
41
+ 'pointer-events-none block rounded-full bg-text-tertiary shadow-md',
42
+ 'ring-0 transition-all duration-200',
43
+ 'translate-x-0.5',
44
+ 'data-[state=checked]:bg-gray-950',
45
+ sizeClasses.thumb
46
+ )}
47
+ />
48
+ </SwitchPrimitive.Root>
49
+ );
50
+
51
+ if (!label) return switchEl;
52
+
53
+ return (
54
+ <div className="flex items-start gap-3">
55
+ {switchEl}
56
+ <div className="flex flex-col gap-0.5">
57
+ <label htmlFor={id} className="text-sm font-medium text-text-primary cursor-pointer leading-tight">
58
+ {label}
59
+ </label>
60
+ {description && (
61
+ <span className="text-xs text-text-tertiary leading-normal">{description}</span>
62
+ )}
63
+ </div>
64
+ </div>
65
+ );
66
+ });
67
+ Switch.displayName = 'Switch';
68
+
69
+ // ─── Checkbox ────────────────────────────────────────────────────────────────
70
+ export interface CheckboxProps extends React.InputHTMLAttributes<HTMLInputElement> {
71
+ label?: string;
72
+ description?: string;
73
+ indeterminate?: boolean;
74
+ }
75
+
76
+ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
77
+ ({ className, label, description, id, indeterminate, ...props }, ref) => {
78
+ const internalRef = React.useRef<HTMLInputElement>(null);
79
+ const resolvedRef = (ref as React.RefObject<HTMLInputElement>) || internalRef;
80
+
81
+ React.useEffect(() => {
82
+ if (resolvedRef.current) {
83
+ resolvedRef.current.indeterminate = indeterminate ?? false;
84
+ }
85
+ }, [indeterminate, resolvedRef]);
86
+
87
+ const checkboxEl = (
88
+ <div className="relative flex items-center">
89
+ <input
90
+ ref={resolvedRef}
91
+ type="checkbox"
92
+ id={id}
93
+ className={cn(
94
+ 'peer size-4 shrink-0 rounded border border-border bg-surface cursor-pointer',
95
+ 'appearance-none transition-all duration-150',
96
+ 'checked:bg-brand-500 checked:border-brand-500',
97
+ 'indeterminate:bg-brand-500 indeterminate:border-brand-500',
98
+ 'hover:border-border-strong',
99
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500/50 focus-visible:ring-offset-1 focus-visible:ring-offset-bg-base',
100
+ 'disabled:cursor-not-allowed disabled:opacity-50',
101
+ className
102
+ )}
103
+ {...props}
104
+ />
105
+ {/* Checkmark SVG overlay */}
106
+ <svg
107
+ className="absolute size-4 pointer-events-none hidden peer-checked:block text-gray-950"
108
+ viewBox="0 0 16 16" fill="none"
109
+ >
110
+ <path d="M3 8l3.5 3.5L13 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
111
+ </svg>
112
+ {/* Indeterminate dash */}
113
+ <svg
114
+ className="absolute size-4 pointer-events-none hidden peer-indeterminate:block text-gray-950"
115
+ viewBox="0 0 16 16" fill="none"
116
+ >
117
+ <path d="M4 8h8" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
118
+ </svg>
119
+ </div>
120
+ );
121
+
122
+ if (!label) return checkboxEl;
123
+
124
+ return (
125
+ <div className="flex items-start gap-3">
126
+ {checkboxEl}
127
+ <div className="flex flex-col gap-0.5 mt-px">
128
+ <label htmlFor={id} className="text-sm font-medium text-text-primary cursor-pointer leading-tight">
129
+ {label}
130
+ </label>
131
+ {description && (
132
+ <span className="text-xs text-text-tertiary leading-normal">{description}</span>
133
+ )}
134
+ </div>
135
+ </div>
136
+ );
137
+ }
138
+ );
139
+ Checkbox.displayName = 'Checkbox';
140
+
141
+ // ─── Billing Toggle ───────────────────────────────────────────────────────────
142
+ export interface BillingToggleProps {
143
+ value: 'monthly' | 'yearly';
144
+ onChange: (value: 'monthly' | 'yearly') => void;
145
+ savingsLabel?: string;
146
+ className?: string;
147
+ }
148
+
149
+ const BillingToggle: React.FC<BillingToggleProps> = ({
150
+ value,
151
+ onChange,
152
+ savingsLabel = 'Save 33%',
153
+ className,
154
+ }) => {
155
+ return (
156
+ <div className={cn('inline-flex items-center gap-3', className)}>
157
+ <span className={cn('text-sm font-medium transition-colors', value === 'monthly' ? 'text-text-primary' : 'text-text-tertiary')}>
158
+ Monthly
159
+ </span>
160
+ <button
161
+ role="switch"
162
+ aria-checked={value === 'yearly'}
163
+ onClick={() => onChange(value === 'monthly' ? 'yearly' : 'monthly')}
164
+ className={cn(
165
+ 'relative h-6 w-12 rounded-full border transition-all duration-300 cursor-pointer',
166
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500',
167
+ value === 'yearly'
168
+ ? 'bg-brand-500 border-brand-500'
169
+ : 'bg-surface border-border'
170
+ )}
171
+ >
172
+ <span
173
+ className={cn(
174
+ 'absolute top-0.5 size-5 rounded-full shadow-md transition-all duration-300',
175
+ value === 'yearly'
176
+ ? 'left-[calc(100%-1.375rem)] bg-gray-950'
177
+ : 'left-0.5 bg-text-tertiary'
178
+ )}
179
+ />
180
+ </button>
181
+ <span className={cn('text-sm font-medium transition-colors flex items-center gap-2', value === 'yearly' ? 'text-text-primary' : 'text-text-tertiary')}>
182
+ Yearly
183
+ <span className="text-[10px] font-mono font-medium bg-accent-400/10 text-accent-400 border border-accent-400/30 px-1.5 py-0.5 rounded">
184
+ {savingsLabel}
185
+ </span>
186
+ </span>
187
+ </div>
188
+ );
189
+ };
190
+
191
+ export { Switch, Checkbox, BillingToggle };
@@ -0,0 +1,178 @@
1
+ import * as React from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import { cn } from '../../lib/utils';
4
+
5
+ // ─── Heading ──────────────────────────────────────────────────────────────────
6
+ const headingVariants = cva(
7
+ 'font-display font-bold tracking-tight leading-tight text-text-primary',
8
+ {
9
+ variants: {
10
+ level: {
11
+ display: 'text-7xl md:text-8xl tracking-tighter',
12
+ h1: 'text-5xl md:text-6xl',
13
+ h2: 'text-4xl md:text-5xl',
14
+ h3: 'text-3xl',
15
+ h4: 'text-2xl',
16
+ h5: 'text-xl',
17
+ h6: 'text-lg',
18
+ },
19
+ weight: {
20
+ light: 'font-light',
21
+ regular: 'font-normal',
22
+ medium: 'font-medium',
23
+ semibold: 'font-semibold',
24
+ bold: 'font-bold',
25
+ extrabold:'font-extrabold',
26
+ },
27
+ color: {
28
+ default: 'text-text-primary',
29
+ secondary: 'text-text-secondary',
30
+ brand: 'text-text-brand',
31
+ accent: 'text-text-accent',
32
+ muted: 'text-text-tertiary',
33
+ },
34
+ gradient: {
35
+ none: '',
36
+ brand: 'bg-gradient-to-r from-brand-400 to-accent-400 bg-clip-text text-transparent',
37
+ mono: 'bg-gradient-to-r from-text-primary to-text-tertiary bg-clip-text text-transparent',
38
+ white: 'bg-gradient-to-b from-white to-white/60 bg-clip-text text-transparent',
39
+ },
40
+ },
41
+ defaultVariants: {
42
+ level: 'h2',
43
+ color: 'default',
44
+ gradient: 'none',
45
+ },
46
+ }
47
+ );
48
+
49
+ type HeadingElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
50
+
51
+ export interface HeadingProps
52
+ extends Omit<React.HTMLAttributes<HTMLHeadingElement>, 'color'>,
53
+ VariantProps<typeof headingVariants> {
54
+ as?: HeadingElement | 'p' | 'span' | 'div';
55
+ }
56
+
57
+ const Heading = React.forwardRef<HTMLHeadingElement, HeadingProps>(
58
+ ({ className, level = 'h2', weight, color, gradient, as, children, ...props }, ref) => {
59
+ const tagMap: Record<string, HeadingElement> = {
60
+ display: 'h1', h1: 'h1', h2: 'h2', h3: 'h3', h4: 'h4', h5: 'h5', h6: 'h6',
61
+ };
62
+ const Tag = (as ?? tagMap[level ?? 'h2'] ?? 'h2') as any;
63
+ return (
64
+ <Tag
65
+ ref={ref}
66
+ className={cn(headingVariants({ level, weight, color, gradient, className }))}
67
+ {...props}
68
+ >
69
+ {children}
70
+ </Tag>
71
+ );
72
+ }
73
+ );
74
+ Heading.displayName = 'Heading';
75
+
76
+ // ─── Text ─────────────────────────────────────────────────────────────────────
77
+ const textVariants = cva('font-body text-text-secondary', {
78
+ variants: {
79
+ size: {
80
+ xs: 'text-xs',
81
+ sm: 'text-sm',
82
+ base: 'text-base',
83
+ md: 'text-md',
84
+ lg: 'text-lg',
85
+ xl: 'text-xl',
86
+ },
87
+ weight: {
88
+ light: 'font-light',
89
+ regular: 'font-normal',
90
+ medium: 'font-medium',
91
+ semibold: 'font-semibold',
92
+ bold: 'font-bold',
93
+ },
94
+ color: {
95
+ primary: 'text-text-primary',
96
+ secondary: 'text-text-secondary',
97
+ tertiary: 'text-text-tertiary',
98
+ disabled: 'text-text-disabled',
99
+ brand: 'text-text-brand',
100
+ accent: 'text-text-accent',
101
+ error: 'text-red-400',
102
+ success: 'text-brand-400',
103
+ warning: 'text-amber-400',
104
+ },
105
+ leading: {
106
+ tight: 'leading-tight',
107
+ snug: 'leading-snug',
108
+ normal: 'leading-normal',
109
+ relaxed: 'leading-relaxed',
110
+ loose: 'leading-loose',
111
+ },
112
+ },
113
+ defaultVariants: {
114
+ size: 'base',
115
+ leading: 'normal',
116
+ },
117
+ });
118
+
119
+ export interface TextProps
120
+ extends Omit<React.HTMLAttributes<HTMLParagraphElement>, 'color'>,
121
+ VariantProps<typeof textVariants> {
122
+ as?: 'p' | 'span' | 'div' | 'label' | 'small' | 'strong' | 'em';
123
+ }
124
+
125
+ const Text = React.forwardRef<HTMLParagraphElement, TextProps>(
126
+ ({ className, size, weight, color, leading, as = 'p', ...props }, ref) => {
127
+ const Tag = as as any;
128
+ return (
129
+ <Tag
130
+ ref={ref}
131
+ className={cn(textVariants({ size, weight, color, leading, className }))}
132
+ {...props}
133
+ />
134
+ );
135
+ }
136
+ );
137
+ Text.displayName = 'Text';
138
+
139
+ // ─── Label ───────────────────────────────────────────────────────────────────
140
+ export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
141
+ required?: boolean;
142
+ optional?: boolean;
143
+ }
144
+
145
+ const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
146
+ ({ className, children, required, optional, ...props }, ref) => (
147
+ <label
148
+ ref={ref}
149
+ className={cn(
150
+ 'block text-sm font-medium text-text-primary tracking-wide mb-1.5',
151
+ className
152
+ )}
153
+ {...props}
154
+ >
155
+ {children}
156
+ {required && <span className="ml-1 text-red-400">*</span>}
157
+ {optional && <span className="ml-1.5 text-text-tertiary font-normal text-xs">(optional)</span>}
158
+ </label>
159
+ )
160
+ );
161
+ Label.displayName = 'Label';
162
+
163
+ // ─── Overline / Caption ───────────────────────────────────────────────────────
164
+ const Overline: React.FC<React.HTMLAttributes<HTMLSpanElement>> = ({ className, ...props }) => (
165
+ <span
166
+ className={cn('text-xs font-mono font-medium tracking-widest uppercase text-text-tertiary', className)}
167
+ {...props}
168
+ />
169
+ );
170
+
171
+ const Caption: React.FC<React.HTMLAttributes<HTMLSpanElement>> = ({ className, ...props }) => (
172
+ <span
173
+ className={cn('text-xs font-body text-text-tertiary leading-normal', className)}
174
+ {...props}
175
+ />
176
+ );
177
+
178
+ export { Heading, Text, Label, Overline, Caption, headingVariants, textVariants };
@@ -0,0 +1,7 @@
1
+ export * from './Button';
2
+ export * from './Badge';
3
+ export * from './Input';
4
+ export * from './Toggle';
5
+ export * from './Avatar';
6
+ export * from './Typography';
7
+ export * from './Misc';