this repo has no description
1import type { ReactNode, CSSProperties } from 'react';
2
3type Space = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
4
5const spaceValues: Record<Space, string> = {
6 none: '0',
7 xs: '0.25rem',
8 sm: '0.5rem',
9 md: '1rem',
10 lg: '1.5rem',
11 xl: '2rem',
12};
13
14interface StackProps {
15 children: ReactNode;
16 gap?: Space;
17 className?: string;
18 style?: CSSProperties;
19}
20
21/**
22 * Stack - vertical layout with consistent gaps
23 */
24export function Stack({ children, gap = 'md', className = '', style }: StackProps) {
25 return (
26 <div
27 className={`stack ${className}`}
28 style={{
29 display: 'flex',
30 flexDirection: 'column',
31 gap: spaceValues[gap],
32 ...style,
33 }}
34 >
35 {children}
36 </div>
37 );
38}
39
40interface ClusterProps {
41 children: ReactNode;
42 gap?: Space;
43 justify?: 'start' | 'center' | 'end' | 'between';
44 align?: 'start' | 'center' | 'end' | 'baseline';
45 wrap?: boolean;
46 className?: string;
47}
48
49/**
50 * Cluster - horizontal layout with wrapping
51 */
52export function Cluster({
53 children,
54 gap = 'sm',
55 justify = 'start',
56 align = 'center',
57 wrap = true,
58 className = '',
59}: ClusterProps) {
60 const justifyMap = {
61 start: 'flex-start',
62 center: 'center',
63 end: 'flex-end',
64 between: 'space-between',
65 };
66
67 const alignMap = {
68 start: 'flex-start',
69 center: 'center',
70 end: 'flex-end',
71 baseline: 'baseline',
72 };
73
74 return (
75 <div
76 className={`cluster ${className}`}
77 style={{
78 display: 'flex',
79 flexWrap: wrap ? 'wrap' : 'nowrap',
80 gap: spaceValues[gap],
81 justifyContent: justifyMap[justify],
82 alignItems: alignMap[align],
83 }}
84 >
85 {children}
86 </div>
87 );
88}
89
90interface BoxProps {
91 children: ReactNode;
92 padding?: Space;
93 className?: string;
94 style?: CSSProperties;
95 as?: 'div' | 'section' | 'article' | 'aside' | 'header' | 'footer';
96}
97
98/**
99 * Box - padded container
100 */
101export function Box({
102 children,
103 padding = 'md',
104 className = '',
105 style,
106 as: Component = 'div',
107}: BoxProps) {
108 return (
109 <Component
110 className={`box ${className}`}
111 style={{
112 padding: spaceValues[padding],
113 ...style,
114 }}
115 >
116 {children}
117 </Component>
118 );
119}
120
121interface DividerProps {
122 char?: string;
123 length?: number;
124}
125
126/**
127 * Divider - horizontal rule in terminal style
128 */
129export function Divider({ char = '~', length = 40 }: DividerProps) {
130 return (
131 <div className="divider" aria-hidden="true">
132 {char.repeat(length)}
133 </div>
134 );
135}