@borisj74/bv-ds 0.1.2 → 0.1.4

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.
Files changed (46) hide show
  1. package/dist/index.cjs +266 -69
  2. package/dist/index.d.cts +128 -49
  3. package/dist/index.d.ts +128 -49
  4. package/dist/index.js +266 -70
  5. package/package.json +11 -9
  6. package/src/components/Button/Button.tsx +1 -1
  7. package/src/components/ButtonDestructive/ButtonDestructive.tsx +2 -2
  8. package/src/components/CalendarCell/CalendarCell.tsx +63 -10
  9. package/src/components/CalendarCell/index.ts +5 -1
  10. package/src/components/CalendarCellDayWeekView/CalendarCellDayWeekView.tsx +28 -2
  11. package/src/components/CalendarCellDayWeekView/index.ts +5 -1
  12. package/src/components/CalendarColumnHeader/CalendarColumnHeader.tsx +21 -5
  13. package/src/components/CalendarColumnHeader/index.ts +2 -0
  14. package/src/components/CalendarEvent/CalendarEvent.tsx +69 -14
  15. package/src/components/CalendarEvent/index.ts +6 -1
  16. package/src/components/CalendarHeader/CalendarHeader.tsx +5 -1
  17. package/src/components/CalendarRowLabel/CalendarRowLabel.tsx +5 -3
  18. package/src/components/CalendarTimemarker/CalendarTimemarker.tsx +8 -2
  19. package/src/components/CalendarTimemarker/index.ts +1 -0
  20. package/src/components/CalendarViewDropdown/CalendarViewDropdown.tsx +19 -3
  21. package/src/components/ChartTooltip/ChartTooltip.tsx +1 -1
  22. package/src/components/Checkbox/checkboxBase.tsx +1 -1
  23. package/src/components/ContentFeatureText/ContentFeatureText.tsx +3 -2
  24. package/src/components/ContextMenu/ContextMenu.tsx +1 -1
  25. package/src/components/FeaturedIcon/FeaturedIcon.tsx +146 -0
  26. package/src/components/FeaturedIcon/index.ts +7 -0
  27. package/src/components/MessageAction/MessageAction.tsx +1 -1
  28. package/src/components/NavAccountCard/NavAccountCard.tsx +1 -1
  29. package/src/components/NavAccountCardMenuItem/NavAccountCardMenuItem.tsx +1 -1
  30. package/src/components/NavButton/NavButton.tsx +1 -1
  31. package/src/components/NavFeaturedCard/NavFeaturedCard.tsx +1 -1
  32. package/src/components/NavItemBase/NavItemBase.tsx +1 -1
  33. package/src/components/NavItemDropdownBase/NavItemDropdownBase.tsx +1 -1
  34. package/src/components/PageHeader/PageHeader.tsx +1 -1
  35. package/src/components/PaginationDotIndicator/PaginationDotIndicator.tsx +1 -1
  36. package/src/components/ProgressBar/ProgressBar.tsx +1 -1
  37. package/src/components/RadioGroupItem/RadioGroupItem.tsx +1 -1
  38. package/src/components/SelectMenuItem/SelectMenuItem.tsx +2 -2
  39. package/src/components/SidebarNavigation/SidebarNavigation.tsx +1 -1
  40. package/src/components/SocialButton/SocialButton.tsx +2 -2
  41. package/src/components/TableHeaderLabel/TableHeaderLabel.tsx +1 -1
  42. package/src/components/Toggle/Toggle.tsx +1 -1
  43. package/src/components/Tooltip/Tooltip.tsx +1 -1
  44. package/src/components/TreeViewItem/TreeViewItem.tsx +1 -1
  45. package/src/components/VerificationCodeInput/VerificationCodeInput.tsx +1 -1
  46. package/src/index.ts +1 -0
