@lateralus-ai/shipping-ui 2.0.0-dev.13 → 2.0.0-dev.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lateralus-ai/shipping-ui",
3
- "version": "2.0.0-dev.13",
3
+ "version": "2.0.0-dev.14",
4
4
  "description": "Shared UI theme and components for Lateralus shipping applications",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.esm.js",
@@ -50,7 +50,7 @@
50
50
  "release:dev:init": "npx release-it --config .release-it.dev.json major --preRelease=dev",
51
51
  "release:dev:init:publish": "npx release-it --config .release-it.dev.json --no-hooks.before:init major --preRelease=dev",
52
52
  "release:dev": "npx release-it --config .release-it.dev.json --preRelease=dev",
53
- "release:dev:publish": "npx release-it --config .release-it.dev.json --no-hooks.before:init --preRelease=dev"
53
+ "release:dev:publish": "npm run build && npx release-it --config .release-it.dev.json --no-hooks.before:init --preRelease=dev"
54
54
  },
55
55
  "repository": {
56
56
  "type": "git",
@@ -93,6 +93,7 @@ export const CollapsibleNavGroup = ({
93
93
  ) : undefined
94
94
  }
95
95
  menuItems={entryMenuItems}
96
+ onNavigate={onNavigate}
96
97
  />
97
98
  ))}
98
99
  </div>
@@ -1,7 +1,12 @@
1
1
  import { type ReactNode } from "react";
2
2
  import { Tooltip } from "../../primitives";
3
3
  import { cn } from "../../utils/cn";
4
- import { sidebarLinkActive, sidebarLinkIdle, sidebarRowClass, sidebarRowInteractiveHover, sidebarSectionAnchorClass } from "./sidebar-styles";
4
+ import {
5
+ sidebarLinkActive,
6
+ sidebarLinkIdle,
7
+ sidebarRowClass,
8
+ sidebarRowInteractiveHover,
9
+ } from "./sidebar-styles";
5
10
 
