this repo has no description
at main 135 lines 2.5 kB view raw
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}