@sybilion/uilib 1.2.5 → 1.2.8

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.
Files changed (37) hide show
  1. package/assets/standalone-global.css +12 -11
  2. package/dist/esm/components/ui/AppHeader/AppHeader.styl.js +1 -1
  3. package/dist/esm/components/ui/Logo/Logo.js +7 -2
  4. package/dist/esm/components/ui/Logo/Logo.styl.js +1 -1
  5. package/dist/esm/components/ui/NavUserHeader/NavUserHeader.js +4 -2
  6. package/dist/esm/components/ui/Sidebar/Sidebar.styl.js +1 -1
  7. package/dist/esm/components/widgets/SybilionAppHeader/SybilionAppHeader.js +4 -2
  8. package/dist/esm/components/widgets/SybilionAppHeader/SybilionAppHeader.styl.js +2 -2
  9. package/dist/esm/docs/contexts/theme-context.js +14 -0
  10. package/dist/esm/docs/lib/theme.js +23 -0
  11. package/dist/esm/types/src/components/ui/Logo/Logo.d.ts +5 -0
  12. package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.d.ts +1 -1
  13. package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.types.d.ts +0 -4
  14. package/dist/esm/types/src/components/widgets/SybilionAppHeader/SybilionAppHeader.d.ts +7 -1
  15. package/dist/esm/types/src/docs/contexts/theme-context.d.ts +1 -0
  16. package/dist/esm/types/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.constants.d.ts +7 -0
  17. package/docs/standalone-apps.md +111 -12
  18. package/package.json +3 -2
  19. package/src/assets/logo.svg +3 -0
  20. package/src/components/ui/AppHeader/AppHeader.styl +5 -0
  21. package/src/components/ui/Logo/Logo.styl +2 -0
  22. package/src/components/ui/Logo/Logo.tsx +12 -1
  23. package/src/components/ui/NavUserHeader/NavUserHeader.tsx +15 -17
  24. package/src/components/ui/NavUserHeader/NavUserHeader.types.ts +0 -4
  25. package/src/components/ui/Sidebar/Sidebar.styl +1 -1
  26. package/src/components/widgets/SybilionAppHeader/SybilionAppHeader.styl +46 -0
  27. package/src/components/widgets/SybilionAppHeader/SybilionAppHeader.styl.d.ts +3 -0
  28. package/src/components/widgets/SybilionAppHeader/SybilionAppHeader.tsx +23 -0
  29. package/src/docs/config/webpack.config.js +4 -3
  30. package/src/docs/contexts/theme-context.tsx +14 -1
  31. package/src/docs/pages/NavUserHeaderPage.tsx +1 -20
  32. package/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.constants.ts +444 -0
  33. package/src/docs/pages/{StandaloneAppLayoutPage.styl → StandaloneAppLayoutPage/StandaloneAppLayoutPage.styl} +11 -21
  34. package/src/docs/pages/{StandaloneAppLayoutPage.styl.d.ts → StandaloneAppLayoutPage/StandaloneAppLayoutPage.styl.d.ts} +1 -0
  35. package/src/docs/pages/{StandaloneAppLayoutPage.tsx → StandaloneAppLayoutPage/StandaloneAppLayoutPage.tsx} +18 -116
  36. package/src/docs/registry.ts +2 -1
  37. /package/dist/esm/types/src/docs/pages/{StandaloneAppLayoutPage.d.ts → StandaloneAppLayoutPage/StandaloneAppLayoutPage.d.ts} +0 -0
@@ -125,17 +125,18 @@
125
125
  --font-family-heading: 'KMR Apparat', sans-serif;
126
126
  --font-family-body: 'Manrope', sans-serif;
127
127
 
128
- --brand-color: var(--sb-purple-400);
129
- --brand-color-50: var(--sb-purple-50);
130
- --brand-color-100: var(--sb-purple-100);
131
- --brand-color-200: var(--sb-purple-200);
132
- --brand-color-300: var(--sb-purple-300);
133
- --brand-color-400: var(--sb-purple-400);
134
- --brand-color-500: var(--sb-purple-500);
135
- --brand-color-600: var(--sb-purple-600);
136
- --brand-color-700: var(--sb-purple-700);
137
- --brand-color-800: var(--sb-purple-800);
138
- --brand-color-900: var(--sb-purple-900);
128
+ /* Same mapping as sybilion-client/assets/globals.css (app variables) */
129
+ --brand-color: var(--sb-cyan-400);
130
+ --brand-color-50: var(--sb-cyan-50);
131
+ --brand-color-100: var(--sb-cyan-100);
132
+ --brand-color-200: var(--sb-cyan-200);
133
+ --brand-color-300: var(--sb-cyan-300);
134
+ --brand-color-400: var(--sb-cyan-400);
135
+ --brand-color-500: var(--sb-cyan-500);
136
+ --brand-color-600: var(--sb-cyan-600);
137
+ --brand-color-700: var(--sb-cyan-700);
138
+ --brand-color-800: var(--sb-cyan-800);
139
+ --brand-color-900: var(--sb-cyan-900);
139
140
  --header-height: 94px;
140
141
  --page-x-padding: var(--p-16);
141
142
  --page-y-padding: var(--p-12);