6
11
  export type SidebarActionProps = {
7
12
  label: string;
@@ -23,26 +28,25 @@ export const SidebarAction = ({
23
28
  className,
24
29
  }: SidebarActionProps) => {
25
30
  const row = (
26
- <div
31
+ <button
32
+ type="button"
33
+ onClick={onClick}
34
+ aria-label={label}
27
35
  className={sidebarRowClass(
28
36
  cn(
37
+ "cursor-pointer text-left",
29
38
  active ? sidebarLinkActive : sidebarLinkIdle,
30
39
  !active && sidebarRowInteractiveHover,
40
+ collapsed ? "justify-center" : "gap-2",
31
41
  className,
32
42
  ),
33
43
  )}
34
44
  data-active={active}
35
45
  data-collapsed={collapsed}
36
46
  >
37
- <button
38
- type="button"
39
- className={sidebarSectionAnchorClass(collapsed ? "justify-center" : undefined)}
40
- onClick={onClick}
41
- >
42
- {icon && <span className="shrink-0 [&>svg]:size-5">{icon}</span>}
43
- {!collapsed && <span className="truncate">{label}</span>}
44
- </button>
45
- </div>
47
+ {icon && <span className="shrink-0 [&>svg]:size-5">{icon}</span>}
48
+ {!collapsed && <span className="min-w-0 flex-1 truncate">{label}</span>}
49
+ </button>
46
50
  );
47
51
 
48
52
  if (!collapsed || !tooltip) return row;
@@ -3,7 +3,6 @@ import { DropdownMenu, DropdownMenuItem, IconButton } from "../../primitives";
3
3
  import { MoreIcon } from "../../icons";
4
4
  import { cn } from "../../utils/cn";
5
5
  import {
6
- sidebarAnchorClass,
7
6
  sidebarEntryHover,
8
7
  sidebarEntryIdle,
9
8
  sidebarEntrySelected,
@@ -66,58 +65,76 @@ export const SidebarEntry = ({
66
65
  )}
67
66
  data-state={state}
68
67
  >
68
+ {/* Stretch hit target over shell padding (hover was on the shell, link was content-only). */}
69
69
  <a
70
70
  href={href}
71
- className={sidebarAnchorClass("gap-1")}
71
+ className="absolute inset-0 z-0 rounded-control"
72
+ aria-label={label}
72
73
  aria-current={state === "selected" ? "true" : undefined}
73
74
  onClick={onNavigate}
74
- >
75
- {icon && <span className="shrink-0 px-1 py-0.5 [&>svg]:size-4">{icon}</span>}
75
+ />
76
+
77
+ <div className="pointer-events-none relative z-10 flex min-w-0 flex-1 items-center gap-2 text-caption-2">
78
+ {icon && (
79
+ <span className="shrink-0 px-1 py-0.5 [&>svg]:size-4">{icon}</span>
80
+ )}
76
81
  <span className="truncate">{label}</span>
77
- </a>
82
+ </div>
78
83
 
79
84
  {badge && !(showMenu && menuVisible) && (
80
85
  <span
81
- className={cn("shrink-0", showMenu && !forceMenuVisible && "group-hover/row:hidden")}
86
+ className={cn(
87
+ "pointer-events-none relative z-10 shrink-0",
88
+ showMenu && !forceMenuVisible && "group-hover/row:hidden",
89
+ )}
82
90
  >
83
91
  {badge}
84
92
  </span>
85
93
  )}
86
94
 
87
95
  {showMenu && (
88
- <DropdownMenu
89
- open={menuOpen}
90
- onOpenChange={setMenuOpen}
91
- align="end"
92
- trigger={
93
- <IconButton
94
- hierarchy="quaternary"
95
- size="small"
96
- aria-label={`Actions for ${label}`}
97
- aria-haspopup="menu"
98
- aria-expanded={menuOpen}
99
- className={cn(
100
- "size-6 min-h-6 shrink-0 p-1",
101
- sidebarQuaternaryIconButton,
102
- !forceMenuVisible && !menuOpen && "hidden group-hover/row:inline-flex",
103
- (forceMenuVisible || menuOpen) && "inline-flex",
104
- )}
105
- >
106
- <MoreIcon size="small" />
107
- </IconButton>
108
- }
109
- >
110
- {menuItems?.map((item) => (
111
- <DropdownMenuItem
112
- key={item.id}
113
- className={cn(item.destructive && "text-red-500 hover:bg-red-50 hover:text-red-700")}
114
- onSelect={() => item.onSelect()}
115
- >
116
- {item.icon && <span className="shrink-0 [&>svg]:size-4">{item.icon}</span>}
117
- {item.label}
118
- </DropdownMenuItem>
119
- ))}
120
- </DropdownMenu>
96
+ <div className="relative z-10 shrink-0">
97
+ <DropdownMenu
98
+ open={menuOpen}
99
+ onOpenChange={setMenuOpen}
100
+ align="end"
101
+ trigger={
102
+ <IconButton
103
+ hierarchy="quaternary"
104
+ size="small"
105
+ aria-label={`Actions for ${label}`}
106
+ aria-haspopup="menu"
107
+ aria-expanded={menuOpen}
108
+ className={cn(
109
+ "size-6 min-h-6 shrink-0 p-1",
110
+ sidebarQuaternaryIconButton,
111
+ !forceMenuVisible &&
112
+ !menuOpen &&
113
+ "hidden group-hover/row:inline-flex",
114
+ (forceMenuVisible || menuOpen) && "inline-flex",
115
+ )}
116
+ >
117
+ <MoreIcon size="small" />
118
+ </IconButton>
119
+ }
120
+ >
121
+ {menuItems?.map((item) => (
122
+ <DropdownMenuItem
123
+ key={item.id}
124
+ className={cn(
125
+ item.destructive &&
126
+ "text-red-500 hover:bg-red-50 hover:text-red-700",
127
+ )}
128
+ onSelect={() => item.onSelect()}
129
+ >
130
+ {item.icon && (
131
+ <span className="shrink-0 [&>svg]:size-4">{item.icon}</span>
132
+ )}
133
+ {item.label}
134
+ </DropdownMenuItem>
135
+ ))}
136
+ </DropdownMenu>
137
+ </div>
121
138
  )}
122
139
  </div>
123
140
  );
@@ -58,6 +58,7 @@ export const SidebarLink = ({
58
58
  const row = collapsed ? (
59
59
  <div
60
60
  className={cn(
61
+ "relative",
61
62
  sidebarSectionShellCollapsed,
62
63
  stateStyles[state],
63
64
  state === "idle" && sidebarRowInteractiveHover,
@@ -68,24 +69,24 @@ export const SidebarLink = ({
68
69
  >
69
70
  <a
70
71
  href={href}
71
- className="flex w-full items-center justify-center"
72
+ className="absolute inset-0 z-0 rounded-control"
72
73
  aria-current={state === "active" ? "page" : undefined}
73
74
  aria-label={label}
74
75
  onClick={onNavigate}
75
- >
76
- <span className="relative inline-flex shrink-0 items-center">
77
- {icon && <span className={sidebarSectionIconClass}>{icon}</span>}
78
- {unread && (
79
- <span aria-hidden className={sidebarUnreadOverlay}>
80
- <span className={sidebarUnreadDot} />
81
- </span>
82
- )}
83
- </span>
84
- </a>
76
+ />
77
+ <span className="pointer-events-none relative z-10 inline-flex shrink-0 items-center">
78
+ {icon && <span className={sidebarSectionIconClass}>{icon}</span>}
79
+ {unread && (
80
+ <span aria-hidden className={sidebarUnreadOverlay}>
81
+ <span className={sidebarUnreadDot} />
82
+ </span>
83
+ )}
84
+ </span>
85
85
  </div>
86
86
  ) : (
87
87
  <div
88
88
  className={cn(
89
+ "relative",
89
90
  tall ? sidebarSectionShellTall : sidebarSectionShell,
90
91
  stateStyles[state],
91
92
  state === "idle" && sidebarRowInteractiveHover,
@@ -94,18 +95,27 @@ export const SidebarLink = ({
94
95
  data-state={state}
95
96
  data-collapsed={collapsed}
96
97
  >
97
- <div className={sidebarSectionContent}>
98
- <a
99
- href={href}
100
- className="flex min-w-0 flex-1 items-center gap-2 truncate text-left"
101
- aria-current={state === "active" ? "page" : undefined}
102
- onClick={onNavigate}
103
- >
98
+ <a
99
+ href={href}
100
+ className="absolute inset-0 z-0 rounded-control"
101
+ aria-current={state === "active" ? "page" : undefined}
102
+ aria-label={label}
103
+ onClick={onNavigate}
104
+ />
105
+ <div
106
+ className={cn(
107
+ sidebarSectionContent,
108
+ "pointer-events-none relative z-10",
109
+ )}
110
+ >
111
+ <span className="flex min-w-0 flex-1 items-center gap-2 truncate text-left">
104
112
  {icon && <span className={sidebarSectionIconClass}>{icon}</span>}
105
113
  <span className={sidebarSectionLabelClass}>{label}</span>
106
114
  {badge}
107
- </a>
108
- {trailing}
115
+ </span>
116
+ {trailing != null && (
117
+ <span className="pointer-events-auto shrink-0">{trailing}</span>
118
+ )}
109
119
  </div>
110
120
  </div>
111
121
  );