@@ -0,0 +1,146 @@
1
+ import React from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type FeaturedIconColor =
5
+ | "brand"
6
+ | "gray"
7
+ | "error"
8
+ | "warning"
9
+ | "success";
10
+
11
+ export type FeaturedIconTheme =
12
+ | "light"
13
+ | "dark"
14
+ | "gradient"
15
+ | "modern"
16
+ | "modern-neue";
17
+
18
+ export type FeaturedIconSize = "sm" | "md" | "lg" | "xl";
19
+
20
+ // `color` is Omitted because the native HTMLAttributes `color` prop collides
21
+ // with our richer FeaturedIconColor union (see claude.md interface-collision rule).
22
+ export interface FeaturedIconProps
23
+ extends Omit<React.HTMLAttributes<HTMLSpanElement>, "color"> {
24
+ /** Icon element (e.g. from @borisj74/bv-ds-icons). Inherits currentColor. */
25
+ icon: React.ReactNode;
26
+ color?: FeaturedIconColor;
27
+ theme?: FeaturedIconTheme;
28
+ size?: FeaturedIconSize;
29
+ }
30
+
31
+ // Confirmed from Figma node 1102:5338 (Misc icons page, batch 30).
32
+ // container px → size-N (32/40/48/56); icon px → wrapper span width/height.
33
+ const boxSize: Record<FeaturedIconSize, string> = {
34
+ sm: "size-8", // 32px
35
+ md: "size-10", // 40px
36
+ lg: "size-12", // 48px
37
+ xl: "size-14", // 56px
38
+ };
39
+
40
+ const iconPx: Record<FeaturedIconSize, number> = {
41
+ sm: 16,
42
+ md: 20,
43
+ lg: 24,
44
+ xl: 28,
45
+ };
46
+
47
+ // Light theme = the only circular treatment; modern-neue = 10px (radius-lg);
48
+ // every other theme = 12px (radius-xl).
49
+ function radiusFor(theme: FeaturedIconTheme): string {
50
+ if (theme === "light") return "rounded-full";
51
+ if (theme === "modern-neue") return "rounded-lg";
52
+ return "rounded-xl";
53
+ }
54
+
55
+ // Light: tinted secondary bg + colour-matched icon (fg). Gray maps to the
56
+ // neutral semantic layer (no dedicated gray featured token in the preset).
57
+ const lightBg: Record<FeaturedIconColor, string> = {
58
+ brand: "bg-bg-brand-secondary",
59
+ gray: "bg-bg-secondary",
60
+ error: "bg-bg-error-secondary",
61
+ warning: "bg-bg-warning-secondary",
62
+ success: "bg-bg-success-secondary",
63
+ };
64
+
65
+ const lightFg: Record<FeaturedIconColor, string> = {
66
+ brand: "text-fg-brand-primary",
67
+ gray: "text-fg-secondary",
68
+ error: "text-fg-error-primary",
69
+ warning: "text-fg-warning-primary",
70
+ success: "text-fg-success-primary",
71
+ };
72
+
73
+ // Dark: solid bg + white icon + skeuomorphic shadow + a 2px white/12 highlight
74
+ // border (arbitrary value — no Figma variable). Gray uses the secondary solid.
75
+ const darkBg: Record<FeaturedIconColor, string> = {
76
+ brand: "bg-bg-brand-solid",
77
+ gray: "bg-bg-secondary-solid",
78
+ error: "bg-bg-error-solid",
79
+ warning: "bg-bg-warning-solid",
80
+ success: "bg-bg-success-solid",
81
+ };
82
+
83
+ // Gradient: 2-stop diagonal fill (utility-{family}-50 → -200) + white icon.
84
+ const gradientFill: Record<FeaturedIconColor, string> = {
85
+ brand: "bg-gradient-to-br from-utility-brand-50 to-utility-brand-200",
86
+ gray: "bg-gradient-to-br from-utility-neutral-50 to-utility-neutral-200",
87
+ error: "bg-gradient-to-br from-utility-red-50 to-utility-red-200",
88
+ warning: "bg-gradient-to-br from-utility-amber-50 to-utility-amber-200",
89
+ success: "bg-gradient-to-br from-utility-green-50 to-utility-green-200",
90
+ };
91
+
92
+ /**
93
+ * FeaturedIcon — Untitled UI "Featured icon" (node 1102:5338).
94
+ *
95
+ * A coloured container wrapping an icon, used by Empty state, Alert, Metric,
96
+ * Notification, etc. Pass the icon via the `icon` slot — it inherits
97
+ * currentColor, so no fill/stroke props are needed.
98
+ *
99
+ * `modern` and `modern-neue` are neutral white-card treatments (gray-only in
100
+ * Figma); the `color` prop is ignored for those two themes.
101
+ */
102
+ export function FeaturedIcon({
103
+ icon,
104
+ color = "brand",
105
+ theme = "light",
106
+ size = "md",
107
+ className,
108
+ ...rest
109
+ }: FeaturedIconProps) {
110
+ const px = iconPx[size];
111
+
112
+ const themeClasses = clsx(
113
+ theme === "light" && [lightBg[color], lightFg[color]],
114
+ theme === "dark" && [
115
+ darkBg[color],
116
+ "text-fg-white border-2 border-[rgba(255,255,255,0.12)] shadow-skeuomorphic",
117
+ ],
118
+ theme === "gradient" && [gradientFill[color], "text-fg-white"],
119
+ theme === "modern" && [
120
+ "bg-bg-primary text-fg-secondary border border-border-primary shadow-skeuomorphic",
121
+ ],
122
+ theme === "modern-neue" && [
123
+ "bg-bg-primary text-fg-secondary border border-border-primary shadow-xs",
124
+ ],
125
+ );
126
+
127
+ return (
128
+ <span
129
+ className={clsx(
130
+ "inline-flex shrink-0 items-center justify-center",
131
+ boxSize[size],
132
+ radiusFor(theme),
133
+ themeClasses,
134
+ className,
135
+ )}
136
+ {...rest}
137
+ >
138
+ <span
139
+ aria-hidden="true"
140
+ style={{ width: px, height: px, display: "inline-flex" }}
141
+ >
142
+ {icon}
143
+ </span>
144
+ </span>
145
+ );
146
+ }
@@ -0,0 +1,7 @@
1
+ export { FeaturedIcon } from "./FeaturedIcon";
2
+ export type {
3
+ FeaturedIconProps,
4
+ FeaturedIconColor,
5
+ FeaturedIconTheme,
6
+ FeaturedIconSize,
7
+ } from "./FeaturedIcon";
@@ -100,7 +100,7 @@ const inputBox =
100
100
  * - **minimal** — single-line field + square send button (row).