@@ -1,6 +1,6 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.AppHeader_root__SdbDv{align-items:center;align-self:flex-end;background-color:var(--color-background);display:flex;max-width:calc(100vw - var(--sidebar-width) - var(--p-3));min-height:var(--header-height);width:100%}.AppHeader_content__kyxem{align-items:center;display:flex;gap:2rem;justify-content:flex-end;padding:0 var(--p-9);width:100%}.AppHeader_logo__v31FX{align-items:center;color:var(--color-foreground);display:flex;font-size:1.5rem;font-weight:400;gap:.5rem;text-decoration:none;white-space:nowrap}.AppHeader_logo__v31FX svg{display:inline-flex;height:32px;transition:transform .1s ease-in-out;width:auto}.AppHeader_logo__v31FX:hover svg{transform:scale(1.05)}.AppHeader_nav__ahN1p{align-items:center;display:flex;flex:1;gap:1.5rem;justify-content:center}@media (max-width:units(768px,\"px\")){.AppHeader_nav__ahN1p{display:none}}.AppHeader_navLink__z43jY{color:var(--color-muted-foreground);font-size:.875rem;font-weight:400;text-decoration:none;transition:color .2s ease}.AppHeader_navLink__z43jY:hover{color:var(--color-foreground)}.AppHeader_actions__QuxEF{align-items:center;display:flex;gap:var(--p-4);margin-right:var(--p-2)}@media (max-width:units(768px,\"px\")){.AppHeader_actions__QuxEF{gap:var(--p-1)}}.AppHeader_pageHeaderActionsAnchor__qzQMs{align-items:center;display:flex;flex-shrink:0;gap:var(--p-4)}";
3
+ var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.AppHeader_root__SdbDv{align-items:center;align-self:flex-end;background-color:var(--color-background);display:flex;max-width:calc(100vw - var(--sidebar-width) - var(--p-3));min-height:var(--header-height);width:100%}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=collapsed] .AppHeader_root__SdbDv{max-width:100%;padding-left:200px}}.AppHeader_content__kyxem{align-items:center;display:flex;gap:2rem;justify-content:flex-end;padding:0 var(--p-9);width:100%}.AppHeader_logo__v31FX{align-items:center;color:var(--color-foreground);display:flex;font-size:1.5rem;font-weight:400;gap:.5rem;text-decoration:none;white-space:nowrap}.AppHeader_logo__v31FX svg{display:inline-flex;height:32px;transition:transform .1s ease-in-out;width:auto}.AppHeader_logo__v31FX:hover svg{transform:scale(1.05)}.AppHeader_nav__ahN1p{align-items:center;display:flex;flex:1;gap:1.5rem;justify-content:center}@media (max-width:units(768px,\"px\")){.AppHeader_nav__ahN1p{display:none}}.AppHeader_navLink__z43jY{color:var(--color-muted-foreground);font-size:.875rem;font-weight:400;text-decoration:none;transition:color .2s ease}.AppHeader_navLink__z43jY:hover{color:var(--color-foreground)}.AppHeader_actions__QuxEF{align-items:center;display:flex;gap:var(--p-4);margin-right:var(--p-2)}@media (max-width:units(768px,\"px\")){.AppHeader_actions__QuxEF{gap:var(--p-1)}}.AppHeader_pageHeaderActionsAnchor__qzQMs{align-items:center;display:flex;flex-shrink:0;gap:var(--p-4)}";
4
4
  var S = {"root":"AppHeader_root__SdbDv","content":"AppHeader_content__kyxem","logo":"AppHeader_logo__v31FX","nav":"AppHeader_nav__ahN1p","navLink":"AppHeader_navLink__z43jY","actions":"AppHeader_actions__QuxEF","pageHeaderActionsAnchor":"AppHeader_pageHeaderActionsAnchor__qzQMs"};
5
5
  styleInject(css_248z);
6
6
 
@@ -2,8 +2,13 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import cn from 'classnames';
3
3
  import S from './Logo.styl.js';
4
4
 
5
+ /**
6
+ * Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
7
+ * to `public/logo.svg` (see standalone-apps guide). Same path as the favicon `<link href>`.
8
+ */
9
+ const SYBILION_STANDALONE_LOGO_PUBLIC_URL = '/logo.svg';
5
10
  function Logo({ showText = true, size = 'md', className, ...props }) {
6
- return (jsxs("div", { className: cn(S.root, S[size], className), ...props, children: [jsx("img", { src: "/logo.svg", alt: "Sybilion", className: S.icon }), showText && jsx("span", { className: S.text, children: "Sybilion" })] }));
11
+ return (jsxs("div", { className: cn(S.root, S[size], className), ...props, children: [jsx("img", { src: SYBILION_STANDALONE_LOGO_PUBLIC_URL, alt: showText ? '' : 'Sybilion', className: S.icon, ...(showText ? { 'aria-hidden': true } : {}) }), showText && jsx("span", { className: S.text, children: "Sybilion" })] }));
7
12
  }
8
13
 
9
- export { Logo };
14
+ export { Logo, SYBILION_STANDALONE_LOGO_PUBLIC_URL };
@@ -1,6 +1,6 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = ".Logo_root__-IFVw{align-items:center;color:var(--color-foreground);display:flex;gap:8px}.Logo_icon__cE1BI{height:24px;width:auto}.Logo_text__YpU3U{font-family:var(--font-family-heading);line-height:48px}.Logo_sm__p25D- .Logo_icon__cE1BI{height:18px}.Logo_sm__p25D- .Logo_text__YpU3U{font-size:var(--text-lg);line-height:36px}.Logo_md__1Y9mG .Logo_icon__cE1BI{height:24px}.Logo_md__1Y9mG .Logo_text__YpU3U{font-size:var(--text-2xl);line-height:48px}.Logo_lg__V9Yy2 .Logo_icon__cE1BI{height:32px}.Logo_lg__V9Yy2 .Logo_text__YpU3U{font-size:var(--text-3xl);line-height:56px}";
3
+ var css_248z = ".Logo_root__-IFVw{align-items:center;color:var(--color-foreground);display:flex;gap:8px}.Logo_icon__cE1BI{display:block;flex-shrink:0;height:24px;width:auto}.Logo_text__YpU3U{font-family:var(--font-family-heading);line-height:48px}.Logo_sm__p25D- .Logo_icon__cE1BI{height:18px}.Logo_sm__p25D- .Logo_text__YpU3U{font-size:var(--text-lg);line-height:36px}.Logo_md__1Y9mG .Logo_icon__cE1BI{height:24px}.Logo_md__1Y9mG .Logo_text__YpU3U{font-size:var(--text-2xl);line-height:48px}.Logo_lg__V9Yy2 .Logo_icon__cE1BI{height:32px}.Logo_lg__V9Yy2 .Logo_text__YpU3U{font-size:var(--text-3xl);line-height:56px}";
4
4
  var S = {"root":"Logo_root__-IFVw","icon":"Logo_icon__cE1BI","text":"Logo_text__YpU3U","sm":"Logo_sm__p25D-","md":"Logo_md__1Y9mG","lg":"Logo_lg__V9Yy2"};
5
5
  styleInject(css_248z);
6
6
 
@@ -1,5 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import cn from 'classnames';
3
+ import { useTheme } from '../../../docs/contexts/theme-context.js';
3
4
  import { UserCircleIcon, SunIcon, MoonIcon, SignOutIcon } from '@phosphor-icons/react';
4
5
  import { ChevronDownIcon } from 'lucide-react';
5
6
  import { Avatar } from '../Avatar/Avatar.js';
@@ -8,7 +9,8 @@ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLab
8
9
  import { Image } from '../Image/Image.js';
9
10
  import S from './NavUserHeader.styl.js';
10
11
 
11
- function NavUserHeader({ variant = 'default', isLoading = false, isAuthenticated, user = null, menuItems, theme, onThemeToggle, onLogout, signInSlot, onSignInClick, }) {
12
+ function NavUserHeader({ variant = 'default', isLoading = false, isAuthenticated, user = null, menuItems, onLogout, signInSlot, onSignInClick, }) {
13
+ const { toggleTheme, theme } = useTheme();
12
14
  const authenticated = isAuthenticated ?? true;
13
15
  const avatarUrl = user?.avatar ?? '';
14
16
  const userName = user?.name ?? '';
@@ -22,7 +24,7 @@ function NavUserHeader({ variant = 'default', isLoading = false, isAuthenticated
22
24
  }
23
25
  return (jsxs(Button, { variant: "ghost", size: "sm", className: S.loginButton, type: "button", onClick: onSignInClick, children: [jsx(UserCircleIcon, { className: S.iconLg }), jsx("span", { children: "Log in" })] }));
24
26
  }
25
- return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "ghost", size: "sm", className: cn(S.userButton, variant === 'compact' && S.compact), children: [jsx(Avatar, { className: S.avatar, children: jsx(Image, { url: avatarUrl, alt: userName, fallback: jsx("div", { className: S.avatarFallback }) }) }), variant === 'default' && (jsxs(Fragment, { children: [jsxs("div", { className: S.userInfo, children: [jsx("span", { className: `${S.userName} ph-no-capture`, children: userName }), jsx("span", { className: S.userEmail, children: userEmail })] }), jsx(ChevronDownIcon, { className: S.iconSm })] }))] }) }), jsxs(DropdownMenuContent, { className: S.dropdownContent, align: "end", elevation: "md", children: [jsx(DropdownMenuLabel, { className: S.userLabel, children: jsxs("div", { className: S.userLabelContent, children: [jsx(Avatar, { className: S.avatar, children: jsx(Image, { url: avatarUrl, alt: userName, fallback: jsx("div", { className: S.avatarFallback }) }) }), jsxs("div", { className: S.userDetails, children: [jsx("span", { className: `${S.userDetailName} ph-no-capture`, children: userName }), jsx("span", { className: S.userDetailEmail, children: userEmail })] })] }) }), jsx(DropdownMenuSeparator, {}), jsxs(DropdownMenuGroup, { children: [menuItems, onThemeToggle ? (jsx(DropdownMenuItem, { onSelect: () => onThemeToggle(), children: theme === 'dark' ? (jsxs(Fragment, { children: [jsx(SunIcon, {}), "Light theme"] })) : (jsxs(Fragment, { children: [jsx(MoonIcon, {}), "Dark theme"] })) })) : null] }), jsx(DropdownMenuSeparator, {}), jsxs(DropdownMenuItem, { variant: "destructive", onSelect: () => onLogout(), children: [jsx(SignOutIcon, {}), "Log out"] })] })] }));
27
+ return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "ghost", size: "sm", className: cn(S.userButton, variant === 'compact' && S.compact), children: [jsx(Avatar, { className: S.avatar, children: jsx(Image, { url: avatarUrl, alt: userName, fallback: jsx("div", { className: S.avatarFallback }) }) }), variant === 'default' && (jsxs(Fragment, { children: [jsxs("div", { className: S.userInfo, children: [jsx("span", { className: `${S.userName} ph-no-capture`, children: userName }), jsx("span", { className: S.userEmail, children: userEmail })] }), jsx(ChevronDownIcon, { className: S.iconSm })] }))] }) }), jsxs(DropdownMenuContent, { className: S.dropdownContent, align: "end", elevation: "md", children: [jsx(DropdownMenuLabel, { className: S.userLabel, children: jsxs("div", { className: S.userLabelContent, children: [jsx(Avatar, { className: S.avatar, children: jsx(Image, { url: avatarUrl, alt: userName, fallback: jsx("div", { className: S.avatarFallback }) }) }), jsxs("div", { className: S.userDetails, children: [jsx("span", { className: `${S.userDetailName} ph-no-capture`, children: userName }), jsx("span", { className: S.userDetailEmail, children: userEmail })] })] }) }), jsx(DropdownMenuSeparator, {}), jsxs(DropdownMenuGroup, { children: [menuItems, jsx(DropdownMenuItem, { onSelect: toggleTheme, children: theme === 'dark' ? (jsxs(Fragment, { children: [jsx(SunIcon, {}), "Light theme"] })) : (jsxs(Fragment, { children: [jsx(MoonIcon, {}), "Dark theme"] })) })] }), jsx(DropdownMenuSeparator, {}), jsxs(DropdownMenuItem, { variant: "destructive", onSelect: () => onLogout(), children: [jsx(SignOutIcon, {}), "Log out"] })] })] }));
26
28
  }
27
29
 
28
30
  export { NavUserHeader };
