@alexandregme/zljs 1.19.0 → 1.19.1

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/CHANGELOG.md CHANGED
@@ -8,6 +8,26 @@ A change that needs action in an app has a **Migration** note. When updating, re
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [1.19.1] - 2026-11-03
12
+
13
+ ### Changed
14
+
15
+ - Collapsed `Sidebar` shows only the logout button in its footer. The avatar, name and email come back when it expands, and the footer and the collapse button keep their height in both states, at 64px and 56px
16
+ - The collapse button of `Sidebar` is named by `collapseLabel` while expanded, no longer `Collapse sidebar`, and shows only its icon when collapsed
17
+ - `Sidebar` links have fewer elements and look the same: the `Icon` is a direct child of the link, and the home link has no empty `span` when there is no `homeLabel`
18
+
19
+ #### Migration
20
+
21
+ Search the app's tests for `Collapse sidebar` and replace it with the value the app passes in `collapseLabel`. `Expand sidebar` stays.
22
+
23
+ ### Fixed
24
+
25
+ - Collapsed `Sidebar` can log out with a mouse. The button sat outside the visible area, and focusing it with the keyboard scrolled the sidebar sideways, out of view
26
+ - `Sidebar` links draw their own focus outline in the text color. They relied on the browser's default, which was 2.53:1 in Chromium
27
+ - The active home link of `Sidebar` has `aria-current="page"`, its link is styled like the others, and the avatar initials are hidden from screen readers
28
+ - A long email in `Sidebar` is cut with an ellipsis. It ran under the logout button
29
+ - The icon of the `Sidebar` collapse button lines up with the link icons, so it is centered when collapsed and doesn't move on toggle. It sat 4px to the right
30
+
11
31
  ## [1.19.0] - 2026-11-02
12
32
 
13
33
  ### Added
