@borisj74/bv-ds 0.1.5 → 0.1.6

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/dist/index.cjs CHANGED
@@ -3844,7 +3844,7 @@ var require_factoryWithTypeCheckers = __commonJS({
3844
3844
  function emptyFunctionThatReturnsNull() {
3845
3845
  return null;
3846
3846
  }
3847
- module.exports = function(isValidElement12, throwOnDirectAccess) {
3847
+ module.exports = function(isValidElement13, throwOnDirectAccess) {
3848
3848
  var ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator;
3849
3849
  var FAUX_ITERATOR_SYMBOL = "@@iterator";
3850
3850
  function getIteratorFn(maybeIterable) {
@@ -3972,7 +3972,7 @@ var require_factoryWithTypeCheckers = __commonJS({
3972
3972
  function createElementTypeChecker() {
3973
3973
  function validate(props, propName, componentName, location, propFullName) {
3974
3974
  var propValue = props[propName];
3975
- if (!isValidElement12(propValue)) {
3975
+ if (!isValidElement13(propValue)) {
3976
3976
  var propType = getPropType(propValue);
3977
3977
  return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + propType + "` supplied to `" + componentName + "`, expected a single ReactElement."));
3978
3978
  }
@@ -4160,7 +4160,7 @@ var require_factoryWithTypeCheckers = __commonJS({
4160
4160
  if (Array.isArray(propValue)) {
4161
4161
  return propValue.every(isNode);
4162
4162
  }
4163
- if (propValue === null || isValidElement12(propValue)) {
4163
+ if (propValue === null || isValidElement13(propValue)) {
4164
4164
  return true;
4165
4165
  }
4166
4166
  var iteratorFn = getIteratorFn(propValue);
@@ -31957,7 +31957,20 @@ function MultiSelect({
31957
31957
  hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx_default("text-sm", invalid ? "text-text-error-primary" : "text-text-tertiary"), children: hint })
31958
31958
  ] });
31959
31959
  }
31960
- var IconBox16 = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "overflow-clip relative shrink-0 size-[16px] flex items-center justify-center", children });
31960
+ function IconBox({ size = 20, className, children }) {
31961
+ const icon = React28.isValidElement(children) ? React28.cloneElement(children, {
31962
+ viewBox: children.props.viewBox ?? "0 0 24 24",
31963
+ className: clsx_default("w-full h-full", children.props.className)
31964
+ }) : children;
31965
+ return /* @__PURE__ */ jsxRuntime.jsx(
31966
+ "span",
31967
+ {
31968
+ className: clsx_default("relative flex shrink-0 items-center justify-center", className),
31969
+ style: { width: size, height: size },
31970
+ children: icon
31971
+ }
31972
+ );
31973
+ }
31961
31974
  var LayeredAvatar = ({ src, online }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex size-10 shrink-0 rounded-full border-[0.75px] border-border-secondary-alt bg-bg-primary p-[1px] shadow-xs", children: [
31962
31975
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-full overflow-hidden rounded-full border-[0.5px] border-[rgba(0,0,0,0.16)]", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: "", className: "size-full rounded-full object-cover" }) }),
31963
31976
  online !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
@@ -31992,7 +32005,7 @@ function NavAccountCard({
31992
32005
  className,
31993
32006
  ...rest
31994
32007
  }) {
31995
- const widthClass = breakpoint === "mobile" ? "w-[256px]" : "w-[280px]";
32008
+ const widthClass = breakpoint === "mobile" ? "w-full max-w-[256px]" : "w-full max-w-[280px]";
31996
32009
  const avatarNode = avatar ?? (src !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(LayeredAvatar, { src, online }) : void 0);
31997
32010
  if (variant === "simple") {
31998
32011
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -32013,7 +32026,7 @@ function NavAccountCard({
32013
32026
  onClick: onSignOut,
32014
32027
  "aria-label": "Sign out",
32015
32028
  className: "absolute right-0 top-[15px] flex items-center justify-center rounded-sm p-sm text-fg-quaternary transition-colors hover:text-fg-quaternary-hover",
32016
- children: /* @__PURE__ */ jsxRuntime.jsx(IconBox16, { children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.LogOut01, { className: "w-full h-full" }) })
32029
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 16, children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.LogOut01, {}) })
32017
32030
  }
32018
32031
  )
32019
32032
  ]
@@ -32036,7 +32049,7 @@ function NavAccountCard({
32036
32049
  "absolute right-[7px] top-[7px] flex items-center justify-center rounded-sm p-sm text-fg-quaternary",
32037
32050
  open && "bg-bg-primary-hover"
32038
32051
  ),
32039
- children: /* @__PURE__ */ jsxRuntime.jsx(IconBox16, { children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.ChevronSelectorVertical, { className: "w-full h-full" }) })
32052
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 16, children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.ChevronSelectorVertical, {}) })
32040
32053
  }