@@ -1,6 +1,6 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.Sidebar_sidebarWrapper__DGm4P{align-items:stretch;display:flex;flex-direction:row;--welcome-alert-height:44px;height:calc(100% - 44px);height:calc(100% - var(--welcome-alert-height));min-height:0;width:100%}.Sidebar_sidebarWrapper__DGm4P #page-sidebar-actions{min-height:100%}@media (max-width:768px){.Sidebar_sidebarWrapper__DGm4P{flex-direction:column;height:100dvh;max-height:100dvh}}.Sidebar_sidebarMainShell__pSWDC{display:flex;flex:1;flex-direction:column;min-height:0;min-width:0}.Sidebar_chatPanelMount__1Zctx{background:var(--background);border-left:1px solid var(--border);flex:0 0 0px;flex:0 0 var(--chat-panel-width,0px);min-height:0;min-width:0;overflow:hidden;width:0;width:var(--chat-panel-width,0)}@media (max-width:768px){.Sidebar_chatPanelMount__1Zctx{border-left:none;border-top:1px solid var(--border);flex:0 0 0px;flex:0 0 var(--chat-panel-height,0px);height:0;height:var(--chat-panel-height,0);transition:flex-basis .2s ease,height .2s ease;width:100%}}.Sidebar_sidebar__0vqNZ{height:0;position:fixed;--top-offset:-10px;--gap-top:calc(var(--header-height) + var(--top-offset));align-self:flex-start;color:var(--sidebar-foreground);display:none;flex-direction:column;top:var(--gap-top);width:var(--sidebar-width)}@media (min-width:768px){.Sidebar_sidebar__0vqNZ[data-state=expanded]{display:flex;height:calc(100vh - var(--gap-top));min-height:0}}.Sidebar_sidebar__0vqNZ[data-collapsible=offcanvas]{overflow:hidden;padding:0;width:0}.Sidebar_sidebarTrigger__ipx2C{cursor:pointer;height:var(--p-5);width:var(--p-5)}.Sidebar_sidebarTrigger__ipx2C svg{height:20px;width:20px}.Sidebar_sidebarRail__uvSpl{position:absolute;inset-y:0;display:hidden;transition:all ease-out;width:1rem;z-index:20}.Sidebar_sidebarRail__uvSpl:hover:after{background-color:var(--sidebar-border)}.Sidebar_sidebarRail__uvSpl[data-side=left]{right:-1rem}.Sidebar_sidebarRail__uvSpl[data-side=right]{left:0}.Sidebar_sidebarRail__uvSpl:after{content:\"\";position:absolute;inset-y:0;left:50%;width:2px}@media (min-width:640px){.Sidebar_sidebarRail__uvSpl{display:flex}}.Sidebar_sidebarRail__uvSpl[data-side=left]{cursor:w-resize}.Sidebar_sidebarRail__uvSpl[data-side=left][data-state=collapsed],.Sidebar_sidebarRail__uvSpl[data-side=right]{cursor:e-resize}.Sidebar_sidebarRail__uvSpl[data-side=right][data-state=collapsed]{cursor:w-resize}.Sidebar_sidebarRail__uvSpl[data-collapsible=offcanvas]{transform:translateX(0)}.Sidebar_sidebarRail__uvSpl[data-collapsible=offcanvas]:hover{background-color:var(--sidebar)}.Sidebar_sidebarRail__uvSpl[data-collapsible=offcanvas]:after{left:100%}.Sidebar_sidebarRail__uvSpl[data-side=left][data-collapsible=offcanvas]{right:-.5rem}.Sidebar_sidebarRail__uvSpl[data-side=right][data-collapsible=offcanvas]{left:-.5rem}.Sidebar_sidebarResizeHandle__kuD6t{background-color:transparent;background-color:var(--page-color);border-radius:2.5px;height:calc(100vh + 200px);opacity:0;position:absolute;top:-200px;touch-action:none;transition:opacity .15s ease-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:5px;z-index:30}.Sidebar_sidebarResizeHandle__kuD6t:before{content:\"\";cursor:col-resize;height:100%;position:absolute;right:0;width:30px}.Sidebar_sidebarResizeHandle__kuD6t[data-side=left]{right:2px}.Sidebar_sidebarResizeHandle__kuD6t[data-side=right]{left:0}.Sidebar_sidebarResizeHandle__kuD6t:hover{opacity:1}.Sidebar_sidebarResizeHandle__kuD6t:active{opacity:0}.Sidebar_fullHeightResizer__jZXnw .Sidebar_sidebarResizeHandle__kuD6t{height:calc(100vh - var(--gap-top)*-1);top:-80px}.Sidebar_sidebarInput__ujQLX{background-color:var(--background);box-shadow:none;height:2rem;width:100%}.Sidebar_sidebarFooter__V3O-l,.Sidebar_sidebarHeader__X33ii{display:flex;flex-direction:column;gap:0;padding:0}.Sidebar_sidebarSeparator__oUkYG{background-color:var(--sidebar-border);margin-left:0;margin-right:0;width:auto}.Sidebar_sidebarContent__Ywe1o{display:flex;flex:1;flex-direction:column;gap:var(--p-16);height:100vh;max-height:100vh;min-height:0;overflow:auto;position:absolute;width:100%}@media (min-width:768px){.Sidebar_sidebarContent__Ywe1o{height:calc(100vh - var(--gap-top))}}.Sidebar_sidebarContent__Ywe1o[data-collapsible=icon]{overflow:hidden}.Sidebar_sidebarGroup__7Mhg2{display:flex;flex-direction:column;min-width:0;padding:40px 0 0;position:relative;width:100%}.Sidebar_sidebarGroupAction__OhVZq{align-items:center;aspect-ratio:1;border-radius:.375rem;color:var(--sidebar-foreground);display:flex;justify-content:center;outline:none;padding:0;position:absolute;right:.75rem;top:.875rem;transition:transform;width:1.25rem}.Sidebar_sidebarGroupAction__OhVZq:hover{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarGroupAction__OhVZq:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarGroupAction__OhVZq>svg{flex-shrink:0;height:1rem;width:1rem}.Sidebar_sidebarGroupAction__OhVZq:after{content:\"\";inset:-.5rem;position:absolute}@media (min-width:768px){.Sidebar_sidebarGroupAction__OhVZq:after{display:none}}.Sidebar_sidebarGroupAction__OhVZq[data-collapsible=icon]{display:none}.Sidebar_sidebarMenu__hYXIo{display:flex;flex-direction:column;gap:var(--p-4);list-style:none;min-width:0;padding:0 var(--p-11) var(--p-10) var(--p-8);width:100%}@media (max-width:768px){.Sidebar_sidebarMenu__hYXIo{padding-right:var(--p-8)}}.Sidebar_sidebarMenuItem__CRhM8{cursor:pointer;position:relative}.Sidebar_sidebarMenuBadge__ttvCR{align-items:center;border-radius:.375rem;color:var(--sidebar-foreground);display:flex;font-size:.75rem;font-weight:500;height:1.25rem;justify-content:center;min-width:1.25rem;padding-left:.25rem;padding-right:.25rem;pointer-events:none;position:absolute;right:.25rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.Sidebar_sidebarMenuBadge__ttvCR[data-size=sm]{top:.25rem}.Sidebar_sidebarMenuBadge__ttvCR[data-size=md]{top:.375rem}.Sidebar_sidebarMenuBadge__ttvCR[data-size=lg]{top:.625rem}.Sidebar_sidebarMenuBadge__ttvCR[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuSkeleton__u2KoI{align-items:center;border-radius:.375rem;display:flex;gap:.5rem;height:2rem;padding-left:.5rem;padding-right:.5rem}.Sidebar_sidebarMenuSkeletonIcon__-1tvv{border-radius:.375rem;height:1rem;width:1rem}.Sidebar_sidebarMenuSkeletonText__dWzWo{flex:1;height:1rem;max-width:var(--skeleton-width)}.Sidebar_sidebarMenuSub__gh8Rn{border-color:var(--sidebar-border);border-left:none;display:flex;flex-direction:column;gap:var(--p-2);list-style:none;margin-left:0;margin-right:0;min-width:0;padding:0;padding-top:var(--p-1);position:relative;transform:translateX(1px)}.Sidebar_sidebarMenuSub__gh8Rn:before{background:var(--sidebar-border);bottom:26px;content:\"\";left:var(--p-5);pointer-events:none;position:absolute;top:0;width:1px}.Sidebar_sidebarMenuSub__gh8Rn[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuSubItem__fTHJa{margin-left:var(--p-6);position:relative}.Sidebar_sidebarMenuSubItem__fTHJa:before{border-bottom:1px solid var(--sidebar-border);border-bottom-left-radius:var(--p-2);border-left:1px solid var(--sidebar-border);bottom:0;content:\"\";height:var(--p-3);left:calc(var(--p-1)*-1);position:absolute;top:var(--p-2);width:var(--p-3)}.Sidebar_sidebarMenuSubItem__fTHJa a:hover{text-decoration:none}.Sidebar_sheetContentSidebar__cM2h2{color:var(--sidebar-foreground);padding:0;width:var(--sidebar-width)}.Sidebar_sheetContentSidebar__cM2h2>button{display:none}@media (max-width:768px){.Sidebar_sheetContentSidebar__cM2h2{z-index:100}}.Sidebar_sheetSidebarInner__U-SMQ{background-color:var(--sidebar);display:flex;flex-direction:column;height:100%;width:100%}.Sidebar_sidebarNone__crRsF{color:var(--sidebar-foreground);display:flex;flex-direction:column;height:100%;width:var(--sidebar-width)}.Sidebar_variant-floating__-qvkJ{padding:.5rem}.Sidebar_variant-floating__-qvkJ[data-collapsible=icon],.Sidebar_variant-inset__oTfrV[data-collapsible=icon]{width:calc(var(--sidebar-width-icon) + 1rem + 2px)}.Sidebar_variant-sidebar__fAe77[data-collapsible=icon]{width:var(--sidebar-width-icon)}.Sidebar_variant-sidebar__fAe77[data-side=left]{border-right:1px solid #e5e7eb}.Sidebar_variant-sidebar__fAe77[data-side=right]{border-left:1px solid #e5e7eb}.Sidebar_sidebarMenuButton__vIEh->span,.Sidebar_sidebarMenuSubButton__c9flh>span{min-width:0;text-transform:capitalize}.Sidebar_sidebarMenuButton__vIEh->span:first-child,.Sidebar_sidebarMenuSubButton__c9flh>span:first-child{flex-grow:1}.Sidebar_sidebarMenuButton__vIEh-{align-items:center;border-radius:var(--p-3);color:var(--sidebar-foreground);cursor:pointer;display:flex;font-size:.875rem;gap:var(--p-2);justify-content:flex-start;outline:none;overflow:hidden;padding:var(--p-6) var(--p-3);text-align:left;text-decoration:none;transition:all;width:100%}.Sidebar_sidebarMenuButton__vIEh-:visited{color:var(--sidebar-foreground)}.Sidebar_sidebarMenuButton__vIEh-:hover{text-decoration:none}.Sidebar_sidebarMenuSubItem__fTHJa:active .Sidebar_sidebarMenuButton__vIEh-,.Sidebar_sidebarMenuSubItem__fTHJa:hover .Sidebar_sidebarMenuButton__vIEh-,.Sidebar_sidebarMenuSubItem__fTHJa[data-state=open] .Sidebar_sidebarMenuButton__vIEh-{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuButton__vIEh-:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarMenuButton__vIEh-:disabled,.Sidebar_sidebarMenuButton__vIEh-[aria-disabled=true]{opacity:.5;pointer-events:none}.Sidebar_sidebarMenuButton__vIEh-[data-active=true]{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground);font-weight:500}.Sidebar_sidebarMenuButton__vIEh-[data-collapsible=icon]{height:2rem!important;padding:.5rem!important;width:2rem!important}.Sidebar_sidebarMenuButton__vIEh->span{flex-grow:1;line-height:20px;overflow:hidden;white-space:nowrap}.Sidebar_sidebarMenuButton__vIEh->svg{flex-shrink:0;height:var(--p-5);width:var(--p-5)}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-sm__7aIbu{font-size:.75rem;height:1.75rem}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-md__rcjmO{font-size:.875rem;height:var(--p-12)}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-lg__1k76S{font-size:.875rem;height:3rem}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-lg__1k76S[data-collapsible=icon]{padding:0!important}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_variant-outline__UmtAz{background-color:var(--background);box-shadow:0 0 0 1px var(--sidebar-border)}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_variant-outline__UmtAz:hover{background-color:var(--sidebar-accent);box-shadow:0 0 0 1px var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuButtonCta__dQAhv{display:flex;justify-content:flex-start;text-align:left;width:100%}.Sidebar_sidebarMenuButtonCta__dQAhv>svg{flex-shrink:0;height:var(--p-5);width:var(--p-5)}.Sidebar_sidebarMenuAction__mFZa1{align-items:center;aspect-ratio:1;border-radius:.375rem;color:var(--sidebar-foreground);cursor:pointer;display:flex;justify-content:center;opacity:0;outline:none;padding:0;position:absolute;right:var(--p-2);top:var(--p-2);transition:transform;width:1.25rem}.Sidebar_sidebarMenuAction__mFZa1:before{background-image:linear-gradient(to left,var(--sidebar-accent) 70%,transparent 100%);content:\"\";height:100%;pointer-events:none;position:absolute;right:0;transition:opacity .2s ease-in-out;width:calc(100% + var(--p-4))}.Sidebar_sidebarMenuSubItem__fTHJa:hover .Sidebar_sidebarMenuAction__mFZa1{opacity:1}.Sidebar_sidebarMenuAction__mFZa1:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarMenuAction__mFZa1>svg{flex-shrink:0;height:1rem;opacity:.5;pointer-events:none;transition:opacity .2s ease-in-out;width:1rem;z-index:1}.Sidebar_sidebarMenuAction__mFZa1:hover>svg{opacity:1}.Sidebar_sidebarMenuAction__mFZa1:after{content:\"\";inset:-.5rem;position:absolute}@media (min-width:768px){.Sidebar_sidebarMenuAction__mFZa1:after{display:none}}.Sidebar_sidebarMenuAction__mFZa1[data-size=sm]{top:.25rem}.Sidebar_sidebarMenuAction__mFZa1[data-size=md]{top:.375rem}.Sidebar_sidebarMenuAction__mFZa1[data-size=lg]{top:.625rem}.Sidebar_sidebarMenuAction__mFZa1[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA[data-active=true]{color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA[data-state=open]{opacity:1}@media (min-width:768px){.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA{opacity:0}.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA:focus-within,.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA:hover{opacity:1}}.Sidebar_sidebarMenuSubButton__c9flh{align-items:center;border-radius:var(--p-3);color:var(--sidebar-foreground);cursor:pointer;display:flex;gap:var(--p-1);height:var(--p-9);margin-left:var(--p-3);min-width:0;outline:none;overflow:hidden;padding:var(--p-1) var(--p-2);text-decoration:none;transform:translateX(-1px)}.Sidebar_sidebarMenuSubButton__c9flh:visited{color:var(--sidebar-foreground)}.Sidebar_sidebarMenuSubButton__c9flh:hover{text-decoration:none}.Sidebar_sidebarMenuSubItem__fTHJa:active .Sidebar_sidebarMenuSubButton__c9flh,.Sidebar_sidebarMenuSubItem__fTHJa:hover .Sidebar_sidebarMenuSubButton__c9flh{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuSubButton__c9flh:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarMenuSubButton__c9flh:disabled,.Sidebar_sidebarMenuSubButton__c9flh[aria-disabled=true]{opacity:.5;pointer-events:none}.Sidebar_sidebarMenuSubButton__c9flh[data-active=true]{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuSubButton__c9flh[data-active=true]:visited{color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuSubButton__c9flh[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuSubButton__c9flh>span:first-child{overflow:hidden;white-space:nowrap}.Sidebar_sidebarMenuSubButton__c9flh>svg{color:var(--sidebar-accent-foreground);flex-shrink:0;height:1rem;width:1rem}.Sidebar_sidebarMenuSubButton__c9flh.Sidebar_size-sm__7aIbu{font-size:.75rem}.Sidebar_sidebarMenuSubButton__c9flh.Sidebar_size-md__rcjmO{font-size:.875rem}.Sidebar_sidebarMenuSubButton__c9flh.Sidebar_size-lg__1k76S{font-size:1rem}::view-transition-old(sidebar-container),::view-transition-old(sidebar-gap){animation-duration:.2s;animation-name:Sidebar_sidebarVtOld__hlKqn;animation-timing-function:ease-out;transform:translateZ(0)}::view-transition-new(sidebar-container),::view-transition-new(sidebar-gap){animation-duration:.2s;animation-name:Sidebar_sidebarVtNew__FFhYU;animation-timing-function:ease-out;transform:translateZ(0)}@keyframes Sidebar_sidebarVtOld__hlKqn{0%{opacity:1}to{opacity:0}}@keyframes Sidebar_sidebarVtNew__FFhYU{0%{opacity:0}to{opacity:1}}";
3
+ var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.Sidebar_sidebarWrapper__DGm4P{align-items:stretch;display:flex;flex-direction:row;--welcome-alert-height:44px;height:calc(100% - 44px);height:calc(100% - var(--welcome-alert-height));min-height:0;width:100%}.Sidebar_sidebarWrapper__DGm4P #page-sidebar-actions{min-height:100%}@media (max-width:768px){.Sidebar_sidebarWrapper__DGm4P{flex-direction:column;height:100dvh;max-height:100dvh}}.Sidebar_sidebarMainShell__pSWDC{display:flex;flex:1;flex-direction:column;min-height:0;min-width:0}.Sidebar_chatPanelMount__1Zctx{background:var(--background);border-left:1px solid var(--border);flex:0 0 0px;flex:0 0 var(--chat-panel-width,0px);min-height:0;min-width:0;overflow:hidden;width:0;width:var(--chat-panel-width,0)}@media (max-width:768px){.Sidebar_chatPanelMount__1Zctx{border-left:none;border-top:1px solid var(--border);flex:0 0 0px;flex:0 0 var(--chat-panel-height,0px);height:0;height:var(--chat-panel-height,0);transition:flex-basis .2s ease,height .2s ease;width:100%}}.Sidebar_sidebar__0vqNZ{height:0;position:fixed;--top-offset:-10px;--gap-top:calc(var(--header-height) + var(--top-offset));align-self:flex-start;color:var(--sidebar-foreground);display:none;flex-direction:column;top:var(--gap-top);width:var(--sidebar-width)}@media (min-width:768px){.Sidebar_sidebar__0vqNZ[data-state=expanded]{display:flex;height:calc(100% - var(--gap-top));min-height:0}}.Sidebar_sidebar__0vqNZ[data-collapsible=offcanvas]{overflow:hidden;padding:0;width:0}.Sidebar_sidebarTrigger__ipx2C{cursor:pointer;height:var(--p-5);width:var(--p-5)}.Sidebar_sidebarTrigger__ipx2C svg{height:20px;width:20px}.Sidebar_sidebarRail__uvSpl{position:absolute;inset-y:0;display:hidden;transition:all ease-out;width:1rem;z-index:20}.Sidebar_sidebarRail__uvSpl:hover:after{background-color:var(--sidebar-border)}.Sidebar_sidebarRail__uvSpl[data-side=left]{right:-1rem}.Sidebar_sidebarRail__uvSpl[data-side=right]{left:0}.Sidebar_sidebarRail__uvSpl:after{content:\"\";position:absolute;inset-y:0;left:50%;width:2px}@media (min-width:640px){.Sidebar_sidebarRail__uvSpl{display:flex}}.Sidebar_sidebarRail__uvSpl[data-side=left]{cursor:w-resize}.Sidebar_sidebarRail__uvSpl[data-side=left][data-state=collapsed],.Sidebar_sidebarRail__uvSpl[data-side=right]{cursor:e-resize}.Sidebar_sidebarRail__uvSpl[data-side=right][data-state=collapsed]{cursor:w-resize}.Sidebar_sidebarRail__uvSpl[data-collapsible=offcanvas]{transform:translateX(0)}.Sidebar_sidebarRail__uvSpl[data-collapsible=offcanvas]:hover{background-color:var(--sidebar)}.Sidebar_sidebarRail__uvSpl[data-collapsible=offcanvas]:after{left:100%}.Sidebar_sidebarRail__uvSpl[data-side=left][data-collapsible=offcanvas]{right:-.5rem}.Sidebar_sidebarRail__uvSpl[data-side=right][data-collapsible=offcanvas]{left:-.5rem}.Sidebar_sidebarResizeHandle__kuD6t{background-color:transparent;background-color:var(--page-color);border-radius:2.5px;height:calc(100vh + 200px);opacity:0;position:absolute;top:-200px;touch-action:none;transition:opacity .15s ease-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:5px;z-index:30}.Sidebar_sidebarResizeHandle__kuD6t:before{content:\"\";cursor:col-resize;height:100%;position:absolute;right:0;width:30px}.Sidebar_sidebarResizeHandle__kuD6t[data-side=left]{right:2px}.Sidebar_sidebarResizeHandle__kuD6t[data-side=right]{left:0}.Sidebar_sidebarResizeHandle__kuD6t:hover{opacity:1}.Sidebar_sidebarResizeHandle__kuD6t:active{opacity:0}.Sidebar_fullHeightResizer__jZXnw .Sidebar_sidebarResizeHandle__kuD6t{height:calc(100vh - var(--gap-top)*-1);top:-80px}.Sidebar_sidebarInput__ujQLX{background-color:var(--background);box-shadow:none;height:2rem;width:100%}.Sidebar_sidebarFooter__V3O-l,.Sidebar_sidebarHeader__X33ii{display:flex;flex-direction:column;gap:0;padding:0}.Sidebar_sidebarSeparator__oUkYG{background-color:var(--sidebar-border);margin-left:0;margin-right:0;width:auto}.Sidebar_sidebarContent__Ywe1o{display:flex;flex:1;flex-direction:column;gap:var(--p-16);height:100vh;max-height:100vh;min-height:0;overflow:auto;position:absolute;width:100%}@media (min-width:768px){.Sidebar_sidebarContent__Ywe1o{height:calc(100vh - var(--gap-top))}}.Sidebar_sidebarContent__Ywe1o[data-collapsible=icon]{overflow:hidden}.Sidebar_sidebarGroup__7Mhg2{display:flex;flex-direction:column;min-width:0;padding:40px 0 0;position:relative;width:100%}.Sidebar_sidebarGroupAction__OhVZq{align-items:center;aspect-ratio:1;border-radius:.375rem;color:var(--sidebar-foreground);display:flex;justify-content:center;outline:none;padding:0;position:absolute;right:.75rem;top:.875rem;transition:transform;width:1.25rem}.Sidebar_sidebarGroupAction__OhVZq:hover{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarGroupAction__OhVZq:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarGroupAction__OhVZq>svg{flex-shrink:0;height:1rem;width:1rem}.Sidebar_sidebarGroupAction__OhVZq:after{content:\"\";inset:-.5rem;position:absolute}@media (min-width:768px){.Sidebar_sidebarGroupAction__OhVZq:after{display:none}}.Sidebar_sidebarGroupAction__OhVZq[data-collapsible=icon]{display:none}.Sidebar_sidebarMenu__hYXIo{display:flex;flex-direction:column;gap:var(--p-4);list-style:none;min-width:0;padding:0 var(--p-11) var(--p-10) var(--p-8);width:100%}@media (max-width:768px){.Sidebar_sidebarMenu__hYXIo{padding-right:var(--p-8)}}.Sidebar_sidebarMenuItem__CRhM8{cursor:pointer;position:relative}.Sidebar_sidebarMenuBadge__ttvCR{align-items:center;border-radius:.375rem;color:var(--sidebar-foreground);display:flex;font-size:.75rem;font-weight:500;height:1.25rem;justify-content:center;min-width:1.25rem;padding-left:.25rem;padding-right:.25rem;pointer-events:none;position:absolute;right:.25rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.Sidebar_sidebarMenuBadge__ttvCR[data-size=sm]{top:.25rem}.Sidebar_sidebarMenuBadge__ttvCR[data-size=md]{top:.375rem}.Sidebar_sidebarMenuBadge__ttvCR[data-size=lg]{top:.625rem}.Sidebar_sidebarMenuBadge__ttvCR[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuSkeleton__u2KoI{align-items:center;border-radius:.375rem;display:flex;gap:.5rem;height:2rem;padding-left:.5rem;padding-right:.5rem}.Sidebar_sidebarMenuSkeletonIcon__-1tvv{border-radius:.375rem;height:1rem;width:1rem}.Sidebar_sidebarMenuSkeletonText__dWzWo{flex:1;height:1rem;max-width:var(--skeleton-width)}.Sidebar_sidebarMenuSub__gh8Rn{border-color:var(--sidebar-border);border-left:none;display:flex;flex-direction:column;gap:var(--p-2);list-style:none;margin-left:0;margin-right:0;min-width:0;padding:0;padding-top:var(--p-1);position:relative;transform:translateX(1px)}.Sidebar_sidebarMenuSub__gh8Rn:before{background:var(--sidebar-border);bottom:26px;content:\"\";left:var(--p-5);pointer-events:none;position:absolute;top:0;width:1px}.Sidebar_sidebarMenuSub__gh8Rn[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuSubItem__fTHJa{margin-left:var(--p-6);position:relative}.Sidebar_sidebarMenuSubItem__fTHJa:before{border-bottom:1px solid var(--sidebar-border);border-bottom-left-radius:var(--p-2);border-left:1px solid var(--sidebar-border);bottom:0;content:\"\";height:var(--p-3);left:calc(var(--p-1)*-1);position:absolute;top:var(--p-2);width:var(--p-3)}.Sidebar_sidebarMenuSubItem__fTHJa a:hover{text-decoration:none}.Sidebar_sheetContentSidebar__cM2h2{color:var(--sidebar-foreground);padding:0;width:var(--sidebar-width)}.Sidebar_sheetContentSidebar__cM2h2>button{display:none}@media (max-width:768px){.Sidebar_sheetContentSidebar__cM2h2{z-index:100}}.Sidebar_sheetSidebarInner__U-SMQ{background-color:var(--sidebar);display:flex;flex-direction:column;height:100%;width:100%}.Sidebar_sidebarNone__crRsF{color:var(--sidebar-foreground);display:flex;flex-direction:column;height:100%;width:var(--sidebar-width)}.Sidebar_variant-floating__-qvkJ{padding:.5rem}.Sidebar_variant-floating__-qvkJ[data-collapsible=icon],.Sidebar_variant-inset__oTfrV[data-collapsible=icon]{width:calc(var(--sidebar-width-icon) + 1rem + 2px)}.Sidebar_variant-sidebar__fAe77[data-collapsible=icon]{width:var(--sidebar-width-icon)}.Sidebar_variant-sidebar__fAe77[data-side=left]{border-right:1px solid #e5e7eb}.Sidebar_variant-sidebar__fAe77[data-side=right]{border-left:1px solid #e5e7eb}.Sidebar_sidebarMenuButton__vIEh->span,.Sidebar_sidebarMenuSubButton__c9flh>span{min-width:0;text-transform:capitalize}.Sidebar_sidebarMenuButton__vIEh->span:first-child,.Sidebar_sidebarMenuSubButton__c9flh>span:first-child{flex-grow:1}.Sidebar_sidebarMenuButton__vIEh-{align-items:center;border-radius:var(--p-3);color:var(--sidebar-foreground);cursor:pointer;display:flex;font-size:.875rem;gap:var(--p-2);justify-content:flex-start;outline:none;overflow:hidden;padding:var(--p-6) var(--p-3);text-align:left;text-decoration:none;transition:all;width:100%}.Sidebar_sidebarMenuButton__vIEh-:visited{color:var(--sidebar-foreground)}.Sidebar_sidebarMenuButton__vIEh-:hover{text-decoration:none}.Sidebar_sidebarMenuSubItem__fTHJa:active .Sidebar_sidebarMenuButton__vIEh-,.Sidebar_sidebarMenuSubItem__fTHJa:hover .Sidebar_sidebarMenuButton__vIEh-,.Sidebar_sidebarMenuSubItem__fTHJa[data-state=open] .Sidebar_sidebarMenuButton__vIEh-{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuButton__vIEh-:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarMenuButton__vIEh-:disabled,.Sidebar_sidebarMenuButton__vIEh-[aria-disabled=true]{opacity:.5;pointer-events:none}.Sidebar_sidebarMenuButton__vIEh-[data-active=true]{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground);font-weight:500}.Sidebar_sidebarMenuButton__vIEh-[data-collapsible=icon]{height:2rem!important;padding:.5rem!important;width:2rem!important}.Sidebar_sidebarMenuButton__vIEh->span{flex-grow:1;line-height:20px;overflow:hidden;white-space:nowrap}.Sidebar_sidebarMenuButton__vIEh->svg{flex-shrink:0;height:var(--p-5);width:var(--p-5)}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-sm__7aIbu{font-size:.75rem;height:1.75rem}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-md__rcjmO{font-size:.875rem;height:var(--p-12)}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-lg__1k76S{font-size:.875rem;height:3rem}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_size-lg__1k76S[data-collapsible=icon]{padding:0!important}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_variant-outline__UmtAz{background-color:var(--background);box-shadow:0 0 0 1px var(--sidebar-border)}.Sidebar_sidebarMenuButton__vIEh-.Sidebar_variant-outline__UmtAz:hover{background-color:var(--sidebar-accent);box-shadow:0 0 0 1px var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuButtonCta__dQAhv{display:flex;justify-content:flex-start;text-align:left;width:100%}.Sidebar_sidebarMenuButtonCta__dQAhv>svg{flex-shrink:0;height:var(--p-5);width:var(--p-5)}.Sidebar_sidebarMenuAction__mFZa1{align-items:center;aspect-ratio:1;border-radius:.375rem;color:var(--sidebar-foreground);cursor:pointer;display:flex;justify-content:center;opacity:0;outline:none;padding:0;position:absolute;right:var(--p-2);top:var(--p-2);transition:transform;width:1.25rem}.Sidebar_sidebarMenuAction__mFZa1:before{background-image:linear-gradient(to left,var(--sidebar-accent) 70%,transparent 100%);content:\"\";height:100%;pointer-events:none;position:absolute;right:0;transition:opacity .2s ease-in-out;width:calc(100% + var(--p-4))}.Sidebar_sidebarMenuSubItem__fTHJa:hover .Sidebar_sidebarMenuAction__mFZa1{opacity:1}.Sidebar_sidebarMenuAction__mFZa1:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarMenuAction__mFZa1>svg{flex-shrink:0;height:1rem;opacity:.5;pointer-events:none;transition:opacity .2s ease-in-out;width:1rem;z-index:1}.Sidebar_sidebarMenuAction__mFZa1:hover>svg{opacity:1}.Sidebar_sidebarMenuAction__mFZa1:after{content:\"\";inset:-.5rem;position:absolute}@media (min-width:768px){.Sidebar_sidebarMenuAction__mFZa1:after{display:none}}.Sidebar_sidebarMenuAction__mFZa1[data-size=sm]{top:.25rem}.Sidebar_sidebarMenuAction__mFZa1[data-size=md]{top:.375rem}.Sidebar_sidebarMenuAction__mFZa1[data-size=lg]{top:.625rem}.Sidebar_sidebarMenuAction__mFZa1[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA[data-active=true]{color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA[data-state=open]{opacity:1}@media (min-width:768px){.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA{opacity:0}.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA:focus-within,.Sidebar_sidebarMenuAction__mFZa1.Sidebar_showOnHover__itXsA:hover{opacity:1}}.Sidebar_sidebarMenuSubButton__c9flh{align-items:center;border-radius:var(--p-3);color:var(--sidebar-foreground);cursor:pointer;display:flex;gap:var(--p-1);height:var(--p-9);margin-left:var(--p-3);min-width:0;outline:none;overflow:hidden;padding:var(--p-1) var(--p-2);text-decoration:none;transform:translateX(-1px)}.Sidebar_sidebarMenuSubButton__c9flh:visited{color:var(--sidebar-foreground)}.Sidebar_sidebarMenuSubButton__c9flh:hover{text-decoration:none}.Sidebar_sidebarMenuSubItem__fTHJa:active .Sidebar_sidebarMenuSubButton__c9flh,.Sidebar_sidebarMenuSubItem__fTHJa:hover .Sidebar_sidebarMenuSubButton__c9flh{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuSubButton__c9flh:focus-visible{box-shadow:0 0 0 2px var(--sidebar-ring)}.Sidebar_sidebarMenuSubButton__c9flh:disabled,.Sidebar_sidebarMenuSubButton__c9flh[aria-disabled=true]{opacity:.5;pointer-events:none}.Sidebar_sidebarMenuSubButton__c9flh[data-active=true]{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuSubButton__c9flh[data-active=true]:visited{color:var(--sidebar-accent-foreground)}.Sidebar_sidebarMenuSubButton__c9flh[data-collapsible=icon]{display:none}.Sidebar_sidebarMenuSubButton__c9flh>span:first-child{overflow:hidden;white-space:nowrap}.Sidebar_sidebarMenuSubButton__c9flh>svg{color:var(--sidebar-accent-foreground);flex-shrink:0;height:1rem;width:1rem}.Sidebar_sidebarMenuSubButton__c9flh.Sidebar_size-sm__7aIbu{font-size:.75rem}.Sidebar_sidebarMenuSubButton__c9flh.Sidebar_size-md__rcjmO{font-size:.875rem}.Sidebar_sidebarMenuSubButton__c9flh.Sidebar_size-lg__1k76S{font-size:1rem}::view-transition-old(sidebar-container),::view-transition-old(sidebar-gap){animation-duration:.2s;animation-name:Sidebar_sidebarVtOld__hlKqn;animation-timing-function:ease-out;transform:translateZ(0)}::view-transition-new(sidebar-container),::view-transition-new(sidebar-gap){animation-duration:.2s;animation-name:Sidebar_sidebarVtNew__FFhYU;animation-timing-function:ease-out;transform:translateZ(0)}@keyframes Sidebar_sidebarVtOld__hlKqn{0%{opacity:1}to{opacity:0}}@keyframes Sidebar_sidebarVtNew__FFhYU{0%{opacity:0}to{opacity:1}}";
4
4
  var SidebarStem = {"sidebarWrapper":"Sidebar_sidebarWrapper__DGm4P","sidebarMainShell":"Sidebar_sidebarMainShell__pSWDC","chatPanelMount":"Sidebar_chatPanelMount__1Zctx","sidebar":"Sidebar_sidebar__0vqNZ","sidebarTrigger":"Sidebar_sidebarTrigger__ipx2C","sidebarRail":"Sidebar_sidebarRail__uvSpl","sidebarResizeHandle":"Sidebar_sidebarResizeHandle__kuD6t","fullHeightResizer":"Sidebar_fullHeightResizer__jZXnw","sidebarInput":"Sidebar_sidebarInput__ujQLX","sidebarHeader":"Sidebar_sidebarHeader__X33ii","sidebarFooter":"Sidebar_sidebarFooter__V3O-l","sidebarSeparator":"Sidebar_sidebarSeparator__oUkYG","sidebarContent":"Sidebar_sidebarContent__Ywe1o","sidebarGroup":"Sidebar_sidebarGroup__7Mhg2","sidebarGroupAction":"Sidebar_sidebarGroupAction__OhVZq","sidebarMenu":"Sidebar_sidebarMenu__hYXIo","sidebarMenuItem":"Sidebar_sidebarMenuItem__CRhM8","sidebarMenuBadge":"Sidebar_sidebarMenuBadge__ttvCR","sidebarMenuSkeleton":"Sidebar_sidebarMenuSkeleton__u2KoI","sidebarMenuSkeletonIcon":"Sidebar_sidebarMenuSkeletonIcon__-1tvv","sidebarMenuSkeletonText":"Sidebar_sidebarMenuSkeletonText__dWzWo","sidebarMenuSub":"Sidebar_sidebarMenuSub__gh8Rn","sidebarMenuSubItem":"Sidebar_sidebarMenuSubItem__fTHJa","sheetContentSidebar":"Sidebar_sheetContentSidebar__cM2h2","sheetSidebarInner":"Sidebar_sheetSidebarInner__U-SMQ","sidebarNone":"Sidebar_sidebarNone__crRsF","variant-floating":"Sidebar_variant-floating__-qvkJ","variant-inset":"Sidebar_variant-inset__oTfrV","variant-sidebar":"Sidebar_variant-sidebar__fAe77","sidebarMenuButton":"Sidebar_sidebarMenuButton__vIEh-","sidebarMenuSubButton":"Sidebar_sidebarMenuSubButton__c9flh","size-sm":"Sidebar_size-sm__7aIbu","size-md":"Sidebar_size-md__rcjmO","size-lg":"Sidebar_size-lg__1k76S","variant-outline":"Sidebar_variant-outline__UmtAz","sidebarMenuButtonCta":"Sidebar_sidebarMenuButtonCta__dQAhv","sidebarMenuAction":"Sidebar_sidebarMenuAction__mFZa1","showOnHover":"Sidebar_showOnHover__itXsA","sidebarVtOld":"Sidebar_sidebarVtOld__hlKqn","sidebarVtNew":"Sidebar_sidebarVtNew__FFhYU"};