101
101
  * - **textarea** — multiline box, attach/emoji + brand Send pinned bottom-right,
102
102
  * record button top-right.
103
- * - **advanced** — AI prompt box on `bg-secondary`; author chip + Shortcuts/Attach
103
+ * - **advanced** — AI prompt box on `bg-bg-secondary`; author chip + Shortcuts/Attach
104
104
  * footer, mic top-right, resize handle.
105
105
  *
106
106
  * Renders real `<input>`/`<textarea>` (controlled via `value`/`onValueChange`);
@@ -86,7 +86,7 @@ const AvatarLabel = ({ avatar, name, email }: { avatar?: ReactNode; name?: React
86
86
  * with a sign-out button; `card` renders a boxed trigger that, when `open`,
87
87
  * reveals a dropdown (the `menu` slot — compose `NavAccountCardMenuItem` rows).
88
88
  *
89
- * The active account is marked with `bg-brand-solid` (the radio inside the
89
+ * The active account is marked with `bg-bg-brand-solid` (the radio inside the
90
90
  * account menu items). Note: Figma opens the desktop menu as a right-side
91
91
  * flyout; this opens it above the trigger (`bottom-full`) — a layout
92
92
  * simplification (see figma-map). Width defaults to 280px; override via
@@ -27,7 +27,7 @@ export interface NavAccountCardMenuItemProps
27
27
  * A single row inside `NavAccountCard`'s dropdown. Two shapes:
28
28
  * - `menu-item` — icon + label + optional shortcut chip (View profile, Settings…).
29
29
  * - `account` — avatar + name/email with a radio indicator; `current` fills the
30
- * radio with `bg-brand-solid` (the active-account marker).
30
+ * radio with `bg-bg-brand-solid` (the active-account marker).
31
31
  */
32
32
  export function NavAccountCardMenuItem({
33
33
  type = "menu-item",
@@ -3,7 +3,7 @@ import clsx from "clsx";
3
3
 
4
4
  export interface NavButtonProps
5
5
  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
6
- /** Active route — applies the selected (`bg-secondary`) background. */
6
+ /** Active route — applies the selected (`bg-bg-secondary`) background. */
7
7
  current?: boolean;
8
8
  /** Render only the leading icon (square button). */
9
9
  iconOnly?: boolean;
@@ -11,7 +11,7 @@ export interface NavFeaturedCardProps
11
11
  children?: ReactNode;
12
12
  /** CTA row — compose Button(s) / link buttons. */
13
13
  action?: ReactNode;
14
- /** Bordered surface (`bg-primary` + border) vs subtle (`bg-secondary`). */
14
+ /** Bordered surface (`bg-bg-primary` + border) vs subtle (`bg-bg-secondary`). */
15
15
  bordered?: boolean;
16
16
  /** Renders an x-close button top-right. */
17
17
  onClose?: () => void;
@@ -3,7 +3,7 @@ import clsx from "clsx";
3
3
 
4
4
  export interface NavItemBaseProps
5
5
  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
6
- /** Active route — selected (`bg-secondary`) background. */
6
+ /** Active route — selected (`bg-bg-secondary`) background. */
7
7
  current?: boolean;
8
8
  /** Leading icon (20px). */
9
9
  icon?: ReactNode;
@@ -3,7 +3,7 @@ import clsx from "clsx";
3
3
 
4
4
  export interface NavItemDropdownBaseProps
5
5
  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
6
- /** Active group — selected (`bg-secondary`) background on the trigger. */
6
+ /** Active group — selected (`bg-bg-secondary`) background on the trigger. */
7
7
  current?: boolean;
8
8
  /** Expanded state — reveals the submenu. */
9
9
  open?: boolean;
@@ -20,7 +20,7 @@ export interface PageHeaderProps
20
20
  actions?: ReactNode;
21
21
  /** Optional breadcrumbs slot above the title. */
22
22
  breadcrumbs?: ReactNode;
23
- /** Banner background image (banner styles); falls back to `bg-tertiary`. */
23
+ /** Banner background image (banner styles); falls back to `bg-bg-tertiary`. */
24
24
  bannerUrl?: string;
25
25
  }
26
26
 
@@ -13,7 +13,7 @@ export interface PaginationDotIndicatorProps
13
13
 
14
14
  /**
15
15
  * Single pagination indicator — a dot or a line. `current` fills it with the
16
- * brand colour, otherwise `bg-quaternary`. Dimensions per size/variant match
16
+ * brand colour, otherwise `bg-bg-quaternary`. Dimensions per size/variant match
17
17
  * Figma (dot md 8 / lg 10; line md h6 / lg h8, both 40 wide).
18
18
  */
19
19
  export function PaginationDotIndicator({
@@ -32,7 +32,7 @@ const Bubble = ({ pct, where }: { pct: number; where: "top" | "bottom" }) => (
32
32
 
33
33
  /**
34
34
  * Progress bar — pure CSS, no chart lib. `value` (0–100) drives an animated fill
35
- * (`fg-brand-primary` on a `bg-quaternary` track). `label`: none / right (inline
35
+ * (`fg-brand-primary` on a `bg-bg-quaternary` track). `label`: none / right (inline
36
36
  * %) / bottom (% under) / top|bottom-floating (tooltip bubble tracking the fill).
37
37
  */
38
38
  export function ProgressBar({ value, label = "none", className, ...rest }: ProgressBarProps) {
@@ -50,7 +50,7 @@ function Control({ kind, selected, size }: { kind: "radio" | "checkbox"; selecte
50
50
 
51
51
  /**
52
52
  * Selectable radio/checkbox card. One component over the 6 Figma `type`s — the
53
- * shared shell (border, padding, `radius-xl`, selected `border-brand`) is
53
+ * shared shell (border, padding, `radius-xl`, selected `border-border-brand`) is
54
54
  * constant; only the leading element and control placement change. `radioButton`
55
55
  * uses a radio (leading); `checkbox` a checkbox (leading); `iconSimple`/`avatar`/
56
56
  * `paymentIcon` put a `leading` visual on the left and the checkbox trailing;
@@ -40,8 +40,8 @@ function CheckboxBox({ selected, big }: { selected: boolean; big: boolean }) {
40
40
  /**
41
41
  * List-item primitive for `Select` and Multi-select dropdowns. One component over
42
42
  * both: `multi` swaps the trailing selected-check for a leading checkbox. The
43
- * shared shell is a full-width row with hover `bg-primary-hover`; `label` is
44
- * `text-primary`, `supportingText` sits inline in `text-tertiary`.
43
+ * shared shell is a full-width row with hover `bg-bg-primary-hover`; `label` is
44
+ * `text-text-primary`, `supportingText` sits inline in `text-text-tertiary`.
45
45
  */
46
46
  export function SelectMenuItem({
47
47
  label,
@@ -37,7 +37,7 @@ const WIDTH: Record<SidebarNavigationType, string> = {
37
37
  * a fixed-width rail (`slim` collapses to 68px). Composes existing `Nav*`
38
38
  * components via slots/children — it does not reimplement nav items. On mobile
39
39
  * the rail is hidden behind a hamburger (`NavMenuButton`); opening it shows a
40
- * `bg-overlay` + `backdrop-blur-md` scrim and slides the rail in as a drawer.
40
+ * `bg-bg-overlay` + `backdrop-blur-md` scrim and slides the rail in as a drawer.
41
41
  *
42
42
  * NOTE: `dualTier`'s icon-rail + expanding-panel split is simplified to a single
43
43
  * 280px column here — compose the icon rail separately if you need the two-tier
@@ -51,8 +51,8 @@ const GLYPH: Record<SocialBrand, ReactNode> = {
51
51
  };
52
52
 
53
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:
54
+ * Social-login button. All themes share the neutral white shell (border-border-primary,
55
+ * shadow-xs, `text-text-secondary` label) — `theme` only controls the brand glyph:
56
56
  * `color`/`brand` = full color, `gray` = monochrome (CSS grayscale, flagged
57
57
  * approximation of UntitledUI's true single-color gray logos). `iconOnly` drops
58
58
  * the label for a square button.
@@ -22,7 +22,7 @@ function ArrowIcon({ arrow }: { arrow: Exclude<TableHeaderLabelArrow, "none"> })
22
22
  }
23
23
 
24
24
  /**
25
- * Column-header label — `text-xs` semibold in `text-quaternary` (→ `text-tertiary`
25
+ * Column-header label — `text-xs` semibold in `text-text-quaternary` (→ `text-text-tertiary`
26
26
  * on hover), with an optional sort `arrow` and trailing `helpIcon` slot. Consumed
27
27
  * by `TableHeaderCell`.
28
28
  */
@@ -22,7 +22,7 @@ const KNOB: Record<ToggleSize, string> = { sm: "size-4", md: "size-5" };
22
22
  const TRAVEL: Record<ToggleSize, string> = { sm: "translate-x-4", md: "translate-x-5" };
23
23
 
24
24
  /**
25
- * Switch toggle. `default` = filled track (`bg-brand-solid` when on); `slim` = a
25
+ * Switch toggle. `default` = filled track (`bg-bg-brand-solid` when on); `slim` = a
26
26
  * thinner track with a bordered knob (uses the `toggle-slim-border-pressed`
27
27
  * tokens when on). The `_Toggle base` control is inline (not a separate export).
28
28
  * Controlled via `checked`/`onCheckedChange`; optional `label`/`supportingText`.
@@ -30,7 +30,7 @@ const ARROW_POS: Record<Exclude<TooltipArrow, "none">, string> = {
30
30
  };
31
31
 
32
32
  /**
33
- * Presentational tooltip bubble (dark `bg-primary-solid`, white text). `text` is
33
+ * Presentational tooltip bubble (dark `bg-bg-primary-solid`, white text). `text` is
34
34
  * the heading; `supportingText` adds a second `utility-neutral-300` line (max
35
35
  * 296px). `arrow` positions a small pointer on the bubble edge (rendered as a
36
36
  * rotated square). Positioning relative to a trigger is the caller's job.
@@ -27,7 +27,7 @@ export interface TreeViewItemProps extends Omit<HTMLAttributes<HTMLDivElement>,
27
27
  /**
28
28
  * One row of a `TreeView`. Composes `TreeViewConnector` for the `level` indent
29
29
  * guides, plus an optional expand chevron, `checkbox`, `icon` and label. Selected
30
- * → `bg-secondary`; hover → `bg-primary-hover`. Width is fluid (parent controls).
30
+ * → `bg-bg-secondary`; hover → `bg-bg-primary-hover`. Width is fluid (parent controls).
31
31
  */
32
32
  export function TreeViewItem({
33
33
  size = "sm",
@@ -27,7 +27,7 @@ const CELL: Record<VerificationCodeSize, string> = {
27
27
  * OTP-style verification code input. `digits` 4 or 6 separate single-character
28
28
  * cells (6 shows a centre "-" separator); large display typography
29
29
  * (`display-lg`/`display-xl`). Controlled via `value`/`onChange`; auto-advances
30
- * focus on entry and steps back on backspace. Cell borders use `border-primary`
30
+ * focus on entry and steps back on backspace. Cell borders use `border-border-primary`
31
31
  * (= `utility-neutral-300` #d4d4d4, same value).
32
32
  */
33
33
  export function VerificationCodeInput({
package/src/index.ts CHANGED
@@ -62,6 +62,7 @@ export * from "./components/DropdownMenuHeader";
62
62
  export * from "./components/DropdownMenuItemInsetIcon";
63
63
  export * from "./components/DropdownMenuListItem";
64
64
  export * from "./components/EmptyState";
65
+ export * from "./components/FeaturedIcon";
65
66
  export * from "./components/FeedItemBase";
66
67
  export * from "./components/FileUpload";
67
68
  export * from "./components/FileUploadBase";