| 1 | import clsx from 'clsx'; |
| 2 | import React from 'react'; |
| 3 | |
| 4 | const Label = ({ |
| 5 | children, |
| 6 | animateRerendering, |
| 7 | color, |
| 8 | }: { |
| 9 | children: React.ReactNode; |
| 10 | animateRerendering?: boolean; |
| 11 | color?: 'default' | 'pink' | 'blue' | 'violet' | 'cyan' | 'orange'; |
| 12 | }) => { |
| 13 | return ( |
| 14 | <div |
| 15 | className={clsx('rounded-full px-1.5 shadow-[0_0_1px_3px_black]', { |
| 16 | 'bg-gray-800 text-gray-300': color === 'default', |
| 17 | 'bg-vercel-pink text-white': color === 'pink', |
| 18 | 'bg-vercel-blue text-white': color === 'blue', |
| 19 | 'bg-vercel-cyan text-white': color === 'cyan', |
| 20 | 'bg-vercel-violet text-violet-100': color === 'violet', |
| 21 | 'bg-vercel-orange text-white': color === 'orange', |
| 22 | 'animate-[highlight_1s_ease-in-out_1]': animateRerendering, |
| 23 | })} |
| 24 | > |
| 25 | {children} |
| 26 | </div> |
| 27 | ); |
| 28 | }; |
| 29 | export const Boundary = ({ |
| 30 | children, |
| 31 | labels = ['children'], |
| 32 | size = 'default', |
| 33 | color = 'default', |
| 34 | animateRerendering = true, |
| 35 | }: { |
| 36 | children: React.ReactNode; |
| 37 | labels?: string[]; |
| 38 | size?: 'small' | 'default'; |
| 39 | color?: 'default' | 'pink' | 'blue' | 'violet' | 'cyan' | 'orange'; |
| 40 | animateRerendering?: boolean; |
| 41 | }) => { |
| 42 | return ( |
| 43 | <div |
| 44 | className={clsx('relative rounded-lg border border-dashed', { |
| 45 | 'p-3 lg:p-5': size === 'small', |
| 46 | 'p-4 lg:p-9': size === 'default', |
| 47 | 'border-gray-700': color === 'default', |
| 48 | 'border-vercel-pink': color === 'pink', |
| 49 | 'border-vercel-blue': color === 'blue', |
| 50 | 'border-vercel-cyan': color === 'cyan', |
| 51 | 'border-vercel-violet': color === 'violet', |
| 52 | 'border-vercel-orange': color === 'orange', |
| 53 | 'text-vercel-pink animate-[rerender_1s_ease-in-out_1]': |
| 54 | animateRerendering, |
| 55 | })} |
| 56 | > |
| 57 | <div |
| 58 | className={clsx( |
| 59 | 'absolute -top-2.5 flex gap-x-1 text-[9px] uppercase leading-4 tracking-widest', |
| 60 | { |
| 61 | 'left-3 lg:left-5': size === 'small', |
| 62 | 'left-4 lg:left-9': size === 'default', |
| 63 | }, |
| 64 | )} |
| 65 | > |
| 66 | {labels.map((label) => { |
| 67 | return ( |
| 68 | <Label |
| 69 | key={label} |
| 70 | color={color} |
| 71 | animateRerendering={animateRerendering} |
| 72 | > |
| 73 | {label} |
| 74 | </Label> |
| 75 | ); |
| 76 | })} |
| 77 | </div> |
| 78 | |
| 79 | {children} |
| 80 | </div> |
| 81 | ); |
| 82 | }; |