5
5
  styleInject(css_248z);
6
6
 
@@ -1,16 +1,18 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import cn from 'classnames';
3
+ import { Link } from 'react-router-dom';
3
4
  import { AppHeaderPortal } from '../../ui/AppHeader/AppHeader.js';
4
5
  import { PAGE_HEADER_ACTIONS_ID } from '../../ui/AppHeader/appChromeAnchors.js';
5
6
  import { Gap } from '../../ui/Gap/Gap.js';
7
+ import { Logo } from '../../ui/Logo/Logo.js';
6
8
  import { NavUserHeader } from '../../ui/NavUserHeader/NavUserHeader.js';
7
9
  import { WorkspaceAppSwitcher } from '../../ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.js';
8
10
  import '@phosphor-icons/react';
9
11
  import 'lucide-react';
10
12
  import S from './SybilionAppHeader.styl.js';
11
13
 
12
- function SybilionAppHeader({ pageHeaderId, actionsAnchorId = PAGE_HEADER_ACTIONS_ID, actionsAnchorClassName, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, ...navUserHeaderProps }) {
13
- return (jsxs(AppHeaderPortal, { pageHeaderId: pageHeaderId, children: [jsx(WorkspaceAppSwitcher, { pathname: pathname, onNavigate: onNavigate, authenticated: authenticated, defaultApps: defaultApps, appsStorageKey: appsStorageKey }), jsx(Gap, {}), jsx("div", { id: actionsAnchorId, className: cn(S.actionsAnchor, actionsAnchorClassName), children: jsx(NavUserHeader, { ...navUserHeaderProps }) })] }));
14
+ function SybilionAppHeader({ pageHeaderId, actionsAnchorId = PAGE_HEADER_ACTIONS_ID, actionsAnchorClassName, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }) {
15
+ return (jsxs(AppHeaderPortal, { pageHeaderId: pageHeaderId, children: [jsx("div", { className: cn(S.logoArea, welcomeBannerOffset && S.logoAreaWithBanner, logoAreaClassName), children: jsx(Link, { to: "/", className: S.logoLink, children: logo ?? jsx(Logo, { size: "md", "aria-hidden": true }) }) }), jsx(WorkspaceAppSwitcher, { pathname: pathname, onNavigate: onNavigate, authenticated: authenticated, defaultApps: defaultApps, appsStorageKey: appsStorageKey }), jsx(Gap, {}), jsx("div", { id: actionsAnchorId, className: cn(S.actionsAnchor, actionsAnchorClassName), children: jsx(NavUserHeader, { ...navUserHeaderProps }) })] }));
14
16
  }
15
17
 
16
18
  export { SybilionAppHeader };
@@ -1,7 +1,7 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.SybilionAppHeader_actionsAnchor__ress2{align-items:center;display:flex;flex-shrink:0;gap:var(--p-4)}";
4
- var S = {"actionsAnchor":"SybilionAppHeader_actionsAnchor__ress2"};
3
+ var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.SybilionAppHeader_actionsAnchor__ress2{align-items:center;display:flex;flex-shrink:0;gap:var(--p-4)}.SybilionAppHeader_logoArea__3HAhG{align-items:center;display:flex;gap:var(--p-2);left:40px;position:absolute;top:22px;z-index:10}@media (max-width:768px){.SybilionAppHeader_logoArea__3HAhG{left:32px}}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=expanded] .SybilionAppHeader_logoArea__3HAhG{position:fixed}}.SybilionAppHeader_logoAreaWithBanner__7Iy78{top:22px;top:calc(22px + var(--welcome-banner-height, 0px))}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=collapsed] .SybilionAppHeader_logoAreaWithBanner__7Iy78{top:22px}}.SybilionAppHeader_logoLink__bH-KX{align-items:center;color:var(--color-foreground);display:flex;font-size:1.5rem;font-weight:400;gap:.5rem;text-decoration:none;white-space:nowrap;width:-moz-fit-content;width:fit-content}.SybilionAppHeader_logoLink__bH-KX svg{display:inline-flex;flex-shrink:0;height:32px;transition:transform .1s ease-in-out;width:auto}.SybilionAppHeader_logoLink__bH-KX:hover svg{transform:scale(1.05)}";
4
+ var S = {"actionsAnchor":"SybilionAppHeader_actionsAnchor__ress2","logoArea":"SybilionAppHeader_logoArea__3HAhG","logoAreaWithBanner":"SybilionAppHeader_logoAreaWithBanner__7Iy78","logoLink":"SybilionAppHeader_logoLink__bH-KX"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { S as default };
@@ -0,0 +1,14 @@
1
+ import 'react/jsx-runtime';
2
+ import { createContext, useContext } from 'react';
3
+ import '@homecode/ui';
4
+ import '../lib/theme.js';
5
+
6
+ const ThemeContext = createContext({
7
+ theme: 'light',
8
+ isDarkMode: false,
9
+ setTheme: () => { },
10
+ toggleTheme: () => { },
11
+ });
12
+ const useTheme = () => useContext(ThemeContext);
13
+
14
+ export { useTheme };
@@ -0,0 +1,23 @@
1
+ import { ThemeHelpers, ThemeDefaults } from '@homecode/ui';
2
+
3
+ const { colors, getColors, getConfig } = ThemeDefaults;
4
+ getColors();
5
+ getConfig();
6
+ ({
7
+ light: {
8
+ ...ThemeHelpers.colorsConfigToVars({
9
+ ...getColors({
10
+ accent: colors.dark,
11
+ decent: colors.light,
12
+ }),
13
+ }),
14
+ },
15
+ dark: {
16
+ ...ThemeHelpers.colorsConfigToVars({
17
+ ...getColors({
18
+ accent: colors.light,
19
+ decent: colors.dark,
20
+ }),
21
+ }),
22
+ },
23
+ });
@@ -1,2 +1,7 @@
1
1
  import type { LogoProps } from './Logo.types';
2
+ /**
3
+ * Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
4
+ * to `public/logo.svg` (see standalone-apps guide). Same path as the favicon `<link href>`.
5
+ */
6
+ export declare const SYBILION_STANDALONE_LOGO_PUBLIC_URL: "/logo.svg";
2
7
  export declare function Logo({ showText, size, className, ...props }: LogoProps): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { NavUserHeaderProps } from './NavUserHeader.types';
2
- export declare function NavUserHeader({ variant, isLoading, isAuthenticated, user, menuItems, theme, onThemeToggle, onLogout, signInSlot, onSignInClick, }: NavUserHeaderProps): string | number | bigint | true | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode>> | import("react/jsx-runtime").JSX.Element;
2
+ export declare function NavUserHeader({ variant, isLoading, isAuthenticated, user, menuItems, onLogout, signInSlot, onSignInClick, }: NavUserHeaderProps): string | number | bigint | true | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode>> | import("react/jsx-runtime").JSX.Element;
@@ -14,10 +14,6 @@ export type NavUserHeaderProps = {
14
14
  user?: NavUserHeaderUser | null;
15
15
  /** Rows inside the menu above theme toggle and logout. Use `DropdownMenuItem` nodes. */
16
16
  menuItems?: ReactNode;
17
- /** Current theme drives the toggle row label/icons. */
18
- theme: 'light' | 'dark';
19
- /** When set, renders the light/dark theme menu row. */
20
- onThemeToggle?: () => void;
21
17
  onLogout: () => void;
22
18
  /** Replaces default “Log in” control when signed out. */
23
19
  signInSlot?: ReactNode;
@@ -1,8 +1,14 @@
1
+ import type { ReactNode } from 'react';
1
2
  import type { NavUserHeaderProps } from '#uilib/components/ui/NavUserHeader';
2
3
  import { type WorkspaceAppSwitcherProps } from '#uilib/components/ui/WorkspaceAppSwitcher';
3
4
  export type SybilionAppHeaderProps = WorkspaceAppSwitcherProps & NavUserHeaderProps & {
4
5
  pageHeaderId?: string;
5
6
  actionsAnchorId?: string;
6
7
  actionsAnchorClassName?: string;
8
+ /** Branded markup; omit for default lucide tile + «Sybilion». */
9
+ logo?: ReactNode;
10
+ logoAreaClassName?: string;
11
+ /** Applies vertical offset when a welcome banner consumes top space (CSS `--welcome-banner-height` on shell). */
12
+ welcomeBannerOffset?: boolean;
7
13
  };
8
- export declare function SybilionAppHeader({ pageHeaderId, actionsAnchorId, actionsAnchorClassName, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, ...navUserHeaderProps }: SybilionAppHeaderProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function SybilionAppHeader({ pageHeaderId, actionsAnchorId, actionsAnchorClassName, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }: SybilionAppHeaderProps): import("react/jsx-runtime").JSX.Element;
@@ -6,4 +6,5 @@ export declare const useTheme: () => {
6
6
  theme: ThemeMode;
7
7
  isDarkMode: boolean;
8
8
  setTheme: (theme: ThemeMode) => void;
9
+ toggleTheme: () => void;
9
10
  };
@@ -0,0 +1,7 @@
1
+ import { WorkspaceAppEntry } from '#uilib/components/ui/WorkspaceAppSwitcher';
2
+ import { SidebarDatasetsItemsGroupedDataset } from '#uilib/components/widgets/SidebarDatasetsItemsGrouped';
3
+ export declare const MOCK_DATASETS: SidebarDatasetsItemsGroupedDataset[];
4
+ export type PreviewPanel = 'home' | 'datasets';
5
+ export declare const TEST_HEADER_ID = "test-header-id";
6
+ export declare const DOCS_WORKSPACE_APPS_LS_KEY = "uilib.docs.workspaceApps";
7
+ export declare const DOCS_PREVIEW_APPS: WorkspaceAppEntry[];
@@ -15,12 +15,48 @@ yarn add react react-dom react-router-dom @auth0/auth0-react @sybilion/uilib @sy
15
15
  yarn add -D vite @vitejs/plugin-react
16
16
  ```
17
17
 
18
+ **React ecosystem versions (avoid collisions):** declare **`react`**, **`react-dom`**, **`react-router-dom`**, and **`@auth0/auth0-react`** as **direct** dependencies and align them with **`@sybilion/uilib`**, not arbitrary latest majors.
19
+
20
+ 1. After installing uilib, open **`node_modules/@sybilion/uilib/package.json`** (or this repo’s root **`package.json`** at the release you pin).
21
+ 2. **`peerDependencies`** — satisfy these ranges in your app (`react` / `react-dom`, `react-router-dom`, `@auth0/auth0-react`, and **`vite`** when you use the Vite helpers).
22
+ 3. **`devDependencies`** — for **`react`**, **`react-dom`**, and **`react-router-dom`**, prefer **the same versions uilib lists there** (what its docs build and tests run against). Re-read this file whenever you bump **`@sybilion/uilib`** so your app does not drift to another React major while uilib does not.
23
+
24
+ Mismatched or duplicated React (two copies in the bundle) causes **invalid hook call** / subtle runtime bugs — and specifically causes **Radix UI interactive widgets** (dropdowns, dialogs, tooltips) to **silently fail** (context broken across the module boundary). If Yarn/npm hoists a second React, fix upstream ranges or use **`resolutions`** (Yarn) / **`overrides`** (npm) so the tree resolves to **one** `react` / `react-dom` pair matching (3). Also add `dedupe` + `@radix-ui/` alias in `vite.config.ts` (see **Local dev: Vite API proxy**).
25
+
26
+ **Current required versions (as of uilib 1.2.x):** `react` / `react-dom` **`^19`**, `@types/react` / `@types/react-dom` **`^19`**. Add resolutions so nested copies stay aligned:
27
+
28
+ ```json
29
+ {
30
+ "resolutions": {
31
+ "@types/react": "^19",
32
+ "@types/react-dom": "^19"
33
+ }
34
+ }
35
+ ```
36
+
18
37
  Import tokens/fonts once (typically `src/main.tsx`):
19
38
 
20
39
  ```ts
21
40
  import '@sybilion/uilib/standalone-global.css';
22
41
  ```
23
42
 
43
+ ### Branding (header logo + optional tab icon)
44
+
45
+ **Header:** **`SybilionAppHeader`** includes **`Logo`** from **`@sybilion/uilib`**. **`Logo`** uses **`SYBILION_STANDALONE_LOGO_PUBLIC_URL`** (**`'/logo.svg'`**). Vite serves that from **`public/logo.svg`**. Copy the published file once:
46
+
47
+ ```bash
48
+ mkdir -p public && cp node_modules/@sybilion/uilib/logo.svg public/logo.svg
49
+ ```
50
+
51
+ That asset is **`src/assets/logo.svg`** in the package (**cyan** glyph). The **uilib docs** repo uses **`assets/logo.svg`** (**purple**) for its own site only—not what **`./logo.svg`** publishes.
52
+
53
+ **Browser tab (optional):** The favicon (tiny icon next to the tab title) and the document title come from **`index.html`**, not from React. **`Logo`** does not set them. To replace Vite’s default tab icon with the package logo, add **`href="/logo.svg"`** — same as **`SYBILION_STANDALONE_LOGO_PUBLIC_URL`** from **`@sybilion/uilib`** — plus **`<title>`** in **`index.html`** `<head>`:
54
+
55
+ ```html
56
+ <link rel="icon" href="/logo.svg" type="image/svg+xml" />
57
+ <title>Your app name</title>
58
+ ```
59
+
24
60
  Mount the tree with `ReactDOM.createRoot` → `App` (wrap with `StrictMode` if you want).
25
61
 
26
62
  ### `package.json` scripts (required)
@@ -99,16 +135,39 @@ Package README: [`@sybilion/sdk`](https://www.npmjs.com/package/@sybilion/sdk)
99
135
 
100
136
  ## Local dev: Vite API proxy
101
137
 
102
- Avoid browser CORS in development by serving the SPA from Vite and proxying **`/api`** to the real API. Use **`sybilionStandaloneViteDev`** from `@sybilion/uilib/vite-standalone-dev` in **`vite.config.ts`**: it reads **`PORT`** (defaults to **3000** if unset or invalid) for **`server`** / **`preview`**, and sets **`proxy['/api']`** → **`VITE_SYBILION_API_BASE_URL`** with `changeOrigin` and `secure: true`.
138
+ Avoid browser CORS in development by serving the SPA from Vite and proxying **`/api`** to the real API.
139
+
140
+ **Reference `vite.config.ts` (minimal standalone Sybilion SPA):** merge your own `plugins` / options into this shape; keep `resolve.dedupe` and the `@radix-ui/` alias unless you know the dependency tree dedupes React and Radix correctly on its own.
141
+
142
+ - **`sybilionStandaloneViteDev`** (`@sybilion/uilib/vite-standalone-dev`) — reads **`PORT`** (defaults **3000** if unset or invalid) for **`server`** and **`preview`** bind; sets **`proxy['/api']`** → **`VITE_SYBILION_API_BASE_URL`** with `changeOrigin` and `secure: true`. Pass Vite’s **`mode`** so env (including `VITE_*`) and proxy target resolve the same way as `vite` / `vite build`.
143
+ - **`defineConfig(({ mode }) => …)`** — callback form gives `mode` per command (`development` / `production` / …); forward it into `sybilionStandaloneViteDev`.
144
+ - **`plugins: [react()]`** — add other plugins (e.g. SVGR) in the same array.
145
+ - **`resolve.dedupe`** — force one physical copy of `react`, `react-dom`, `react-router`, and `react-router-dom`. If the app and `@sybilion/uilib` resolve different copies, React context and router state break (`Invalid hook call`, blank subtree, Radix menus that never open). `react-router` is listed because it is a shared transitive dependency of the router packages and can duplicate independently.
146
+ - **`resolve.alias` for `@radix-ui/*`** — uilib’s published bundle uses bare `@radix-ui/react-*` imports. Yarn/npm can still place those packages under `node_modules/@sybilion/uilib/node_modules/@radix-ui/…`, so Vite may bundle two Radix trees and split React context across them. The regex alias rewrites every `@radix-ui/…` import to **`./node_modules/@radix-ui/`** (project root). **`path.resolve(… ) + '/'`** is required so subpaths like `@radix-ui/react-dialog` resolve under that folder.
147
+ - **`path`** — Node built-in `node:path`; only used at config evaluation time.
103
148
 
104
149
  ```ts
150
+ // vite.config.ts — reference config for a standalone app using @sybilion/uilib + proxy.
105
151
  import { sybilionStandaloneViteDev } from '@sybilion/uilib/vite-standalone-dev';
106
152
  import react from '@vitejs/plugin-react';
153
+ import path from 'node:path';
107
154
  import { defineConfig } from 'vite';
108
155
 
156
+ // Pass `mode` into sybilionStandaloneViteDev so proxy + VITE_* match the active Vite command.
109
157
  export default defineConfig(({ mode }) => ({
110
158
  ...sybilionStandaloneViteDev({ mode }),
111
159
  plugins: [react()],
160
+ resolve: {
161
+ // One copy of React + Router across app and uilib (avoids invalid hook call / dead Radix UI).
162
+ dedupe: ['react', 'react-dom', 'react-router', 'react-router-dom'],
163
+ alias: [
164
+ {
165
+ find: /^@radix-ui\//,
166
+ // Pin all Radix imports to the app’s root node_modules; trailing slash keeps subpaths working.
167
+ replacement: path.resolve('./node_modules/@radix-ui/') + '/',
168
+ },
169
+ ],
170
+ },
112
171
  }));
113
172
  ```
114
173
 
@@ -169,6 +228,44 @@ export function AppProviders({ children }: { children: ReactNode }) {
169
228
 
170
229
  **Hooks:** `useSybilionAuth()`, `useSybilionApiFetch()` (or `createSybilionApiFetch` / `sybilionApiFetch` helpers).
171
230
 
231
+ ### Loading the user profile for `SybilionAppHeader`
232
+
233
+ `useSybilionAuth()` gives you `isAuthenticated` / `logout` but **not** a user object. Fetch it once with `sybilionSdk.auth.getMe()` after authentication. The response shape is:
234
+
235
+ ```ts
236
+ // GET /api/v1/users/me → { data: { user: BackendUser }, message, status }
237
+ // BackendUser includes `picture` (profile image URL from the API). Do not read deprecated `avatar` on the wire.
238
+ ```
239
+
240
+ **Agents:** import **`MeResponse`** (and rely on **`BackendUser`** inside it) from `@sybilion/sdk`. Profile image on the API is **`picture` only**; `NavUserHeader` / `SybilionAppHeader` still expect the prop key **`avatar`**—map with `avatar: u.picture ?? ''`. No `UserProfile` intersections, no `u.avatar` fallback, no manual `res as { data?: … }` once `getMe()` is typed.
241
+
242
+ `NavUserHeader` (used inside `SybilionAppHeader`) accepts `user: { name, email, avatar? }`.
243
+
244
+ ```ts
245
+ import type { MeResponse } from '@sybilion/sdk';
246
+
247
+ useEffect(() => {
248
+ if (!isAuthenticated) {
249
+ setUser(null);
250
+ return;
251
+ }
252
+ sybilionSdk.auth
253
+ .getMe()
254
+ .then((res: MeResponse) => {
255
+ const u = res.data?.user;
256
+ if (u)
257
+ setUser({
258
+ name: u.name,
259
+ email: u.email,
260
+ avatar: u.picture ?? '',
261
+ });
262
+ })
263
+ .catch(() => undefined);
264
+ }, [isAuthenticated]);
265
+ ```
266
+
267
+ Pass `user` (or `null` while loading with `isLoading` on `NavUserHeader`) and `isAuthenticated` to `SybilionAppHeader`.
268
+
172
269
  ## 4. Layout (AppShell)
173
270
 
174
271
  With §2 `sybilionSdk` and §3 `AppProviders` / `SybilionAuthProvider` defined, compose routing + shell so Auth0 callbacks and JWT-backed hooks wrap the whole UI.
@@ -275,7 +372,7 @@ export function AppLayout({ children }: { children: ReactNode }) {
275
372
  }
276
373
  ```
277
374
 
278
- Wire **`authenticated`**, **`user`** / **`isAuthenticated`**, **`theme`** / **`onLogout`**, **`menuItems`**, and **`defaultApps`** / **`appsStorageKey`** to real auth and workspace config (`useSybilionAuth`, §3). **`NavUserHeader`** behavior reference: `src/docs/pages/NavUserHeaderPage.tsx` (slug `nav-user-header`). Full shell preview: `src/docs/pages/StandaloneAppLayoutPage.tsx` (slug **`standalone-app-layout`**).
375
+ Wire **`authenticated`**, **`user`** / **`isAuthenticated`**, **`theme`** / **`onLogout`**, **`menuItems`**, and **`defaultApps`** / **`appsStorageKey`** to real auth and workspace config (`useSybilionAuth`, §3). **`NavUserHeader`** behavior reference: `src/docs/pages/NavUserHeaderPage.tsx` (slug `nav-user-header`). Full shell preview: `src/docs/pages/StandaloneAppLayoutPage` (slug **`standalone-app-layout`**).
279
376
 
280
377
  #### Sidebar (`AppSidebar.tsx`)
281
378
 
@@ -391,16 +488,18 @@ Composition: `PageScroll` → `AppShell` → `AppSidebar` → `AppShellMainConte
391
488
 
392
489
  ### Greenfield checklist (agents)
393
490
 
394
- | Step | Deliverable |
395
- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
396
- | Env files | **`.env.example`** (committed) + **`.env`** locally; **`PORT=3000`** recommended for Auth0 test tenant; **`VITE_*`** as in §1 table. |
397
- | Scripts | **`package.json`** includes mandatory **`dev`** (e.g. `"vite"`); optional **`build`**, **`preview`**. |
398
- | Vite proxy | **`vite.config.ts`** spreads **`sybilionStandaloneViteDev({ mode })`**; SDK **`baseUrl`** empty in dev (§2). |
399
- | Files | `src/libs/sybilion-sdk.ts`, `AppProviders.tsx`, `AppLayout.tsx`, `AppSidebar.tsx`, `App.tsx`, `main.tsx`, route pages under e.g. `src/pages/`. |
400
- | Pages + UI | **§4 Route page body** (mandatory stack) + **Discovering** (barrel-first; bespoke markup only when no export fits). |
401
- | Auth0 | SPA callback / logout URLs + allowed web origins **`http://localhost:<PORT>`** for local dev and deploy URLs (and previews). |
402
- | API | **Dev:** proxy handles API traffic (no browser CORS to API). **Prod:** Sybilion backend **CORS** your deploy `Origin`, unless API is same-origin. |
403
- | Go (if applicable) | Server proxies **`/api`** to Sybilion; SPA dev **`baseUrl`** stays `''` when same-origin. |
491
+ | Step | Deliverable |
492
+ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
493
+ | React / router | **`react`**, **`react-dom`**, **`react-router-dom`**, **`@auth0/auth0-react`** (and **`vite`** if applicable) aligned with **`@sybilion/uilib`** **`package.json`** §1 _React ecosystem versions_. |
494
+ | Env files | **`.env.example`** (committed) + **`.env`** locally; **`PORT=3000`** recommended for Auth0 test tenant; **`VITE_*`** as in §1 table. |
495
+ | Scripts | **`package.json`** includes mandatory **`dev`** (e.g. `"vite"`); optional **`build`**, **`preview`**. |
496
+ | Vite proxy | **`vite.config.ts`** spreads **`sybilionStandaloneViteDev({ mode })`**; SDK **`baseUrl`** empty in dev (§2). |
497
+ | Files | `src/libs/sybilion-sdk.ts`, `AppProviders.tsx`, `AppLayout.tsx`, `AppSidebar.tsx`, `App.tsx`, `main.tsx`, route pages under e.g. `src/pages/`. |
498
+ | Branding | **`public/logo.svg`** for **`Logo`** / **`SybilionAppHeader`**: `cp node_modules/@sybilion/uilib/logo.svg public/logo.svg`. **`index.html`**: `<title>`; optional **`<link rel="icon">`** for tab icon (§1 _Branding_). |
499
+ | Pages + UI | **§4 Route page body** (mandatory stack) + **Discovering** (barrel-first; bespoke markup only when no export fits). |
500
+ | Auth0 | SPA callback / logout URLs + allowed web origins **`http://localhost:<PORT>`** for local dev and deploy URLs (and previews). |
501
+ | API | **Dev:** proxy handles API traffic (no browser CORS to API). **Prod:** Sybilion backend **CORS** → your deploy `Origin`, unless API is same-origin. |
502
+ | Go (if applicable) | Server proxies **`/api`** to Sybilion; SPA dev **`baseUrl`** stays `''` when same-origin. |
404
503
 
405
504
  ### Glossary (high-use pieces)
406
505
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sybilion/uilib",
3
- "version": "1.2.5",
3
+ "version": "1.2.8",
4
4
  "description": "Sybilion Design System — React UI components (Webpack + Stylus)",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -35,7 +35,8 @@
35
35
  "types": "./dist/standalone/vite-sybilion-standalone-dev.d.ts",
36
36
  "import": "./dist/standalone/vite-sybilion-standalone-dev.js",
37
37
  "default": "./dist/standalone/vite-sybilion-standalone-dev.js"
38
- }
38
+ },
39
+ "./logo.svg": "./src/assets/logo.svg"
39
40
  },
40
41
  "files": [
41
42
  "assets",
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
2
+ <path fill="#59f0ff" d="M13.43 24.023h-2.836v-2.836h2.836zm-2.835-2.844H5.63v-2.74h4.965Zm10.527-2.74h-2.726v2.74h-4.965v-2.74h4.952v-4.965h2.74zm-15.5 0h-2.74v-4.965h2.74ZM2.87 13.462H.034v-2.836H2.87Zm21.096 0H21.13v-2.836h2.836zM5.617 10.635h-2.74V5.669h2.74zm15.505 0h-2.74V5.669h2.74zM10.588 2.927v2.74H5.623v-2.74Zm2.842 0h4.96v2.74h-4.966v-2.74h-2.83V.09h2.836z" style="stroke-width:.13252" />
3
+ </svg>
@@ -9,6 +9,11 @@
9
9
  min-height var(--header-height)
10
10
  background-color var(--color-background)
11
11
 
12
+ @media (min-width MOBILE)
13
+ :global([data-slot='sidebar-wrapper'][data-state='collapsed']) &
14
+ padding-left 200px
15
+ max-width 100%
16
+
12
17
  .content
13
18
  display flex
14
19
  align-items center
@@ -5,6 +5,8 @@
5
5
  color var(--color-foreground)
6
6
 
7
7
  .icon
8
+ display block
9
+ flex-shrink 0
8
10
  height 24px
9
11
  width auto
10
12
 
@@ -3,6 +3,12 @@ import cn from 'classnames';
3
3
  import S from './Logo.styl';
4
4
  import type { LogoProps } from './Logo.types';
5
5
 
6
+ /**
7
+ * Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
8
+ * to `public/logo.svg` (see standalone-apps guide). Same path as the favicon `<link href>`.
9
+ */
10
+ export const SYBILION_STANDALONE_LOGO_PUBLIC_URL = '/logo.svg' as const;
11
+
6
12
  export function Logo({
7
13
  showText = true,
8
14
  size = 'md',
@@ -11,7 +17,12 @@ export function Logo({
11
17
  }: LogoProps) {
12
18
  return (
13
19
  <div className={cn(S.root, S[size], className)} {...props}>
14
- <img src="/logo.svg" alt="Sybilion" className={S.icon} />
20
+ <img
21
+ src={SYBILION_STANDALONE_LOGO_PUBLIC_URL}
22
+ alt={showText ? '' : 'Sybilion'}
23
+ className={S.icon}
24
+ {...(showText ? { 'aria-hidden': true } : {})}
25
+ />
15
26
  {showText && <span className={S.text}>Sybilion</span>}
16
27
  </div>
17
28
  );