@borisj74/bv-ds 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/index.cjs +33885 -0
- package/dist/index.d.cts +2715 -0
- package/dist/index.d.ts +2715 -0
- package/dist/index.js +33717 -0
- package/package.json +67 -0
- package/src/components/ActivityFeed/ActivityFeed.tsx +48 -0
- package/src/components/ActivityFeed/index.ts +2 -0
- package/src/components/ActivityGauge/ActivityGauge.tsx +155 -0
- package/src/components/ActivityGauge/index.ts +7 -0
- package/src/components/AdvancedFilterBar/AdvancedFilterBar.tsx +80 -0
- package/src/components/AdvancedFilterBar/index.ts +2 -0
- package/src/components/Alert/Alert.tsx +210 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/Avatar/Avatar.tsx +111 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/AvatarAddButton/AvatarAddButton.tsx +65 -0
- package/src/components/AvatarAddButton/index.ts +5 -0
- package/src/components/AvatarGroup/AvatarGroup.tsx +79 -0
- package/src/components/AvatarGroup/index.ts +6 -0
- package/src/components/AvatarLabelGroup/AvatarLabelGroup.tsx +62 -0
- package/src/components/AvatarLabelGroup/index.ts +5 -0
- package/src/components/AvatarProfilePhoto/AvatarProfilePhoto.tsx +117 -0
- package/src/components/AvatarProfilePhoto/index.ts +5 -0
- package/src/components/Badge/ColorBadge.tsx +36 -0
- package/src/components/Badge/ModernBadge.tsx +38 -0
- package/src/components/Badge/PillBadge.tsx +36 -0
- package/src/components/Badge/badgeShared.tsx +139 -0
- package/src/components/Badge/index.ts +7 -0
- package/src/components/BadgeCloseX/BadgeCloseX.tsx +64 -0
- package/src/components/BadgeCloseX/index.ts +2 -0
- package/src/components/BadgeGroup/BadgeGroup.tsx +61 -0
- package/src/components/BadgeGroup/index.ts +7 -0
- package/src/components/BreadcrumbButtonBase/BreadcrumbButtonBase.tsx +75 -0
- package/src/components/BreadcrumbButtonBase/index.ts +5 -0
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +62 -0
- package/src/components/Breadcrumbs/index.ts +2 -0
- package/src/components/Button/Button.tsx +71 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/ButtonCloseX/ButtonCloseX.tsx +54 -0
- package/src/components/ButtonCloseX/index.ts +2 -0
- package/src/components/ButtonDestructive/ButtonDestructive.tsx +67 -0
- package/src/components/ButtonDestructive/index.ts +6 -0
- package/src/components/ButtonGroup/ButtonGroup.tsx +28 -0
- package/src/components/ButtonGroup/index.ts +2 -0
- package/src/components/ButtonGroupSegment/ButtonGroupSegment.tsx +54 -0
- package/src/components/ButtonGroupSegment/index.ts +5 -0
- package/src/components/ButtonUtility/ButtonUtility.tsx +67 -0
- package/src/components/ButtonUtility/index.ts +6 -0
- package/src/components/CalendarCell/CalendarCell.tsx +82 -0
- package/src/components/CalendarCell/index.ts +2 -0
- package/src/components/CalendarCellDayWeekView/CalendarCellDayWeekView.tsx +56 -0
- package/src/components/CalendarCellDayWeekView/index.ts +2 -0
- package/src/components/CalendarColumnHeader/CalendarColumnHeader.tsx +45 -0
- package/src/components/CalendarColumnHeader/index.ts +5 -0
- package/src/components/CalendarDateIcon/CalendarDateIcon.tsx +25 -0
- package/src/components/CalendarDateIcon/index.ts +2 -0
- package/src/components/CalendarEvent/CalendarEvent.tsx +76 -0
- package/src/components/CalendarEvent/index.ts +2 -0
- package/src/components/CalendarEventDayWeekView/CalendarEventDayWeekView.tsx +76 -0
- package/src/components/CalendarEventDayWeekView/index.ts +2 -0
- package/src/components/CalendarHeader/CalendarHeader.tsx +47 -0
- package/src/components/CalendarHeader/index.ts +2 -0
- package/src/components/CalendarRowLabel/CalendarRowLabel.tsx +21 -0
- package/src/components/CalendarRowLabel/index.ts +2 -0
- package/src/components/CalendarTimemarker/CalendarTimemarker.tsx +46 -0
- package/src/components/CalendarTimemarker/index.ts +5 -0
- package/src/components/CalendarViewDropdown/CalendarViewDropdown.tsx +101 -0
- package/src/components/CalendarViewDropdown/index.ts +6 -0
- package/src/components/CardHeader/CardHeader.tsx +57 -0
- package/src/components/CardHeader/index.ts +2 -0
- package/src/components/CarouselArrow/CarouselArrow.tsx +47 -0
- package/src/components/CarouselArrow/index.ts +6 -0
- package/src/components/CarouselImage/CarouselImage.tsx +60 -0
- package/src/components/CarouselImage/index.ts +2 -0
- package/src/components/Change/Change.tsx +73 -0
- package/src/components/Change/index.ts +2 -0
- package/src/components/ChartLegend/ChartLegend.tsx +38 -0
- package/src/components/ChartLegend/index.ts +2 -0
- package/src/components/ChartMarker/ChartMarker.tsx +54 -0
- package/src/components/ChartMarker/index.ts +2 -0
- package/src/components/ChartMini/ChartMini.tsx +86 -0
- package/src/components/ChartMini/index.ts +2 -0
- package/src/components/ChartTooltip/ChartTooltip.tsx +44 -0
- package/src/components/ChartTooltip/index.ts +2 -0
- package/src/components/Checkbox/Checkbox.tsx +65 -0
- package/src/components/Checkbox/checkboxBase.tsx +81 -0
- package/src/components/Checkbox/index.ts +3 -0
- package/src/components/CodeSnippet/CodeSnippet.tsx +94 -0
- package/src/components/CodeSnippet/index.ts +2 -0
- package/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx +44 -0
- package/src/components/CodeSnippetTabs/index.ts +2 -0
- package/src/components/CommandBar/CommandBar.tsx +80 -0
- package/src/components/CommandBar/index.ts +2 -0
- package/src/components/CommandBarFooter/CommandBarFooter.tsx +125 -0
- package/src/components/CommandBarFooter/index.ts +5 -0
- package/src/components/CommandBarMenuSection/CommandBarMenuSection.tsx +28 -0
- package/src/components/CommandBarMenuSection/index.ts +2 -0
- package/src/components/CommandBarNavigationIcon/CommandBarNavigationIcon.tsx +47 -0
- package/src/components/CommandBarNavigationIcon/index.ts +2 -0
- package/src/components/CommandDropdownMenuItem/CommandDropdownMenuItem.tsx +51 -0
- package/src/components/CommandDropdownMenuItem/index.ts +2 -0
- package/src/components/CommandInput/CommandInput.tsx +74 -0
- package/src/components/CommandInput/index.ts +2 -0
- package/src/components/CommandShortcut/CommandShortcut.tsx +26 -0
- package/src/components/CommandShortcut/index.ts +2 -0
- package/src/components/ContentDivider/ContentDivider.tsx +80 -0
- package/src/components/ContentDivider/index.ts +6 -0
- package/src/components/ContentFeatureText/ContentFeatureText.tsx +60 -0
- package/src/components/ContentFeatureText/index.ts +5 -0
- package/src/components/ContentHeading/ContentHeading.tsx +43 -0
- package/src/components/ContentHeading/index.ts +5 -0
- package/src/components/ContentParagraph/ContentParagraph.tsx +39 -0
- package/src/components/ContentParagraph/index.ts +5 -0
- package/src/components/ContentQuote/ContentQuote.tsx +114 -0
- package/src/components/ContentQuote/index.ts +6 -0
- package/src/components/ContentRule/ContentRule.tsx +31 -0
- package/src/components/ContentRule/index.ts +2 -0
- package/src/components/ContextMenu/ContextMenu.tsx +67 -0
- package/src/components/ContextMenu/index.ts +7 -0
- package/src/components/ContextMenu/useContextMenu.ts +41 -0
- package/src/components/DatePickerCell/DatePickerCell.tsx +77 -0
- package/src/components/DatePickerCell/index.ts +2 -0
- package/src/components/DatePickerListItem/DatePickerListItem.tsx +39 -0
- package/src/components/DatePickerListItem/index.ts +2 -0
- package/src/components/DatePickerMenu/DatePickerMenu.tsx +131 -0
- package/src/components/DatePickerMenu/index.ts +2 -0
- package/src/components/DropdownAccountListItem/DropdownAccountListItem.tsx +69 -0
- package/src/components/DropdownAccountListItem/index.ts +2 -0
- package/src/components/DropdownMenuFooter/DropdownMenuFooter.tsx +50 -0
- package/src/components/DropdownMenuFooter/index.ts +5 -0
- package/src/components/DropdownMenuHeader/DropdownMenuHeader.tsx +93 -0
- package/src/components/DropdownMenuHeader/index.ts +5 -0
- package/src/components/DropdownMenuItemInsetIcon/DropdownMenuItemInsetIcon.tsx +89 -0
- package/src/components/DropdownMenuItemInsetIcon/index.ts +5 -0
- package/src/components/DropdownMenuListItem/DropdownMenuListItem.tsx +84 -0
- package/src/components/DropdownMenuListItem/index.ts +2 -0
- package/src/components/EmptyState/EmptyState.tsx +65 -0
- package/src/components/EmptyState/index.ts +2 -0
- package/src/components/FeedItemBase/FeedItemBase.tsx +135 -0
- package/src/components/FeedItemBase/index.ts +2 -0
- package/src/components/FileUpload/FileUpload.tsx +112 -0
- package/src/components/FileUpload/index.ts +2 -0
- package/src/components/FileUploadBase/FileUploadBase.tsx +69 -0
- package/src/components/FileUploadBase/index.ts +2 -0
- package/src/components/FileUploadItemBase/FileUploadItemBase.tsx +190 -0
- package/src/components/FileUploadItemBase/index.ts +7 -0
- package/src/components/FilterBar/FilterBar.tsx +62 -0
- package/src/components/FilterBar/index.ts +2 -0
- package/src/components/FilterTabs/FilterTabs.tsx +41 -0
- package/src/components/FilterTabs/index.ts +2 -0
- package/src/components/FiltersDropdownMenu/FiltersDropdownMenu.tsx +104 -0
- package/src/components/FiltersDropdownMenu/index.ts +2 -0
- package/src/components/FiltersSlideoutMenu/FiltersSlideoutMenu.tsx +71 -0
- package/src/components/FiltersSlideoutMenu/index.ts +2 -0
- package/src/components/HeaderNavigation/HeaderNavigation.tsx +178 -0
- package/src/components/HeaderNavigation/index.ts +6 -0
- package/src/components/HelpIcon/HelpIcon.tsx +49 -0
- package/src/components/HelpIcon/index.ts +2 -0
- package/src/components/InputField/InputField.tsx +108 -0
- package/src/components/InputField/index.ts +3 -0
- package/src/components/InputField/inputFieldShared.tsx +68 -0
- package/src/components/LeadingInputField/LeadingInputField.tsx +60 -0
- package/src/components/LeadingInputField/index.ts +2 -0
- package/src/components/LineAndBarChart/LineAndBarChart.tsx +96 -0
- package/src/components/LineAndBarChart/index.ts +2 -0
- package/src/components/LinkMessage/LinkMessage.tsx +52 -0
- package/src/components/LinkMessage/index.ts +2 -0
- package/src/components/LoadingIndicator/LoadingIndicator.tsx +108 -0
- package/src/components/LoadingIndicator/index.ts +6 -0
- package/src/components/MediaMessage/MediaMessage.tsx +109 -0
- package/src/components/MediaMessage/index.ts +2 -0
- package/src/components/MegaInputFieldBase/MegaInputFieldBase.tsx +49 -0
- package/src/components/MegaInputFieldBase/index.ts +5 -0
- package/src/components/Message/Message.tsx +85 -0
- package/src/components/Message/index.ts +3 -0
- package/src/components/Message/messageShared.tsx +73 -0
- package/src/components/MessageAction/MessageAction.tsx +221 -0
- package/src/components/MessageAction/index.ts +2 -0
- package/src/components/MessageActionButton/MessageActionButton.tsx +36 -0
- package/src/components/MessageActionButton/index.ts +2 -0
- package/src/components/MessageActionPanel/MessageActionPanel.tsx +36 -0
- package/src/components/MessageActionPanel/index.ts +2 -0
- package/src/components/MessageReaction/MessageReaction.tsx +37 -0
- package/src/components/MessageReaction/index.ts +2 -0
- package/src/components/MessageStatusIcon/MessageStatusIcon.tsx +54 -0
- package/src/components/MessageStatusIcon/index.ts +2 -0
- package/src/components/MetricItem/MetricItem.tsx +147 -0
- package/src/components/MetricItem/index.ts +2 -0
- package/src/components/ModalActions/ModalActions.tsx +57 -0
- package/src/components/ModalActions/index.ts +2 -0
- package/src/components/ModalHeader/ModalHeader.tsx +99 -0
- package/src/components/ModalHeader/index.ts +2 -0
- package/src/components/MultiSelect/MultiSelect.tsx +118 -0
- package/src/components/MultiSelect/index.ts +2 -0
- package/src/components/NavAccountCard/NavAccountCard.tsx +124 -0
- package/src/components/NavAccountCard/index.ts +2 -0
- package/src/components/NavAccountCardMenuItem/NavAccountCardMenuItem.tsx +101 -0
- package/src/components/NavAccountCardMenuItem/index.ts +5 -0
- package/src/components/NavButton/NavButton.tsx +50 -0
- package/src/components/NavButton/index.ts +2 -0
- package/src/components/NavFeaturedCard/NavFeaturedCard.tsx +82 -0
- package/src/components/NavFeaturedCard/index.ts +2 -0
- package/src/components/NavItemBase/NavItemBase.tsx +79 -0
- package/src/components/NavItemBase/index.ts +2 -0
- package/src/components/NavItemDropdownBase/NavItemDropdownBase.tsx +74 -0
- package/src/components/NavItemDropdownBase/index.ts +2 -0
- package/src/components/NavMenuButton/NavMenuButton.tsx +47 -0
- package/src/components/NavMenuButton/index.ts +2 -0
- package/src/components/Notification/Notification.tsx +102 -0
- package/src/components/Notification/index.ts +2 -0
- package/src/components/NumberInput/NumberInput.tsx +114 -0
- package/src/components/NumberInput/index.ts +2 -0
- package/src/components/PageHeader/PageHeader.tsx +88 -0
- package/src/components/PageHeader/index.ts +2 -0
- package/src/components/Pagination/Pagination.tsx +124 -0
- package/src/components/Pagination/index.ts +2 -0
- package/src/components/PaginationButtonGroupBase/PaginationButtonGroupBase.tsx +69 -0
- package/src/components/PaginationButtonGroupBase/index.ts +5 -0
- package/src/components/PaginationCards/PaginationCards.tsx +72 -0
- package/src/components/PaginationCards/index.ts +2 -0
- package/src/components/PaginationDotGroup/PaginationDotGroup.tsx +66 -0
- package/src/components/PaginationDotGroup/index.ts +2 -0
- package/src/components/PaginationDotIndicator/PaginationDotIndicator.tsx +39 -0
- package/src/components/PaginationDotIndicator/index.ts +6 -0
- package/src/components/PaginationNumberBase/PaginationNumberBase.tsx +42 -0
- package/src/components/PaginationNumberBase/index.ts +5 -0
- package/src/components/PieChart/PieChart.tsx +73 -0
- package/src/components/PieChart/index.ts +2 -0
- package/src/components/ProgressBar/ProgressBar.tsx +75 -0
- package/src/components/ProgressBar/index.ts +2 -0
- package/src/components/ProgressCircle/ProgressCircle.tsx +89 -0
- package/src/components/ProgressCircle/index.ts +6 -0
- package/src/components/RadarChart/RadarChart.tsx +62 -0
- package/src/components/RadarChart/index.ts +2 -0
- package/src/components/Radio/Radio.tsx +55 -0
- package/src/components/Radio/index.ts +2 -0
- package/src/components/RadioGroup/RadioGroup.tsx +54 -0
- package/src/components/RadioGroup/index.ts +2 -0
- package/src/components/RadioGroupItem/RadioGroupItem.tsx +118 -0
- package/src/components/RadioGroupItem/index.ts +6 -0
- package/src/components/SectionFooter/SectionFooter.tsx +40 -0
- package/src/components/SectionFooter/index.ts +2 -0
- package/src/components/SectionHeader/SectionHeader.tsx +44 -0
- package/src/components/SectionHeader/index.ts +2 -0
- package/src/components/SectionLabel/SectionLabel.tsx +51 -0
- package/src/components/SectionLabel/index.ts +2 -0
- package/src/components/Select/Select.tsx +121 -0
- package/src/components/Select/index.ts +2 -0
- package/src/components/SelectMenuItem/SelectMenuItem.tsx +85 -0
- package/src/components/SelectMenuItem/index.ts +2 -0
- package/src/components/SidebarNavigation/SidebarNavigation.tsx +100 -0
- package/src/components/SidebarNavigation/index.ts +2 -0
- package/src/components/SlideOutMenuHeader/SlideOutMenuHeader.tsx +56 -0
- package/src/components/SlideOutMenuHeader/index.ts +2 -0
- package/src/components/Slider/Slider.tsx +125 -0
- package/src/components/Slider/index.ts +2 -0
- package/src/components/SocialButton/SocialButton.tsx +88 -0
- package/src/components/SocialButton/index.ts +2 -0
- package/src/components/StatusIcon/StatusIcon.tsx +75 -0
- package/src/components/StatusIcon/index.ts +2 -0
- package/src/components/StepBase/StepBase.tsx +90 -0
- package/src/components/StepBase/index.ts +2 -0
- package/src/components/StepIconBase/StepIconBase.tsx +65 -0
- package/src/components/StepIconBase/index.ts +7 -0
- package/src/components/TabButtonBase/TabButtonBase.tsx +88 -0
- package/src/components/TabButtonBase/index.ts +2 -0
- package/src/components/TableCell/TableCell.tsx +44 -0
- package/src/components/TableCell/index.ts +2 -0
- package/src/components/TableHeaderCell/TableHeaderCell.tsx +34 -0
- package/src/components/TableHeaderCell/index.ts +2 -0
- package/src/components/TableHeaderLabel/TableHeaderLabel.tsx +37 -0
- package/src/components/TableHeaderLabel/index.ts +2 -0
- package/src/components/Tabs/Tabs.tsx +80 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Tag/Tag.tsx +91 -0
- package/src/components/Tag/index.ts +2 -0
- package/src/components/TagsInputField/TagsInputField.tsx +90 -0
- package/src/components/TagsInputField/index.ts +2 -0
- package/src/components/TextEditorToolbar/TextEditorToolbar.tsx +33 -0
- package/src/components/TextEditorToolbar/index.ts +2 -0
- package/src/components/TextEditorTooltip/TextEditorTooltip.tsx +28 -0
- package/src/components/TextEditorTooltip/index.ts +2 -0
- package/src/components/TextareaInputField/TextareaInputField.tsx +45 -0
- package/src/components/TextareaInputField/index.ts +2 -0
- package/src/components/Toggle/Toggle.tsx +87 -0
- package/src/components/Toggle/index.ts +2 -0
- package/src/components/Tooltip/Tooltip.tsx +59 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/TrailingInputField/TrailingInputField.tsx +62 -0
- package/src/components/TrailingInputField/index.ts +2 -0
- package/src/components/TreeView/TreeView.tsx +86 -0
- package/src/components/TreeView/index.ts +2 -0
- package/src/components/TreeViewConnector/TreeViewConnector.tsx +36 -0
- package/src/components/TreeViewConnector/index.ts +2 -0
- package/src/components/TreeViewItem/TreeViewItem.tsx +111 -0
- package/src/components/TreeViewItem/index.ts +2 -0
- package/src/components/VerificationCodeInput/VerificationCodeInput.tsx +114 -0
- package/src/components/VerificationCodeInput/index.ts +2 -0
- package/src/illustrations/BoxIllustration.tsx +13 -0
- package/src/illustrations/CloudIllustration.tsx +18 -0
- package/src/illustrations/CreditCardIllustration.tsx +13 -0
- package/src/illustrations/DocumentsIllustration.tsx +13 -0
- package/src/illustrations/index.ts +4 -0
- package/src/index.ts +147 -0
- package/src/internal/chartTheme.ts +30 -0
- package/src/internal/ringBase.tsx +82 -0
- package/src/styles.css +3 -0
- package/tailwind-preset.js +295 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type SocialBrand = "google" | "facebook" | "apple" | "twitter" | "figma" | "dribbble";
|
|
5
|
+
export type SocialButtonTheme = "color" | "gray" | "brand";
|
|
6
|
+
export type SocialButtonSize = "md" | "lg";
|
|
7
|
+
|
|
8
|
+
export interface SocialButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
|
|
9
|
+
social: SocialBrand;
|
|
10
|
+
/** `color`/`brand` = full-color logo; `gray` = monochrome. */
|
|
11
|
+
theme?: SocialButtonTheme;
|
|
12
|
+
size?: SocialButtonSize;
|
|
13
|
+
/** Icon-only (no label) — renders a square button. */
|
|
14
|
+
iconOnly?: boolean;
|
|
15
|
+
/** Label override; defaults to "Sign in with <Brand>". */
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const LABEL: Record<SocialBrand, string> = {
|
|
20
|
+
google: "Sign in with Google",
|
|
21
|
+
facebook: "Sign in with Facebook",
|
|
22
|
+
apple: "Sign in with Apple",
|
|
23
|
+
twitter: "Sign in with X",
|
|
24
|
+
figma: "Sign in with Figma",
|
|
25
|
+
dribbble: "Sign in with Dribbble",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Full-color brand glyphs (viewBox 0 0 24 24). Gray theme desaturates via CSS. */
|
|
29
|
+
const GLYPH: Record<SocialBrand, ReactNode> = {
|
|
30
|
+
google: (
|
|
31
|
+
<>
|
|
32
|
+
<path d="M23.04 12.26c0-.82-.07-1.6-.21-2.36H12v4.48h6.19a5.3 5.3 0 0 1-2.3 3.48v2.9h3.72c2.18-2 3.43-4.96 3.43-8.5Z" fill="#4285F4" />
|
|
33
|
+
<path d="M12 24c3.1 0 5.7-1.03 7.6-2.79l-3.72-2.88c-1.03.69-2.35 1.1-3.88 1.1-2.98 0-5.5-2.01-6.4-4.72H1.75v2.96A12 12 0 0 0 12 24Z" fill="#34A853" />
|
|
34
|
+
<path d="M5.6 14.71A7.2 7.2 0 0 1 5.22 12c0-.94.16-1.86.38-2.71V6.33H1.75A12 12 0 0 0 .48 12c0 1.94.46 3.77 1.27 5.67l3.85-2.96Z" fill="#FBBC05" />
|
|
35
|
+
<path d="M12 4.77c1.68 0 3.19.58 4.38 1.71l3.28-3.28C17.7 1.19 15.1 0 12 0A12 12 0 0 0 1.75 6.33l3.85 2.96C6.5 6.58 9.02 4.77 12 4.77Z" fill="#EA4335" />
|
|
36
|
+
</>
|
|
37
|
+
),
|
|
38
|
+
facebook: <path d="M24 12a12 12 0 1 0-13.87 11.85v-8.38H7.08V12h3.05V9.36c0-3.01 1.79-4.67 4.53-4.67 1.31 0 2.69.23 2.69.23v2.95h-1.52c-1.49 0-1.96.93-1.96 1.87V12h3.33l-.53 3.47h-2.8v8.38A12 12 0 0 0 24 12Z" fill="#1877F2" />,
|
|
39
|
+
apple: <path d="M18.4 12.74c-.02-2.07 1.69-3.06 1.77-3.11-.96-1.41-2.46-1.6-2.99-1.62-1.27-.13-2.49.75-3.13.75-.65 0-1.65-.73-2.71-.71-1.39.02-2.68.81-3.39 2.05-1.45 2.51-.37 6.22 1.03 8.26.69.99 1.5 2.11 2.57 2.07 1.03-.04 1.42-.67 2.67-.67 1.24 0 1.6.67 2.69.65 1.11-.02 1.81-1.01 2.49-2.01.78-1.15 1.1-2.27 1.12-2.32-.02-.01-2.15-.83-2.17-3.27ZM16.34 6.58c.57-.69.95-1.65.85-2.6-.82.03-1.81.54-2.4 1.23-.52.61-.98 1.59-.86 2.52.91.07 1.84-.46 2.41-1.15Z" fill="#000" />,
|
|
40
|
+
twitter: <path d="M18.24 2.25h3.31l-7.23 8.26L22.83 21.75h-6.66l-5.22-6.82-5.97 6.82H1.66l7.73-8.83L1.17 2.25h6.83l4.71 6.23 5.53-6.23Zm-1.16 17.52h1.83L7.01 4.13H5.04l12.04 15.64Z" fill="#000" />,
|
|
41
|
+
figma: (
|
|
42
|
+
<>
|
|
43
|
+
<path d="M8 24c2.21 0 4-1.79 4-4v-4H8a4 4 0 1 0 0 8Z" fill="#0ACF83" />
|
|
44
|
+
<path d="M4 12a4 4 0 0 1 4-4h4v8H8a4 4 0 0 1-4-4Z" fill="#A259FF" />
|
|
45
|
+
<path d="M4 4a4 4 0 0 1 4-4h4v8H8a4 4 0 0 1-4-4Z" fill="#F24E1E" />
|
|
46
|
+
<path d="M12 0h4a4 4 0 0 1 0 8h-4V0Z" fill="#FF7262" />
|
|
47
|
+
<path d="M20 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z" fill="#1ABCFE" />
|
|
48
|
+
</>
|
|
49
|
+
),
|
|
50
|
+
dribbble: <path d="M12 0a12 12 0 1 0 0 24 12 12 0 0 0 0-24Zm7.93 5.53a10.16 10.16 0 0 1 2.3 6.36c-.34-.07-3.71-.75-7.1-.33-.08-.18-.15-.36-.23-.55-.21-.5-.45-1-.7-1.49 3.76-1.53 5.47-3.74 5.73-3.99ZM12 1.79c2.55 0 4.88.96 6.65 2.53-.22.31-1.76 2.38-5.39 3.74A52.4 52.4 0 0 0 9.4 2.2 10.2 10.2 0 0 1 12 1.79Zm-4.57 1.1a61.7 61.7 0 0 1 3.83 5.79c-4.83 1.29-9.1 1.26-9.56 1.26a10.24 10.24 0 0 1 5.73-7.05ZM1.78 12.01v-.31c.44.01 5.46.07 10.62-1.48.3.58.58 1.17.84 1.76l-.41.12c-5.33 1.72-8.16 6.42-8.4 6.81a10.18 10.18 0 0 1-2.65-6.9Zm10.22 10.2c-2.3 0-4.42-.78-6.11-2.08.18-.39 2.32-4.5 8.15-6.53l.07-.02c1.45 3.77 2.05 6.93 2.2 7.84a10.13 10.13 0 0 1-4.31.79Zm6.06-1.74c-.1-.63-.65-3.65-2-7.36 3.2-.51 5.99.33 6.34.44a10.2 10.2 0 0 1-4.34 6.92Z" fill="#EA4C89" />,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Social-login button. All themes share the neutral white shell (border-primary,
|
|
55
|
+
* shadow-xs, `text-secondary` label) — `theme` only controls the brand glyph:
|
|
56
|
+
* `color`/`brand` = full color, `gray` = monochrome (CSS grayscale, flagged
|
|
57
|
+
* approximation of UntitledUI's true single-color gray logos). `iconOnly` drops
|
|
58
|
+
* the label for a square button.
|
|
59
|
+
*/
|
|
60
|
+
export function SocialButton({
|
|
61
|
+
social,
|
|
62
|
+
theme = "color",
|
|
63
|
+
size = "md",
|
|
64
|
+
iconOnly = false,
|
|
65
|
+
children,
|
|
66
|
+
className,
|
|
67
|
+
...rest
|
|
68
|
+
}: SocialButtonProps) {
|
|
69
|
+
return (
|
|
70
|
+
<button
|
|
71
|
+
type="button"
|
|
72
|
+
className={clsx(
|
|
73
|
+
"inline-flex items-center justify-center rounded-md border border-border-primary bg-bg-primary font-semibold text-text-secondary shadow-xs transition-colors hover:bg-bg-primary-hover",
|
|
74
|
+
size === "lg" ? "gap-sm text-md" : "gap-xs text-sm",
|
|
75
|
+
iconOnly
|
|
76
|
+
? size === "lg" ? "size-11" : "size-10"
|
|
77
|
+
: size === "lg" ? "px-xl py-2.5" : "px-xl py-md",
|
|
78
|
+
className,
|
|
79
|
+
)}
|
|
80
|
+
{...rest}
|
|
81
|
+
>
|
|
82
|
+
<svg viewBox="0 0 24 24" className={clsx("shrink-0", size === "lg" ? "size-5" : "size-5", theme === "gray" && "grayscale")} aria-hidden>
|
|
83
|
+
{GLYPH[social]}
|
|
84
|
+
</svg>
|
|
85
|
+
{!iconOnly && <span className="whitespace-nowrap">{children ?? LABEL[social]}</span>}
|
|
86
|
+
</button>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type HTMLAttributes } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type StatusIconType = "online" | "offline" | "count" | "avatar" | "verified";
|
|
5
|
+
|
|
6
|
+
export interface StatusIconProps extends HTMLAttributes<HTMLSpanElement> {
|
|
7
|
+
type?: StatusIconType;
|
|
8
|
+
/** Number shown for `type="count"`. */
|
|
9
|
+
count?: number;
|
|
10
|
+
/** Image src for `type="avatar"`. */
|
|
11
|
+
imageUrl?: string;
|
|
12
|
+
/** Outer box size in px (default 16). */
|
|
13
|
+
size?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Small overlay status badge — meant to sit on the corner of an avatar/icon.
|
|
18
|
+
* `online`/`offline` = colored dot; `count` = error-colored numeric bubble;
|
|
19
|
+
* `avatar` = ringed mini image; `verified` = brand verified tick (approximated
|
|
20
|
+
* as a brand disc + check, no burst star).
|
|
21
|
+
*/
|
|
22
|
+
export function StatusIcon({
|
|
23
|
+
type = "offline",
|
|
24
|
+
count,
|
|
25
|
+
imageUrl,
|
|
26
|
+
size = 16,
|
|
27
|
+
className,
|
|
28
|
+
style,
|
|
29
|
+
...rest
|
|
30
|
+
}: StatusIconProps) {
|
|
31
|
+
const box = { width: size, height: size, ...style };
|
|
32
|
+
|
|
33
|
+
if (type === "avatar") {
|
|
34
|
+
return (
|
|
35
|
+
<span className={clsx("inline-block overflow-hidden rounded-full border-[1.5px] border-bg-primary", className)} style={box} {...rest}>
|
|
36
|
+
{imageUrl && <img src={imageUrl} alt="" className="size-full object-cover" />}
|
|
37
|
+
</span>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (type === "count") {
|
|
42
|
+
return (
|
|
43
|
+
<span
|
|
44
|
+
className={clsx("inline-flex items-center justify-center rounded-full border-[1.5px] border-bg-primary bg-fg-error-secondary text-[10px] font-bold leading-none text-text-white", className)}
|
|
45
|
+
style={box}
|
|
46
|
+
{...rest}
|
|
47
|
+
>
|
|
48
|
+
{count}
|
|
49
|
+
</span>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (type === "verified") {
|
|
54
|
+
return (
|
|
55
|
+
<span className={clsx("inline-flex items-center justify-center rounded-full bg-bg-brand-solid text-fg-white", className)} style={box} {...rest}>
|
|
56
|
+
<svg viewBox="0 0 16 16" fill="none" className="size-2.5" aria-hidden>
|
|
57
|
+
<path d="M13 4.5 6.5 11 3 7.5" stroke="currentColor" strokeWidth="1.67" strokeLinecap="round" strokeLinejoin="round" />
|
|
58
|
+
</svg>
|
|
59
|
+
</span>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// online / offline dot
|
|
64
|
+
return (
|
|
65
|
+
<span
|
|
66
|
+
className={clsx(
|
|
67
|
+
"inline-block rounded-full border-[1.5px] border-bg-primary",
|
|
68
|
+
type === "online" ? "bg-fg-success-secondary" : "bg-utility-neutral-300",
|
|
69
|
+
className,
|
|
70
|
+
)}
|
|
71
|
+
style={box}
|
|
72
|
+
{...rest}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import {
|
|
4
|
+
StepIconBase,
|
|
5
|
+
type StepIconType,
|
|
6
|
+
type StepStatus,
|
|
7
|
+
type StepIconSize,
|
|
8
|
+
} from "../StepIconBase";
|
|
9
|
+
|
|
10
|
+
export type StepOrientation = "left" | "top";
|
|
11
|
+
|
|
12
|
+
export interface StepBaseProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
13
|
+
status?: StepStatus;
|
|
14
|
+
size?: StepIconSize;
|
|
15
|
+
/** Icon column position: `left` (vertical list) or `top` (horizontal list). */
|
|
16
|
+
orientation?: StepOrientation;
|
|
17
|
+
/** Indicator style. Ignored when `icon` (featured) is supplied. */
|
|
18
|
+
iconType?: StepIconType;
|
|
19
|
+
/** Step number (number indicator). */
|
|
20
|
+
step?: ReactNode;
|
|
21
|
+
/** Featured-icon slot — replaces the StepIconBase indicator. */
|
|
22
|
+
icon?: ReactNode;
|
|
23
|
+
title?: ReactNode;
|
|
24
|
+
description?: ReactNode;
|
|
25
|
+
/** Render a connecting line toward the next step. */
|
|
26
|
+
connector?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* One step row/column for `ProgressSteps`. Composes `StepIconBase` (or a featured
|
|
31
|
+
* `icon` slot) + title/description, with an optional `connector` line (vertical
|
|
32
|
+
* below for `left`, horizontal to the right for `top`). The 5 assembled Figma
|
|
33
|
+
* layout frames are reference-only — build step lists by laying these out.
|
|
34
|
+
*
|
|
35
|
+
* NOTE: the connector renders on one side only (toward the next step); the last
|
|
36
|
+
* step should set `connector={false}`.
|
|
37
|
+
*/
|
|
38
|
+
export function StepBase({
|
|
39
|
+
status = "incomplete",
|
|
40
|
+
size = "sm",
|
|
41
|
+
orientation = "left",
|
|
42
|
+
iconType = "check",
|
|
43
|
+
step,
|
|
44
|
+
icon,
|
|
45
|
+
title,
|
|
46
|
+
description,
|
|
47
|
+
connector = false,
|
|
48
|
+
className,
|
|
49
|
+
...rest
|
|
50
|
+
}: StepBaseProps) {
|
|
51
|
+
const indicator = icon ?? (
|
|
52
|
+
<StepIconBase type={iconType} status={status} size={size} step={step} />
|
|
53
|
+
);
|
|
54
|
+
const lineColor = status === "complete" ? "bg-bg-brand-solid" : "bg-border-primary";
|
|
55
|
+
|
|
56
|
+
const titleEl = title && (
|
|
57
|
+
<p className={clsx("text-sm font-semibold", status === "current" ? "text-text-brand-secondary" : "text-text-secondary")}>
|
|
58
|
+
{title}
|
|
59
|
+
</p>
|
|
60
|
+
);
|
|
61
|
+
const descEl = description && <p className="text-sm text-text-tertiary">{description}</p>;
|
|
62
|
+
|
|
63
|
+
if (orientation === "top") {
|
|
64
|
+
return (
|
|
65
|
+
<div className={clsx("flex flex-col gap-md", className)} {...rest}>
|
|
66
|
+
<div className="flex w-full items-center gap-xs">
|
|
67
|
+
{indicator}
|
|
68
|
+
{connector && <span className={clsx("h-0.5 flex-1 rounded-full", lineColor)} />}
|
|
69
|
+
</div>
|
|
70
|
+
<div className="flex flex-col gap-xxs">
|
|
71
|
+
{titleEl}
|
|
72
|
+
{descEl}
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className={clsx("flex gap-md", className)} {...rest}>
|
|
80
|
+
<div className="flex flex-col items-center self-stretch">
|
|
81
|
+
{indicator}
|
|
82
|
+
{connector && <span className={clsx("mt-xs w-0.5 flex-1 rounded-full", lineColor)} />}
|
|
83
|
+
</div>
|
|
84
|
+
<div className="flex flex-col gap-xxs pb-xl">
|
|
85
|
+
{titleEl}
|
|
86
|
+
{descEl}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type StepIconType = "check" | "number";
|
|
5
|
+
export type StepStatus = "incomplete" | "current" | "complete";
|
|
6
|
+
export type StepIconSize = "sm" | "md";
|
|
7
|
+
|
|
8
|
+
export interface StepIconBaseProps extends HTMLAttributes<HTMLDivElement> {
|
|
9
|
+
type?: StepIconType;
|
|
10
|
+
status?: StepStatus;
|
|
11
|
+
size?: StepIconSize;
|
|
12
|
+
/** Number to show when `type="number"`. */
|
|
13
|
+
step?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Check = ({ className }: { className?: string }) => (
|
|
17
|
+
<svg viewBox="0 0 16 16" fill="none" className={className} aria-hidden>
|
|
18
|
+
<path d="M13.33 4 6 11.33 2.67 8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
19
|
+
</svg>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Step indicator dot for `ProgressSteps`. `type` check (dot / brand fill / check)
|
|
24
|
+
* or number; `status` incomplete / current (brand ring) / complete (filled +
|
|
25
|
+
* check). Composed by `StepBase`.
|
|
26
|
+
*/
|
|
27
|
+
export function StepIconBase({
|
|
28
|
+
type = "check",
|
|
29
|
+
status = "incomplete",
|
|
30
|
+
size = "sm",
|
|
31
|
+
step,
|
|
32
|
+
className,
|
|
33
|
+
...rest
|
|
34
|
+
}: StepIconBaseProps) {
|
|
35
|
+
const dim = size === "md" ? "size-8" : "size-6";
|
|
36
|
+
const isComplete = status === "complete";
|
|
37
|
+
const isCurrent = status === "current";
|
|
38
|
+
const completeFill = type === "number" ? "bg-bg-success-solid" : "bg-bg-brand-solid";
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
className={clsx(
|
|
43
|
+
"relative flex shrink-0 items-center justify-center overflow-visible rounded-full",
|
|
44
|
+
dim,
|
|
45
|
+
isComplete && completeFill,
|
|
46
|
+
isCurrent && type === "check" && "bg-bg-brand-solid ring-2 ring-utility-brand-500 ring-offset-2",
|
|
47
|
+
isCurrent && type === "number" && "border border-border-secondary bg-bg-primary",
|
|
48
|
+
status === "incomplete" && type === "check" && "border-2 border-border-primary bg-bg-primary",
|
|
49
|
+
status === "incomplete" && type === "number" && "border border-border-secondary bg-bg-primary",
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
52
|
+
{...rest}
|
|
53
|
+
>
|
|
54
|
+
{type === "check" && !isComplete && (
|
|
55
|
+
<span className={clsx("rounded-full", size === "md" ? "size-2.5" : "size-2", isCurrent ? "bg-fg-white" : "bg-fg-quaternary")} />
|
|
56
|
+
)}
|
|
57
|
+
{type === "number" && !isComplete && (
|
|
58
|
+
<span className={clsx("font-semibold", size === "md" ? "text-sm" : "text-xs", isCurrent ? "text-text-secondary" : "text-text-quaternary")}>
|
|
59
|
+
{step}
|
|
60
|
+
</span>
|
|
61
|
+
)}
|
|
62
|
+
{isComplete && <Check className={clsx("text-fg-white", size === "md" ? "size-4" : "size-3")} />}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type TabButtonType =
|
|
5
|
+
| "buttonBrand"
|
|
6
|
+
| "buttonGray"
|
|
7
|
+
| "buttonWhite"
|
|
8
|
+
| "buttonMinimal"
|
|
9
|
+
| "underline"
|
|
10
|
+
| "line";
|
|
11
|
+
export type TabButtonSize = "sm" | "md";
|
|
12
|
+
|
|
13
|
+
export interface TabButtonBaseProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
|
|
14
|
+
/** Visual style. Maps to the Figma `Type` axis. */
|
|
15
|
+
variant?: TabButtonType;
|
|
16
|
+
current?: boolean;
|
|
17
|
+
size?: TabButtonSize;
|
|
18
|
+
/** Leading icon slot. */
|
|
19
|
+
icon?: ReactNode;
|
|
20
|
+
/** Trailing badge/count slot. */
|
|
21
|
+
badge?: ReactNode;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Single tab control consumed by `Tabs`. Six `variant`s: pill styles
|
|
27
|
+
* (`buttonBrand`/`buttonGray`/`buttonWhite`/`buttonMinimal`), `underline`
|
|
28
|
+
* (horizontal bottom border) and `line` (vertical left border). `current` is the
|
|
29
|
+
* active state. The native `type` attribute is Omitted (taken over by `variant`).
|
|
30
|
+
*/
|
|
31
|
+
export function TabButtonBase({
|
|
32
|
+
variant = "buttonBrand",
|
|
33
|
+
current = false,
|
|
34
|
+
size = "sm",
|
|
35
|
+
icon,
|
|
36
|
+
badge,
|
|
37
|
+
children,
|
|
38
|
+
className,
|
|
39
|
+
...rest
|
|
40
|
+
}: TabButtonBaseProps) {
|
|
41
|
+
const pill = variant !== "underline" && variant !== "line";
|
|
42
|
+
|
|
43
|
+
const styles: Record<TabButtonType, string> = {
|
|
44
|
+
buttonBrand: clsx(
|
|
45
|
+
"rounded-sm px-2.5 py-md",
|
|
46
|
+
current ? "bg-bg-brand-primary-alt text-text-secondary" : "text-text-quaternary hover:bg-bg-primary-hover hover:text-text-tertiary",
|
|
47
|
+
),
|
|
48
|
+
buttonGray: clsx(
|
|
49
|
+
"rounded-sm px-2.5 py-md",
|
|
50
|
+
current ? "bg-bg-primary-hover text-utility-brand-700" : "text-text-quaternary hover:bg-bg-primary-hover hover:text-text-tertiary",
|
|
51
|
+
),
|
|
52
|
+
buttonWhite: clsx(
|
|
53
|
+
"rounded-sm px-2.5 py-md",
|
|
54
|
+
current ? "border border-border-primary bg-bg-primary text-text-secondary shadow-xs" : "text-text-quaternary hover:text-text-tertiary",
|
|
55
|
+
),
|
|
56
|
+
buttonMinimal: clsx(
|
|
57
|
+
"rounded-sm px-2.5 py-md",
|
|
58
|
+
current ? "text-text-secondary" : "text-text-quaternary hover:text-text-tertiary",
|
|
59
|
+
),
|
|
60
|
+
underline: clsx(
|
|
61
|
+
"border-b-2 px-xxs pb-lg",
|
|
62
|
+
current ? "border-fg-brand-primary-alt text-utility-brand-700" : "border-transparent text-text-quaternary hover:text-text-tertiary",
|
|
63
|
+
),
|
|
64
|
+
line: clsx(
|
|
65
|
+
"border-l-2 px-lg py-xxs",
|
|
66
|
+
current ? "border-fg-brand-primary text-utility-brand-700" : "border-transparent text-text-quaternary hover:text-text-tertiary",
|
|
67
|
+
),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
aria-current={current ? "page" : undefined}
|
|
74
|
+
className={clsx(
|
|
75
|
+
"inline-flex items-center justify-center gap-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
|
|
76
|
+
size === "md" ? "text-sm" : "text-xs",
|
|
77
|
+
pill && "h-9",
|
|
78
|
+
styles[variant],
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
{...rest}
|
|
82
|
+
>
|
|
83
|
+
{icon && <span className="flex size-4 shrink-0 items-center justify-center">{icon}</span>}
|
|
84
|
+
{children && <span className="whitespace-nowrap px-xxs">{children}</span>}
|
|
85
|
+
{badge}
|
|
86
|
+
</button>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type TableCellSize = "sm" | "md";
|
|
5
|
+
|
|
6
|
+
export interface TableCellProps extends HTMLAttributes<HTMLTableCellElement> {
|
|
7
|
+
size?: TableCellSize;
|
|
8
|
+
/** Leading checkbox slot (first column). */
|
|
9
|
+
checkbox?: ReactNode;
|
|
10
|
+
/** Hover/selected row background. */
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
/** Cell content — any of the 14 Figma `Type` layouts (see stories). */
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generic `<td>` shell — border-bottom row cell. One component over the 14 Figma
|
|
18
|
+
* `Type`s (Text, Avatar, Badge, Trend, Progress bar, Action icons, Star ratings,
|
|
19
|
+
* …): the differing content goes in `children`; the shell (height, padding,
|
|
20
|
+
* border, hover bg) is constant. Same one-shell-many-examples pattern as
|
|
21
|
+
* `NavFeaturedCard`. `sm` = 64px row, `md` = 72px.
|
|
22
|
+
*
|
|
23
|
+
* NOTE: the Figma `Star ratings` cell references a raw `Colors/Yellow/400` var —
|
|
24
|
+
* do NOT use it; substitute the `warning-primary`/`utility-yellow` token if a
|
|
25
|
+
* star fill colour is needed.
|
|
26
|
+
*/
|
|
27
|
+
export function TableCell({ size = "md", checkbox, selected = false, children, className, ...rest }: TableCellProps) {
|
|
28
|
+
return (
|
|
29
|
+
<td
|
|
30
|
+
className={clsx(
|
|
31
|
+
"border-b border-border-secondary align-middle text-sm",
|
|
32
|
+
size === "md" ? "h-[72px] px-3xl py-xl" : "h-16 px-3xl py-lg",
|
|
33
|
+
selected ? "bg-bg-primary-hover" : "bg-bg-primary",
|
|
34
|
+
className,
|
|
35
|
+
)}
|
|
36
|
+
{...rest}
|
|
37
|
+
>
|
|
38
|
+
<div className="flex items-center gap-lg">
|
|
39
|
+
{checkbox}
|
|
40
|
+
{children}
|
|
41
|
+
</div>
|
|
42
|
+
</td>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type TableHeaderCellSize = "sm" | "md";
|
|
5
|
+
|
|
6
|
+
export interface TableHeaderCellProps extends HTMLAttributes<HTMLTableCellElement> {
|
|
7
|
+
size?: TableHeaderCellSize;
|
|
8
|
+
/** Leading checkbox slot (first column). */
|
|
9
|
+
checkbox?: ReactNode;
|
|
10
|
+
/** Label content — typically a `TableHeaderLabel`. */
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `<th>` wrapper — white cell with a bottom border; composes a leading `checkbox`
|
|
16
|
+
* slot + a `TableHeaderLabel` (`children`). `sm` = 40px row, `md` = 44px row.
|
|
17
|
+
*/
|
|
18
|
+
export function TableHeaderCell({ size = "sm", checkbox, children, className, ...rest }: TableHeaderCellProps) {
|
|
19
|
+
return (
|
|
20
|
+
<th
|
|
21
|
+
className={clsx(
|
|
22
|
+
"border-b border-border-secondary bg-bg-primary text-left align-middle",
|
|
23
|
+
size === "md" ? "h-11 px-3xl py-lg" : "h-10 px-2xl py-md",
|
|
24
|
+
className,
|
|
25
|
+
)}
|
|
26
|
+
{...rest}
|
|
27
|
+
>
|
|
28
|
+
<div className={clsx("flex items-center", checkbox ? "gap-lg" : "gap-xs")}>
|
|
29
|
+
{checkbox}
|
|
30
|
+
{children}
|
|
31
|
+
</div>
|
|
32
|
+
</th>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
export type TableHeaderLabelArrow = "none" | "down" | "up" | "chevronSelector";
|
|
5
|
+
|
|
6
|
+
export interface TableHeaderLabelProps extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
/** Sort indicator. */
|
|
9
|
+
arrow?: TableHeaderLabelArrow;
|
|
10
|
+
/** Trailing help-icon slot. */
|
|
11
|
+
helpIcon?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function ArrowIcon({ arrow }: { arrow: Exclude<TableHeaderLabelArrow, "none"> }) {
|
|
15
|
+
return (
|
|
16
|
+
<svg viewBox="0 0 12 12" fill="none" className="size-3 shrink-0" aria-hidden>
|
|
17
|
+
{arrow === "down" && <path d="M6 2.5v7M6 9.5 9 6.5M6 9.5 3 6.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />}
|
|
18
|
+
{arrow === "up" && <path d="M6 9.5v-7M6 2.5 9 5.5M6 2.5 3 5.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />}
|
|
19
|
+
{arrow === "chevronSelector" && <path d="M3.5 7.5 6 10l2.5-2.5M3.5 4.5 6 2l2.5 2.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />}
|
|
20
|
+
</svg>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Column-header label — `text-xs` semibold in `text-quaternary` (→ `text-tertiary`
|
|
26
|
+
* on hover), with an optional sort `arrow` and trailing `helpIcon` slot. Consumed
|
|
27
|
+
* by `TableHeaderCell`.
|
|
28
|
+
*/
|
|
29
|
+
export function TableHeaderLabel({ children, arrow = "none", helpIcon, className, ...rest }: TableHeaderLabelProps) {
|
|
30
|
+
return (
|
|
31
|
+
<div className={clsx("group/th inline-flex items-center gap-xs text-xs font-semibold text-text-quaternary", className)} {...rest}>
|
|
32
|
+
<span className="whitespace-nowrap">{children}</span>
|
|
33
|
+
{helpIcon}
|
|
34
|
+
{arrow !== "none" && <ArrowIcon arrow={arrow} />}
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { TabButtonBase, type TabButtonType, type TabButtonSize } from "../TabButtonBase";
|
|
4
|
+
|
|
5
|
+
export type TabsOrientation = "horizontal" | "vertical";
|
|
6
|
+
|
|
7
|
+
export interface TabItem {
|
|
8
|
+
value: string;
|
|
9
|
+
label: ReactNode;
|
|
10
|
+
icon?: ReactNode;
|
|
11
|
+
badge?: ReactNode;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface TabsProps {
|
|
16
|
+
items: TabItem[];
|
|
17
|
+
value?: string;
|
|
18
|
+
onValueChange?: (value: string) => void;
|
|
19
|
+
orientation?: TabsOrientation;
|
|
20
|
+
/** Tab style — passed to `TabButtonBase`. Defaults: horizontal→buttonBrand, vertical→line. */
|
|
21
|
+
variant?: TabButtonType;
|
|
22
|
+
size?: TabButtonSize;
|
|
23
|
+
/** Stretch tabs to fill the row (horizontal only). */
|
|
24
|
+
fullWidth?: boolean;
|
|
25
|
+
className?: string;
|
|
26
|
+
"aria-label"?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Tab bar composing `TabButtonBase`. `orientation="horizontal"` lays tabs in a
|
|
31
|
+
* row (underline variant gets a shared bottom border); `vertical` stacks them
|
|
32
|
+
* (defaults to the `line` variant). Controlled via `value`/`onValueChange`.
|
|
33
|
+
*/
|
|
34
|
+
export function Tabs({
|
|
35
|
+
items,
|
|
36
|
+
value,
|
|
37
|
+
onValueChange,
|
|
38
|
+
orientation = "horizontal",
|
|
39
|
+
variant,
|
|
40
|
+
size = "sm",
|
|
41
|
+
fullWidth = false,
|
|
42
|
+
className,
|
|
43
|
+
"aria-label": ariaLabel,
|
|
44
|
+
}: TabsProps) {
|
|
45
|
+
const vertical = orientation === "vertical";
|
|
46
|
+
const resolved: TabButtonType = variant ?? (vertical ? "line" : "buttonBrand");
|
|
47
|
+
const underlineRow = resolved === "underline" && !vertical;
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
role="tablist"
|
|
52
|
+
aria-label={ariaLabel}
|
|
53
|
+
aria-orientation={orientation}
|
|
54
|
+
className={clsx(
|
|
55
|
+
"flex",
|
|
56
|
+
vertical ? "flex-col items-start gap-xxs" : "items-center gap-xs",
|
|
57
|
+
underlineRow && "gap-0 border-b border-border-secondary",
|
|
58
|
+
className,
|
|
59
|
+
)}
|
|
60
|
+
>
|
|
61
|
+
{items.map((item) => (
|
|
62
|
+
<TabButtonBase
|
|
63
|
+
key={item.value}
|
|
64
|
+
role="tab"
|
|
65
|
+
variant={resolved}
|
|
66
|
+
size={size}
|
|
67
|
+
current={item.value === value}
|
|
68
|
+
aria-selected={item.value === value}
|
|
69
|
+
disabled={item.disabled}
|
|
70
|
+
icon={item.icon}
|
|
71
|
+
badge={item.badge}
|
|
72
|
+
onClick={() => onValueChange?.(item.value)}
|
|
73
|
+
className={clsx(fullWidth && !vertical && "flex-1", vertical && "w-full justify-start")}
|
|
74
|
+
>
|
|
75
|
+
{item.label}
|
|
76
|
+
</TabButtonBase>
|
|
77
|
+
))}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|