A design system in a box. hip-ui.tngl.io/docs/introduction
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

showcases

+2637 -187
+18
.cursor/rules/hip.mdc
··· 1 + --- 2 + alwaysApply: false 3 + --- 4 + 5 + ## Components 6 + 7 + - Use components from @apps/docs/src/components/ 8 + - Prefer to use the @apps/docs/src/components/flex or @apps/docs/src/components/flex/index.tsx for layout 9 + - Dont write custom styles for text, instead use the @apps/docs/src/components/text/index.tsx component. 10 + 11 + ## Custom styles 12 + 13 + - If you need to apply colors use @apps/docs/src/components/theme/semantic-color.stylex.tsx 14 + - If you need to apply spacing use the tokens in @apps/docs/src/components/theme/spacing.stylex.tsx 15 + - If you need to apply radius use the tokens in @apps/docs/src/components/theme/radius.stylex.tsx 16 + - If you need to apply shadow use the tokens in @apps/docs/src/components/theme/shadow.stylex.tsx 17 + - If you need to apply animations use the tokens in @apps/docs/src/components/theme/animations.stylex.tsx 18 + - If you need to apply text styles in a stylex block use the tokens in @apps/docs/src/components/theme/typography.stylex.tsx
+10 -2
apps/docs/src/components/aspect-ratio/index.tsx
··· 7 7 aspectRatio, 8 8 }), 9 9 container: { 10 + overflow: "hidden", 10 11 position: "relative", 11 12 }, 13 + rounded: { 14 + borderTopLeftRadius: radius["md"], 15 + borderBottomLeftRadius: radius["md"], 16 + borderTopRightRadius: radius["md"], 17 + borderBottomRightRadius: radius["md"], 18 + }, 12 19 imageContainer: { 13 20 inset: 0, 14 21 position: "absolute", 15 22 }, 16 23 image: { 17 - borderRadius: radius["md"], 18 24 height: "100%", 19 25 objectFit: "cover", 20 - overflow: "hidden", 21 26 width: "100%", 22 27 }, 23 28 }); ··· 26 31 extends Omit<React.ComponentProps<"div">, "style" | "className"> { 27 32 style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 28 33 aspectRatio?: number; 34 + rounded?: boolean; 29 35 } 30 36 31 37 export function AspectRatio({ 32 38 style, 33 39 aspectRatio = 1, 40 + rounded = true, 34 41 ...props 35 42 }: AspectRatioProps) { 36 43 return ( ··· 39 46 {...stylex.props( 40 47 styles.container, 41 48 styles.aspectRatio(aspectRatio), 49 + rounded && styles.rounded, 42 50 style, 43 51 )} 44 52 />
+13 -1
apps/docs/src/components/card/index.tsx
··· 13 13 card: { 14 14 borderRadius: radius["lg"], 15 15 display: "flex", 16 + overflow: "hidden", 16 17 flexDirection: "column", 17 18 fontFamily: fontFamily["sans"], 18 19 gap: "var(--card-gap)", ··· 81 82 display: "flex", 82 83 gap: spacing["2"], 83 84 justifyContent: "flex-end", 85 + }, 86 + cardImage: { 87 + borderTopLeftRadius: { default: 0, ":first-child": radius.md }, 88 + borderBottomLeftRadius: { default: 0, ":last-child": radius.md }, 89 + borderTopRightRadius: { default: 0, ":first-child": radius.md }, 90 + borderBottomRightRadius: { default: 0, ":last-child": radius.md }, 91 + overflow: "hidden", 84 92 }, 85 93 }); 86 94 ··· 198 206 return ( 199 207 <AspectRatio 200 208 aspectRatio={aspectRatio} 201 - style={[styles.cardSection as unknown as stylex.StyleXStyles, style]} 209 + style={[ 210 + styles.cardSection as unknown as stylex.StyleXStyles, 211 + styles.cardImage, 212 + style, 213 + ]} 202 214 > 203 215 <AspectRatioImage {...props} /> 204 216 </AspectRatio>
+1 -4
apps/docs/src/components/link/index.tsx
··· 11 11 12 12 const styles = stylex.create({ 13 13 link: { 14 - color: { 15 - default: primaryColor.text1, 16 - ":visited": primaryColor.text2, 17 - }, 14 + color: primaryColor.text2, 18 15 cursor: "pointer", 19 16 fontFamily: fontFamily["sans"], 20 17 fontWeight: fontWeight["normal"],
+1
apps/docs/src/components/table/index.tsx
··· 61 61 ":is([data-table-size=md] *)": spacing["2"], 62 62 ":is([data-table-size=lg] *)": spacing["3"], 63 63 }, 64 + textAlign: "left", 64 65 }, 65 66 }); 66 67
+1 -1
apps/docs/src/components/toggle-button-group/index.tsx
··· 62 62 } 63 63 64 64 interface ToggleButtonGroupGroupedProps extends ToggleButtonGroupBaseProps { 65 - variant: "grouped"; 65 + variant?: "grouped"; 66 66 itemsPerRow?: never; 67 67 } 68 68
+7
apps/docs/src/components/typography/text.tsx
··· 66 66 "variant-destructive": { color: criticalColor.text2 }, 67 67 68 68 strikethrough: { textDecoration: "line-through" }, 69 + 70 + left: { textAlign: "left" }, 71 + center: { textAlign: "center" }, 72 + right: { textAlign: "right" }, 69 73 }); 70 74 71 75 interface TextProps ··· 78 82 tracking?: ThemeKeys<typeof tracking>; 79 83 variant?: "primary" | "secondary" | "destructive"; 80 84 strikethrough?: boolean; 85 + align?: "left" | "center" | "right"; 81 86 } 82 87 83 88 export const Text = ({ ··· 89 94 tracking, 90 95 variant, 91 96 strikethrough = false, 97 + align, 92 98 ...props 93 99 }: TextProps) => { 94 100 return ( ··· 101 107 tracking && styles[`tracking-${tracking}`], 102 108 variant && styles[`variant-${variant}`], 103 109 strikethrough && styles.strikethrough, 110 + align && styles[align], 104 111 style, 105 112 )} 106 113 {...props}
+4 -4
apps/docs/src/docs/components/alert-dialog.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Dialog](/components/dialog) - For general modal dialogs 29 - - [Button](/components/button) - For dialog action buttons 30 - - [Popover](/components/popover) - For non-modal overlays 31 - - [Tooltip](/components/tooltip) - For contextual help 28 + - [Dialog](/docs/components/dialog) - For general modal dialogs 29 + - [Button](/docs/components/button) - For dialog action buttons 30 + - [Popover](/docs/components/popover) - For non-modal overlays 31 + - [Tooltip](/docs/components/tooltip) - For contextual help
+4 -4
apps/docs/src/docs/components/aspect-ratio.mdx
··· 34 34 35 35 ## Related Components 36 36 37 - - [Card](/components/card) - For cards with aspect ratio images 38 - - [Grid](/components/grid) - For grid layouts with aspect ratio items 39 - - [Flex](/components/flex) - For flex layouts with aspect ratio items 40 - - [Avatar](/components/avatar) - For user avatars with consistent aspect ratios 37 + - [Card](/docs/components/card) - For cards with aspect ratio images 38 + - [Grid](/docs/components/grid) - For grid layouts with aspect ratio items 39 + - [Flex](/docs/components/flex) - For flex layouts with aspect ratio items 40 + - [Avatar](/docs/components/avatar) - For user avatars with consistent aspect ratios
+4 -4
apps/docs/src/docs/components/avatar.mdx
··· 48 48 49 49 ## Related Components 50 50 51 - - [Badge](/components/badge) - For status indicators on avatars 52 - - [Card](/components/card) - For cards with user avatars 53 - - [AspectRatio](/components/aspect-ratio) - For maintaining avatar aspect ratios 54 - - [Typography](/components/typography) - For text alongside avatars 51 + - [Badge](/docs/components/badge) - For status indicators on avatars 52 + - [Card](/docs/components/card) - For cards with user avatars 53 + - [AspectRatio](/docs/components/aspect-ratio) - For maintaining avatar aspect ratios 54 + - [Typography](/docs/components/typography) - For text alongside avatars
+4 -4
apps/docs/src/docs/components/badge.mdx
··· 55 55 56 56 ## Related Components 57 57 58 - - [Avatar](/components/avatar) - For user avatars with status badges 59 - - [Card](/components/card) - For cards with status badges 60 - - [Table](/components/table) - For table cells with status badges 61 - - [Button](/components/button) - For buttons with notification badges 58 + - [Avatar](/docs/components/avatar) - For user avatars with status badges 59 + - [Card](/docs/components/card) - For cards with status badges 60 + - [Table](/docs/components/table) - For table cells with status badges 61 + - [Button](/docs/components/button) - For buttons with notification badges
+4 -4
apps/docs/src/docs/components/button-group.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Button](/components/button) - Individual buttons within the group 29 - - [IconButton](/components/icon-button) - Icon-only buttons for the group 30 - - [ToggleButton](/components/toggle-button) - Toggleable buttons for the group 31 - - [ToggleButtonGroup](/components/toggle-button-group) - For grouping toggle buttons specifically 28 + - [Button](/docs/components/button) - Individual buttons within the group 29 + - [IconButton](/docs/components/icon-button) - Icon-only buttons for the group 30 + - [ToggleButton](/docs/components/toggle-button) - Toggleable buttons for the group 31 + - [ToggleButtonGroup](/docs/components/toggle-button-group) - For grouping toggle buttons specifically
+4 -4
apps/docs/src/docs/components/button.mdx
··· 62 62 63 63 ## Related Components 64 64 65 - - [IconButton](/components/icon-button) - For icon-only buttons 66 - - [ToggleButton](/components/toggle-button) - For toggleable buttons 67 - - [ButtonGroup](/components/button-group) - For grouping buttons together 68 - - [Link](/components/link) - For navigation links that look like buttons 65 + - [IconButton](/docs/components/icon-button) - For icon-only buttons 66 + - [ToggleButton](/docs/components/toggle-button) - For toggleable buttons 67 + - [ButtonGroup](/docs/components/button-group) - For grouping buttons together 68 + - [Link](/docs/components/link) - For navigation links that look like buttons
+4 -4
apps/docs/src/docs/components/card.mdx
··· 55 55 56 56 ## Related Components 57 57 58 - - [Table](/components/table) - For structured data display 59 - - [Badge](/components/badge) - For status indicators in cards 60 - - [Button](/components/button) - For card actions 61 - - [AspectRatio](/components/aspect-ratio) - For card images 58 + - [Table](/docs/components/table) - For structured data display 59 + - [Badge](/docs/components/badge) - For status indicators in cards 60 + - [Button](/docs/components/button) - For card actions 61 + - [AspectRatio](/docs/components/aspect-ratio) - For card images
+4 -4
apps/docs/src/docs/components/checkbox.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [Radio](/components/radio) - For single selection from multiple options 45 - - [Switch](/components/switch) - For binary toggle choices 46 - - [Select](/components/select) - For dropdown selection 47 - - [Label](/components/label) - For form labels and descriptions 44 + - [Radio](/docs/components/radio) - For single selection from multiple options 45 + - [Switch](/docs/components/switch) - For binary toggle choices 46 + - [Select](/docs/components/select) - For dropdown selection 47 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/color-field.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [ColorSwatch](/components/color-swatch) - For displaying color values 29 - - [TextField](/components/text-field) - For general text input 30 - - [NumberField](/components/number-field) - For numeric input 31 - - [Label](/components/label) - For form labels and descriptions 28 + - [ColorSwatch](/docs/components/color-swatch) - For displaying color values 29 + - [TextField](/docs/components/text-field) - For general text input 30 + - [NumberField](/docs/components/number-field) - For numeric input 31 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/color-swatch.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [ColorField](/components/color-field) - For color input with color swatches 29 - - [Card](/components/card) - For displaying color swatches in cards 30 - - [Grid](/components/grid) - For organizing color swatches in grids 31 - - [Button](/components/button) - For interactive color swatches 28 + - [ColorField](/docs/components/color-field) - For color input with color swatches 29 + - [Card](/docs/components/card) - For displaying color swatches in cards 30 + - [Grid](/docs/components/grid) - For organizing color swatches in grids 31 + - [Button](/docs/components/button) - For interactive color swatches
+4 -4
apps/docs/src/docs/components/combobox.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Select](/components/select) - For dropdown selection without search 29 - - [SearchField](/components/search-field) - For search input with clear button 30 - - [TextField](/components/text-field) - For general text input 31 - - [Label](/components/label) - For form labels and descriptions 28 + - [Select](/docs/components/select) - For dropdown selection without search 29 + - [SearchField](/docs/components/search-field) - For search input with clear button 30 + - [TextField](/docs/components/text-field) - For general text input 31 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/command-menu.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [SearchField](/components/search-field) - For the search input in command menus 29 - - [Menu](/components/menu) - The underlying menu component 30 - - [Dialog](/components/dialog) - For the modal container 31 - - [ListBox](/components/listbox) - For displaying command results 28 + - [SearchField](/docs/components/search-field) - For the search input in command menus 29 + - [Menu](/docs/components/menu) - The underlying menu component 30 + - [Dialog](/docs/components/dialog) - For the modal container 31 + - [ListBox](/docs/components/listbox) - For displaying command results
+4 -4
apps/docs/src/docs/components/context-menu.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Menu](/components/menu) - The underlying menu component 29 - - [Popover](/components/popover) - For positioning the context menu 30 - - [CommandMenu](/components/command-menu) - For command palette menus 31 - - [Button](/components/button) - For context menu triggers 28 + - [Menu](/docs/components/menu) - The underlying menu component 29 + - [Popover](/docs/components/popover) - For positioning the context menu 30 + - [CommandMenu](/docs/components/command-menu) - For command palette menus 31 + - [Button](/docs/components/button) - For context menu triggers
+4 -4
apps/docs/src/docs/components/date-field.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [TimeField](/components/time-field) - For time input 29 - - [TextField](/components/text-field) - For general text input 30 - - [NumberField](/components/number-field) - For numeric input 31 - - [Label](/components/label) - For form labels and descriptions 28 + - [TimeField](/docs/components/time-field) - For time input 29 + - [TextField](/docs/components/text-field) - For general text input 30 + - [NumberField](/docs/components/number-field) - For numeric input 31 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/dialog.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [AlertDialog](/components/alert-dialog) - For critical actions and confirmations 45 - - [Popover](/components/popover) - For non-modal overlays 46 - - [Button](/components/button) - For dialog action buttons 47 - - [Form](/components/form) - For forms within dialogs 44 + - [AlertDialog](/docs/components/alert-dialog) - For critical actions and confirmations 45 + - [Popover](/docs/components/popover) - For non-modal overlays 46 + - [Button](/docs/components/button) - For dialog action buttons 47 + - [Form](/docs/components/form) - For forms within dialogs
+4 -4
apps/docs/src/docs/components/file-drop-zone.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Button](/components/button) - For file upload triggers 29 - - [Card](/components/card) - For containing file drop zones 30 - - [Badge](/components/badge) - For file upload status indicators 31 - - [Typography](/components/typography) - For file upload instructions 28 + - [Button](/docs/components/button) - For file upload triggers 29 + - [Card](/docs/components/card) - For containing file drop zones 30 + - [Badge](/docs/components/badge) - For file upload status indicators 31 + - [Typography](/docs/components/typography) - For file upload instructions
+4 -4
apps/docs/src/docs/components/flex.mdx
··· 55 55 56 56 ## Related Components 57 57 58 - - [Grid](/components/grid) - For two-dimensional layouts 59 - - [Card](/components/card) - For grouping content in flex layouts 60 - - [ButtonGroup](/components/button-group) - For grouping buttons in flex layouts 61 - - [Separator](/components/separator) - For visual separation in flex layouts 58 + - [Grid](/docs/components/grid) - For two-dimensional layouts 59 + - [Card](/docs/components/card) - For grouping content in flex layouts 60 + - [ButtonGroup](/docs/components/button-group) - For grouping buttons in flex layouts 61 + - [Separator](/docs/components/separator) - For visual separation in flex layouts
+4 -4
apps/docs/src/docs/components/grid.mdx
··· 34 34 35 35 ## Related Components 36 36 37 - - [Flex](/components/flex) - For one-dimensional flexible layouts 38 - - [Card](/components/card) - For grouping content in grid layouts 39 - - [AspectRatio](/components/aspect-ratio) - For maintaining aspect ratios in grid items 40 - - [Table](/components/table) - For structured data in grid layouts 37 + - [Flex](/docs/components/flex) - For one-dimensional flexible layouts 38 + - [Card](/docs/components/card) - For grouping content in grid layouts 39 + - [AspectRatio](/docs/components/aspect-ratio) - For maintaining aspect ratios in grid items 40 + - [Table](/docs/components/table) - For structured data in grid layouts
+4 -4
apps/docs/src/docs/components/icon-button.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [Button](/components/button) - For buttons with text and icons 45 - - [ToggleButton](/components/toggle-button) - For toggleable icon buttons 46 - - [Tooltip](/components/tooltip) - For providing context on icon-only buttons 47 - - [ButtonGroup](/components/button-group) - For grouping icon buttons together 44 + - [Button](/docs/components/button) - For buttons with text and icons 45 + - [ToggleButton](/docs/components/toggle-button) - For toggleable icon buttons 46 + - [Tooltip](/docs/components/tooltip) - For providing context on icon-only buttons 47 + - [ButtonGroup](/docs/components/button-group) - For grouping icon buttons together
+4 -4
apps/docs/src/docs/components/label.mdx
··· 34 34 35 35 ## Related Components 36 36 37 - - [TextField](/components/text-field) - Form inputs that use labels 38 - - [Checkbox](/components/checkbox) - Form controls that use labels 39 - - [Radio](/components/radio) - Form controls that use labels 40 - - [Switch](/components/switch) - Form controls that use labels 37 + - [TextField](/docs/components/text-field) - Form inputs that use labels 38 + - [Checkbox](/docs/components/checkbox) - Form controls that use labels 39 + - [Radio](/docs/components/radio) - Form controls that use labels 40 + - [Switch](/docs/components/switch) - Form controls that use labels
+4 -4
apps/docs/src/docs/components/link.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Button](/components/button) - For action buttons that look like links 29 - - [IconButton](/components/icon-button) - For icon-only navigation buttons 30 - - [Typography](/components/typography) - For text styling and hierarchy 31 - - [Badge](/components/badge) - For status indicators on links 28 + - [Button](/docs/components/button) - For action buttons that look like links 29 + - [IconButton](/docs/components/icon-button) - For icon-only navigation buttons 30 + - [Typography](/docs/components/typography) - For text styling and hierarchy 31 + - [Badge](/docs/components/badge) - For status indicators on links
+4 -4
apps/docs/src/docs/components/listbox.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Select](/components/select) - For dropdown selection using ListBox 29 - - [ComboBox](/components/combobox) - For searchable selection using ListBox 30 - - [Tree](/components/tree) - For hierarchical data display 31 - - [Table](/components/table) - For structured data display 28 + - [Select](/docs/components/select) - For dropdown selection using ListBox 29 + - [ComboBox](/docs/components/combobox) - For searchable selection using ListBox 30 + - [Tree](/docs/components/tree) - For hierarchical data display 31 + - [Table](/docs/components/table) - For structured data display
+4 -4
apps/docs/src/docs/components/menu.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [ContextMenu](/components/context-menu) - For right-click context menus 29 - - [CommandMenu](/components/command-menu) - For command palette menus 30 - - [Popover](/components/popover) - For menu containers 31 - - [Button](/components/button) - For menu triggers 28 + - [ContextMenu](/docs/components/context-menu) - For right-click context menus 29 + - [CommandMenu](/docs/components/command-menu) - For command palette menus 30 + - [Popover](/docs/components/popover) - For menu containers 31 + - [Button](/docs/components/button) - For menu triggers
+4 -4
apps/docs/src/docs/components/number-field.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [TextField](/components/text-field) - For general text input 29 - - [TextArea](/components/text-area) - For multi-line text input 30 - - [SearchField](/components/search-field) - For search input with clear button 31 - - [Label](/components/label) - For form labels and descriptions 28 + - [TextField](/docs/components/text-field) - For general text input 29 + - [TextArea](/docs/components/text-area) - For multi-line text input 30 + - [SearchField](/docs/components/search-field) - For search input with clear button 31 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/popover.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [Dialog](/components/dialog) - For modal overlays 29 - - [Tooltip](/components/tooltip) - For contextual help overlays 30 - - [Menu](/components/menu) - For dropdown menus 31 - - [ContextMenu](/components/context-menu) - For right-click context menus 28 + - [Dialog](/docs/components/dialog) - For modal overlays 29 + - [Tooltip](/docs/components/tooltip) - For contextual help overlays 30 + - [Menu](/docs/components/menu) - For dropdown menus 31 + - [ContextMenu](/docs/components/context-menu) - For right-click context menus
+4 -4
apps/docs/src/docs/components/radio.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [Checkbox](/components/checkbox) - For multiple selection options 45 - - [Switch](/components/switch) - For binary toggle choices 46 - - [Select](/components/select) - For dropdown selection 47 - - [Label](/components/label) - For form labels and descriptions 44 + - [Checkbox](/docs/components/checkbox) - For multiple selection options 45 + - [Switch](/docs/components/switch) - For binary toggle choices 46 + - [Select](/docs/components/select) - For dropdown selection 47 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/search-field.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [TextField](/components/text-field) - For general text input 29 - - [ComboBox](/components/combobox) - For searchable dropdown selection 30 - - [CommandMenu](/components/command-menu) - For command palette with search 31 - - [Label](/components/label) - For form labels and descriptions 28 + - [TextField](/docs/components/text-field) - For general text input 29 + - [ComboBox](/docs/components/combobox) - For searchable dropdown selection 30 + - [CommandMenu](/docs/components/command-menu) - For command palette with search 31 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/select.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [ComboBox](/components/combobox) - For searchable dropdown selection 45 - - [Radio](/components/radio) - For single selection from multiple options 46 - - [Checkbox](/components/checkbox) - For multiple selection options 47 - - [Label](/components/label) - For form labels and descriptions 44 + - [ComboBox](/docs/components/combobox) - For searchable dropdown selection 45 + - [Radio](/docs/components/radio) - For single selection from multiple options 46 + - [Checkbox](/docs/components/checkbox) - For multiple selection options 47 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/separator.mdx
··· 34 34 35 35 ## Related Components 36 36 37 - - [Flex](/components/flex) - For layouts that use separators 38 - - [Card](/components/card) - For cards that use separators 39 - - [Menu](/components/menu) - For menu items with separators 40 - - [Typography](/components/typography) - For text sections with separators 37 + - [Flex](/docs/components/flex) - For layouts that use separators 38 + - [Card](/docs/components/card) - For cards that use separators 39 + - [Menu](/docs/components/menu) - For menu items with separators 40 + - [Typography](/docs/components/typography) - For text sections with separators
+4 -4
apps/docs/src/docs/components/switch.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [Checkbox](/components/checkbox) - For multiple selection options 45 - - [Radio](/components/radio) - For single selection from multiple options 46 - - [ToggleButton](/components/toggle-button) - For toggleable button states 47 - - [Label](/components/label) - For form labels and descriptions 44 + - [Checkbox](/docs/components/checkbox) - For multiple selection options 45 + - [Radio](/docs/components/radio) - For single selection from multiple options 46 + - [ToggleButton](/docs/components/toggle-button) - For toggleable button states 47 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/table.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [ListBox](/components/listbox) - For selectable list data 29 - - [Tree](/components/tree) - For hierarchical data display 30 - - [Card](/components/card) - For displaying table data in cards 31 - - [Badge](/components/badge) - For status indicators in table cells 28 + - [ListBox](/docs/components/listbox) - For selectable list data 29 + - [Tree](/docs/components/tree) - For hierarchical data display 30 + - [Card](/docs/components/card) - For displaying table data in cards 31 + - [Badge](/docs/components/badge) - For status indicators in table cells
+4 -4
apps/docs/src/docs/components/text-area.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [TextField](/components/text-field) - For single-line text input 29 - - [NumberField](/components/number-field) - For numeric input 30 - - [SearchField](/components/search-field) - For search input with clear button 31 - - [Label](/components/label) - For form labels and descriptions 28 + - [TextField](/docs/components/text-field) - For single-line text input 29 + - [NumberField](/docs/components/number-field) - For numeric input 30 + - [SearchField](/docs/components/search-field) - For search input with clear button 31 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/text-field.mdx
··· 55 55 56 56 ## Related Components 57 57 58 - - [TextArea](/components/text-area) - For multi-line text input 59 - - [NumberField](/components/number-field) - For numeric input 60 - - [SearchField](/components/search-field) - For search input with clear button 61 - - [Label](/components/label) - For form labels and descriptions 58 + - [TextArea](/docs/components/text-area) - For multi-line text input 59 + - [NumberField](/docs/components/number-field) - For numeric input 60 + - [SearchField](/docs/components/search-field) - For search input with clear button 61 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/time-field.mdx
··· 55 55 56 56 ## Related Components 57 57 58 - - [DateField](/components/date-field) - For date input 59 - - [TextField](/components/text-field) - For general text input 60 - - [NumberField](/components/number-field) - For numeric input 61 - - [Label](/components/label) - For form labels and descriptions 58 + - [DateField](/docs/components/date-field) - For date input 59 + - [TextField](/docs/components/text-field) - For general text input 60 + - [NumberField](/docs/components/number-field) - For numeric input 61 + - [Label](/docs/components/label) - For form labels and descriptions
+4 -4
apps/docs/src/docs/components/toggle-button-group.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [ToggleButton](/components/toggle-button) - Individual toggle buttons within the group 45 - - [ButtonGroup](/components/button-group) - For grouping regular buttons together 46 - - [Radio](/components/radio) - For single-selection from multiple options 47 - - [Checkbox](/components/checkbox) - For multiple-selection options 44 + - [ToggleButton](/docs/components/toggle-button) - Individual toggle buttons within the group 45 + - [ButtonGroup](/docs/components/button-group) - For grouping regular buttons together 46 + - [Radio](/docs/components/radio) - For single-selection from multiple options 47 + - [Checkbox](/docs/components/checkbox) - For multiple-selection options
+4 -4
apps/docs/src/docs/components/toggle-button.mdx
··· 41 41 42 42 ## Related Components 43 43 44 - - [Button](/components/button) - For regular clickable buttons 45 - - [IconButton](/components/icon-button) - For icon-only toggle buttons 46 - - [ToggleButtonGroup](/components/toggle-button-group) - For grouping toggle buttons together 47 - - [Switch](/components/switch) - For toggle switches with labels 44 + - [Button](/docs/components/button) - For regular clickable buttons 45 + - [IconButton](/docs/components/icon-button) - For icon-only toggle buttons 46 + - [ToggleButtonGroup](/docs/components/toggle-button-group) - For grouping toggle buttons together 47 + - [Switch](/docs/components/switch) - For toggle switches with labels
+4 -4
apps/docs/src/docs/components/tooltip.mdx
··· 54 54 55 55 ## Related Components 56 56 57 - - [Popover](/components/popover) - For more complex overlay content 58 - - [IconButton](/components/icon-button) - Often used with tooltips for context 59 - - [Button](/components/button) - Can be enhanced with tooltips 60 - - [Badge](/components/badge) - Can be enhanced with tooltips for additional info 57 + - [Popover](/docs/components/popover) - For more complex overlay content 58 + - [IconButton](/docs/components/icon-button) - Often used with tooltips for context 59 + - [Button](/docs/components/button) - Can be enhanced with tooltips 60 + - [Badge](/docs/components/badge) - Can be enhanced with tooltips for additional info
+4 -4
apps/docs/src/docs/components/tree.mdx
··· 25 25 26 26 ## Related Components 27 27 28 - - [ListBox](/components/listbox) - For flat list data 29 - - [Table](/components/table) - For structured data display 30 - - [Card](/components/card) - For displaying tree data in cards 31 - - [Menu](/components/menu) - For hierarchical menu structures 28 + - [ListBox](/docs/components/listbox) - For flat list data 29 + - [Table](/docs/components/table) - For structured data display 30 + - [Card](/docs/components/card) - For displaying tree data in cards 31 + - [Menu](/docs/components/menu) - For hierarchical menu structures
+4 -4
apps/docs/src/docs/components/typography.mdx
··· 48 48 49 49 ## Related Components 50 50 51 - - [Link](/components/link) - For text links within typography 52 - - [Badge](/components/badge) - For status indicators in text 53 - - [Card](/components/card) - For containing typography content 54 - - [Label](/components/label) - For form labels and descriptions 51 + - [Link](/docs/components/link) - For text links within typography 52 + - [Badge](/docs/components/badge) - For status indicators in text 53 + - [Card](/docs/components/card) - For containing typography content 54 + - [Label](/docs/components/label) - For form labels and descriptions
+8
apps/docs/src/docs/showcase/ecommerce.mdx
··· 1 + --- 2 + title: Ecommerce App 3 + description: An example showing what building an ecommerce app looks like with Hip. 4 + --- 5 + 6 + import { EcommerceApp } from "../../showcases/ecommerce"; 7 + 8 + <EcommerceApp />
+8
apps/docs/src/docs/showcase/invoice.mdx
··· 1 + --- 2 + title: Invoice App 3 + description: An example showing what building an invoice app looks like with Hip. 4 + --- 5 + 6 + import { InvoiceApp } from "../../showcases/invoice"; 7 + 8 + <InvoiceApp />
+8
apps/docs/src/docs/showcase/music.mdx
··· 1 + --- 2 + title: Music App 3 + description: An example showing what building a music app looks like with Hip. 4 + --- 5 + 6 + import { Music } from "../../showcases/music"; 7 + 8 + <Music />
+8 -2
apps/docs/src/examples/alert-dialog/basic.tsx
··· 3 3 AlertDialogHeader, 4 4 AlertDialogFooter, 5 5 AlertDialogDescription, 6 + AlertDialogCancelButton, 7 + AlertDialogActionButton, 6 8 } from "@/components/alert-dialog"; 7 9 import { Button } from "@/components/button"; 8 10 ··· 14 16 This action cannot be undone. This will permanently delete the item. 15 17 </AlertDialogDescription> 16 18 <AlertDialogFooter> 17 - <Button variant="secondary">Cancel</Button> 18 - <Button variant="critical">Delete</Button> 19 + <AlertDialogCancelButton variant="secondary"> 20 + Cancel 21 + </AlertDialogCancelButton> 22 + <AlertDialogActionButton variant="critical"> 23 + Delete 24 + </AlertDialogActionButton> 19 25 </AlertDialogFooter> 20 26 </AlertDialog> 21 27 );
+12 -5
apps/docs/src/examples/label/basic.tsx
··· 1 + import { Flex } from "@/components/flex"; 1 2 import { Label, Description } from "@/components/label"; 2 3 import { TextField } from "@/components/text-field"; 3 4 4 5 export function Basic() { 5 6 return ( 6 - <div> 7 - <Label>Email Address</Label> 8 - <TextField placeholder="Enter your email" /> 9 - <Description>We'll never share your email with anyone else.</Description> 10 - </div> 7 + <Flex direction="column" gap="2"> 8 + <Label id="email-address">Email Address</Label> 9 + <TextField 10 + aria-labelledby="email-address" 11 + aria-describedby="email-address-description" 12 + placeholder="Enter your email" 13 + /> 14 + <Description id="email-address-description"> 15 + We'll never share your email with anyone else. 16 + </Description> 17 + </Flex> 11 18 ); 12 19 }
+18 -3
apps/docs/src/routes/docs.$.tsx
··· 22 22 import { uiColor } from "../components/theme/semantic-color.stylex"; 23 23 24 24 const styles = stylex.create({ 25 + main: { 26 + maxWidth: "80ch", 27 + paddingTop: spacing["20"], 28 + paddingBottom: spacing["20"], 29 + paddingLeft: spacing["16"], 30 + paddingRight: spacing["16"], 31 + }, 25 32 pre: { 26 33 marginTop: spacing["8"], 27 34 marginBottom: spacing["8"], ··· 61 68 ":is(li *)": spacing["0"], 62 69 }, 63 70 }, 71 + header: { 72 + marginBottom: spacing["12"], 73 + }, 64 74 }); 65 75 66 76 function Link(props: LinkProps) { ··· 97 107 } 98 108 99 109 const Content = pages[location.pathname]; 110 + const isShowcase = location.pathname.includes("showcase"); 111 + 112 + if (isShowcase) { 113 + return <Content components={components} />; 114 + } 100 115 101 116 return ( 102 - <div> 103 - <Flex direction="column" gap="4"> 117 + <div {...stylex.props(styles.main)}> 118 + <Flex direction="column" gap="4" style={styles.header}> 104 119 <Heading1>{doc?.title}</Heading1> 105 120 <Text size="xl" variant="secondary"> 106 121 {doc?.description} 107 122 </Text> 108 123 </Flex> 109 - {Content && <Content components={components} />} 124 + <Content components={components} /> 110 125 </div> 111 126 ); 112 127 }
+14 -6
apps/docs/src/routes/docs.tsx
··· 26 26 paddingTop: spacing["4"], 27 27 paddingBottom: spacing["4"], 28 28 }, 29 - main: { 30 - maxWidth: "80ch", 31 - paddingTop: spacing["10"], 32 - paddingBottom: spacing["20"], 33 - }, 34 29 }); 35 30 36 31 interface SidebarItem { ··· 46 41 ); 47 42 const foundationDocs = allDocs.filter((doc) => 48 43 doc._meta.directory.startsWith("foundations"), 44 + ); 45 + const showcaseDocs = allDocs.filter((doc) => 46 + doc._meta.directory.startsWith("showcase"), 49 47 ); 50 48 51 49 const sidebarItems: SidebarItem[] = [ ··· 68 66 id: "components", 69 67 label: "Components", 70 68 items: componentDocs.map((doc) => ({ 69 + id: doc._meta.path, 70 + label: doc.title, 71 + to: "/docs/$", 72 + params: { _splat: doc._meta.path }, 73 + })), 74 + }, 75 + { 76 + id: "showcases", 77 + label: "Showcases", 78 + items: showcaseDocs.map((doc) => ({ 71 79 id: doc._meta.path, 72 80 label: doc.title, 73 81 to: "/docs/$", ··· 121 129 <aside {...stylex.props(styles.aside)}> 122 130 <Sidebar /> 123 131 </aside> 124 - <main {...stylex.props(styles.main)}> 132 + <main> 125 133 <Outlet /> 126 134 </main> 127 135 </Grid>
+1031
apps/docs/src/showcases/ecommerce.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import * as stylex from "@stylexjs/stylex"; 3 + import { 4 + Card, 5 + CardBody, 6 + CardDescription, 7 + CardFooter, 8 + CardHeader, 9 + CardHeaderAction, 10 + CardImage, 11 + CardTitle, 12 + } from "@/components/card"; 13 + import { Button } from "@/components/button"; 14 + import { Text } from "@/components/typography/text"; 15 + import { Separator } from "@/components/separator"; 16 + import { Select, SelectItem } from "@/components/select"; 17 + import { ToggleButtonGroup } from "@/components/toggle-button-group"; 18 + import { ToggleButton } from "@/components/toggle-button"; 19 + import { ColorSwatch } from "@/components/color-swatch"; 20 + import { Grid } from "@/components/grid"; 21 + import { Fragment } from "react/jsx-runtime"; 22 + import { Avatar } from "@/components/avatar"; 23 + import { spacing } from "../components/theme/spacing.stylex"; 24 + import { IconButton } from "@/components/icon-button"; 25 + import { Bookmark, Shredder, Upload } from "lucide-react"; 26 + import { Badge } from "@/components/badge"; 27 + import { AspectRatio, AspectRatioImage } from "@/components/aspect-ratio"; 28 + import { LabelText, SmallBody } from "@/components/typography"; 29 + import { Link } from "@/components/link"; 30 + import { TextField } from "@/components/text-field"; 31 + import { NumberField } from "@/components/number-field"; 32 + import { FileDropZone } from "@/components/file-drop-zone"; 33 + import { TextArea } from "@/components/text-area"; 34 + import { SearchField } from "@/components/search-field"; 35 + 36 + const styles = stylex.create({ 37 + heightFull: { 38 + height: "100%", 39 + }, 40 + grow: { 41 + flexGrow: 1, 42 + flexShrink: 0, 43 + flexBasis: "0%", 44 + minWidth: 0, 45 + }, 46 + medium: { 47 + flexGrow: 0.75, 48 + flexShrink: 0, 49 + flexBasis: "0%", 50 + }, 51 + skinny: { 52 + flexGrow: 0.5, 53 + flexShrink: 0, 54 + flexBasis: "0%", 55 + }, 56 + relative: { 57 + position: "relative", 58 + }, 59 + bottomRight: { 60 + position: "absolute", 61 + bottom: 0, 62 + right: 0, 63 + marginRight: spacing["4"], 64 + marginBottom: spacing["4"], 65 + }, 66 + timelineContainer: { 67 + position: "relative", 68 + }, 69 + timelineLine: { 70 + position: "absolute", 71 + left: spacing["2"], 72 + top: spacing["3"], 73 + bottom: spacing["3"], 74 + width: "2px", 75 + backgroundColor: "#14b8a6", // teal color 76 + }, 77 + timelineItem: { 78 + position: "relative", 79 + paddingLeft: spacing["10"], 80 + }, 81 + timelineDot: { 82 + position: "absolute", 83 + left: spacing["1"], 84 + top: spacing["1"], 85 + width: spacing["2.5"], 86 + height: spacing["2.5"], 87 + borderRadius: "50%", 88 + backgroundColor: "#14b8a6", // teal color 89 + flexShrink: 0, 90 + }, 91 + gridHeight: { 92 + height: "400px", 93 + }, 94 + cardSection: { 95 + paddingTop: spacing["6"], 96 + paddingBottom: spacing["6"], 97 + paddingLeft: spacing["6"], 98 + paddingRight: spacing["6"], 99 + display: "flex", 100 + flexDirection: "column", 101 + justifyContent: "center", 102 + alignItems: "center", 103 + }, 104 + customerRow: { 105 + paddingTop: spacing["4"], 106 + paddingBottom: spacing["4"], 107 + paddingLeft: spacing["4"], 108 + paddingRight: spacing["4"], 109 + }, 110 + separator: { 111 + height: "auto", 112 + }, 113 + main: { 114 + padding: spacing["4"], 115 + width: 2000, 116 + }, 117 + }); 118 + 119 + function SmallProductCard() { 120 + return ( 121 + <Card size="sm"> 122 + <CardImage src="https://images.unsplash.com/photo-1620799140408-edc6dcb6d633?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=560&h=424&q=80" /> 123 + <CardHeader> 124 + <CardTitle>Back to basics</CardTitle> 125 + <CardDescription>Simple and versatile</CardDescription> 126 + <CardHeaderAction> 127 + <Button variant="secondary">Show now</Button> 128 + </CardHeaderAction> 129 + </CardHeader> 130 + </Card> 131 + ); 132 + } 133 + 134 + function SmallProductCardWithBuying() { 135 + return ( 136 + <Card size="sm"> 137 + <div {...stylex.props(styles.relative)}> 138 + <CardImage src="https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=560&h=540&q=80" /> 139 + <div {...stylex.props(styles.bottomRight)}> 140 + <IconButton label="Bookmark" variant="secondary"> 141 + <Bookmark /> 142 + </IconButton> 143 + </div> 144 + </div> 145 + <CardBody> 146 + <Flex direction="column" gap="4"> 147 + <Flex direction="column" gap="2"> 148 + <Text size="sm">Footwear</Text> 149 + <Text weight="semibold">Sneakers #12</Text> 150 + <Text size="sm" variant="secondary"> 151 + Love at the first sight for enthusiasts seeking a fresh and 152 + whimsical style. 153 + </Text> 154 + </Flex> 155 + <Separator /> 156 + <Flex align="end" gap="2"> 157 + <Select 158 + label="Color" 159 + defaultValue="red" 160 + style={styles.grow} 161 + variant="secondary" 162 + > 163 + <SelectItem id="red">Red</SelectItem> 164 + <SelectItem id="blue">Blue</SelectItem> 165 + <SelectItem id="green">Green</SelectItem> 166 + <SelectItem id="yellow">Yellow</SelectItem> 167 + <SelectItem id="purple">Purple</SelectItem> 168 + <SelectItem id="orange">Orange</SelectItem> 169 + <SelectItem id="pink">Pink</SelectItem> 170 + <SelectItem id="brown">Brown</SelectItem> 171 + <SelectItem id="gray">Gray</SelectItem> 172 + </Select> 173 + <Select 174 + label="Size" 175 + defaultValue="8" 176 + style={styles.grow} 177 + variant="secondary" 178 + > 179 + <SelectItem id="8">8</SelectItem> 180 + <SelectItem id="9">9</SelectItem> 181 + <SelectItem id="10">10</SelectItem> 182 + <SelectItem id="11">11</SelectItem> 183 + <SelectItem id="12">12</SelectItem> 184 + <SelectItem id="13">13</SelectItem> 185 + <SelectItem id="14">14</SelectItem> 186 + <SelectItem id="15">15</SelectItem> 187 + <SelectItem id="16">16</SelectItem> 188 + </Select> 189 + <Button>Buy</Button> 190 + </Flex> 191 + </Flex> 192 + </CardBody> 193 + </Card> 194 + ); 195 + } 196 + 197 + function ProductOptionsCard() { 198 + return ( 199 + <Card size="sm"> 200 + <CardBody> 201 + <Flex direction="column" gap="5"> 202 + <Flex direction="column" gap="2"> 203 + <Text weight="semibold">Delivery</Text> 204 + <ToggleButtonGroup 205 + variant="separate" 206 + itemsPerRow={2} 207 + selectionMode="single" 208 + > 209 + <ToggleButton id="tomorrow" variant="secondary"> 210 + Tomorrow 211 + </ToggleButton> 212 + <ToggleButton id="within-3-days" variant="secondary"> 213 + Within 3 days 214 + </ToggleButton> 215 + </ToggleButtonGroup> 216 + </Flex> 217 + <Flex direction="column" gap="2"> 218 + <Text weight="semibold">Size</Text> 219 + <ToggleButtonGroup 220 + variant="separate" 221 + itemsPerRow={5} 222 + selectionMode="single" 223 + > 224 + <ToggleButton id="5.5" variant="secondary"> 225 + 5.5 226 + </ToggleButton> 227 + <ToggleButton id="6" variant="secondary"> 228 + 6 229 + </ToggleButton> 230 + <ToggleButton id="6.5" variant="secondary"> 231 + 6.5 232 + </ToggleButton> 233 + <ToggleButton id="7" variant="secondary"> 234 + 7 235 + </ToggleButton> 236 + <ToggleButton id="7.5" variant="secondary"> 237 + 7.5 238 + </ToggleButton> 239 + <ToggleButton id="8" variant="secondary"> 240 + 8 241 + </ToggleButton> 242 + <ToggleButton id="8.5" variant="secondary"> 243 + 8.5 244 + </ToggleButton> 245 + <ToggleButton id="9" variant="secondary"> 246 + 9 247 + </ToggleButton> 248 + <ToggleButton id="9.5" variant="secondary"> 249 + 9.5 250 + </ToggleButton> 251 + <ToggleButton id="10" variant="secondary"> 252 + 10 253 + </ToggleButton> 254 + </ToggleButtonGroup> 255 + </Flex> 256 + <Flex direction="column" gap="2"> 257 + <Text weight="semibold">Material</Text> 258 + <ToggleButtonGroup 259 + variant="separate" 260 + itemsPerRow={5} 261 + selectionMode="single" 262 + > 263 + <ToggleButton id="leather" variant="secondary"> 264 + Leather 265 + </ToggleButton> 266 + <ToggleButton id="suede" variant="secondary"> 267 + Suede 268 + </ToggleButton> 269 + <ToggleButton id="mesh" variant="secondary"> 270 + Mesh 271 + </ToggleButton> 272 + <ToggleButton id="canvas" variant="secondary"> 273 + Canvas 274 + </ToggleButton> 275 + </ToggleButtonGroup> 276 + </Flex> 277 + <Flex direction="column" gap="2"> 278 + <Text weight="semibold">Color</Text> 279 + <ToggleButtonGroup 280 + variant="separate" 281 + itemsPerRow={3} 282 + selectionMode="single" 283 + > 284 + <ToggleButton id="white" variant="secondary"> 285 + <ColorSwatch color="#fff" size="sm" /> 286 + White 287 + </ToggleButton> 288 + <ToggleButton id="grey" variant="secondary"> 289 + <ColorSwatch color="#808080" size="sm" /> 290 + Grey 291 + </ToggleButton> 292 + <ToggleButton id="black" variant="secondary"> 293 + <ColorSwatch color="#000" size="sm" /> 294 + Black 295 + </ToggleButton> 296 + <ToggleButton id="red" variant="secondary"> 297 + <ColorSwatch color="#f00" size="sm" /> 298 + Red 299 + </ToggleButton> 300 + <ToggleButton id="pink" variant="secondary"> 301 + <ColorSwatch color="#f0f" size="sm" /> 302 + Pink 303 + </ToggleButton> 304 + <ToggleButton id="violet" variant="secondary"> 305 + <ColorSwatch color="#800080" size="sm" /> 306 + Violet 307 + </ToggleButton> 308 + <ToggleButton id="blue" variant="secondary"> 309 + <ColorSwatch color="#00f" size="sm" /> 310 + Blue 311 + </ToggleButton> 312 + <ToggleButton id="green" variant="secondary"> 313 + <ColorSwatch color="#0f0" size="sm" /> 314 + Green 315 + </ToggleButton> 316 + <ToggleButton id="beige" variant="secondary"> 317 + <ColorSwatch color="#f5f5dc" size="sm" /> 318 + Beige 319 + </ToggleButton> 320 + </ToggleButtonGroup> 321 + </Flex> 322 + </Flex> 323 + </CardBody> 324 + </Card> 325 + ); 326 + } 327 + 328 + function ShoppingCartCard() { 329 + const cart = [ 330 + { 331 + title: "Poncho #4", 332 + image: 333 + "https://images.unsplash.com/photo-1434389677669-e08b4cac3105?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=80&h=80&q=80&crop=entropy", 334 + price: 79, 335 + size: "M", 336 + count: 1, 337 + }, 338 + { 339 + title: "Jeans #8", 340 + image: 341 + "https://images.unsplash.com/photo-1602293589930-45aad59ba3ab?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=80&h=80&q=80&crop=entropy", 342 + price: 59, 343 + size: "30", 344 + count: 2, 345 + }, 346 + { 347 + title: "Sneakers #14", 348 + image: 349 + "https://images.unsplash.com/photo-1549298916-b41d501d3772?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=80&h=80&q=80&crop=center", 350 + price: 116, 351 + size: "8", 352 + count: 1, 353 + }, 354 + ]; 355 + 356 + return ( 357 + <Card size="sm"> 358 + <CardHeader> 359 + <CardTitle>Shopping Cart</CardTitle> 360 + </CardHeader> 361 + <CardBody> 362 + <Flex direction="column" gap="4"> 363 + <Grid columns="auto 1fr auto auto" columnGap="3" alignItems="center"> 364 + {cart.map((item) => ( 365 + <Fragment key={item.title}> 366 + <Avatar 367 + src={item.image} 368 + alt={item.title} 369 + fallback={item.title.charAt(0)} 370 + size="lg" 371 + /> 372 + <Flex direction="column" gap="1"> 373 + <Text weight="medium">{item.title}</Text> 374 + <Text variant="secondary" size="sm"> 375 + Size {item.size} 376 + </Text> 377 + </Flex> 378 + <Select defaultValue={item.count.toString()}> 379 + <SelectItem id="1">1</SelectItem> 380 + <SelectItem id="2">2</SelectItem> 381 + <SelectItem id="3">3</SelectItem> 382 + <SelectItem id="4">4</SelectItem> 383 + <SelectItem id="5">5</SelectItem> 384 + <SelectItem id="6">6</SelectItem> 385 + <SelectItem id="7">7</SelectItem> 386 + <SelectItem id="8">8</SelectItem> 387 + <SelectItem id="9">9</SelectItem> 388 + <SelectItem id="10">10</SelectItem> 389 + </Select> 390 + <Text size="sm" variant="secondary"> 391 + {Intl.NumberFormat("en-US", { 392 + style: "currency", 393 + currency: "USD", 394 + }).format(item.price * item.count)} 395 + </Text> 396 + </Fragment> 397 + ))} 398 + </Grid> 399 + <Separator /> 400 + <Flex gap="2" justify="between"> 401 + <div></div> 402 + <Button>Go to checkout</Button> 403 + </Flex> 404 + </Flex> 405 + </CardBody> 406 + </Card> 407 + ); 408 + } 409 + 410 + function Delivery() { 411 + return ( 412 + <Card size="sm"> 413 + <Flex direction="column" gap="5"> 414 + <CardHeader> 415 + <CardTitle>Delivery</CardTitle> 416 + <CardHeaderAction> 417 + <Badge variant="warning" size="sm"> 418 + Guaranteed 419 + </Badge> 420 + </CardHeaderAction> 421 + </CardHeader> 422 + <CardBody> 423 + <Flex direction="column" gap="1.5"> 424 + <Text weight="semibold">Tomorrow</Text> 425 + <Text variant="secondary" size="sm"> 426 + 12:00 pm - 2:00 pm 427 + </Text> 428 + </Flex> 429 + 430 + <Flex direction="column" gap="1.5"> 431 + <Text weight="semibold">Luna Rodriguez</Text> 432 + <Text variant="secondary" size="sm"> 433 + 9876 Maple Avenue 434 + <br /> 435 + Cityville, WA 54321 436 + </Text> 437 + </Flex> 438 + </CardBody> 439 + <CardImage src="https://workos.imgix.net/images/bc04b345-f225-488d-8a46-1811096d0c3b.png?auto=format&fit=clip&q=90&w=840&h=654" /> 440 + <CardFooter> 441 + <Button variant="secondary">Edit</Button> 442 + <Button>Confirm</Button> 443 + </CardFooter> 444 + </Flex> 445 + </Card> 446 + ); 447 + } 448 + 449 + function Bookmarks() { 450 + const bookmarks = [ 451 + { 452 + title: "Jeans #8", 453 + image: 454 + "https://images.unsplash.com/photo-1602293589930-45aad59ba3ab?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=272&h=272&q=80&crop=entropy", 455 + price: 118, 456 + }, 457 + { 458 + title: "Jacket #3", 459 + image: 460 + "https://images.unsplash.com/photo-1591047139829-d91aecb6caea?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&crop=entropy&w=272&h=272&q=80", 461 + price: 49, 462 + }, 463 + { 464 + title: "Pants #10", 465 + image: 466 + "https://images.unsplash.com/photo-1506629082955-511b1aa562c8?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=272&h=272&q=80", 467 + price: 32, 468 + }, 469 + { 470 + title: "Shirt #11", 471 + image: 472 + "https://images.unsplash.com/photo-1611312449412-6cefac5dc3e4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=272&h=272&q=80", 473 + price: 39, 474 + }, 475 + ]; 476 + 477 + return ( 478 + <Card size="sm"> 479 + <CardHeader> 480 + <CardTitle>Bookmarks</CardTitle> 481 + <CardHeaderAction> 482 + <Button variant="tertiary">Buy all</Button> 483 + </CardHeaderAction> 484 + </CardHeader> 485 + <CardBody> 486 + <Grid columns="1fr 1fr" columnGap="2"> 487 + {bookmarks.map((bookmark) => ( 488 + <Flex direction="column" gap="2" key={bookmark.title}> 489 + <AspectRatio aspectRatio={1}> 490 + <AspectRatioImage src={bookmark.image} /> 491 + </AspectRatio> 492 + <div> 493 + <Text weight="medium" size="sm"> 494 + {bookmark.title} 495 + </Text> 496 + <Text variant="secondary" size="sm"> 497 + {", "} 498 + {Intl.NumberFormat("en-US", { 499 + style: "currency", 500 + currency: "USD", 501 + }).format(bookmark.price)} 502 + </Text> 503 + </div> 504 + </Flex> 505 + ))} 506 + </Grid> 507 + </CardBody> 508 + </Card> 509 + ); 510 + } 511 + 512 + function DiscardedCard() { 513 + return ( 514 + <Card> 515 + <CardBody> 516 + <Flex direction="column" gap="4" align="center"> 517 + <Shredder size={48} /> 518 + <Text weight="semibold" size="lg"> 519 + Product discarded 520 + </Text> 521 + <SmallBody variant="secondary"> 522 + It's still available in the <Link>archive.</Link> 523 + </SmallBody> 524 + <Flex gap="2"> 525 + <Button variant="secondary">Undo</Button> 526 + <Button>Done</Button> 527 + </Flex> 528 + </Flex> 529 + </CardBody> 530 + </Card> 531 + ); 532 + } 533 + 534 + function EditProductCard() { 535 + return ( 536 + <Card> 537 + <CardHeader> 538 + <CardTitle>Edit product</CardTitle> 539 + </CardHeader> 540 + <CardBody> 541 + <Grid columns="1fr 140px" columnGap="2"> 542 + <TextField label="Title" defaultValue="Sneakers #12" /> 543 + <NumberField 544 + label="Price" 545 + defaultValue={116} 546 + formatOptions={{ 547 + style: "currency", 548 + currency: "USD", 549 + }} 550 + /> 551 + </Grid> 552 + <Flex direction="column" gap="2"> 553 + <LabelText>Media</LabelText> 554 + <Grid columns="1fr 1fr 1fr" columnGap="2"> 555 + <AspectRatio> 556 + <AspectRatioImage src="https://images.unsplash.com/photo-1551163943-3f6a855d1153?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&h=400&q=80&crop=bottom" /> 557 + </AspectRatio> 558 + <AspectRatio> 559 + <AspectRatioImage src="https://workos.imgix.net/images/c773ee38-9136-49d1-804c-6d166dad9c65.png?auto=format&fit=clip&q=80w=400&h=400" /> 560 + </AspectRatio> 561 + <AspectRatio> 562 + <FileDropZone style={styles.heightFull}> 563 + <IconButton variant="secondary" label="Upload image"> 564 + <Upload /> 565 + </IconButton> 566 + </FileDropZone> 567 + </AspectRatio> 568 + </Grid> 569 + </Flex> 570 + <TextArea 571 + label="Description" 572 + defaultValue="This is a description of the product." 573 + rows={4} 574 + /> 575 + <Flex direction="column" gap="2"> 576 + <Text weight="semibold">Material</Text> 577 + <ToggleButtonGroup 578 + variant="separate" 579 + itemsPerRow={3} 580 + selectionMode="single" 581 + > 582 + <ToggleButton id="synthetic" variant="secondary"> 583 + Synthetic 584 + </ToggleButton> 585 + <ToggleButton id="wool" variant="secondary"> 586 + Wool 587 + </ToggleButton> 588 + <ToggleButton id="cotton" variant="secondary"> 589 + Cotton 590 + </ToggleButton> 591 + <ToggleButton id="linen" variant="secondary"> 592 + Linen 593 + </ToggleButton> 594 + <ToggleButton id="denim" variant="secondary"> 595 + Denim 596 + </ToggleButton> 597 + <ToggleButton id="leather" variant="secondary"> 598 + Leather 599 + </ToggleButton> 600 + <ToggleButton id="silk" variant="secondary"> 601 + Silk 602 + </ToggleButton> 603 + <ToggleButton id="chiffon" variant="secondary"> 604 + Chiffon 605 + </ToggleButton> 606 + <ToggleButton id="other" variant="secondary"> 607 + Other 608 + </ToggleButton> 609 + </ToggleButtonGroup> 610 + </Flex> 611 + <Flex direction="column" gap="2"> 612 + <Text weight="semibold">Main Color</Text> 613 + <ToggleButtonGroup 614 + variant="separate" 615 + itemsPerRow={3} 616 + selectionMode="single" 617 + > 618 + <ToggleButton id="white" variant="secondary"> 619 + <ColorSwatch color="#fff" size="sm" /> 620 + White 621 + </ToggleButton> 622 + <ToggleButton id="grey" variant="secondary"> 623 + <ColorSwatch color="#808080" size="sm" /> 624 + Grey 625 + </ToggleButton> 626 + <ToggleButton id="black" variant="secondary"> 627 + <ColorSwatch color="#000" size="sm" /> 628 + Black 629 + </ToggleButton> 630 + <ToggleButton id="red" variant="secondary"> 631 + <ColorSwatch color="#f00" size="sm" /> 632 + Red 633 + </ToggleButton> 634 + <ToggleButton id="pink" variant="secondary"> 635 + <ColorSwatch color="#f0f" size="sm" /> 636 + Pink 637 + </ToggleButton> 638 + <ToggleButton id="violet" variant="secondary"> 639 + <ColorSwatch color="#800080" size="sm" /> 640 + Violet 641 + </ToggleButton> 642 + <ToggleButton id="blue" variant="secondary"> 643 + <ColorSwatch color="#00f" size="sm" /> 644 + Blue 645 + </ToggleButton> 646 + <ToggleButton id="green" variant="secondary"> 647 + <ColorSwatch color="#0f0" size="sm" /> 648 + Green 649 + </ToggleButton> 650 + <ToggleButton id="beige" variant="secondary"> 651 + <ColorSwatch color="#f5f5dc" size="sm" /> 652 + Beige 653 + </ToggleButton> 654 + </ToggleButtonGroup> 655 + </Flex> 656 + <Flex direction="column" gap="2"> 657 + <Text weight="semibold">Size</Text> 658 + <ToggleButtonGroup 659 + variant="separate" 660 + itemsPerRow={3} 661 + selectionMode="single" 662 + > 663 + <ToggleButton id="xs" variant="secondary"> 664 + XS 665 + </ToggleButton> 666 + <ToggleButton id="s" variant="secondary"> 667 + S 668 + </ToggleButton> 669 + <ToggleButton id="m" variant="secondary"> 670 + M 671 + </ToggleButton> 672 + <ToggleButton id="l" variant="secondary"> 673 + L 674 + </ToggleButton> 675 + <ToggleButton id="xl" variant="secondary"> 676 + XL 677 + </ToggleButton> 678 + <ToggleButton id="xxl" variant="secondary"> 679 + XXL 680 + </ToggleButton> 681 + </ToggleButtonGroup> 682 + </Flex> 683 + </CardBody> 684 + </Card> 685 + ); 686 + } 687 + 688 + function ShipmentTracking() { 689 + const trackingEvents = [ 690 + { 691 + date: "July 1, 2023, 10:28 AM", 692 + description: "Package picked up from the warehouse in Phoenix, TX", 693 + }, 694 + { 695 + date: "July 1, 2023, 12:43 PM", 696 + description: "Departed from Phoenix, TX", 697 + }, 698 + { 699 + date: "July 2, 2023, 3:20 PM", 700 + description: "Arrived at a sorting facility in Seattle, WA", 701 + }, 702 + { 703 + date: "July 2, 2023, 7:31 PM", 704 + description: "Departed Seattle, WA", 705 + }, 706 + { 707 + date: "July 2, 2023, 11:03 PM", 708 + description: "Arrived to a facility in Greenville, WA", 709 + }, 710 + ]; 711 + 712 + return ( 713 + <Card> 714 + <CardBody> 715 + <Flex direction="column" gap="6" style={styles.heightFull}> 716 + <Flex direction="column" gap="4"> 717 + <Text weight="semibold" size="lg"> 718 + Shipment tracking 719 + </Text> 720 + <SearchField placeholder="Enter package number" /> 721 + </Flex> 722 + 723 + <Grid columns="2fr 3fr" columnGap="6" style={styles.grow}> 724 + <Flex direction="column" gap="4"> 725 + <Flex direction="column" gap="1"> 726 + <Text variant="secondary" size="xs"> 727 + Package number 728 + </Text> 729 + <Text weight="medium" size="sm"> 730 + LASC966124786554 731 + </Text> 732 + </Flex> 733 + 734 + <Flex direction="column" gap="1"> 735 + <Text variant="secondary" size="xs"> 736 + Order number 737 + </Text> 738 + <Text weight="medium" size="sm"> 739 + #94356 740 + </Text> 741 + </Flex> 742 + 743 + <Flex direction="column" gap="1"> 744 + <Text variant="secondary" size="xs"> 745 + Ship to 746 + </Text> 747 + <Text weight="medium" leading="lg" size="sm"> 748 + Sophia Martinez 749 + <br /> 750 + 512 Oakwood Avenue, Unit 201 751 + <br /> 752 + Greenville, SC 67890 753 + </Text> 754 + </Flex> 755 + 756 + <Grid columns="auto auto auto" columnGap="6" alignItems="center"> 757 + <Flex direction="column" gap="1"> 758 + <Text variant="secondary" size="sm"> 759 + Status 760 + </Text> 761 + <Badge variant="success" size="sm"> 762 + On time 763 + </Badge> 764 + </Flex> 765 + <Flex direction="column" gap="1"> 766 + <Text variant="secondary" size="sm"> 767 + Weight 768 + </Text> 769 + <Text weight="medium">3 lb</Text> 770 + </Flex> 771 + <Flex direction="column" gap="1"> 772 + <Text variant="secondary" size="sm"> 773 + Order total 774 + </Text> 775 + <Text weight="medium">$243</Text> 776 + </Flex> 777 + </Grid> 778 + </Flex> 779 + 780 + <Flex direction="column" gap="3" style={styles.timelineContainer}> 781 + <div {...stylex.props(styles.timelineLine)} /> 782 + {trackingEvents.map((event, index) => ( 783 + <Flex 784 + key={index} 785 + align="start" 786 + gap="3" 787 + style={styles.timelineItem} 788 + > 789 + <div {...stylex.props(styles.timelineDot)} /> 790 + <Flex direction="column" gap="1"> 791 + <Text weight="medium" size="sm"> 792 + {event.date} 793 + </Text> 794 + <Text variant="secondary" size="sm" leading="lg"> 795 + {event.description} 796 + </Text> 797 + </Flex> 798 + </Flex> 799 + ))} 800 + </Flex> 801 + </Grid> 802 + </Flex> 803 + </CardBody> 804 + </Card> 805 + ); 806 + } 807 + 808 + function TopCustomersCard() { 809 + const customers = [ 810 + { 811 + name: "Elijah Wilson", 812 + customerSince: "November 3, 2017", 813 + address: "735 Pine Street, Apartment 4C, Portland, OR 34567", 814 + sales: 15432.56, 815 + orders: 42, 816 + }, 817 + { 818 + name: "Cameron Johnson", 819 + customerSince: "June 10, 2020", 820 + address: "2465 Main Street, Apt 3B, Springfield, OH 12345", 821 + sales: 13976.43, 822 + orders: 12, 823 + }, 824 + { 825 + name: "Sophia Martinez", 826 + customerSince: "September 27, 2019", 827 + address: "512 Oakwood Avenue, Unit 201, Greenville, SC 67890", 828 + sales: 11653.03, 829 + orders: 34, 830 + }, 831 + { 832 + name: "Nathan Thompson", 833 + customerSince: "May 5, 2018", 834 + address: "837 Maple Lane, Suite 102, Lexington, KY 45678", 835 + sales: 8245.92, 836 + orders: 22, 837 + }, 838 + { 839 + name: "Olivia Adams", 840 + customerSince: "January 12, 2021", 841 + address: "1123 Elmwood Drive, Boulder, CO 23456", 842 + sales: 6789.21, 843 + orders: 18, 844 + }, 845 + ]; 846 + 847 + return ( 848 + <Card> 849 + <CardHeader> 850 + <CardTitle>Top customers</CardTitle> 851 + </CardHeader> 852 + <CardBody> 853 + <Flex gap="4" direction="column"> 854 + <Flex gap="3" align="center"> 855 + <SearchField 856 + placeholder="Search" 857 + variant="secondary" 858 + style={styles.grow} 859 + /> 860 + <Select defaultValue="all-customers" variant="secondary"> 861 + <SelectItem id="all-customers">All customers</SelectItem> 862 + <SelectItem id="new-customers">New customers</SelectItem> 863 + <SelectItem id="vip-customers">VIP customers</SelectItem> 864 + </Select> 865 + </Flex> 866 + </Flex> 867 + <Flex direction="column" gap="6"> 868 + {customers.map((customer) => ( 869 + <Flex 870 + key={customer.name} 871 + justify="between" 872 + align="center" 873 + gap="8" 874 + {...stylex.props(styles.customerRow)} 875 + > 876 + <Flex direction="column" gap="1" style={styles.grow}> 877 + <Text weight="semibold">{customer.name}</Text> 878 + <Text variant="secondary" size="sm"> 879 + Customer since {customer.customerSince} 880 + </Text> 881 + <Text variant="secondary" size="xs"> 882 + {customer.address} 883 + </Text> 884 + </Flex> 885 + <Flex gap="6"> 886 + <Flex direction="column" gap="1" align="end"> 887 + <Text variant="secondary" size="sm"> 888 + Sales 889 + </Text> 890 + <Text weight="semibold" size="lg"> 891 + {Intl.NumberFormat("en-US", { 892 + style: "currency", 893 + currency: "USD", 894 + }).format(customer.sales)} 895 + </Text> 896 + </Flex> 897 + <Separator orientation="vertical" style={styles.separator} /> 898 + <Flex direction="column" gap="1" align="start"> 899 + <Text variant="secondary" size="sm"> 900 + Orders 901 + </Text> 902 + <Text weight="semibold" size="lg"> 903 + {customer.orders} 904 + </Text> 905 + </Flex> 906 + </Flex> 907 + </Flex> 908 + ))} 909 + </Flex> 910 + </CardBody> 911 + </Card> 912 + ); 913 + } 914 + 915 + function MarketingCallout() { 916 + const fashionItems = [ 917 + "Men's Polo", 918 + "Shirt", 919 + "Sneakers", 920 + "Jeans", 921 + "T-shirt", 922 + "Pants", 923 + "Socks", 924 + "Watch", 925 + "Belt", 926 + "Bag", 927 + "Suit", 928 + "Shorts", 929 + "Shoes", 930 + "Women's Blouse", 931 + "Dress", 932 + "Skirt", 933 + "Heels", 934 + "Sandals", 935 + "Scarf", 936 + "Earrings", 937 + "Bracelet", 938 + "Necklace", 939 + "Glasses", 940 + "Perfume", 941 + ]; 942 + 943 + return ( 944 + <Card> 945 + <Grid columns="1fr 1fr 1fr"> 946 + {/* Top Left - Dare to stand out */} 947 + <AspectRatio style={styles.cardSection} rounded={false}> 948 + <Flex direction="column" gap="4" justify="center" align="center"> 949 + <Text weight="bold" size="2xl"> 950 + Dare to stand out 951 + </Text> 952 + <Text>Striking patterns, vibrant hues, and unusual designs.</Text> 953 + <Button variant="secondary">Shop now</Button> 954 + </Flex> 955 + </AspectRatio> 956 + 957 + {/* Top Middle - Woman with sunglasses */} 958 + <AspectRatio rounded={false}> 959 + <AspectRatioImage 960 + src="https://images.unsplash.com/photo-1514866747592-c2d279258a78?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=600&q=80" 961 + alt="Woman with sunglasses" 962 + /> 963 + </AspectRatio> 964 + 965 + {/* Top Right - Fashion items list */} 966 + <AspectRatio style={styles.cardSection} rounded={false}> 967 + <Flex wrap gap="1"> 968 + {fashionItems.map((item, index) => ( 969 + <Text variant="secondary" key={index} leading="2xl" size="sm"> 970 + {item} 971 + </Text> 972 + ))} 973 + </Flex> 974 + </AspectRatio> 975 + 976 + {/* Bottom Left - Woman with plaid shirt */} 977 + <AspectRatio rounded={false}> 978 + <AspectRatioImage 979 + src="https://plus.unsplash.com/premium_photo-1668485968648-f29fe5157463?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=600&q=80" 980 + alt="Woman with plaid shirt" 981 + /> 982 + </AspectRatio> 983 + 984 + {/* Bottom Middle - Discount callout */} 985 + <AspectRatio style={styles.cardSection} rounded={false}> 986 + <Flex direction="column" gap="2" justify="between" align="center"> 987 + <Text>15 - 30 Mar</Text> 988 + <Text weight="bold" size="4xl"> 989 + -25% 990 + </Text> 991 + <Text>Get our boldest designs.</Text> 992 + </Flex> 993 + </AspectRatio> 994 + 995 + {/* Bottom Right - Man with floral jacket */} 996 + <AspectRatio rounded={false}> 997 + <AspectRatioImage 998 + src="https://images.unsplash.com/photo-1532660621034-fb55e2e59762?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=700&q=80" 999 + alt="Man with floral jacket" 1000 + /> 1001 + </AspectRatio> 1002 + </Grid> 1003 + </Card> 1004 + ); 1005 + } 1006 + 1007 + export function EcommerceApp() { 1008 + return ( 1009 + <Flex gap="4" style={styles.main}> 1010 + <Flex direction="column" gap="4" style={styles.skinny}> 1011 + <SmallProductCard /> 1012 + <SmallProductCardWithBuying /> 1013 + <ProductOptionsCard /> 1014 + </Flex> 1015 + <Flex direction="column" gap="4" style={styles.skinny}> 1016 + <Delivery /> 1017 + <Bookmarks /> 1018 + <ShoppingCartCard /> 1019 + </Flex> 1020 + <Flex direction="column" gap="4" style={styles.medium}> 1021 + <DiscardedCard /> 1022 + <EditProductCard /> 1023 + </Flex> 1024 + <Flex direction="column" gap="4" style={styles.grow}> 1025 + <TopCustomersCard /> 1026 + <ShipmentTracking /> 1027 + <MarketingCallout /> 1028 + </Flex> 1029 + </Flex> 1030 + ); 1031 + }
+931
apps/docs/src/showcases/invoice.tsx
··· 1 + import { Avatar } from "@/components/avatar"; 2 + import { Button } from "@/components/button"; 3 + import { 4 + Card, 5 + CardBody, 6 + CardDescription, 7 + CardFooter, 8 + CardHeader, 9 + CardTitle, 10 + } from "@/components/card"; 11 + import { Flex } from "@/components/flex"; 12 + import { Grid, GridItem } from "@/components/grid"; 13 + import { IconButton } from "@/components/icon-button"; 14 + import { Link } from "@/components/link"; 15 + import { Menu, MenuItem, MenuSeparator } from "@/components/menu"; 16 + import { Separator } from "@/components/separator"; 17 + import { TextField } from "@/components/text-field"; 18 + import { Body, Heading5, SmallBody } from "@/components/typography"; 19 + import { 20 + ArrowDown, 21 + ArrowUp, 22 + CheckCircle, 23 + CheckCircle2, 24 + Copy, 25 + ExternalLink, 26 + MoreHorizontal, 27 + Pin, 28 + Plus, 29 + Share, 30 + X, 31 + } from "lucide-react"; 32 + import { Fragment } from "react/jsx-runtime"; 33 + import * as stylex from "@stylexjs/stylex"; 34 + import { Switch } from "@/components/switch"; 35 + import { fontFamily, typeramp } from "../components/theme/typography.stylex"; 36 + import { Text } from "@/components/typography/text"; 37 + import { ToggleButton } from "@/components/toggle-button"; 38 + import { spacing } from "../components/theme/spacing.stylex"; 39 + import { Badge } from "@/components/badge"; 40 + import { Checkbox } from "@/components/checkbox"; 41 + import { 42 + ui, 43 + primary, 44 + successColor, 45 + primaryColor, 46 + } from "../components/theme/semantic-color.stylex"; 47 + import { radius } from "../components/theme/radius.stylex"; 48 + 49 + const styles = stylex.create({ 50 + relative: { 51 + position: "relative", 52 + }, 53 + textCenter: { 54 + textAlign: "center", 55 + }, 56 + grow: { 57 + flexGrow: 1, 58 + flexShrink: 0, 59 + flexBasis: "0%", 60 + minWidth: 0, 61 + }, 62 + skinny: { 63 + flexGrow: 0.75, 64 + flexShrink: 0, 65 + flexBasis: "0%", 66 + }, 67 + pinnedButtons: { 68 + position: "absolute", 69 + top: 0, 70 + right: 0, 71 + marginRight: spacing["4"], 72 + marginTop: spacing["4"], 73 + }, 74 + invoiceCard: { 75 + padding: spacing["6"], 76 + }, 77 + check: { 78 + color: successColor.solid2, 79 + }, 80 + creditCardWrapper: { 81 + borderRadius: radius["lg"], 82 + padding: spacing["8"], 83 + }, 84 + creditCard: { 85 + fontFamily: fontFamily["mono"], 86 + borderRadius: radius["lg"], 87 + padding: spacing["4"], 88 + height: spacing["40"], 89 + backgroundImage: `linear-gradient(135deg, ${primaryColor.solid2} 0%, ${primaryColor.text1} 100%)`, 90 + }, 91 + copyCardNumber: { 92 + color: "white", 93 + backgroundColor: { 94 + default: "transparent", 95 + ":hover": "rgba(255, 255, 255, 0.3)", 96 + }, 97 + }, 98 + main: { 99 + padding: spacing["4"], 100 + width: 1600, 101 + }, 102 + }); 103 + 104 + function YourTeam() { 105 + const members = [ 106 + { 107 + name: "Oliver Chen", 108 + email: "oliver.chen@example.com", 109 + avatar: 110 + "https://images.unsplash.com/photo-1544005313-94ddf0286df2?&w=64&h=64&dpr=2&q=70&crop=faces&fit=crop", 111 + }, 112 + { 113 + name: "Amelia Rodriguez", 114 + email: "amelia.r@example.com", 115 + avatar: 116 + "https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?&w=64&h=64&dpr=2&q=70&crop=faces&fit=crop", 117 + }, 118 + { 119 + name: "Theodore Kim", 120 + email: "theo.kim@example.com", 121 + avatar: 122 + "https://images.unsplash.com/photo-1526510747491-58f928ec870f?&w=64&h=64&dpr=2&q=70&crop=focalpoint&fp-x=0.48&fp-y=0.48&fp-z=1.3&fit=crop", 123 + }, 124 + { 125 + name: "Sofia Patel", 126 + email: "sofia.patel@example.com", 127 + avatar: 128 + "https://images.unsplash.com/photo-1541823709867-1b206113eafd?&w=64&h=64&dpr=2&q=70&crop=focalpoint&fp-x=0.5&fp-y=0.3&fp-z=1.5&fit=crop", 129 + }, 130 + { 131 + name: "Mateo Garcia", 132 + email: "m.garcia@example.com", 133 + avatar: 134 + "https://images.unsplash.com/photo-1532073150508-0c1df022bdd1?&w=64&h=64&dpr=2&q=70&crop=focalpoint&fp-x=0.48&fp-y=0.35&fp-z=2&fit=crop", 135 + }, 136 + ]; 137 + 138 + return ( 139 + <Card> 140 + <CardHeader> 141 + <CardTitle>Your Team</CardTitle> 142 + <CardDescription>Invite and manage your team members.</CardDescription> 143 + </CardHeader> 144 + <CardBody> 145 + <Flex direction="column" gap="8"> 146 + <Flex align="center" gap="2"> 147 + <TextField 148 + aria-label="Email" 149 + placeholder="you@example.com" 150 + style={styles.grow} 151 + /> 152 + <Button>Invite</Button> 153 + </Flex> 154 + 155 + <Grid 156 + columns="auto max-content 1fr auto" 157 + columnGap="4" 158 + rowGap="5" 159 + alignItems="center" 160 + > 161 + {members.map((member, index) => ( 162 + <Fragment key={member.email}> 163 + <Avatar 164 + size="lg" 165 + src={member.avatar} 166 + fallback={member.name.charAt(0)} 167 + /> 168 + <Link href={`mailto:${member.email}`}>{member.name}</Link> 169 + <SmallBody variant="secondary">{member.email}</SmallBody> 170 + <Menu 171 + trigger={ 172 + <IconButton label="More" variant="tertiary"> 173 + <MoreHorizontal /> 174 + </IconButton> 175 + } 176 + > 177 + <MenuItem>View profile</MenuItem> 178 + <MenuItem>Change role</MenuItem> 179 + <MenuSeparator /> 180 + <MenuItem variant="destructive">Remove</MenuItem> 181 + </Menu> 182 + {index < members.length - 1 && ( 183 + <GridItem columnStart={1} columnEnd={-1}> 184 + <Separator /> 185 + </GridItem> 186 + )} 187 + </Fragment> 188 + ))} 189 + </Grid> 190 + </Flex> 191 + </CardBody> 192 + </Card> 193 + ); 194 + } 195 + 196 + function Pricing() { 197 + return ( 198 + <Card> 199 + <CardHeader> 200 + <CardTitle>Pricing</CardTitle> 201 + <CardDescription> 202 + No credit card required. Every plan includes a 30-day trial of all Pro 203 + features. 204 + </CardDescription> 205 + </CardHeader> 206 + <CardBody> 207 + <Flex gap="8"> 208 + <Flex direction="column" gap="5" style={styles.grow}> 209 + <Flex direction="column" gap="2"> 210 + <Text weight="semibold" size="xl"> 211 + Basic 212 + </Text> 213 + <Text size="sm" variant="secondary"> 214 + 3 team members 215 + </Text> 216 + </Flex> 217 + <Text weight="semibold" size="xl"> 218 + $0<Text variant="secondary">{" / mo"}</Text> 219 + </Text> 220 + <Flex direction="column" gap="2"> 221 + <Flex align="center" gap="2"> 222 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 223 + <Text size="sm">Expense tracking</Text> 224 + </Flex> 225 + <Flex align="center" gap="2"> 226 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 227 + <Text size="sm">Invoicing</Text> 228 + </Flex> 229 + <Flex align="center" gap="2"> 230 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 231 + <Text size="sm">Payment tracking</Text> 232 + </Flex> 233 + <Flex align="center" gap="2"> 234 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 235 + <Text size="sm">Transaction recording</Text> 236 + </Flex> 237 + <Flex align="center" gap="2"> 238 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 239 + <Text size="sm">Basic reports</Text> 240 + </Flex> 241 + <Flex align="center" gap="2"> 242 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 243 + <Text size="sm">Email support</Text> 244 + </Flex> 245 + </Flex> 246 + <Button variant="outline">Downgrade</Button> 247 + </Flex> 248 + <Flex direction="column" gap="5" style={styles.grow}> 249 + <Flex direction="column" gap="2"> 250 + <Text weight="semibold" size="xl"> 251 + Growth 252 + </Text> 253 + <Text size="sm" variant="secondary"> 254 + 10 team members 255 + </Text> 256 + </Flex> 257 + <Text weight="semibold" size="xl"> 258 + $49<Text variant="secondary">{" / mo"}</Text> 259 + </Text> 260 + <Flex direction="column" gap="2"> 261 + <Flex align="center" gap="2"> 262 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 263 + <Text size="sm">Online payments</Text> 264 + </Flex> 265 + <Flex align="center" gap="2"> 266 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 267 + <Text size="sm">Recurring invoices</Text> 268 + </Flex> 269 + <Flex align="center" gap="2"> 270 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 271 + <Text size="sm">Bill management</Text> 272 + </Flex> 273 + <Flex align="center" gap="2"> 274 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 275 + <Text size="sm">Inventory tracking</Text> 276 + </Flex> 277 + <Flex align="center" gap="2"> 278 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 279 + <Text size="sm">Detailed reports</Text> 280 + </Flex> 281 + <Flex align="center" gap="2"> 282 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 283 + <Text size="sm">Phone support</Text> 284 + </Flex> 285 + </Flex> 286 + <Button variant="outline">Go to billing</Button> 287 + </Flex> 288 + <Flex direction="column" gap="5" style={styles.grow}> 289 + <Flex direction="column" gap="2"> 290 + <Text weight="semibold" size="xl"> 291 + Pro 292 + </Text> 293 + <Text size="sm" variant="secondary"> 294 + Unlimited team members 295 + </Text> 296 + </Flex> 297 + <Text weight="semibold" size="xl"> 298 + $99<Text variant="secondary">{" / mo"}</Text> 299 + </Text> 300 + <Flex direction="column" gap="2"> 301 + <Flex align="center" gap="2"> 302 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 303 + <Text size="sm">Custom invoices</Text> 304 + </Flex> 305 + <Flex align="center" gap="2"> 306 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 307 + <Text size="sm">Multi-business</Text> 308 + </Flex> 309 + <Flex align="center" gap="2"> 310 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 311 + <Text size="sm">Team collaboration</Text> 312 + </Flex> 313 + <Flex align="center" gap="2"> 314 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 315 + <Text size="sm">App integrations</Text> 316 + </Flex> 317 + <Flex align="center" gap="2"> 318 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 319 + <Text size="sm">Advanced security</Text> 320 + </Flex> 321 + <Flex align="center" gap="2"> 322 + <CheckCircle {...stylex.props(styles.check)} size={16} /> 323 + <Text size="sm">Priority support</Text> 324 + </Flex> 325 + </Flex> 326 + <Button>Upgrade</Button> 327 + </Flex> 328 + </Flex> 329 + </CardBody> 330 + </Card> 331 + ); 332 + } 333 + 334 + function Notifications() { 335 + const sections = [ 336 + { 337 + title: "Comments", 338 + description: 339 + "Receive notifications when someone comments on your documents or mentions you.", 340 + }, 341 + { 342 + title: "Favorites", 343 + description: 344 + "Receive notifications when there is activity related to your favorited items.", 345 + }, 346 + { 347 + title: "New documents", 348 + description: 349 + "Receive notifications whenever people on your team create new documents.", 350 + }, 351 + ]; 352 + 353 + return ( 354 + <Card> 355 + <CardHeader> 356 + <CardTitle>Notifications</CardTitle> 357 + <CardDescription>Manage your notification settings.</CardDescription> 358 + </CardHeader> 359 + <CardBody> 360 + <Grid columns="1fr auto" rowGap="6" alignItems="start"> 361 + {sections.map((section, index) => ( 362 + <Fragment key={section.title}> 363 + <Flex direction="column" gap="1"> 364 + <Heading5>{section.title}</Heading5> 365 + <SmallBody variant="secondary">{section.description}</SmallBody> 366 + </Flex> 367 + <Flex direction="column" gap="2"> 368 + <Switch>Push</Switch> 369 + <Switch>Email</Switch> 370 + <Switch isDisabled>Slack</Switch> 371 + </Flex> 372 + {index < sections.length - 1 && ( 373 + <GridItem columnStart={1} columnEnd={-1}> 374 + <Separator /> 375 + </GridItem> 376 + )} 377 + </Fragment> 378 + ))} 379 + </Grid> 380 + </CardBody> 381 + </Card> 382 + ); 383 + } 384 + 385 + function RecentActivity() { 386 + const activities = [ 387 + { 388 + name: "Oliver Chen", 389 + timestamp: "06-08-2025 10:00 AM", 390 + description: ( 391 + <> 392 + Approved invoice <Link href="#">#3461</Link>{" "} 393 + </> 394 + ), 395 + avatar: 396 + "https://images.unsplash.com/photo-1521119989659-a83eee488004?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=focalpoint&amp;fp-x=0.45&amp;fp-y=0.37&amp;fp-z=3.5&amp;fit=crop", 397 + }, 398 + { 399 + name: "Amelia Rodriguez", 400 + timestamp: "06-08-2025 10:00 AM", 401 + description: ( 402 + <> 403 + Purchased <Link href="#">15 office chairs</Link>{" "} 404 + </> 405 + ), 406 + avatar: 407 + "https://images.unsplash.com/photo-1632765854612-9b02b6ec2b15?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=focalpoint&amp;fp-x=0.4&amp;fp-y=0.35&amp;fp-z=1.05&amp;fit=crop", 408 + }, 409 + { 410 + name: "Theodore Kim", 411 + timestamp: "06-08-2025 10:00 AM", 412 + avatar: 413 + "https://images.unsplash.com/photo-1632765854612-9b02b6ec2b15?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=focalpoint&amp;fp-x=0.4&amp;fp-y=0.35&amp;fp-z=1.05&amp;fit=crop", 414 + description: ( 415 + <> 416 + Responded to your commente <Link href="#">#7514</Link>{" "} 417 + </> 418 + ), 419 + }, 420 + { 421 + name: "Jasper Eriksson", 422 + timestamp: "06-08-2025 10:00 AM", 423 + avatar: 424 + "https://images.unsplash.com/photo-1586822339087-80cc375ac083?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=focalpoint&amp;fp-x=0.5&amp;fp-y=0.6&amp;fp-z=1&amp;fit=crop", 425 + description: ( 426 + <> 427 + Created <Link href="#">4 invoices</Link>{" "} 428 + </> 429 + ), 430 + }, 431 + { 432 + name: "Travis Ross", 433 + timestamp: "06-08-2025 10:00 AM", 434 + avatar: 435 + "https://images.unsplash.com/photo-1564564321837-a57b7070ac4f?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=focalpoint&amp;fp-x=0.52&amp;fp-y=0.47&amp;fp-z=1.3&amp;fit=crop", 436 + description: ( 437 + <> 438 + Updated client details for <Link href="#">Acme Co.</Link>{" "} 439 + </> 440 + ), 441 + }, 442 + { 443 + name: "Gizela Kavková", 444 + timestamp: "06-08-2025 10:00 AM", 445 + avatar: 446 + "https://images.unsplash.com/photo-1525304937537-4d586f394674?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=faces&amp;fit=crop", 447 + description: ( 448 + <> 449 + Created <Link href="#">4 invoices</Link>{" "} 450 + </> 451 + ), 452 + }, 453 + { 454 + name: "Gizela Kavková", 455 + timestamp: "06-08-2025 8:00 AM", 456 + avatar: 457 + "https://images.unsplash.com/photo-1525304937537-4d586f394674?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=faces&amp;fit=crop", 458 + description: ( 459 + <> 460 + Deleted report <Link href="#">#1234</Link>{" "} 461 + </> 462 + ), 463 + }, 464 + { 465 + name: "Da-Xia Wu", 466 + timestamp: "06-08-2025 8:00 AM", 467 + avatar: 468 + "https://images.unsplash.com/photo-1541823709867-1b206113eafd?&amp;w=64&amp;h=64&amp;dpr=2&amp;q=70&amp;crop=focalpoint&amp;fp-x=0.5&amp;fp-y=0.3&amp;fp-z=1.5&amp;fit=crop", 469 + description: <>Joined the team</>, 470 + }, 471 + ]; 472 + 473 + return ( 474 + <Card style={styles.relative}> 475 + <CardHeader> 476 + <CardTitle>Recent activity</CardTitle> 477 + <CardDescription> 478 + Review what has happened over the past days. 479 + </CardDescription> 480 + </CardHeader> 481 + <CardBody> 482 + <Grid 483 + columns="auto 1fr auto" 484 + columnGap="4" 485 + rowGap="5" 486 + alignItems="center" 487 + > 488 + {activities.map((activity, index) => ( 489 + <Fragment key={activity.timestamp}> 490 + <Avatar 491 + size="lg" 492 + src={activity.avatar} 493 + fallback={activity.name.charAt(0)} 494 + /> 495 + <Flex direction="column" gap="2"> 496 + <Text weight="medium">{activity.name}</Text> 497 + <SmallBody variant="secondary"> 498 + {activity.description} 499 + </SmallBody> 500 + </Flex> 501 + <SmallBody variant="secondary"> 502 + {Intl.DateTimeFormat("en-US", { 503 + dateStyle: "short", 504 + timeStyle: "short", 505 + }).format(new Date(activity.timestamp))} 506 + </SmallBody> 507 + {index < activities.length - 1 && ( 508 + <GridItem columnStart={1} columnEnd={-1}> 509 + <Separator /> 510 + </GridItem> 511 + )} 512 + </Fragment> 513 + ))} 514 + </Grid> 515 + <Flex gap="1" style={styles.pinnedButtons}> 516 + <IconButton variant="tertiary" label="Open in new tab"> 517 + <ExternalLink /> 518 + </IconButton> 519 + <ToggleButton defaultSelected variant="tertiary"> 520 + <Pin /> 521 + </ToggleButton> 522 + </Flex> 523 + </CardBody> 524 + </Card> 525 + ); 526 + } 527 + 528 + function FinancialPerformance() { 529 + const data = [ 530 + { 531 + label: "MRR", 532 + change: "3.2%", 533 + value: "$350K", 534 + trend: "positive", 535 + direction: "up", 536 + }, 537 + { 538 + label: "OpEx", 539 + change: "12.8%", 540 + value: "$211K", 541 + trend: "negative", 542 + direction: "up", 543 + }, 544 + { 545 + label: "CapEx", 546 + change: "8.8%", 547 + value: "$94K", 548 + trend: "positive", 549 + direction: "down", 550 + }, 551 + { 552 + label: "GPM", 553 + change: "1.2%", 554 + value: "44.6%", 555 + trend: "negative", 556 + direction: "down", 557 + }, 558 + { 559 + label: "NPM", 560 + change: "0.0%", 561 + value: "9.1%", 562 + trend: "neutral", 563 + direction: "none", 564 + }, 565 + { 566 + label: "EBITDA", 567 + change: "4.1%", 568 + value: "$443K", 569 + trend: "positive", 570 + direction: "up", 571 + }, 572 + { 573 + label: "CAC", 574 + change: "11.0%", 575 + value: "$146", 576 + trend: "positive", 577 + direction: "down", 578 + }, 579 + { 580 + label: "LTV", 581 + change: "3%", 582 + value: "$1,849", 583 + trend: "positive", 584 + direction: "up", 585 + }, 586 + { 587 + label: "Churn", 588 + change: "1.1%", 589 + value: "12.4%", 590 + trend: "negative", 591 + direction: "up", 592 + }, 593 + ]; 594 + 595 + return ( 596 + <Card style={styles.relative}> 597 + <CardHeader> 598 + <CardTitle>Financial performance</CardTitle> 599 + <CardDescription> 600 + Review your company's KPIs compared to the month before. . 601 + </CardDescription> 602 + </CardHeader> 603 + <CardBody> 604 + <Grid 605 + columns="1fr 1fr 1fr" 606 + columnGap="10" 607 + rowGap="10" 608 + alignItems="center" 609 + > 610 + {data.map((item) => ( 611 + <Flex 612 + key={`${item.label}-${item.change}`} 613 + direction="column" 614 + gap="4" 615 + > 616 + <Flex gap="2" align="center"> 617 + <Text variant="secondary">{item.label}</Text> 618 + <Badge 619 + size="sm" 620 + variant={ 621 + item.trend === "positive" 622 + ? "success" 623 + : item.trend === "negative" 624 + ? "critical" 625 + : "default" 626 + } 627 + > 628 + {item.direction === "up" && <ArrowUp />} 629 + {item.direction === "down" && <ArrowDown />} 630 + {item.change} 631 + </Badge> 632 + </Flex> 633 + <Text size="3xl" weight="semibold"> 634 + {item.value} 635 + </Text> 636 + </Flex> 637 + ))} 638 + </Grid> 639 + <Flex gap="1" style={styles.pinnedButtons}> 640 + <IconButton variant="tertiary" label="Open in new tab"> 641 + <ExternalLink /> 642 + </IconButton> 643 + <ToggleButton defaultSelected variant="tertiary"> 644 + <Pin /> 645 + </ToggleButton> 646 + </Flex> 647 + </CardBody> 648 + </Card> 649 + ); 650 + } 651 + 652 + function Todos() { 653 + const todos = [ 654 + { 655 + id: "1", 656 + title: ( 657 + <span> 658 + Respond to comment <Link>#384</Link> from Travis Ross 659 + </span> 660 + ), 661 + completed: false, 662 + }, 663 + { 664 + id: "2", 665 + title: <span>Invite Acme Co. team to Slack</span>, 666 + completed: false, 667 + }, 668 + { 669 + id: "3", 670 + title: <span>Create a report requested by Danilo Sousa</span>, 671 + completed: false, 672 + }, 673 + { 674 + id: "4", 675 + title: ( 676 + <span> 677 + Review support request <Link>#85</Link> 678 + </span> 679 + ), 680 + completed: false, 681 + }, 682 + { id: "5", title: <span>Close Q2 finances</span>, completed: true }, 683 + { 684 + id: "6", 685 + title: ( 686 + <span> 687 + Review invoice <Link>#3456</Link> 688 + </span> 689 + ), 690 + completed: true, 691 + }, 692 + ]; 693 + 694 + return ( 695 + <Card style={styles.relative}> 696 + <CardHeader> 697 + <CardTitle>To-do</CardTitle> 698 + <CardDescription>Stay on top of your daily tasks.</CardDescription> 699 + </CardHeader> 700 + <CardBody> 701 + <Flex direction="column" gap="4"> 702 + {todos.map((todo) => ( 703 + <Checkbox isSelected={todo.completed} key={todo.id}> 704 + <Text strikethrough={todo.completed}>{todo.title}</Text> 705 + </Checkbox> 706 + ))} 707 + </Flex> 708 + <Flex gap="1" style={styles.pinnedButtons}> 709 + <IconButton variant="tertiary" label="Share tasks"> 710 + <Share /> 711 + </IconButton> 712 + <IconButton variant="tertiary" label="Add new task"> 713 + <Plus /> 714 + </IconButton> 715 + </Flex> 716 + </CardBody> 717 + </Card> 718 + ); 719 + } 720 + 721 + function SignUpForm() { 722 + return ( 723 + <Card> 724 + <CardHeader> 725 + <CardTitle>Sign Up</CardTitle> 726 + </CardHeader> 727 + <CardBody> 728 + <Flex direction="column" gap="4"> 729 + <TextField label="Email Address" type="email" /> 730 + <TextField 731 + type="password" 732 + label={ 733 + <Flex justify="between" align="center"> 734 + <span>Password</span> 735 + <Link style={typeramp.sublabel}>Forgot Password?</Link> 736 + </Flex> 737 + } 738 + /> 739 + </Flex> 740 + </CardBody> 741 + <CardFooter> 742 + <Button variant="secondary">Create Account</Button> 743 + <Button>Sign In</Button> 744 + </CardFooter> 745 + </Card> 746 + ); 747 + } 748 + 749 + function SampleInvoice() { 750 + return ( 751 + <Card style={styles.relative}> 752 + <CardHeader> 753 + <CardTitle> 754 + Invoice <Link>#3461</Link> 755 + </CardTitle> 756 + </CardHeader> 757 + <CardBody> 758 + <Flex direction="column" gap="8"> 759 + <Grid columns="1fr 1fr" columnGap="6"> 760 + <Flex direction="column" gap="2"> 761 + <Text size="sm" variant="secondary"> 762 + Issued 763 + </Text> 764 + <Text weight="medium">June 21, 2023</Text> 765 + </Flex> 766 + <Flex direction="column" gap="2"> 767 + <Text size="sm" variant="secondary"> 768 + Due 769 + </Text> 770 + <Text weight="medium">July 21, 2023</Text> 771 + </Flex> 772 + <Flex direction="column" gap="2"> 773 + <Text size="sm" variant="secondary"> 774 + To 775 + </Text> 776 + <Text weight="medium">Paradise Ventures</Text> 777 + <Text size="sm"> 778 + 742 Evergreen Terrace, Springfield, IL 62704 779 + </Text> 780 + </Flex> 781 + <Flex direction="column" gap="2"> 782 + <Text size="sm" variant="secondary"> 783 + From 784 + </Text> 785 + <Text weight="medium">Rogue Widgets</Text> 786 + <Text size="sm">1600 Baker Street NW, Washington, DC 20500</Text> 787 + </Flex> 788 + </Grid> 789 + 790 + <Flex direction="column" gap="4"> 791 + <Flex justify="between" align="center"> 792 + <Text size="sm" variant="secondary"> 793 + Services 794 + </Text> 795 + <Text size="sm" variant="secondary"> 796 + Price 797 + </Text> 798 + </Flex> 799 + <Flex justify="between" align="center"> 800 + <Text weight="medium" size="lg"> 801 + Branding 802 + </Text> 803 + <Text>$20,000</Text> 804 + </Flex> 805 + <Flex justify="between" align="center"> 806 + <Text weight="medium" size="lg"> 807 + Marketing website 808 + </Text> 809 + <Text>$17,500</Text> 810 + </Flex> 811 + <Separator /> 812 + <Flex justify="between" align="center"> 813 + <Text>Total</Text> 814 + <Text>$37,500</Text> 815 + </Flex> 816 + </Flex> 817 + </Flex> 818 + <Flex gap="1" style={styles.pinnedButtons}> 819 + <IconButton variant="tertiary" label="Close"> 820 + <X /> 821 + </IconButton> 822 + </Flex> 823 + </CardBody> 824 + <CardFooter> 825 + <Button variant="critical-outline">Reject</Button> 826 + <Button>Approve</Button> 827 + </CardFooter> 828 + </Card> 829 + ); 830 + } 831 + 832 + function InvoicePaid() { 833 + return ( 834 + <Card style={[styles.relative, styles.invoiceCard]}> 835 + <Flex direction="column" gap="6" style={styles.textCenter}> 836 + <Flex align="center" justify="center"> 837 + <CheckCircle2 size={48} {...stylex.props(styles.check)} /> 838 + </Flex> 839 + <Text size="xl" weight="medium"> 840 + Invoice paid 841 + </Text> 842 + <Body> 843 + You paid $17,975.30. A receipt copy was sent to{" "} 844 + <Text weight="semibold">accounting@example.com</Text> 845 + </Body> 846 + <Flex direction="column" gap="2"> 847 + <Button>Next invoice</Button> 848 + <Button variant="outline">Done</Button> 849 + </Flex> 850 + </Flex> 851 + <Flex gap="1" style={styles.pinnedButtons}> 852 + <IconButton variant="tertiary" label="Close"> 853 + <X /> 854 + </IconButton> 855 + </Flex> 856 + </Card> 857 + ); 858 + } 859 + 860 + function YourCompanyCard() { 861 + return ( 862 + <Card> 863 + <CardHeader> 864 + <CardTitle>Your Company Card</CardTitle> 865 + <CardDescription>View and manage your corporate card.</CardDescription> 866 + </CardHeader> 867 + <CardBody> 868 + <div 869 + {...stylex.props( 870 + styles.creditCardWrapper, 871 + ui.bgDim, 872 + primary.textContrast, 873 + )} 874 + > 875 + <Flex 876 + direction="column" 877 + justify="between" 878 + gap="2" 879 + style={styles.creditCard} 880 + > 881 + <Text>Shane Goodall</Text> 882 + <Flex direction="column" gap="2"> 883 + <Flex align="center" gap="2"> 884 + <Text>1234 5678 9012 3456</Text> 885 + <IconButton 886 + size="sm" 887 + variant="tertiary" 888 + label="Copy card number" 889 + style={styles.copyCardNumber} 890 + > 891 + <Copy /> 892 + </IconButton> 893 + </Flex> 894 + <Flex align="center" gap="2"> 895 + <Text>01/27</Text> 896 + <Text>999</Text> 897 + </Flex> 898 + </Flex> 899 + </Flex> 900 + </div> 901 + </CardBody> 902 + <CardFooter> 903 + <Button variant="critical-outline">Freeze</Button> 904 + <Button>Done</Button> 905 + </CardFooter> 906 + </Card> 907 + ); 908 + } 909 + 910 + export function InvoiceApp() { 911 + return ( 912 + <Flex gap="6" style={styles.main}> 913 + <Flex direction="column" gap="6" style={styles.grow}> 914 + <YourTeam /> 915 + <Notifications /> 916 + <Pricing /> 917 + </Flex> 918 + <Flex direction="column" gap="6" style={styles.skinny}> 919 + <SignUpForm /> 920 + <YourCompanyCard /> 921 + <InvoicePaid /> 922 + <SampleInvoice /> 923 + </Flex> 924 + <Flex direction="column" gap="6" style={styles.grow}> 925 + <FinancialPerformance /> 926 + <RecentActivity /> 927 + <Todos /> 928 + </Flex> 929 + </Flex> 930 + ); 931 + }
+360
apps/docs/src/showcases/music.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { 3 + Card, 4 + CardBody, 5 + CardHeader, 6 + CardHeaderAction, 7 + CardTitle, 8 + } from "@/components/card"; 9 + import { spacing } from "../components/theme/spacing.stylex"; 10 + import { primaryColor } from "../components/theme/semantic-color.stylex"; 11 + import * as stylex from "@stylexjs/stylex"; 12 + import { Button } from "@/components/button"; 13 + import { AspectRatio, AspectRatioImage } from "@/components/aspect-ratio"; 14 + import { Text } from "@/components/typography/text"; 15 + import { Heart, Star } from "lucide-react"; 16 + import { IconButton } from "@/components/icon-button"; 17 + import { TextField } from "@/components/text-field"; 18 + import { Checkbox, CheckboxGroup } from "@/components/checkbox"; 19 + import { Separator } from "@/components/separator"; 20 + 21 + const styles = stylex.create({ 22 + main: { 23 + padding: spacing["4"], 24 + width: 2000, 25 + }, 26 + skinny: { 27 + width: 500, 28 + }, 29 + queueCard: { 30 + width: 280, 31 + }, 32 + grow: { 33 + flex: 1, 34 + }, 35 + albumArt: { 36 + width: 52, 37 + height: 52, 38 + }, 39 + albumCardArt: { 40 + width: "60%", 41 + }, 42 + starOutline: { 43 + color: primaryColor.solid1, 44 + }, 45 + filled: { 46 + color: primaryColor.solid1, 47 + fill: primaryColor.solid1, 48 + }, 49 + membershipTier: { 50 + paddingLeft: spacing["3"], 51 + paddingRight: spacing["3"], 52 + paddingTop: spacing["3"], 53 + paddingBottom: spacing["3"], 54 + marginLeft: `calc(${spacing["3"]} * -1)`, 55 + marginRight: `calc(${spacing["3"]} * -1)`, 56 + borderRadius: spacing["2"], 57 + cursor: "pointer", 58 + backgroundColor: { 59 + ":hover": primaryColor.component2, 60 + }, 61 + }, 62 + selectedTier: { 63 + backgroundColor: { 64 + default: primaryColor.component2, 65 + ":hover": primaryColor.component3, 66 + }, 67 + color: primaryColor.text2, 68 + }, 69 + priceBox: { 70 + padding: spacing["2"], 71 + borderRadius: spacing["1"], 72 + borderWidth: 1, 73 + borderStyle: "solid", 74 + borderColor: primaryColor.border2, 75 + backgroundColor: primaryColor.bgSubtle, 76 + color: primaryColor.text1, 77 + }, 78 + selectedPriceBox: { 79 + borderColor: primaryColor.solid2, 80 + backgroundColor: primaryColor.solid1, 81 + color: primaryColor.textContrast, 82 + }, 83 + membershipCard: { 84 + gap: spacing["2"], 85 + }, 86 + }); 87 + 88 + function MembershipCard() { 89 + return ( 90 + <Card style={styles.membershipCard}> 91 + <CardHeader> 92 + <CardTitle>Membership</CardTitle> 93 + <CardHeaderAction> 94 + <Button variant="tertiary">Done</Button> 95 + </CardHeaderAction> 96 + </CardHeader> 97 + <CardBody> 98 + <Flex direction="column" gap="5"> 99 + {/* Membership Tiers */} 100 + <Flex direction="column" gap="2"> 101 + {/* Individual */} 102 + <Flex 103 + align="center" 104 + justify="between" 105 + style={styles.membershipTier as unknown as stylex.StyleXStyles} 106 + > 107 + <Flex direction="column" gap="2"> 108 + <Text weight="medium">Individual</Text> 109 + <Text variant="secondary" size="sm"> 110 + Sign up with 1 account 111 + </Text> 112 + </Flex> 113 + <Text {...stylex.props(styles.priceBox)}>$4.99</Text> 114 + </Flex> 115 + 116 + {/* Duo - Selected */} 117 + <Flex 118 + align="center" 119 + justify="between" 120 + style={ 121 + [ 122 + styles.membershipTier, 123 + styles.selectedTier, 124 + ] as unknown as stylex.StyleXStyles 125 + } 126 + > 127 + <Flex direction="column" gap="1"> 128 + <Text weight="medium">Duo</Text> 129 + <Text variant="secondary" size="sm"> 130 + Sign up 2 accounts 131 + </Text> 132 + </Flex> 133 + <Text style={[styles.priceBox, styles.selectedPriceBox]}> 134 + $6.99 135 + </Text> 136 + </Flex> 137 + 138 + {/* Family */} 139 + <Flex 140 + align="center" 141 + justify="between" 142 + style={[styles.membershipTier] as unknown as stylex.StyleXStyles} 143 + > 144 + <Flex direction="column" gap="1"> 145 + <Text weight="medium">Family</Text> 146 + <Text variant="secondary" size="sm"> 147 + Sign up to 6 accounts 148 + </Text> 149 + </Flex> 150 + <Text style={styles.priceBox}>$12.99</Text> 151 + </Flex> 152 + </Flex> 153 + 154 + <Separator /> 155 + 156 + <Flex direction="column" gap="4"> 157 + <Text variant="secondary" size="sm"> 158 + Your next payment is $6.99 on November 14, 2025 159 + </Text> 160 + <Button variant="critical-outline" size="sm"> 161 + Cancel subscription 162 + </Button> 163 + </Flex> 164 + </Flex> 165 + </CardBody> 166 + </Card> 167 + ); 168 + } 169 + 170 + function ProfileCard() { 171 + return ( 172 + <Card> 173 + <CardHeader> 174 + <CardTitle>Your profile</CardTitle> 175 + <CardHeaderAction> 176 + <Button variant="tertiary" size="sm"> 177 + Cancel 178 + </Button> 179 + <Button variant="tertiary" size="sm"> 180 + Save 181 + </Button> 182 + </CardHeaderAction> 183 + </CardHeader> 184 + <CardBody> 185 + <Flex direction="column" gap="6"> 186 + <Flex direction="column" gap="4"> 187 + <TextField label="Name" defaultValue="Vlad Moroz" /> 188 + <TextField label="Username" defaultValue="@vladmoroz" /> 189 + <TextField label="Email" defaultValue="hi@vladmoroz.com" /> 190 + </Flex> 191 + <CheckboxGroup 192 + label="Privacy" 193 + defaultValue={[ 194 + "display-listening-history", 195 + "show-playlists-in-search", 196 + ]} 197 + > 198 + <Checkbox value="display-listening-history"> 199 + Display my listening history 200 + </Checkbox> 201 + <Checkbox value="everyone-can-follow-activity"> 202 + Everyone can follow my activity 203 + </Checkbox> 204 + <Checkbox value="show-playlists-in-search"> 205 + Show my playlists in search 206 + </Checkbox> 207 + </CheckboxGroup> 208 + <Flex direction="column" gap="4"> 209 + <Text weight="medium" size="lg"> 210 + Danger zone 211 + </Text> 212 + <Flex direction="column" gap="2"> 213 + <Button variant="critical-outline">Reset recommendations</Button> 214 + <Button variant="critical-outline">Delete profile</Button> 215 + </Flex> 216 + </Flex> 217 + </Flex> 218 + </CardBody> 219 + </Card> 220 + ); 221 + } 222 + 223 + function AlbumCard() { 224 + return ( 225 + <Card> 226 + <CardBody> 227 + <Flex direction="column" gap="6" align="center"> 228 + <AspectRatio style={[styles.albumCardArt]}> 229 + <AspectRatioImage 230 + src="https://workos.imgix.net/images/e35b46dc-4384-43d1-932c-24fa44e212cd.png?auto=format&fit=clip&q=80" 231 + alt="King Krule - The OOZ" 232 + /> 233 + </AspectRatio> 234 + <Flex direction="row" gap="1"> 235 + {[1, 2, 3, 4, 5].map((star) => 236 + 4 >= star ? ( 237 + <Star {...stylex.props(styles.filled)} /> 238 + ) : ( 239 + <Star {...stylex.props(styles.starOutline)} /> 240 + ), 241 + )} 242 + </Flex> 243 + <Text weight="bold" size="2xl"> 244 + King Krule - The OOZ 245 + </Text> 246 + <Text variant="secondary" align="center"> 247 + A dark and introspective album that showcases King Krule's 248 + distinctive blend of genres, while delivering hauntingly raw and 249 + poetic lyrics. 250 + </Text> 251 + <Flex direction="row" gap="2" align="center"> 252 + <Button variant="primary">Listen Now</Button> 253 + <IconButton label="Like" variant="outline"> 254 + <Heart /> 255 + </IconButton> 256 + </Flex> 257 + </Flex> 258 + </CardBody> 259 + </Card> 260 + ); 261 + } 262 + 263 + function QueueCard() { 264 + const songs = [ 265 + { 266 + id: 1, 267 + title: "The Less I Know the Better", 268 + artist: "Tame Impala", 269 + album: "Currents", 270 + duration: "3:39", 271 + albumArt: 272 + "https://workos.imgix.net/images/79645741-51e0-47fc-bb40-2fa66cf9f68e.png?auto=format&fit=clip&q=80&w=192", 273 + }, 274 + { 275 + id: 2, 276 + title: "Pieces", 277 + artist: "Villagers", 278 + album: "Becoming a Jackal", 279 + duration: "5:25", 280 + albumArt: 281 + "https://workos.imgix.net/images/95ff9b99-36f3-46d8-a3fe-9387fd7c3c32.png?auto=format&fit=clip&q=80&w=192", 282 + }, 283 + { 284 + id: 3, 285 + title: "Cola", 286 + artist: "Arlo Parks", 287 + album: "Super Sad Generation", 288 + duration: "3:50", 289 + albumArt: 290 + "https://workos.imgix.net/images/945c66a9-afd9-4b1c-8eb0-4ce3992731ca.png?auto=format&fit=clip&q=80&w=192", 291 + }, 292 + { 293 + id: 4, 294 + title: "Do the Astral Plane", 295 + artist: "Flying Lotus", 296 + album: "Cosmogramma", 297 + duration: "3:58", 298 + albumArt: 299 + "https://workos.imgix.net/images/3d9075e4-c232-4fb5-a1a4-b0a33d669192.png?auto=format&fit=clip&q=80&w=192", 300 + }, 301 + { 302 + id: 5, 303 + title: "Left Hand Free", 304 + artist: "Alt-J", 305 + album: "This Is All Yours", 306 + duration: "2:54", 307 + albumArt: 308 + "https://workos.imgix.net/images/8d431b64-ebe8-41be-b986-2f59cb5c567d.png?auto=format&fit=clip&q=80&w=192", 309 + }, 310 + ]; 311 + 312 + return ( 313 + <Card> 314 + <CardHeader> 315 + <CardTitle>Queue</CardTitle> 316 + <CardHeaderAction> 317 + <Button variant="tertiary" size="sm"> 318 + Clear 319 + </Button> 320 + <Button variant="tertiary" size="sm"> 321 + Repeat 322 + </Button> 323 + </CardHeaderAction> 324 + </CardHeader> 325 + <CardBody> 326 + <Flex direction="column" gap="3"> 327 + {songs.map((song) => ( 328 + <Flex key={song.id} gap="3" align="center"> 329 + <AspectRatio style={styles.albumArt}> 330 + <AspectRatioImage src={song.albumArt} alt={song.title} /> 331 + </AspectRatio> 332 + <Flex direction="column" gap="1.5" style={styles.grow}> 333 + <Text weight="medium">{song.title}</Text> 334 + <Text variant="secondary" size="sm"> 335 + {song.artist} - {song.album} 336 + </Text> 337 + </Flex> 338 + <Text variant="secondary" size="sm"> 339 + {song.duration} 340 + </Text> 341 + </Flex> 342 + ))} 343 + </Flex> 344 + </CardBody> 345 + </Card> 346 + ); 347 + } 348 + 349 + export function Music() { 350 + return ( 351 + <Flex gap="4" style={styles.main}> 352 + <Flex direction="column" gap="4" style={styles.skinny}> 353 + <MembershipCard /> 354 + <ProfileCard /> 355 + <QueueCard /> 356 + <AlbumCard /> 357 + </Flex> 358 + </Flex> 359 + ); 360 + }
+11 -2
packages/hip-ui/src/components/aspect-ratio/index.tsx
··· 7 7 aspectRatio, 8 8 }), 9 9 container: { 10 + overflow: "hidden", 10 11 position: "relative", 12 + }, 13 + rounded: { 14 + borderTopLeftRadius: radius["md"], 15 + borderBottomLeftRadius: radius["md"], 16 + borderTopRightRadius: radius["md"], 17 + borderBottomRightRadius: radius["md"], 11 18 }, 12 19 imageContainer: { 13 20 inset: 0, 14 21 position: "absolute", 15 22 }, 16 23 image: { 17 - borderRadius: radius["md"], 18 24 height: "100%", 19 25 objectFit: "cover", 20 - overflow: "hidden", 21 26 width: "100%", 22 27 }, 23 28 }); ··· 26 31 extends Omit<React.ComponentProps<"div">, "style" | "className"> { 27 32 style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 28 33 aspectRatio?: number; 34 + rounded?: boolean; 29 35 } 30 36 31 37 export function AspectRatio({ 32 38 style, 33 39 aspectRatio = 1, 40 + rounded = true, 34 41 ...props 35 42 }: AspectRatioProps) { 43 + console.log(style); 36 44 return ( 37 45 <div 38 46 {...props} 39 47 {...stylex.props( 40 48 styles.container, 41 49 styles.aspectRatio(aspectRatio), 50 + rounded && styles.rounded, 42 51 style, 43 52 )} 44 53 />
+13 -1
packages/hip-ui/src/components/card/index.tsx
··· 13 13 card: { 14 14 borderRadius: radius["lg"], 15 15 display: "flex", 16 + overflow: "hidden", 16 17 flexDirection: "column", 17 18 fontFamily: fontFamily["sans"], 18 19 gap: "var(--card-gap)", ··· 81 82 display: "flex", 82 83 gap: spacing["2"], 83 84 justifyContent: "flex-end", 85 + }, 86 + cardImage: { 87 + borderTopLeftRadius: { default: 0, ":first-child": radius.md }, 88 + borderBottomLeftRadius: { default: 0, ":last-child": radius.md }, 89 + borderTopRightRadius: { default: 0, ":first-child": radius.md }, 90 + borderBottomRightRadius: { default: 0, ":last-child": radius.md }, 91 + overflow: "hidden", 84 92 }, 85 93 }); 86 94 ··· 198 206 return ( 199 207 <AspectRatio 200 208 aspectRatio={aspectRatio} 201 - style={[styles.cardSection as unknown as stylex.StyleXStyles, style]} 209 + style={[ 210 + styles.cardSection as unknown as stylex.StyleXStyles, 211 + styles.cardImage, 212 + style, 213 + ]} 202 214 > 203 215 <AspectRatioImage {...props} /> 204 216 </AspectRatio>
+1 -4
packages/hip-ui/src/components/link/index.tsx
··· 11 11 12 12 const styles = stylex.create({ 13 13 link: { 14 - color: { 15 - default: primaryColor.text1, 16 - ":visited": primaryColor.text2, 17 - }, 14 + color: primaryColor.text2, 18 15 cursor: "pointer", 19 16 fontFamily: fontFamily["sans"], 20 17 fontWeight: fontWeight["normal"],
+7
packages/hip-ui/src/components/typography/text.tsx
··· 66 66 "variant-destructive": { color: criticalColor.text2 }, 67 67 68 68 strikethrough: { textDecoration: "line-through" }, 69 + 70 + left: { textAlign: "left" }, 71 + center: { textAlign: "center" }, 72 + right: { textAlign: "right" }, 69 73 }); 70 74 71 75 interface TextProps ··· 78 82 tracking?: ThemeKeys<typeof tracking>; 79 83 variant?: "primary" | "secondary" | "destructive"; 80 84 strikethrough?: boolean; 85 + align?: "left" | "center" | "right"; 81 86 } 82 87 83 88 export const Text = ({ ··· 89 94 tracking, 90 95 variant, 91 96 strikethrough = false, 97 + align, 92 98 ...props 93 99 }: TextProps) => { 94 100 return ( ··· 101 107 tracking && styles[`tracking-${tracking}`], 102 108 variant && styles[`variant-${variant}`], 103 109 strikethrough && styles.strikethrough, 110 + align && styles[align], 104 111 style, 105 112 )} 106 113 {...props}