32041
32054
  )
32042
32055
  ]
@@ -32193,7 +32206,7 @@ function NavItemBase({
32193
32206
  {
32194
32207
  type,
32195
32208
  className: clsx_default(
32196
- "flex w-[272px] items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32209
+ "flex w-full items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32197
32210
  className
32198
32211
  ),
32199
32212
  ...rest,
@@ -32207,11 +32220,11 @@ function NavItemBase({
32207
32220
  children: [
32208
32221
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-md", children: [
32209
32222
  dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-2 shrink-0 rounded-full bg-fg-success-secondary" }),
32210
- icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-5 shrink-0 items-center justify-center text-fg-quaternary [&>svg]:size-5", children: icon }),
32223
+ icon && /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 20, className: "text-fg-quaternary", children: icon }),
32211
32224
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-left text-sm font-semibold text-text-secondary", children: label })
32212
32225
  ] }),
32213
32226
  badge != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded-full border border-utility-neutral-200 bg-utility-neutral-50 px-md py-xxs text-xs font-medium text-utility-neutral-700", children: badge }),
32214
- trailingChevron && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-fg-quaternary", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "overflow-clip relative shrink-0 size-[16px] flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.ChevronDown, { className: "w-full h-full" }) }) })
32227
+ trailingChevron && /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 16, className: "text-fg-quaternary", children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.ChevronDown, {}) })
32215
32228
  ]
32216
32229
  }
32217
32230
  )
@@ -32229,13 +32242,13 @@ function NavItemDropdownBase({
32229
32242
  type = "button",
32230
32243
  ...rest
32231
32244
  }) {
32232
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx_default("flex w-[272px] flex-col", className), children: [
32245
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx_default("flex w-full flex-col", className), children: [
32233
32246
  /* @__PURE__ */ jsxRuntime.jsx(
32234
32247
  "button",
32235
32248
  {
32236
32249
  type,
32237
32250
  onClick: onToggle,
32238
- className: "flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32251
+ className: "flex w-full items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32239
32252
  ...rest,
32240
32253
  children: /* @__PURE__ */ jsxRuntime.jsxs(
32241
32254
  "div",
@@ -32246,15 +32259,10 @@ function NavItemDropdownBase({
32246
32259
  ),
32247
32260
  children: [
32248
32261
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-md", children: [
32249
- icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-5 shrink-0 items-center justify-center text-fg-quaternary [&>svg]:size-5", children: icon }),
32262
+ icon && /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 20, className: "text-fg-quaternary", children: icon }),
32250
32263
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-left text-sm font-semibold text-text-secondary", children: label })
32251
32264
  ] }),
32252
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-fg-quaternary", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "overflow-clip relative shrink-0 size-[16px] flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
32253
- bvDsIcons.ChevronDown,
32254
- {
32255
- className: clsx_default("w-full h-full transition-transform", open && "rotate-180")
32256
- }
32257
- ) }) })
32265
+ /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 16, className: "text-fg-quaternary", children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.ChevronDown, { className: clsx_default("transition-transform", open && "rotate-180") }) })
32258
32266
  ]
32259
32267
  }
32260
32268
  )
@@ -32263,7 +32271,6 @@ function NavItemDropdownBase({
32263
32271
  open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col pb-xs", children })
32264
32272
  ] });
32265
32273
  }
32266
- var IconBox = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "overflow-clip relative shrink-0 size-[20px] flex items-center justify-center", children });
32267
32274
  function NavMenuButton({
32268
32275
  opened = false,
32269
32276
  className,
@@ -32282,7 +32289,7 @@ function NavMenuButton({
32282
32289
  className
32283
32290
  ),
32284
32291
  ...rest,
32285
- children: opened ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-70", children: /* @__PURE__ */ jsxRuntime.jsx(IconBox, { children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.XClose, { className: "w-full h-full" }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(IconBox, { children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.Menu02, { className: "w-full h-full" }) })
32292
+ children: opened ? /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 20, className: "opacity-70", children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.XClose, {}) }) : /* @__PURE__ */ jsxRuntime.jsx(IconBox, { size: 20, children: /* @__PURE__ */ jsxRuntime.jsx(bvDsIcons.Menu02, {}) })
32286
32293
  }
