@hilum/ui 2.0.3 → 2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hilum/ui",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "private": false,
5
5
  "description": "Hilum UI — design system primitives (Button, Input, Dialog, Combobox, …) + tokens + fonts + icons",
6
6
  "license": "MIT",
@@ -0,0 +1,115 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import {
5
+ DropdownMenuContent,
6
+ DropdownMenuItem,
7
+ DropdownMenuSeparator,
8
+ } from "./dropdown-menu";
9
+ import { Avatar, AvatarFallback, AvatarImage } from "./avatar";
10
+ import { cn } from "../lib/utils";
11
+
12
+ const AccountMenuContent = React.forwardRef<
13
+ React.ComponentRef<typeof DropdownMenuContent>,
14
+ React.ComponentPropsWithoutRef<typeof DropdownMenuContent>
15
+ >(({ className, sideOffset = 8, ...props }, ref) => (
16
+ <DropdownMenuContent
17
+ ref={ref}
18
+ sideOffset={sideOffset}
19
+ className={cn(
20
+ "w-80 overflow-hidden rounded-3xl bg-ground-900 p-0 text-ground-50 shadow-elevated",
21
+ "ring-1 ring-ground-800",
22
+ className,
23
+ )}
24
+ {...props}
25
+ />
26
+ ));
27
+ AccountMenuContent.displayName = "AccountMenuContent";
28
+
29
+ interface AccountMenuHeaderProps extends React.ComponentProps<"div"> {
30
+ name: React.ReactNode;
31
+ email?: React.ReactNode;
32
+ avatarSrc?: string | null;
33
+ avatarAlt?: string;
34
+ fallback?: React.ReactNode;
35
+ }
36
+
37
+ const AccountMenuHeader = React.forwardRef<HTMLDivElement, AccountMenuHeaderProps>(
38
+ ({ name, email, avatarSrc, avatarAlt, fallback, className, ...props }, ref) => (
39
+ <div
40
+ ref={ref}
41
+ className={cn("flex flex-col items-center px-6 py-8 text-center", className)}
42
+ {...props}
43
+ >
44
+ <Avatar size="xl" className="mb-4 size-16">
45
+ {avatarSrc && <AvatarImage src={avatarSrc} alt={avatarAlt ?? ""} />}
46
+ <AvatarFallback className="bg-brand-primary text-2xl text-primary-foreground">
47
+ {fallback}
48
+ </AvatarFallback>
49
+ </Avatar>
50
+ <p className="body-lg font-medium leading-tight text-ground-50">{name}</p>
51
+ {email && <p className="body text-ground-400">{email}</p>}
52
+ </div>
53
+ ),
54
+ );
55
+ AccountMenuHeader.displayName = "AccountMenuHeader";
56
+
57
+ const AccountMenuSection = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
58
+ ({ className, ...props }, ref) => (
59
+ <div ref={ref} className={cn("p-3", className)} {...props} />
60
+ ),
61
+ );
62
+ AccountMenuSection.displayName = "AccountMenuSection";
63
+
64
+ interface AccountMenuItemProps
65
+ extends React.ComponentPropsWithoutRef<typeof DropdownMenuItem> {
66
+ icon?: React.ReactNode;
67
+ trailing?: React.ReactNode;
68
+ description?: React.ReactNode;
69
+ }
70
+
71
+ const AccountMenuItem = React.forwardRef<
72
+ React.ComponentRef<typeof DropdownMenuItem>,
73
+ AccountMenuItemProps
74
+ >(({ icon, trailing, description, children, className, ...props }, ref) => (
75
+ <DropdownMenuItem
76
+ ref={ref}
77
+ className={cn(
78
+ "min-h-11 rounded-lg px-3 py-2.5 text-ground-50",
79
+ "group",
80
+ "focus:bg-primary focus:text-primary-foreground",
81
+ "data-[disabled]:opacity-40",
82
+ "[&_svg:not([class*='size-'])]:size-5",
83
+ className,
84
+ )}
85
+ {...props}
86
+ >
87
+ {icon && <span className="flex size-6 shrink-0 items-center justify-center">{icon}</span>}
88
+ <span className="flex min-w-0 flex-1 flex-col">
89
+ <span className="body-lg truncate font-medium leading-tight">{children}</span>
90
+ {description && (
91
+ <span className="body truncate font-normal text-ground-400 group-focus:text-primary-foreground/80">
92
+ {description}
93
+ </span>
94
+ )}
95
+ </span>
96
+ {trailing && <span className="ml-3 shrink-0 text-ground-400">{trailing}</span>}
97
+ </DropdownMenuItem>
98
+ ));
99
+ AccountMenuItem.displayName = "AccountMenuItem";
100
+
101
+ const AccountMenuSeparator = React.forwardRef<
102
+ React.ComponentRef<typeof DropdownMenuSeparator>,
103
+ React.ComponentPropsWithoutRef<typeof DropdownMenuSeparator>
104
+ >(({ className, ...props }, ref) => (
105
+ <DropdownMenuSeparator ref={ref} className={cn("m-0 bg-ground-800", className)} {...props} />
106
+ ));
107
+ AccountMenuSeparator.displayName = "AccountMenuSeparator";
108
+
109
+ export {
110
+ AccountMenuContent,
111
+ AccountMenuHeader,
112
+ AccountMenuSection,
113
+ AccountMenuItem,
114
+ AccountMenuSeparator,
115
+ };
@@ -20,7 +20,7 @@ const ContextMenuContent = React.forwardRef<
20
20
  <ContextMenu.Content
21
21
  ref={ref}
22
22
  className={cn(
23
- "z-50 min-w-[8rem] bg-card rounded-xl shadow-natural p-1",
23
+ "z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-card p-1 text-card-foreground shadow-elevated outline-none",
24
24
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
25
25
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
26
26
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -164,7 +164,7 @@ const ContextMenuSubContent = React.forwardRef<
164
164
  <ContextMenu.SubContent
165
165
  ref={ref}
166
166
  className={cn(
167
- "z-50 min-w-[8rem] bg-card rounded-xl border border-border shadow-natural p-1",
167
+ "z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border bg-card p-1 text-card-foreground shadow-elevated outline-none",
168
168
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
169
169
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
170
170
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  export { cn } from "./lib/utils";
10
10
 
11
11
  // Components (alphabetical)
12
+ export * from "./components/account-menu";
12
13
  export * from "./components/accordion";
13
14
  export * from "./components/action-panel";
14
15
  export * from "./components/activity-feed";