diff --git a/apps/dashboard/src/components/dashboard-account-settings/sidebar-layout.tsx b/apps/dashboard/src/components/dashboard-account-settings/sidebar-layout.tsx
new file mode 100644
index 000000000..ad905e9ac
--- /dev/null
+++ b/apps/dashboard/src/components/dashboard-account-settings/sidebar-layout.tsx
@@ -0,0 +1,144 @@
+'use client';
+
+import { useHash } from '@stackframe/stack-shared/dist/hooks/use-hash';
+import { Button } from '@/components/ui/button';
+import { cn } from '@/lib/utils';
+import { X } from '@phosphor-icons/react';
+import React, { ReactNode } from 'react';
+import { useStackApp } from '@stackframe/stack';
+
+export type SidebarItem = {
+ title: React.ReactNode,
+ type: 'item' | 'divider',
+ description?: React.ReactNode,
+ id?: string,
+ icon?: React.ReactNode,
+ content?: React.ReactNode,
+ contentTitle?: React.ReactNode,
+}
+
+export function SidebarLayout(props: { items: SidebarItem[], title?: ReactNode, className?: string }) {
+ const hash = useHash();
+ const selectedIndex = props.items.findIndex(item => item.id && (item.id === hash));
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+}
+
+function Items(props: { items: SidebarItem[], selectedIndex: number }) {
+ const app = useStackApp();
+ const navigate = app.useNavigate();
+
+ const activeItemIndex = props.selectedIndex === -1 ? 0 : props.selectedIndex;
+
+ return props.items.map((item, index) => (
+ item.type === 'item' ? (
+
+ ) : (
+
+ {item.title}
+
+ )
+ ));
+}
+
+function DesktopLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {
+ const selectedItem = props.items[props.selectedIndex === -1 ? 0 : props.selectedIndex];
+
+ return (
+
+
+ {props.title && (
+
+
+ {props.title}
+
+
+ )}
+
+
+
+
+
+
+
+ {selectedItem.contentTitle || selectedItem.title}
+
+ {selectedItem.description && (
+
+ {selectedItem.description}
+
+ )}
+
+
+ {selectedItem.content}
+
+
+
+
+ );
+}
+
+function MobileLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {
+ const selectedItem = props.items[props.selectedIndex];
+ const app = useStackApp();
+ const navigate = app.useNavigate();
+
+ if (props.selectedIndex === -1) {
+ return (
+
+ {props.title && (
+
+
{props.title}
+
+ )}
+
+
+
+ );
+ } else {
+ return (
+
+
+
+
{selectedItem.title}
+
+
+ {selectedItem.description &&
{selectedItem.description}
}
+
+
+ {selectedItem.content}
+
+
+ );
+ }
+}