32287
32294
  );
32288
32295
  }
@@ -33131,17 +33138,20 @@ function SidebarNavigation({
33131
33138
  "nav",
33132
33139
  {
33133
33140
  className: clsx_default(
33141
+ // Padding is applied per-section (Figma node 1161:8593): header 20px,
33142
+ // nav items 16px, footer 16px/20px — not a uniform rail inset, so the
33143
+ // full-width nav items align to their own 16px gutter without clipping.
33134
33144
  "flex h-full flex-col gap-2xl border-r border-border-secondary bg-bg-primary",
33135
- slim ? "items-center px-md py-xl" : "px-lg py-xl",
33145
+ slim ? "items-center px-md py-xl" : "py-xl",
33136
33146
  WIDTH[type],
33137
33147
  className
33138
33148
  ),
33139
33149
  ...rest,
33140
33150
  children: [
33141
- logo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx_default("shrink-0", slim ? "" : "px-md"), children: logo }),
33142
- header && !slim && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: header }),
33143
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-xxs overflow-y-auto", children }),
33144
- footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 flex-col gap-lg", children: footer })
33151
+ logo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx_default("shrink-0", slim ? "" : "px-2xl"), children: logo }),
33152
+ header && !slim && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 px-2xl", children: header }),
33153
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx_default("flex min-h-0 flex-1 flex-col gap-xxs overflow-y-auto", !slim && "px-xl"), children }),
33154
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx_default("flex shrink-0 flex-col gap-lg", !slim && "px-xl"), children: footer })
33145
33155
  ]
33146
33156
  }
33147
33157
  );
