@marianmeres/stuic 3.87.0 → 3.89.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/API.md +41 -0
- package/dist/components/Checkout/CheckoutAddressForm.svelte +61 -0
- package/dist/components/Checkout/CheckoutAddressForm.svelte.d.ts +6 -1
- package/dist/components/Checkout/CheckoutGuestForm.svelte +57 -0
- package/dist/components/Checkout/CheckoutGuestForm.svelte.d.ts +6 -1
- package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte +81 -6
- package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte.d.ts +6 -1
- package/dist/components/Checkout/CheckoutLoginForm.svelte +36 -1
- package/dist/components/Checkout/CheckoutLoginForm.svelte.d.ts +6 -1
- package/dist/components/Checkout/CheckoutShippingStep.svelte +41 -0
- package/dist/components/Checkout/CheckoutShippingStep.svelte.d.ts +6 -1
- package/dist/components/LoginForm/LoginForm.svelte +7 -1
- package/dist/components/RegisterForm/RegisterForm.svelte +7 -1
- package/dist/components/UserAvatarMenu/README.md +188 -0
- package/dist/components/UserAvatarMenu/UserAvatarMenu.svelte +416 -0
- package/dist/components/UserAvatarMenu/UserAvatarMenu.svelte.d.ts +143 -0
- package/dist/components/UserAvatarMenu/index.css +95 -0
- package/dist/components/UserAvatarMenu/index.d.ts +1 -0
- package/dist/components/UserAvatarMenu/index.js +1 -0
- package/dist/icons/index.d.ts +3 -0
- package/dist/icons/index.js +3 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/docs/domains/components.md +59 -0
- package/package.json +1 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { DropdownMenuItem, DropdownMenuPosition } from "../DropdownMenu/DropdownMenu.svelte";
|
|
3
|
+
import type { Props as AvatarProps } from "../Avatar/Avatar.svelte";
|
|
4
|
+
/**
|
|
5
|
+
* Identity passed by the consumer. When `null` / `undefined`, the menu
|
|
6
|
+
* renders in unauthenticated mode. When provided, the menu renders the
|
|
7
|
+
* header tile (avatar + email) and the authenticated item set.
|
|
8
|
+
*/
|
|
9
|
+
export interface UserAvatarMenuIdentity {
|
|
10
|
+
/** Used for initials + auto-color hashing. Required when `identity` is set. */
|
|
11
|
+
email: string;
|
|
12
|
+
/** Optional display name (preferred over email in the header tile if present). */
|
|
13
|
+
name?: string;
|
|
14
|
+
/** Optional photo URL (forwarded to Avatar `src`). */
|
|
15
|
+
src?: string;
|
|
16
|
+
/** Optional role list — rendered under the email if `showRoles` is enabled. */
|
|
17
|
+
roles?: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Standard built-in actions. Consumers wire these by passing handlers;
|
|
21
|
+
* omitting a handler hides the corresponding item.
|
|
22
|
+
*
|
|
23
|
+
* The component never navigates, logs out, or toggles theme on its own —
|
|
24
|
+
* it only invokes callbacks. The only built-in side effect is
|
|
25
|
+
* `ColorScheme.toggle()` inside the color-scheme item (see `colorScheme`).
|
|
26
|
+
*/
|
|
27
|
+
export interface UserAvatarMenuActions {
|
|
28
|
+
/** "View profile" item. Hidden when not provided. (Auth state only.) */
|
|
29
|
+
onProfile?: () => void;
|
|
30
|
+
/** "Settings" item. Hidden when not provided. (Auth state only.) */
|
|
31
|
+
onSettings?: () => void;
|
|
32
|
+
/** "Logout" item. Hidden when not provided. (Auth state only.) */
|
|
33
|
+
onLogout?: () => void;
|
|
34
|
+
/**
|
|
35
|
+
* "Login or register" item — combined affordance, typically wired to
|
|
36
|
+
* open a `LoginOrRegisterFormModal`. Hidden when not provided.
|
|
37
|
+
* (Unauth state only.) Independent of `onLogin` / `onRegister`; pass
|
|
38
|
+
* any combination of the three.
|
|
39
|
+
*/
|
|
40
|
+
onLoginOrRegister?: () => void;
|
|
41
|
+
/** "Login" item. Hidden when not provided. (Unauth state only.) */
|
|
42
|
+
onLogin?: () => void;
|
|
43
|
+
/** "Register" item. Hidden when not provided. (Unauth state only.) */
|
|
44
|
+
onRegister?: () => void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Labels for built-in items. All optional — defaults are English strings.
|
|
48
|
+
* Consumers running i18n pass already-translated strings here.
|
|
49
|
+
*/
|
|
50
|
+
export interface UserAvatarMenuLabels {
|
|
51
|
+
viewProfile?: string;
|
|
52
|
+
settings?: string;
|
|
53
|
+
logout?: string;
|
|
54
|
+
loginOrRegister?: string;
|
|
55
|
+
login?: string;
|
|
56
|
+
register?: string;
|
|
57
|
+
lightMode?: string;
|
|
58
|
+
darkMode?: string;
|
|
59
|
+
/** Trigger aria-label when authenticated. Default: "User menu". */
|
|
60
|
+
triggerAuthed?: string;
|
|
61
|
+
/** Trigger aria-label when unauthenticated. Default: "Sign in". */
|
|
62
|
+
triggerAnon?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Color-scheme item config. Defaults to enabled.
|
|
66
|
+
* Pass `false` to disable; pass an object to customize.
|
|
67
|
+
*/
|
|
68
|
+
export type UserAvatarMenuColorScheme = boolean | {
|
|
69
|
+
enabled?: boolean;
|
|
70
|
+
/** Override the default `ColorScheme.toggle()` behavior. */
|
|
71
|
+
onToggle?: () => void;
|
|
72
|
+
/** Read current "is dark" state. Defaults to `ColorScheme.getValue() === "dark"`. */
|
|
73
|
+
isDark?: () => boolean;
|
|
74
|
+
};
|
|
75
|
+
export interface Props {
|
|
76
|
+
/** Current user. `null` / `undefined` → unauthenticated mode. */
|
|
77
|
+
identity?: UserAvatarMenuIdentity | null;
|
|
78
|
+
/** Action handlers (see `UserAvatarMenuActions`). */
|
|
79
|
+
actions?: UserAvatarMenuActions;
|
|
80
|
+
/** Translated / customized labels. */
|
|
81
|
+
labels?: UserAvatarMenuLabels;
|
|
82
|
+
/** Color-scheme toggle config. Default: enabled. */
|
|
83
|
+
colorScheme?: UserAvatarMenuColorScheme;
|
|
84
|
+
/** Render the identity header tile (avatar + email) in the dropdown. Default: `true`. */
|
|
85
|
+
showHeaderTile?: boolean;
|
|
86
|
+
/** Render roles under the email in the header tile. Default: `false`. */
|
|
87
|
+
showRoles?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Extra items appended to the standard set (after Logout / Register).
|
|
90
|
+
* Use for app-specific actions ("Switch project", "Billing", etc.).
|
|
91
|
+
*/
|
|
92
|
+
extraItems?: DropdownMenuItem[];
|
|
93
|
+
/**
|
|
94
|
+
* Full override. When provided, the standard item set is IGNORED and the
|
|
95
|
+
* component renders exactly these items. `identity` is still consulted for
|
|
96
|
+
* the trigger; everything else (`actions`, `labels`, `colorScheme`,
|
|
97
|
+
* `showHeaderTile`, `showRoles`) is not.
|
|
98
|
+
*/
|
|
99
|
+
items?: DropdownMenuItem[];
|
|
100
|
+
/** Forwarded to the default `Avatar` trigger and header-tile avatar. */
|
|
101
|
+
avatar?: Partial<Omit<AvatarProps, "onclick" | "initials" | "src" | "el">>;
|
|
102
|
+
/** Forwarded to `DropdownMenu`. */
|
|
103
|
+
position?: DropdownMenuPosition;
|
|
104
|
+
offset?: string;
|
|
105
|
+
maxHeight?: string;
|
|
106
|
+
closeOnSelect?: boolean;
|
|
107
|
+
classDropdown?: string;
|
|
108
|
+
classTrigger?: string;
|
|
109
|
+
/** Bindable open state (forwarded to `DropdownMenu`). */
|
|
110
|
+
isOpen?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Optional custom trigger snippet. Receives the same args as
|
|
113
|
+
* `DropdownMenu`'s `trigger` snippet — `isOpen`, `toggle`, `triggerProps`.
|
|
114
|
+
*/
|
|
115
|
+
trigger?: Snippet<[
|
|
116
|
+
{
|
|
117
|
+
isOpen: boolean;
|
|
118
|
+
toggle: () => void;
|
|
119
|
+
triggerProps: {
|
|
120
|
+
id: string;
|
|
121
|
+
"aria-haspopup": "menu";
|
|
122
|
+
"aria-expanded": boolean;
|
|
123
|
+
"aria-controls": string;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
]>;
|
|
127
|
+
/**
|
|
128
|
+
* Optional custom header-tile snippet. Replaces the default
|
|
129
|
+
* avatar + email tile rendered at the top of the menu.
|
|
130
|
+
*/
|
|
131
|
+
headerTile?: Snippet<[{
|
|
132
|
+
identity: UserAvatarMenuIdentity;
|
|
133
|
+
}]>;
|
|
134
|
+
/** Skip default styling. */
|
|
135
|
+
unstyled?: boolean;
|
|
136
|
+
/** Additional CSS classes on the wrapper. */
|
|
137
|
+
class?: string;
|
|
138
|
+
/** Bindable wrapper element. */
|
|
139
|
+
el?: HTMLDivElement;
|
|
140
|
+
}
|
|
141
|
+
declare const UserAvatarMenu: import("svelte").Component<Props, {}, "el" | "isOpen">;
|
|
142
|
+
type UserAvatarMenu = ReturnType<typeof UserAvatarMenu>;
|
|
143
|
+
export default UserAvatarMenu;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
.stuic-user-avatar-menu {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* Fixed dropdown width so every instance opens at the same size, regardless
|
|
6
|
+
* of content length. Override the var, or pass `classDropdown` (Tailwind
|
|
7
|
+
* class wins via tw-merge). Long emails/names/roles truncate against this
|
|
8
|
+
* bounded width. */
|
|
9
|
+
.stuic-user-avatar-menu-dropdown {
|
|
10
|
+
width: var(--stuic-user-avatar-menu-dropdown-width, 16rem);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.stuic-user-avatar-menu-trigger {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
background: transparent;
|
|
18
|
+
border: 0;
|
|
19
|
+
padding: 0;
|
|
20
|
+
margin: 0;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
border-radius: var(
|
|
23
|
+
--stuic-user-avatar-menu-trigger-radius,
|
|
24
|
+
var(--stuic-radius, var(--radius-md))
|
|
25
|
+
);
|
|
26
|
+
transition: opacity
|
|
27
|
+
var(--stuic-user-avatar-menu-transition, var(--stuic-transition, 150ms)) ease;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.stuic-user-avatar-menu-trigger:hover {
|
|
31
|
+
opacity: var(--stuic-user-avatar-menu-trigger-opacity-hover, 0.85);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.stuic-user-avatar-menu-trigger:focus-visible {
|
|
35
|
+
outline: 2px solid
|
|
36
|
+
var(
|
|
37
|
+
--stuic-user-avatar-menu-trigger-outline-color,
|
|
38
|
+
var(--stuic-color-primary, currentColor)
|
|
39
|
+
);
|
|
40
|
+
outline-offset: 2px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.stuic-user-avatar-menu-header {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: var(--stuic-user-avatar-menu-header-gap, 0.5rem);
|
|
48
|
+
padding: var(--stuic-user-avatar-menu-header-padding, 0.75rem 0.5rem);
|
|
49
|
+
margin-bottom: var(--stuic-user-avatar-menu-header-margin-bottom, 0.25rem);
|
|
50
|
+
background: var(
|
|
51
|
+
--stuic-user-avatar-menu-header-bg,
|
|
52
|
+
var(--stuic-color-muted, transparent)
|
|
53
|
+
);
|
|
54
|
+
color: var(
|
|
55
|
+
--stuic-user-avatar-menu-header-color,
|
|
56
|
+
var(--stuic-color-muted-foreground, inherit)
|
|
57
|
+
);
|
|
58
|
+
border-radius: var(
|
|
59
|
+
--stuic-user-avatar-menu-header-radius,
|
|
60
|
+
var(--stuic-radius, var(--radius-md))
|
|
61
|
+
);
|
|
62
|
+
/* fill the dropdown's content width so children can truncate against a
|
|
63
|
+
* known boundary (instead of growing to their intrinsic width) */
|
|
64
|
+
width: 100%;
|
|
65
|
+
min-width: 0;
|
|
66
|
+
overflow: hidden;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Direct text children of the header tile must each get the full row width
|
|
70
|
+
* so `text-overflow: ellipsis` has something to clip against (under
|
|
71
|
+
* align-items: center, children otherwise shrink to their intrinsic width). */
|
|
72
|
+
.stuic-user-avatar-menu-header-email,
|
|
73
|
+
.stuic-user-avatar-menu-header-roles {
|
|
74
|
+
display: block;
|
|
75
|
+
width: 100%;
|
|
76
|
+
min-width: 0;
|
|
77
|
+
text-align: center;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
text-overflow: ellipsis;
|
|
80
|
+
white-space: nowrap;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.stuic-user-avatar-menu-header-email {
|
|
84
|
+
font-size: var(--stuic-user-avatar-menu-header-email-font-size, inherit);
|
|
85
|
+
color: var(--stuic-user-avatar-menu-header-email-color, inherit);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.stuic-user-avatar-menu-header-roles {
|
|
89
|
+
font-size: var(--stuic-user-avatar-menu-header-roles-font-size, 0.75rem);
|
|
90
|
+
color: var(
|
|
91
|
+
--stuic-user-avatar-menu-header-roles-color,
|
|
92
|
+
var(--stuic-color-muted-foreground, currentColor)
|
|
93
|
+
);
|
|
94
|
+
opacity: var(--stuic-user-avatar-menu-header-roles-opacity, 0.7);
|
|
95
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as UserAvatarMenu, type Props as UserAvatarMenuProps, type UserAvatarMenuIdentity, type UserAvatarMenuActions, type UserAvatarMenuLabels, type UserAvatarMenuColorScheme, } from "./UserAvatarMenu.svelte";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as UserAvatarMenu, } from "./UserAvatarMenu.svelte";
|
package/dist/icons/index.d.ts
CHANGED
|
@@ -40,11 +40,14 @@ export { iconLucideGripHorizontal as iconGripHorizontal } from "@marianmeres/ico
|
|
|
40
40
|
export { iconLucideGripVertical as iconGripVertical } from "@marianmeres/icons-fns/lucide/iconLucideGripVertical.js";
|
|
41
41
|
export { iconLucideLanguages as iconLanguages } from "@marianmeres/icons-fns/lucide/iconLucideLanguages.js";
|
|
42
42
|
export { iconLucideList as iconList } from "@marianmeres/icons-fns/lucide/iconLucideList.js";
|
|
43
|
+
export { iconLucideLogOut as iconLogOut } from "@marianmeres/icons-fns/lucide/iconLucideLogOut.js";
|
|
43
44
|
export { iconLucideMenu as iconMenu } from "@marianmeres/icons-fns/lucide/iconLucideMenu.js";
|
|
45
|
+
export { iconLucideMoon as iconMoon } from "@marianmeres/icons-fns/lucide/iconLucideMoon.js";
|
|
44
46
|
export { iconLucideSearch as iconSearch } from "@marianmeres/icons-fns/lucide/iconLucideSearch.js";
|
|
45
47
|
export { iconLucideSlidersHorizontal as iconSlidersHorizontal } from "@marianmeres/icons-fns/lucide/iconLucideSlidersHorizontal.js";
|
|
46
48
|
export { iconLucideSettings as iconSettings } from "@marianmeres/icons-fns/lucide/iconLucideSettings.js";
|
|
47
49
|
export { iconLucideSquare as iconSquare } from "@marianmeres/icons-fns/lucide/iconLucideSquare.js";
|
|
50
|
+
export { iconLucideSun as iconSun } from "@marianmeres/icons-fns/lucide/iconLucideSun.js";
|
|
48
51
|
export { iconLucideUser as iconUser } from "@marianmeres/icons-fns/lucide/iconLucideUser.js";
|
|
49
52
|
export { iconLucideX as iconX } from "@marianmeres/icons-fns/lucide/iconLucideX.js";
|
|
50
53
|
export { iconLucidePencil as iconPencil } from "@marianmeres/icons-fns/lucide/iconLucidePencil.js";
|
package/dist/icons/index.js
CHANGED
|
@@ -45,11 +45,14 @@ export { iconLucideGripHorizontal as iconGripHorizontal } from "@marianmeres/ico
|
|
|
45
45
|
export { iconLucideGripVertical as iconGripVertical } from "@marianmeres/icons-fns/lucide/iconLucideGripVertical.js";
|
|
46
46
|
export { iconLucideLanguages as iconLanguages } from "@marianmeres/icons-fns/lucide/iconLucideLanguages.js";
|
|
47
47
|
export { iconLucideList as iconList } from "@marianmeres/icons-fns/lucide/iconLucideList.js";
|
|
48
|
+
export { iconLucideLogOut as iconLogOut } from "@marianmeres/icons-fns/lucide/iconLucideLogOut.js";
|
|
48
49
|
export { iconLucideMenu as iconMenu } from "@marianmeres/icons-fns/lucide/iconLucideMenu.js";
|
|
50
|
+
export { iconLucideMoon as iconMoon } from "@marianmeres/icons-fns/lucide/iconLucideMoon.js";
|
|
49
51
|
export { iconLucideSearch as iconSearch } from "@marianmeres/icons-fns/lucide/iconLucideSearch.js";
|
|
50
52
|
export { iconLucideSlidersHorizontal as iconSlidersHorizontal } from "@marianmeres/icons-fns/lucide/iconLucideSlidersHorizontal.js";
|
|
51
53
|
export { iconLucideSettings as iconSettings } from "@marianmeres/icons-fns/lucide/iconLucideSettings.js";
|
|
52
54
|
export { iconLucideSquare as iconSquare } from "@marianmeres/icons-fns/lucide/iconLucideSquare.js";
|
|
55
|
+
export { iconLucideSun as iconSun } from "@marianmeres/icons-fns/lucide/iconLucideSun.js";
|
|
53
56
|
export { iconLucideUser as iconUser } from "@marianmeres/icons-fns/lucide/iconLucideUser.js";
|
|
54
57
|
export { iconLucideX as iconX } from "@marianmeres/icons-fns/lucide/iconLucideX.js";
|
|
55
58
|
export { iconLucidePencil as iconPencil } from "@marianmeres/icons-fns/lucide/iconLucidePencil.js";
|
package/dist/index.css
CHANGED
|
@@ -95,6 +95,7 @@ In practice:
|
|
|
95
95
|
@import "./components/ThemePreview/index.css";
|
|
96
96
|
@import "./components/Tree/index.css";
|
|
97
97
|
@import "./components/TwCheck/index.css";
|
|
98
|
+
@import "./components/UserAvatarMenu/index.css";
|
|
98
99
|
@import "./components/WithSidePanel/index.css";
|
|
99
100
|
@import "./components/X/index.css";
|
|
100
101
|
|
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,7 @@ export * from "./components/ThemePreview/index.js";
|
|
|
74
74
|
export * from "./components/Tree/index.js";
|
|
75
75
|
export * from "./components/TwCheck/index.js";
|
|
76
76
|
export * from "./components/TypeaheadInput/index.js";
|
|
77
|
+
export * from "./components/UserAvatarMenu/index.js";
|
|
77
78
|
export * from "./components/WithSidePanel/index.js";
|
|
78
79
|
export * from "./components/X/index.js";
|
|
79
80
|
export * from "./utils/index.js";
|
package/dist/index.js
CHANGED
|
@@ -75,6 +75,7 @@ export * from "./components/ThemePreview/index.js";
|
|
|
75
75
|
export * from "./components/Tree/index.js";
|
|
76
76
|
export * from "./components/TwCheck/index.js";
|
|
77
77
|
export * from "./components/TypeaheadInput/index.js";
|
|
78
|
+
export * from "./components/UserAvatarMenu/index.js";
|
|
78
79
|
export * from "./components/WithSidePanel/index.js";
|
|
79
80
|
export * from "./components/X/index.js";
|
|
80
81
|
// utils
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
| Component | Purpose |
|
|
73
73
|
| --------------- | ------------------------------------------------------------------- |
|
|
74
74
|
| Avatar | User avatars with fallback |
|
|
75
|
+
| UserAvatarMenu | Avatar trigger + dropdown menu with header tile, color-scheme toggle, authed/unauthed states |
|
|
75
76
|
| Pill | Inline rounded badge/tag/chip (intent + variant + size, dismissible, dot, polymorphic span/a/button) |
|
|
76
77
|
| KbdShortcut | Keyboard shortcut hints |
|
|
77
78
|
| Carousel | Image/content slider with snap, keyboard nav, wheel scroll, arrows |
|
|
@@ -901,6 +902,63 @@ Prefix: `--stuic-tree-*`
|
|
|
901
902
|
|
|
902
903
|
---
|
|
903
904
|
|
|
905
|
+
## UserAvatarMenu
|
|
906
|
+
|
|
907
|
+
Thin opinionated wrapper around `Avatar` + `DropdownMenu` for the common "user avatar in the header opens a small menu" pattern. Renders in both authenticated (header tile, View profile, color-scheme toggle, Logout) and unauthenticated (Login, Register) states from the same trigger position. Color scheme is the one built-in side effect; everything else is consumer callbacks.
|
|
908
|
+
|
|
909
|
+
### Exports
|
|
910
|
+
|
|
911
|
+
| Export | Kind | Description |
|
|
912
|
+
| ---------------------------- | --------- | ------------------------------------------ |
|
|
913
|
+
| `UserAvatarMenu` | component | Main component |
|
|
914
|
+
| `UserAvatarMenuProps` | type | Props type |
|
|
915
|
+
| `UserAvatarMenuIdentity` | type | `{ email, name?, src?, roles? }` |
|
|
916
|
+
| `UserAvatarMenuActions` | type | `{ onProfile?, onSettings?, onLogout?, onLoginOrRegister?, onLogin?, onRegister? }` |
|
|
917
|
+
| `UserAvatarMenuLabels` | type | Label overrides (all optional, English defaults) |
|
|
918
|
+
| `UserAvatarMenuColorScheme` | type | `boolean \| { enabled?, onToggle?, isDark? }` |
|
|
919
|
+
|
|
920
|
+
### Key Props
|
|
921
|
+
|
|
922
|
+
| Prop | Type | Default | Description |
|
|
923
|
+
| ---------------- | --------------------------------------------- | ------- | -------------------------------------------------------------------------------------- |
|
|
924
|
+
| `identity` | `UserAvatarMenuIdentity \| null` | `null` | Current user. `null` / `undefined` → unauthenticated mode. |
|
|
925
|
+
| `actions` | `UserAvatarMenuActions` | `{}` | Handlers; missing → corresponding item hidden. |
|
|
926
|
+
| `labels` | `UserAvatarMenuLabels` | English | Translated strings for built-in items. |
|
|
927
|
+
| `colorScheme` | `boolean \| { enabled?, onToggle?, isDark? }` | `true` | Built-in dark/light toggle. `false` to disable. |
|
|
928
|
+
| `showHeaderTile` | `boolean` | `true` | Render avatar+email tile inside the dropdown (auth only). |
|
|
929
|
+
| `showRoles` | `boolean` | `false` | Render `identity.roles` under the email in the header tile. |
|
|
930
|
+
| `extraItems` | `DropdownMenuItem[]` | — | Appended to the standard item set. |
|
|
931
|
+
| `items` | `DropdownMenuItem[]` | — | Full override of items (trigger + shell still render). |
|
|
932
|
+
| `avatar` | `Partial<AvatarProps>` | — | Forwarded to the default trigger Avatar (and header-tile Avatar). |
|
|
933
|
+
| `position` | `DropdownMenuPosition` | — | Forwarded to `DropdownMenu`. |
|
|
934
|
+
| `classDropdown` | `string` | — | Forwarded. |
|
|
935
|
+
| `classTrigger` | `string` | — | Class merged onto the default trigger `<button>`. |
|
|
936
|
+
| `trigger` | `Snippet<[{ isOpen, toggle, triggerProps }]>` | — | Custom trigger snippet (replaces default Avatar trigger). |
|
|
937
|
+
| `headerTile` | `Snippet<[{ identity }]>` | — | Custom header-tile snippet (replaces default avatar+email tile). |
|
|
938
|
+
| `isOpen` | `boolean` | `false` | Bindable open state. |
|
|
939
|
+
|
|
940
|
+
### Default item order
|
|
941
|
+
|
|
942
|
+
**Authenticated:** header tile → View profile → Settings → Color scheme → Divider → Logout → `extraItems`. Each rendered only if its precondition (handler present, etc.) holds.
|
|
943
|
+
|
|
944
|
+
**Unauthenticated:** Login or register → Login → Register → Color scheme → `extraItems`. Each rendered only if the corresponding handler is provided. The three are independent — pass any combination. The combined `onLoginOrRegister` (typically opening a `LoginOrRegisterFormModal`) is the most common variant. No header tile.
|
|
945
|
+
|
|
946
|
+
### Opinionated decisions
|
|
947
|
+
|
|
948
|
+
- Color scheme is the only built-in side effect (`ColorScheme.toggle()` + re-read on select). Opt out with `colorScheme={false}`.
|
|
949
|
+
- English label defaults; consumers pass `labels` for i18n. No i18n library imported.
|
|
950
|
+
- No auth state ownership, no router, no modal triggering — all consumer callbacks.
|
|
951
|
+
|
|
952
|
+
### CSS Tokens
|
|
953
|
+
|
|
954
|
+
Prefix: `--stuic-user-avatar-menu-*`
|
|
955
|
+
|
|
956
|
+
`dropdown-width` (16rem), `trigger-radius`, `trigger-opacity-hover`, `trigger-outline-color`, `transition`, `header-gap`, `header-padding`, `header-margin-bottom`, `header-bg`, `header-color`, `header-radius`, `header-email-font-size`, `header-email-color`, `header-roles-font-size`, `header-roles-color`, `header-roles-opacity`
|
|
957
|
+
|
|
958
|
+
The dropdown has a fixed `width` so every instance opens identically — short and long content alike. Email, name, and roles truncate with `text-overflow: ellipsis`. Header tile defaults: `--stuic-color-muted` bg + `--stuic-color-muted-foreground` text.
|
|
959
|
+
|
|
960
|
+
---
|
|
961
|
+
|
|
904
962
|
## Key Files
|
|
905
963
|
|
|
906
964
|
| File | Purpose |
|
|
@@ -916,4 +974,5 @@ Prefix: `--stuic-tree-*`
|
|
|
916
974
|
| src/lib/components/Checkout/ | E-commerce checkout flow (14 exported sub-components) |
|
|
917
975
|
| src/lib/components/Card/ | Card with image/title/footer variants |
|
|
918
976
|
| src/lib/components/Tree/ | Hierarchical tree with drag-and-drop |
|
|
977
|
+
| src/lib/components/UserAvatarMenu/ | Avatar trigger + dropdown for user menu |
|
|
919
978
|
| src/lib/index.ts | All component exports |
|