@@ -282,7 +302,8 @@ Replace the shade with the class of the `color` being tested, for example `/(^|\
282
302
 
283
303
  The message of `Error` is `text-zl-danger`. `none` and `ghost` didn't change.
284
304
 
285
- [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.19.0...HEAD
305
+ [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.19.1...HEAD
306
+ [1.19.1]: https://github.com/alexandregme/zljs/compare/v1.19.0...v1.19.1
286
307
  [1.19.0]: https://github.com/alexandregme/zljs/compare/v1.18.1...v1.19.0
287
308
  [1.18.1]: https://github.com/alexandregme/zljs/compare/v1.18.0...v1.18.1
288
309
  [1.18.0]: https://github.com/alexandregme/zljs/compare/v1.17.0...v1.18.0
package/dist/index.js CHANGED
@@ -829,7 +829,7 @@ import Link from "next/link.js";
829
829
  // core/sidebar/sidebar.styles.ts
830
830
  import { tv as tv10 } from "tailwind-variants";
831
831
  var sidebar = tv10({
832
- base: "h-screen bg-neutral-800 text-neutral-300 flex flex-col overflow-hidden transition-all duration-200",
832
+ base: "h-screen bg-neutral-800 text-neutral-300 flex flex-col overflow-hidden transition-all duration-200 divide-y divide-neutral-600/50",
833
833
  variants: {
834
834
  collapsed: {
835
835
  true: "w-14",
@@ -841,62 +841,52 @@ var sidebar = tv10({
841
841
  }
842
842
  });
843
843
  var nav = tv10({
844
- base: "flex-1 min-h-0 overflow-y-auto overflow-x-hidden"
844
+ base: "flex-1 min-h-0 overflow-y-auto overflow-x-hidden divide-y divide-neutral-600/50"
845
845
  });
846
846
  var header2 = tv10({
847
- base: "shrink-0 border-b border-neutral-600/50 grid p-2"
847
+ base: "shrink-0 p-2"
848
848
  });
849
849
  var section = tv10({
850
- base: "border-b border-neutral-600/50 last:border-b-0 grid gap-1 p-2"
850
+ base: "grid gap-1 p-2"
851
851
  });
852
852
  var item = tv10({
853
- base: "flex w-full items-center rounded-md text-sm whitespace-nowrap transition-colors cursor-pointer p-1",
853
+ // [&>*+*] is the label: Text takes no className, and the icon comes first, so a link with no label has nothing to hide.
854
+ base: "flex items-center rounded-md transition-colors h-10 px-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current [&>*+*]:truncate [&>*+*]:transition-all [&>*+*]:duration-200",
854
855
  variants: {
855
856
  active: {
856
857
  true: "bg-neutral-700 text-white",
857
858
  false: "text-neutral-400 hover:bg-neutral-700/50 hover:text-white"
859
+ },
860
+ collapsed: {
861
+ true: "[&>*+*]:w-0 [&>*+*]:opacity-0",
862
+ false: "[&>*+*]:ml-2 [&>*+*]:opacity-100"
858
863
  }
859
864
  },
860
865
  defaultVariants: {
861
- active: false
866
+ active: false,
867
+ collapsed: false
862
868
  }
863
869
  });
864
- var itemIcon = tv10({
865
- base: "p-2"
866
- });
867
- var itemLabel = tv10({
868
- base: "truncate transition-all duration-200",
870
+ var footer = tv10({
871
+ base: "shrink-0 h-16 p-3 flex items-center gap-3",
869
872
  variants: {
870
873
  collapsed: {
871
- true: "opacity-0 w-0",
872
- false: "opacity-100"
874
+ true: "justify-center"
873
875
  }
874
- },
875
- defaultVariants: {
876
- collapsed: false
877
876
  }
878
877
  });
879
- var footer = tv10({
880
- base: "shrink-0 border-t border-neutral-600/50 p-3 flex items-center gap-3 whitespace-nowrap"
881
- });
882
878
  var avatar = tv10({
883
- base: "shrink-0 w-8 h-8 rounded-full bg-neutral-600 text-white text-xs font-medium flex items-center justify-center"
879
+ base: "shrink-0 size-8 rounded-full bg-neutral-600 text-white text-xs font-medium flex items-center justify-center"
884
880
  });
885
881
  var userInfo = tv10({
886
- base: "flex flex-col min-w-0"
887
- });
888
- var userName = tv10({
889
- base: "text-sm text-white truncate"
890
- });
891
- var userEmail = tv10({
892
- base: "text-xs text-neutral-400"
882
+ base: "flex flex-col min-w-0 text-white [&>*]:truncate [&>*:last-child]:text-xs [&>*:last-child]:text-neutral-400"
893
883
  });
894
884
  var toggleButton = tv10({
895
- base: "shrink-0 border-t border-neutral-600/50 grid p-2 [&>button]:justify-start [&>button]:overflow-hidden [&>button]:whitespace-nowrap"
885
+ base: "shrink-0 h-14 grid p-2 [&>button]:justify-start [&>button]:px-3 [&>button]:overflow-hidden [&>button]:whitespace-nowrap"
896
886
  });
897
887
 
898
888
  // core/sidebar/sidebar.tsx
899
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
889
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
900
890
  var getInitials = (name) => {
901
891
  const parts = name.trim().split(/\s+/);
902
892
  if (parts.length >= 2) {
@@ -917,39 +907,42 @@ var Sidebar = ({
917
907
  const [collapsed, setCollapsed] = useState3(defaultCollapsed);
918
908
  const initials = getInitials(user.name);
919
909
  return /* @__PURE__ */ jsxs12("aside", { className: sidebar({ collapsed }), children: [
920
- homeHref && /* @__PURE__ */ jsx14(
910
+ homeHref && /* @__PURE__ */ jsx14("div", { className: header2(), children: /* @__PURE__ */ jsxs12(
921
911
  Link,
922
912
  {
923
913
  href: homeHref,
924
- className: header2(),
914
+ className: item({ active: homeHref === activeHref, collapsed }),
925
915
  "aria-label": homeLabel || "Home",
926
- children: /* @__PURE__ */ jsxs12("span", { className: item({ active: homeHref === activeHref }), children: [
927
- /* @__PURE__ */ jsx14("span", { className: itemIcon(), children: /* @__PURE__ */ jsx14(Icon, { name: "Home" }) }),
928
- /* @__PURE__ */ jsx14("span", { className: itemLabel({ collapsed }), children: homeLabel })
929
- ] })
916
+ ...homeHref === activeHref && { "aria-current": "page" },
917
+ children: [
918
+ /* @__PURE__ */ jsx14(Icon, { name: "Home" }),
919
+ homeLabel && /* @__PURE__ */ jsx14(Text, { as: "span", variant: "caption", children: homeLabel })
920
+ ]
930
921
  }
931
- ),
922
+ ) }),
932
923
  /* @__PURE__ */ jsx14("nav", { "aria-label": "Main navigation", className: nav(), children: sections.map((sectionData, i) => /* @__PURE__ */ jsx14("div", { className: section(), children: sectionData.items.map((sidebarItem) => {
933
924
  const isActive = sidebarItem.href === activeHref;
934
925
  return /* @__PURE__ */ jsxs12(
935
926
  Link,
936
927
  {
937
928
  href: sidebarItem.href,
938
- className: item({ active: isActive }),
929
+ className: item({ active: isActive, collapsed }),
939
930
  ...isActive && { "aria-current": "page" },
940
931
  children: [
941
- /* @__PURE__ */ jsx14("span", { className: itemIcon(), children: /* @__PURE__ */ jsx14(Icon, { name: sidebarItem.icon }) }),
942
- /* @__PURE__ */ jsx14("span", { className: itemLabel({ collapsed }), children: sidebarItem.label })
932
+ /* @__PURE__ */ jsx14(Icon, { name: sidebarItem.icon }),
933
+ /* @__PURE__ */ jsx14(Text, { as: "span", variant: "caption", children: sidebarItem.label })
943
934
  ]
944
935
  },
945
936
  sidebarItem.href
946
937
  );
947
938
  }) }, i)) }),
948
- /* @__PURE__ */ jsxs12("div", { className: footer(), children: [
949
- /* @__PURE__ */ jsx14("div", { className: avatar(), children: initials }),
950
- /* @__PURE__ */ jsxs12("div", { className: userInfo(), children: [
951
- /* @__PURE__ */ jsx14("span", { className: userName(), children: user.name }),
952
- /* @__PURE__ */ jsx14("span", { className: userEmail(), children: user.email })
939
+ /* @__PURE__ */ jsxs12("div", { className: footer({ collapsed }), children: [
940
+ !collapsed && /* @__PURE__ */ jsxs12(Fragment3, { children: [
941
+ /* @__PURE__ */ jsx14("div", { "aria-hidden": "true", className: avatar(), children: initials }),
942
+ /* @__PURE__ */ jsxs12("div", { className: userInfo(), children: [
943
+ /* @__PURE__ */ jsx14(Text, { as: "span", variant: "caption", children: user.name }),
944
+ /* @__PURE__ */ jsx14(Text, { as: "span", variant: "caption", children: user.email })
945
+ ] })
953
946
  ] }),
954
947
  /* @__PURE__ */ jsx14(
955
948
  Button,
@@ -964,11 +957,12 @@ var Sidebar = ({
964
957
  /* @__PURE__ */ jsx14("div", { className: toggleButton(), children: /* @__PURE__ */ jsx14(
965
958
  Button,
966
959
  {
960
+ variant: "default",
967
961
  color: "ghost",
968
962
  icon: collapsed ? "ChevronRight" : "ChevronLeft",
969
- "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
963
+ "aria-label": collapsed ? "Expand sidebar" : void 0,
970
964
  onClick: () => setCollapsed(!collapsed),
971
- children: collapseLabel
965
+ children: collapsed ? void 0 : collapseLabel
972
966
  }
973
967
  ) })
974
968
  ] });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexandregme/zljs",
3
- "version": "1.19.0",
3
+ "version": "1.19.1",
4
4
  "description": "Opinionated, accessible React component library for enterprise apps (Next.js, Tailwind CSS v4).",
5
5
  "keywords": [
6
6
  "react",