package/dist/index.js CHANGED
@@ -3823,7 +3823,7 @@ var require_factoryWithTypeCheckers = __commonJS({
3823
3823
  function emptyFunctionThatReturnsNull() {
3824
3824
  return null;
3825
3825
  }
3826
- module.exports = function(isValidElement12, throwOnDirectAccess) {
3826
+ module.exports = function(isValidElement13, throwOnDirectAccess) {
3827
3827
  var ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator;
3828
3828
  var FAUX_ITERATOR_SYMBOL = "@@iterator";
3829
3829
  function getIteratorFn(maybeIterable) {
@@ -3951,7 +3951,7 @@ var require_factoryWithTypeCheckers = __commonJS({
3951
3951
  function createElementTypeChecker() {
3952
3952
  function validate(props, propName, componentName, location, propFullName) {
3953
3953
  var propValue = props[propName];
3954
- if (!isValidElement12(propValue)) {
3954
+ if (!isValidElement13(propValue)) {
3955
3955
  var propType = getPropType(propValue);
3956
3956
  return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + propType + "` supplied to `" + componentName + "`, expected a single ReactElement."));
3957
3957
  }
@@ -4139,7 +4139,7 @@ var require_factoryWithTypeCheckers = __commonJS({
4139
4139
  if (Array.isArray(propValue)) {
4140
4140
  return propValue.every(isNode);
4141
4141
  }
4142
- if (propValue === null || isValidElement12(propValue)) {
4142
+ if (propValue === null || isValidElement13(propValue)) {
4143
4143
  return true;
4144
4144
  }
4145
4145
  var iteratorFn = getIteratorFn(propValue);
@@ -31936,7 +31936,20 @@ function MultiSelect({
31936
31936
  hint && /* @__PURE__ */ jsx("span", { className: clsx_default("text-sm", invalid ? "text-text-error-primary" : "text-text-tertiary"), children: hint })
31937
31937
  ] });
31938
31938
  }
31939
- var IconBox16 = ({ children }) => /* @__PURE__ */ jsx("span", { className: "overflow-clip relative shrink-0 size-[16px] flex items-center justify-center", children });
31939
+ function IconBox({ size = 20, className, children }) {
31940
+ const icon = isValidElement(children) ? cloneElement(children, {
31941
+ viewBox: children.props.viewBox ?? "0 0 24 24",
31942
+ className: clsx_default("w-full h-full", children.props.className)
31943
+ }) : children;
31944
+ return /* @__PURE__ */ jsx(
31945
+ "span",
31946
+ {
31947
+ className: clsx_default("relative flex shrink-0 items-center justify-center", className),
31948
+ style: { width: size, height: size },
31949
+ children: icon
31950
+ }
31951
+ );
31952
+ }
31940
31953
  var LayeredAvatar = ({ src, online }) => /* @__PURE__ */ jsxs("span", { className: "relative inline-flex size-10 shrink-0 rounded-full border-[0.75px] border-border-secondary-alt bg-bg-primary p-[1px] shadow-xs", children: [
31941
31954
  /* @__PURE__ */ jsx("span", { className: "flex size-full overflow-hidden rounded-full border-[0.5px] border-[rgba(0,0,0,0.16)]", children: /* @__PURE__ */ jsx("img", { src, alt: "", className: "size-full rounded-full object-cover" }) }),
31942
31955
  online !== void 0 && /* @__PURE__ */ jsx(
@@ -31971,7 +31984,7 @@ function NavAccountCard({
31971
31984
  className,
31972
31985
  ...rest
31973
31986
  }) {
31974
- const widthClass = breakpoint === "mobile" ? "w-[256px]" : "w-[280px]";
31987
+ const widthClass = breakpoint === "mobile" ? "w-full max-w-[256px]" : "w-full max-w-[280px]";
31975
31988
  const avatarNode = avatar ?? (src !== void 0 ? /* @__PURE__ */ jsx(LayeredAvatar, { src, online }) : void 0);
31976
31989
  if (variant === "simple") {
31977
31990
  return /* @__PURE__ */ jsxs(
@@ -31992,7 +32005,7 @@ function NavAccountCard({
31992
32005
  onClick: onSignOut,
31993
32006
  "aria-label": "Sign out",
31994
32007
  className: "absolute right-0 top-[15px] flex items-center justify-center rounded-sm p-sm text-fg-quaternary transition-colors hover:text-fg-quaternary-hover",
31995
- children: /* @__PURE__ */ jsx(IconBox16, { children: /* @__PURE__ */ jsx(LogOut01, { className: "w-full h-full" }) })
32008
+ children: /* @__PURE__ */ jsx(IconBox, { size: 16, children: /* @__PURE__ */ jsx(LogOut01, {}) })
31996
32009
  }
31997
32010
  )
31998
32011
  ]
@@ -32015,7 +32028,7 @@ function NavAccountCard({
32015
32028
  "absolute right-[7px] top-[7px] flex items-center justify-center rounded-sm p-sm text-fg-quaternary",
32016
32029
  open && "bg-bg-primary-hover"
32017
32030
  ),
32018
- children: /* @__PURE__ */ jsx(IconBox16, { children: /* @__PURE__ */ jsx(ChevronSelectorVertical, { className: "w-full h-full" }) })
32031
+ children: /* @__PURE__ */ jsx(IconBox, { size: 16, children: /* @__PURE__ */ jsx(ChevronSelectorVertical, {}) })
32019
32032
  }
32020
32033
  )
32021
32034
  ]
@@ -32172,7 +32185,7 @@ function NavItemBase({
32172
32185
  {
32173
32186
  type,
32174
32187
  className: clsx_default(
32175
- "flex w-[272px] items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32188
+ "flex w-full items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32176
32189
  className
32177
32190
  ),
32178
32191
  ...rest,
@@ -32186,11 +32199,11 @@ function NavItemBase({
32186
32199
  children: [
32187
32200
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-md", children: [
32188
32201
  dot && /* @__PURE__ */ jsx("span", { className: "size-2 shrink-0 rounded-full bg-fg-success-secondary" }),
32189
- icon && /* @__PURE__ */ jsx("span", { className: "flex size-5 shrink-0 items-center justify-center text-fg-quaternary [&>svg]:size-5", children: icon }),
32202
+ icon && /* @__PURE__ */ jsx(IconBox, { size: 20, className: "text-fg-quaternary", children: icon }),
32190
32203
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left text-sm font-semibold text-text-secondary", children: label })
32191
32204
  ] }),
32192
32205
  badge != null && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full border border-utility-neutral-200 bg-utility-neutral-50 px-md py-xxs text-xs font-medium text-utility-neutral-700", children: badge }),
32193
- trailingChevron && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-fg-quaternary", children: /* @__PURE__ */ jsx("span", { className: "overflow-clip relative shrink-0 size-[16px] flex items-center justify-center", children: /* @__PURE__ */ jsx(ChevronDown$1, { className: "w-full h-full" }) }) })
32206
+ trailingChevron && /* @__PURE__ */ jsx(IconBox, { size: 16, className: "text-fg-quaternary", children: /* @__PURE__ */ jsx(ChevronDown$1, {}) })
32194
32207
  ]
32195
32208
  }
32196
32209
  )
@@ -32208,13 +32221,13 @@ function NavItemDropdownBase({
32208
32221
  type = "button",
32209
32222
  ...rest
32210
32223
  }) {
32211
- return /* @__PURE__ */ jsxs("div", { className: clsx_default("flex w-[272px] flex-col", className), children: [
32224
+ return /* @__PURE__ */ jsxs("div", { className: clsx_default("flex w-full flex-col", className), children: [
32212
32225
  /* @__PURE__ */ jsx(
32213
32226
  "button",
32214
32227
  {
32215
32228
  type,
32216
32229
  onClick: onToggle,
32217
- className: "flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32230
+ className: "flex w-full items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
32218
32231
  ...rest,
32219
32232
  children: /* @__PURE__ */ jsxs(
32220
32233
  "div",
@@ -32225,15 +32238,10 @@ function NavItemDropdownBase({
32225
32238
  ),
32226
32239
  children: [
32227
32240
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-md", children: [
32228
- icon && /* @__PURE__ */ jsx("span", { className: "flex size-5 shrink-0 items-center justify-center text-fg-quaternary [&>svg]:size-5", children: icon }),
32241
+ icon && /* @__PURE__ */ jsx(IconBox, { size: 20, className: "text-fg-quaternary", children: icon }),
32229
32242
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left text-sm font-semibold text-text-secondary", children: label })
32230
32243
  ] }),
32231
- /* @__PURE__ */ jsx("span", { className: "shrink-0 text-fg-quaternary", children: /* @__PURE__ */ jsx("span", { className: "overflow-clip relative shrink-0 size-[16px] flex items-center justify-center", children: /* @__PURE__ */ jsx(
32232
- ChevronDown$1,
32233
- {
32234
- className: clsx_default("w-full h-full transition-transform", open && "rotate-180")
32235
- }
32236
- ) }) })
32244
+ /* @__PURE__ */ jsx(IconBox, { size: 16, className: "text-fg-quaternary", children: /* @__PURE__ */ jsx(ChevronDown$1, { className: clsx_default("transition-transform", open && "rotate-180") }) })
32237
32245
  ]
32238
32246
  }
32239
32247
  )
@@ -32242,7 +32250,6 @@ function NavItemDropdownBase({
32242
32250
  open && /* @__PURE__ */ jsx("div", { className: "flex flex-col pb-xs", children })
32243
32251
  ] });
32244
32252
  }
32245
- var IconBox = ({ children }) => /* @__PURE__ */ jsx("span", { className: "overflow-clip relative shrink-0 size-[20px] flex items-center justify-center", children });
32246
32253
  function NavMenuButton({
32247
32254
  opened = false,
32248
32255
  className,
@@ -32261,7 +32268,7 @@ function NavMenuButton({
32261
32268
  className
32262
32269
  ),
32263
32270
  ...rest,
32264
- children: opened ? /* @__PURE__ */ jsx("span", { className: "opacity-70", children: /* @__PURE__ */ jsx(IconBox, { children: /* @__PURE__ */ jsx(XClose$1, { className: "w-full h-full" }) }) }) : /* @__PURE__ */ jsx(IconBox, { children: /* @__PURE__ */ jsx(Menu02, { className: "w-full h-full" }) })
32271
+ children: opened ? /* @__PURE__ */ jsx(IconBox, { size: 20, className: "opacity-70", children: /* @__PURE__ */ jsx(XClose$1, {}) }) : /* @__PURE__ */ jsx(IconBox, { size: 20, children: /* @__PURE__ */ jsx(Menu02, {}) })
32265
32272
  }
32266
32273
  );
32267
32274
  }
@@ -33110,17 +33117,20 @@ function SidebarNavigation({
33110
33117
  "nav",
33111
33118
  {
33112
33119
  className: clsx_default(
33120
+ // Padding is applied per-section (Figma node 1161:8593): header 20px,
33121
+ // nav items 16px, footer 16px/20px — not a uniform rail inset, so the
33122
+ // full-width nav items align to their own 16px gutter without clipping.
33113
33123
  "flex h-full flex-col gap-2xl border-r border-border-secondary bg-bg-primary",
33114
- slim ? "items-center px-md py-xl" : "px-lg py-xl",
33124
+ slim ? "items-center px-md py-xl" : "py-xl",
33115
33125
  WIDTH[type],
33116
33126
  className
33117
33127
  ),
33118
33128
  ...rest,
33119
33129
  children: [
33120
- logo && /* @__PURE__ */ jsx("div", { className: clsx_default("shrink-0", slim ? "" : "px-md"), children: logo }),
33121
- header && !slim && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: header }),
33122
- /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-xxs overflow-y-auto", children }),
33123
- footer && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-col gap-lg", children: footer })
33130
+ logo && /* @__PURE__ */ jsx("div", { className: clsx_default("shrink-0", slim ? "" : "px-2xl"), children: logo }),
33131
+ header && !slim && /* @__PURE__ */ jsx("div", { className: "shrink-0 px-2xl", children: header }),
33132
+ /* @__PURE__ */ jsx("div", { className: clsx_default("flex min-h-0 flex-1 flex-col gap-xxs overflow-y-auto", !slim && "px-xl"), children }),
33133
+ footer && /* @__PURE__ */ jsx("div", { className: clsx_default("flex shrink-0 flex-col gap-lg", !slim && "px-xl"), children: footer })
33124
33134
  ]
33125
33135
  }
33126
33136
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@borisj74/bv-ds",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "bv-ds — React component library synced from Figma (Untitled UI v8.0), built on Tailwind CSS",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,6 +1,7 @@
1
1
  import { type HTMLAttributes, type ReactNode } from "react";
2
2
  import clsx from "clsx";
3
3
  import { ChevronSelectorVertical, LogOut01 } from "@borisj74/bv-ds-icons";
4
+ import { IconBox } from "../../internal/iconBox";
4
5
 
5
6
  export type NavAccountCardVariant = "simple" | "card";
6
7
  export type NavAccountCardBreakpoint = "desktop" | "mobile";
@@ -32,13 +33,6 @@ export interface NavAccountCardProps
32
33
  menu?: ReactNode;
33
34
  }
34
35
 
35
- // 16px icon container (Figma nav account card).
36
- const IconBox16 = ({ children }: { children: ReactNode }) => (
37
- <span className="overflow-clip relative shrink-0 size-[16px] flex items-center justify-center">
38
- {children}
39
- </span>
40
- );
41
-
42
36
  /**
43
37
  * Layered avatar treatment from Figma (node 7891:87996): white outer ring +
44
38
  * inner hairline border + status dot. `border-[rgba(0,0,0,0.16)]` is a one-off
@@ -97,7 +91,9 @@ export function NavAccountCard({
97
91
  className,
98
92
  ...rest
99
93
  }: NavAccountCardProps) {
100
- const widthClass = breakpoint === "mobile" ? "w-[256px]" : "w-[280px]";
94
+ // Fill the container (e.g. a padded sidebar footer) but cap at the Figma
95
+ // standalone width so it doesn't stretch unbounded outside a sidebar.
96
+ const widthClass = breakpoint === "mobile" ? "w-full max-w-[256px]" : "w-full max-w-[280px]";
101
97
  const avatarNode = avatar ?? (src !== undefined ? <LayeredAvatar src={src} online={online} /> : undefined);
102
98
 
103
99
  if (variant === "simple") {
@@ -117,9 +113,9 @@ export function NavAccountCard({
117
113
  aria-label="Sign out"
118
114
  className="absolute right-0 top-[15px] flex items-center justify-center rounded-sm p-sm text-fg-quaternary transition-colors hover:text-fg-quaternary-hover"
119
115
  >
120
- <IconBox16>
121
- <LogOut01 className="w-full h-full" />
122
- </IconBox16>
116
+ <IconBox size={16}>
117
+ <LogOut01 />
118
+ </IconBox>
123
119
  </button>
124
120
  </div>
125
121
  );
@@ -139,9 +135,9 @@ export function NavAccountCard({
139
135
  open && "bg-bg-primary-hover",
140
136
  )}
141
137
  >
142
- <IconBox16>
143
- <ChevronSelectorVertical className="w-full h-full" />
144
- </IconBox16>
138
+ <IconBox size={16}>
139
+ <ChevronSelectorVertical />
140
+ </IconBox>
145
141
  </span>
146
142
  </button>
147
143
 
@@ -1,6 +1,7 @@
1
1
  import { type ButtonHTMLAttributes, type ReactNode } from "react";
2
2
  import clsx from "clsx";
3
3
  import { ChevronDown } from "@borisj74/bv-ds-icons";
4
+ import { IconBox } from "../../internal/iconBox";
4
5
 
5
6
  export interface NavItemBaseProps
6
7
  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
@@ -36,7 +37,7 @@ export function NavItemBase({
36
37
  <button
37
38
  type={type}
38
39
  className={clsx(
39
- "flex w-[272px] items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
40
+ "flex w-full items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
40
41
  className,
41
42
  )}
42
43
  {...rest}
@@ -50,9 +51,9 @@ export function NavItemBase({
50
51
  <div className="flex min-w-0 flex-1 items-center gap-md">
51
52
  {dot && <span className="size-2 shrink-0 rounded-full bg-fg-success-secondary" />}
52
53
  {icon && (
53
- <span className="flex size-5 shrink-0 items-center justify-center text-fg-quaternary [&>svg]:size-5">
54
+ <IconBox size={20} className="text-fg-quaternary">
54
55
  {icon}
55
- </span>
56
+ </IconBox>
56
57
  )}
57
58
  <span className="min-w-0 flex-1 truncate text-left text-sm font-semibold text-text-secondary">
58
59
  {label}
@@ -64,11 +65,9 @@ export function NavItemBase({
64
65
  </span>
65
66
  )}
66
67
  {trailingChevron && (
67
- <span className="shrink-0 text-fg-quaternary">
68
- <span className="overflow-clip relative shrink-0 size-[16px] flex items-center justify-center">
69
- <ChevronDown className="w-full h-full" />
70
- </span>
71
- </span>
68
+ <IconBox size={16} className="text-fg-quaternary">
69
+ <ChevronDown />
70
+ </IconBox>
72
71
  )}
73
72
  </div>
74
73
  </button>
@@ -1,6 +1,7 @@
1
1
  import { type ButtonHTMLAttributes, type ReactNode } from "react";
2
2
  import clsx from "clsx";
3
3
  import { ChevronDown } from "@borisj74/bv-ds-icons";
4
+ import { IconBox } from "../../internal/iconBox";
4
5
 
5
6
  export interface NavItemDropdownBaseProps
6
7
  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
@@ -33,11 +34,11 @@ export function NavItemDropdownBase({
33
34
  ...rest
34
35
  }: NavItemDropdownBaseProps) {
35
36
  return (
36
- <div className={clsx("flex w-[272px] flex-col", className)}>
37
+ <div className={clsx("flex w-full flex-col", className)}>
37
38
  <button
38
39
  type={type}
39
40
  onClick={onToggle}
40
- className="flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2"
41
+ className="flex w-full items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2"
41
42
  {...rest}
42
43
  >
43
44
  <div
@@ -48,21 +49,17 @@ export function NavItemDropdownBase({
48
49
  >
49
50
  <div className="flex min-w-0 flex-1 items-center gap-md">
50
51
  {icon && (
51
- <span className="flex size-5 shrink-0 items-center justify-center text-fg-quaternary [&>svg]:size-5">
52
+ <IconBox size={20} className="text-fg-quaternary">
52
53
  {icon}
53
- </span>
54
+ </IconBox>
54
55
  )}
55
56
  <span className="min-w-0 flex-1 truncate text-left text-sm font-semibold text-text-secondary">
56
57
  {label}
57
58
  </span>
58
59
  </div>
59
- <span className="shrink-0 text-fg-quaternary">
60
- <span className="overflow-clip relative shrink-0 size-[16px] flex items-center justify-center">
61
- <ChevronDown
62
- className={clsx("w-full h-full transition-transform", open && "rotate-180")}
63
- />
64
- </span>
65
- </span>
60
+ <IconBox size={16} className="text-fg-quaternary">
61
+ <ChevronDown className={clsx("transition-transform", open && "rotate-180")} />
62
+ </IconBox>
66
63
  </div>
67
64
  </button>
68
65
  {open && (
@@ -1,6 +1,7 @@
1
- import { type ButtonHTMLAttributes, type ReactNode } from "react";
1
+ import { type ButtonHTMLAttributes } from "react";
2
2
  import clsx from "clsx";
3
3
  import { Menu02, XClose } from "@borisj74/bv-ds-icons";
4
+ import { IconBox } from "../../internal/iconBox";
4
5
 
5
6
  export interface NavMenuButtonProps
6
7
  extends ButtonHTMLAttributes<HTMLButtonElement> {
@@ -8,13 +9,6 @@ export interface NavMenuButtonProps
8
9
  opened?: boolean;
9
10
  }
10
11
 
11
- // 20px icon container (Figma nav menu button).
12
- const IconBox = ({ children }: { children: ReactNode }) => (
13
- <span className="overflow-clip relative shrink-0 size-[20px] flex items-center justify-center">
14
- {children}
15
- </span>
16
- );
17
-
18
12
  /**
19
13
  * Hamburger / collapse toggle for the mobile header & sidebar. Shows the
20
14
  * hamburger when closed, an x-close (dimmed) when `opened`. Brand focus ring.
@@ -38,14 +32,12 @@ export function NavMenuButton({
38
32
  {...rest}
39
33
  >
40
34
  {opened ? (
41
- <span className="opacity-70">
42
- <IconBox>
43
- <XClose className="w-full h-full" />
44
- </IconBox>
45
- </span>
35
+ <IconBox size={20} className="opacity-70">
36
+ <XClose />
37
+ </IconBox>
46
38
  ) : (
47
- <IconBox>
48
- <Menu02 className="w-full h-full" />
39
+ <IconBox size={20}>
40
+ <Menu02 />
49
41
  </IconBox>
50
42
  )}
51
43
  </button>
@@ -62,17 +62,22 @@ export function SidebarNavigation({
62
62
  const rail = (
63
63
  <nav
64
64
  className={clsx(
65
+ // Padding is applied per-section (Figma node 1161:8593): header 20px,
66
+ // nav items 16px, footer 16px/20px — not a uniform rail inset, so the
67
+ // full-width nav items align to their own 16px gutter without clipping.
65
68
  "flex h-full flex-col gap-2xl border-r border-border-secondary bg-bg-primary",
66
- slim ? "items-center px-md py-xl" : "px-lg py-xl",
69
+ slim ? "items-center px-md py-xl" : "py-xl",
67
70
  WIDTH[type],
68
71
  className,
69
72
  )}
70
73
  {...rest}
71
74
  >
72
- {logo && <div className={clsx("shrink-0", slim ? "" : "px-md")}>{logo}</div>}
73
- {header && !slim && <div className="shrink-0">{header}</div>}
74
- <div className="flex min-h-0 flex-1 flex-col gap-xxs overflow-y-auto">{children}</div>
75
- {footer && <div className="flex shrink-0 flex-col gap-lg">{footer}</div>}
75
+ {logo && <div className={clsx("shrink-0", slim ? "" : "px-2xl")}>{logo}</div>}
76
+ {header && !slim && <div className="shrink-0 px-2xl">{header}</div>}
77
+ <div className={clsx("flex min-h-0 flex-1 flex-col gap-xxs overflow-y-auto", !slim && "px-xl")}>
78
+ {children}
79
+ </div>
80
+ {footer && <div className={clsx("flex shrink-0 flex-col gap-lg", !slim && "px-xl")}>{footer}</div>}
76
81
  </nav>
77
82
  );
78
83
 
@@ -0,0 +1,36 @@
1
+ import { cloneElement, isValidElement, type ReactElement, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface IconBoxProps {
5
+ /** Box size in px (Figma: 20 for nav icons, 16 for trailing/chevron icons). */
6
+ size?: 16 | 20 | 24;
7
+ className?: string;
8
+ children: ReactNode;
9
+ }
10
+
11
+ /**
12
+ * Sizes an icon to an exact px box and makes it scale correctly.
13
+ *
14
+ * The `@borisj74/bv-ds-icons` package (v0.1.0) ships SVGs with `width="1em"`
15
+ * and **no `viewBox`**, so a 24-unit glyph can't scale into a smaller box and
16
+ * its edges get cropped. We inject `viewBox="0 0 24 24"` (the Untitled UI grid)
17
+ * and `w-full h-full` onto the icon element so it scales into the box cleanly —
18
+ * no `overflow-clip` cropping. Icons inherit `currentColor`.
19
+ */
20
+ export function IconBox({ size = 20, className, children }: IconBoxProps) {
21
+ const icon = isValidElement(children)
22
+ ? cloneElement(children as ReactElement<{ viewBox?: string; className?: string }>, {
23
+ viewBox: (children as ReactElement<{ viewBox?: string }>).props.viewBox ?? "0 0 24 24",
24
+ className: clsx("w-full h-full", (children as ReactElement<{ className?: string }>).props.className),
25
+ })
26
+ : children;
27
+
28
+ return (
29
+ <span
30
+ className={clsx("relative flex shrink-0 items-center justify-center", className)}
31
+ style={{ width: size, height: size }}
32
+ >
33
+ {icon}
34
+ </span>
35
+ );
36
+ }