fix: improve sidebar buttons

This commit is contained in:
Carl-Gerhard Lindesvärd
2026-02-16 22:16:08 +01:00
parent edadda2c45
commit b7eafb0f37
6 changed files with 119 additions and 108 deletions

View File

@@ -1,15 +1,12 @@
import { op } from '@/utils/op';
import { useRouteContext } from '@tanstack/react-router'; import { useRouteContext } from '@tanstack/react-router';
import { SparklesIcon } from 'lucide-react'; import { cn } from '@/lib/utils';
import { Button } from './ui/button'; import { op } from '@/utils/op';
export function FeedbackButton() { export function FeedbackButton({ className }: { className?: string }) {
const context = useRouteContext({ strict: false }); const context = useRouteContext({ strict: false });
return ( return (
<Button <button
variant={'outline'} className={cn('justify-start text-left text-[13px]', className)}
className="text-left justify-start text-[13px]"
icon={SparklesIcon}
onClick={() => { onClick={() => {
op.track('feedback_button_clicked'); op.track('feedback_button_clicked');
if ('uj' in window && window.uj !== undefined) { if ('uj' in window && window.uj !== undefined) {
@@ -23,8 +20,9 @@ export function FeedbackButton() {
}, 10); }, 10);
} }
}} }}
type="button"
> >
Give feedback Give feedback
</Button> </button>
); );
} }

View File

@@ -1,4 +1,5 @@
import { Button } from '@/components/ui/button'; import { CheckIcon, UserIcon } from 'lucide-react';
import { themeConfig } from './theme-provider';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -10,11 +11,9 @@ import {
DropdownMenuSubTrigger, DropdownMenuSubTrigger,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'; } from '@/components/ui/dropdown-menu';
import { useTheme } from '@/hooks/use-theme';
import { CheckIcon, UserIcon } from 'lucide-react';
import { useLogout } from '@/hooks/use-logout'; import { useLogout } from '@/hooks/use-logout';
import { themeConfig } from './theme-provider'; import { useTheme } from '@/hooks/use-theme';
import { cn } from '@/lib/utils';
interface Props { interface Props {
className?: string; className?: string;
@@ -27,10 +26,13 @@ export function ProfileToggle({ className }: Props) {
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant="outline" size="icon" className={className}> <button
className={cn(className, 'center-center outline-0')}
type="button"
>
<UserIcon className="size-4" /> <UserIcon className="size-4" />
<span className="sr-only">Profile</span> <span className="sr-only">Profile</span>
</Button> </button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="center" className="w-56"> <DropdownMenuContent align="center" className="w-56">
<DropdownMenuSub> <DropdownMenuSub>
@@ -44,9 +46,9 @@ export function ProfileToggle({ className }: Props) {
<DropdownMenuSubContent className="p-0"> <DropdownMenuSubContent className="p-0">
{themes.map((themeOption) => ( {themes.map((themeOption) => (
<DropdownMenuItem <DropdownMenuItem
className="capitalize"
key={themeOption.key} key={themeOption.key}
onClick={() => setTheme(themeOption.key)} onClick={() => setTheme(themeOption.key)}
className="capitalize"
> >
<span className="mr-2">{themeOption.icon}</span> <span className="mr-2">{themeOption.icon}</span>
{themeOption.label} {themeOption.label}

View File

@@ -1,21 +1,15 @@
import { Link, useNavigate } from '@tanstack/react-router';
import { AnimatePresence, motion } from 'framer-motion';
import { import {
ChevronDownIcon,
CogIcon, CogIcon,
CreditCardIcon, CreditCardIcon,
LayoutListIcon, LayoutListIcon,
PlusIcon,
UsersIcon, UsersIcon,
WorkflowIcon, WorkflowIcon,
} from 'lucide-react'; } from 'lucide-react';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import { useAppContext } from '@/hooks/use-app-context';
import { useAppParams } from '@/hooks/use-app-params';
import { pushModal } from '@/modals';
import type { RouterOutputs } from '@/trpc/client';
import { cn } from '@/utils/cn';
import { Link, useNavigate, useRouteContext } from '@tanstack/react-router';
import { AnimatePresence, motion } from 'framer-motion';
import { ChevronDownIcon, PlusIcon } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { Badge } from './ui/badge'; import { Badge } from './ui/badge';
import { import {
DropdownMenu, DropdownMenu,
@@ -23,6 +17,11 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from './ui/dropdown-menu'; } from './ui/dropdown-menu';
import { Button } from '@/components/ui/button';
import { useAppContext } from '@/hooks/use-app-context';
import { pushModal } from '@/modals';
import type { RouterOutputs } from '@/trpc/client';
import { cn } from '@/utils/cn';
export default function SidebarOrganizationMenu({ export default function SidebarOrganizationMenu({
organization, organization,
@@ -34,35 +33,35 @@ export default function SidebarOrganizationMenu({
return ( return (
<> <>
<Link <Link
className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium transition-all hover:bg-def-200 text-[13px]',
)}
activeOptions={{ exact: true }} activeOptions={{ exact: true }}
to="/$organizationId" className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium text-[13px] transition-all hover:bg-def-200'
)}
from="/$organizationId" from="/$organizationId"
to="/$organizationId"
> >
<LayoutListIcon size={20} /> <LayoutListIcon size={20} />
<div className="flex-1">Projects</div> <div className="flex-1">Projects</div>
</Link> </Link>
<Link <Link
className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium transition-all hover:bg-def-200 text-[13px]',
)}
activeOptions={{ exact: true }} activeOptions={{ exact: true }}
to="/$organizationId/settings" className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium text-[13px] transition-all hover:bg-def-200'
)}
from="/$organizationId" from="/$organizationId"
to="/$organizationId/settings"
> >
<CogIcon size={20} /> <CogIcon size={20} />
<div className="flex-1">Settings</div> <div className="flex-1">Settings</div>
</Link> </Link>
{!isSelfHosted && ( {!isSelfHosted && (
<Link <Link
className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium transition-all hover:bg-def-200 text-[13px]',
)}
activeOptions={{ exact: true }} activeOptions={{ exact: true }}
to="/$organizationId/billing" className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium text-[13px] transition-all hover:bg-def-200'
)}
from="/$organizationId" from="/$organizationId"
to="/$organizationId/billing"
> >
<CreditCardIcon size={20} /> <CreditCardIcon size={20} />
<div className="flex-1">Billing</div> <div className="flex-1">Billing</div>
@@ -74,20 +73,20 @@ export default function SidebarOrganizationMenu({
)} )}
<Link <Link
className={cn( className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium transition-all hover:bg-def-200 text-[13px]', 'flex items-center gap-2 rounded-md px-3 py-2 font-medium text-[13px] transition-all hover:bg-def-200'
)} )}
to="/$organizationId/members"
from="/$organizationId" from="/$organizationId"
to="/$organizationId/members"
> >
<UsersIcon size={20} /> <UsersIcon size={20} />
<div className="flex-1">Members</div> <div className="flex-1">Members</div>
</Link> </Link>
<Link <Link
className={cn( className={cn(
'flex items-center gap-2 rounded-md px-3 py-2 font-medium transition-all hover:bg-def-200 text-[13px]', 'flex items-center gap-2 rounded-md px-3 py-2 font-medium text-[13px] transition-all hover:bg-def-200'
)} )}
to="/$organizationId/integrations"
from="/$organizationId" from="/$organizationId"
to="/$organizationId/integrations"
> >
<WorkflowIcon size={20} /> <WorkflowIcon size={20} />
<div className="flex-1">Integrations</div> <div className="flex-1">Integrations</div>
@@ -138,20 +137,20 @@ export function ActionCTAButton() {
<Button className="w-full justify-between" size="default"> <Button className="w-full justify-between" size="default">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<PlusIcon size={16} /> <PlusIcon size={16} />
<div className="relative h-5 flex items-center"> <div className="relative flex h-5 items-center">
<AnimatePresence mode="popLayout"> <AnimatePresence mode="popLayout">
<motion.span <motion.span
key={currentActionIndex}
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }} animate={{ y: 0, opacity: 1 }}
className="absolute whitespace-nowrap"
exit={{ y: -20, opacity: 0 }} exit={{ y: -20, opacity: 0 }}
initial={{ y: 20, opacity: 0 }}
key={currentActionIndex}
transition={{ transition={{
type: 'spring', type: 'spring',
stiffness: 300, stiffness: 300,
damping: 25, damping: 25,
duration: 0.3, duration: 0.3,
}} }}
className="absolute whitespace-nowrap"
> >
{ACTIONS[currentActionIndex].label} {ACTIONS[currentActionIndex].label}
</motion.span> </motion.span>
@@ -161,12 +160,12 @@ export function ActionCTAButton() {
<ChevronDownIcon size={16} /> <ChevronDownIcon size={16} />
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="start"> <DropdownMenuContent align="start" className="w-56">
{ACTIONS.map((action) => ( {ACTIONS.map((action) => (
<DropdownMenuItem <DropdownMenuItem
onClick={action.onClick}
className="cursor-pointer" className="cursor-pointer"
key={action.label} key={action.label}
onClick={action.onClick}
> >
<action.icon className="mr-2 h-4 w-4" /> <action.icon className="mr-2 h-4 w-4" />
{action.label} {action.label}

View File

@@ -1,5 +1,3 @@
import { Button } from '@/components/ui/button';
import { pushModal } from '@/modals';
import type { IServiceDashboards } from '@openpanel/db'; import type { IServiceDashboards } from '@openpanel/db';
import { useNavigate } from '@tanstack/react-router'; import { useNavigate } from '@tanstack/react-router';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
@@ -30,6 +28,8 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from './ui/dropdown-menu'; } from './ui/dropdown-menu';
import { Button } from '@/components/ui/button';
import { pushModal } from '@/modals';
interface SidebarProjectMenuProps { interface SidebarProjectMenuProps {
dashboards: IServiceDashboards; dashboards: IServiceDashboards;
@@ -40,38 +40,42 @@ export default function SidebarProjectMenu({
}: SidebarProjectMenuProps) { }: SidebarProjectMenuProps) {
return ( return (
<> <>
<div className="mb-2 font-medium text-muted-foreground">Analytics</div> <div className="mb-2 font-medium text-muted-foreground text-sm">
<SidebarLink icon={WallpaperIcon} label="Overview" href={'/'} /> Analytics
</div>
<SidebarLink href={'/'} icon={WallpaperIcon} label="Overview" />
<SidebarLink <SidebarLink
href={'/dashboards'}
icon={LayoutPanelTopIcon} icon={LayoutPanelTopIcon}
label="Dashboards" label="Dashboards"
href={'/dashboards'}
/> />
<SidebarLink <SidebarLink
href={'/insights'}
icon={TrendingUpDownIcon} icon={TrendingUpDownIcon}
label="Insights" label="Insights"
href={'/insights'}
/> />
<SidebarLink icon={LayersIcon} label="Pages" href={'/pages'} /> <SidebarLink href={'/pages'} icon={LayersIcon} label="Pages" />
<SidebarLink icon={Globe2Icon} label="Realtime" href={'/realtime'} /> <SidebarLink href={'/realtime'} icon={Globe2Icon} label="Realtime" />
<SidebarLink icon={GanttChartIcon} label="Events" href={'/events'} /> <SidebarLink href={'/events'} icon={GanttChartIcon} label="Events" />
<SidebarLink icon={UsersIcon} label="Sessions" href={'/sessions'} /> <SidebarLink href={'/sessions'} icon={UsersIcon} label="Sessions" />
<SidebarLink icon={UsersIcon} label="Profiles" href={'/profiles'} /> <SidebarLink href={'/profiles'} icon={UsersIcon} label="Profiles" />
<div className="mt-4 mb-2 font-medium text-muted-foreground">Manage</div> <div className="mt-4 mb-2 font-medium text-muted-foreground text-sm">
Manage
</div>
<SidebarLink <SidebarLink
exact={false} exact={false}
href={'/settings'}
icon={CogIcon} icon={CogIcon}
label="Settings" label="Settings"
href={'/settings'}
/> />
<SidebarLink icon={GridIcon} label="References" href={'/references'} /> <SidebarLink href={'/references'} icon={GridIcon} label="References" />
<SidebarLink <SidebarLink
exact={false} exact={false}
href={'/notifications'}
icon={BellIcon} icon={BellIcon}
label="Notifications" label="Notifications"
href={'/notifications'}
/> />
<SidebarLink icon={UndoDotIcon} label="Back to workspace" href={'..'} /> <SidebarLink href={'..'} icon={UndoDotIcon} label="Back to workspace" />
</> </>
); );
} }
@@ -143,20 +147,20 @@ export function ActionCTAButton() {
<Button className="w-full justify-between" size="default"> <Button className="w-full justify-between" size="default">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<PlusIcon size={16} /> <PlusIcon size={16} />
<div className="relative h-5 flex items-center"> <div className="relative flex h-5 items-center">
<AnimatePresence mode="popLayout"> <AnimatePresence mode="popLayout">
<motion.span <motion.span
key={currentActionIndex}
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }} animate={{ y: 0, opacity: 1 }}
className="absolute whitespace-nowrap"
exit={{ y: -20, opacity: 0 }} exit={{ y: -20, opacity: 0 }}
initial={{ y: 20, opacity: 0 }}
key={currentActionIndex}
transition={{ transition={{
type: 'spring', type: 'spring',
stiffness: 300, stiffness: 300,
damping: 25, damping: 25,
duration: 0.3, duration: 0.3,
}} }}
className="absolute whitespace-nowrap"
> >
{ACTIONS[currentActionIndex].label} {ACTIONS[currentActionIndex].label}
</motion.span> </motion.span>
@@ -166,12 +170,12 @@ export function ActionCTAButton() {
<ChevronDownIcon size={16} /> <ChevronDownIcon size={16} />
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="start"> <DropdownMenuContent align="start" className="w-56">
{ACTIONS.map((action) => ( {ACTIONS.map((action) => (
<DropdownMenuItem <DropdownMenuItem
onClick={action.onClick}
className="cursor-pointer" className="cursor-pointer"
key={action.label} key={action.label}
onClick={action.onClick}
> >
<action.icon className="mr-2 h-4 w-4" /> <action.icon className="mr-2 h-4 w-4" />
{action.label} {action.label}

View File

@@ -1,6 +1,3 @@
import { useAppContext } from '@/hooks/use-app-context';
import { useTRPC } from '@/integrations/trpc/react';
import { cn } from '@/utils/cn';
import type { IServiceOrganization } from '@openpanel/db'; import type { IServiceOrganization } from '@openpanel/db';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Link, useLocation, useParams } from '@tanstack/react-router'; import { Link, useLocation, useParams } from '@tanstack/react-router';
@@ -17,6 +14,9 @@ import SidebarProjectMenu, {
ActionCTAButton as ActionProjectCTAButton, ActionCTAButton as ActionProjectCTAButton,
} from './sidebar-project-menu'; } from './sidebar-project-menu';
import { Button } from './ui/button'; import { Button } from './ui/button';
import { useAppContext } from '@/hooks/use-app-context';
import { useTRPC } from '@/integrations/trpc/react';
import { cn } from '@/utils/cn';
export function Sidebar() { export function Sidebar() {
const { organizationId, projectId } = useParams({ strict: false }); const { organizationId, projectId } = useParams({ strict: false });
@@ -24,7 +24,7 @@ export function Sidebar() {
// Get organizations data // Get organizations data
const { data: organizations = [] } = useQuery( const { data: organizations = [] } = useQuery(
trpc.organization.list.queryOptions(), trpc.organization.list.queryOptions()
); );
// Get projects data when we have an organization // Get projects data when we have an organization
@@ -86,67 +86,75 @@ export function SidebarContainer({
return ( return (
<> <>
<button <button
type="button"
onClick={() => setActive(false)}
className={cn( className={cn(
'fixed bottom-0 left-0 right-0 top-0 z-40 backdrop-blur-sm transition-opacity', 'fixed top-0 right-0 bottom-0 left-0 z-40 backdrop-blur-sm transition-opacity',
active active
? 'pointer-events-auto opacity-100' ? 'pointer-events-auto opacity-100'
: 'pointer-events-none opacity-0', : 'pointer-events-none opacity-0'
)} )}
onClick={() => setActive(false)}
type="button"
/> />
<div <div
className={cn( className={cn(
'fixed left-0 top-0 z-40 flex h-screen w-72 flex-col border-r border-border bg-card transition-transform', 'fixed top-0 left-0 z-40 flex h-screen w-72 flex-col border-border border-r bg-card transition-transform',
'-translate-x-72 lg:-translate-x-0', // responsive '-translate-x-72 lg:-translate-x-0', // responsive
active && 'translate-x-0', // force active on mobile active && 'translate-x-0' // force active on mobile
)} )}
> >
<div className="absolute -right-12 flex h-16 items-center lg:hidden"> <div className="absolute -right-12 flex h-16 items-center lg:hidden">
<Button <Button
size="icon"
onClick={() => setActive((p) => !p)} onClick={() => setActive((p) => !p)}
size="icon"
variant={'outline'} variant={'outline'}
> >
{active ? <XIcon size={16} /> : <MenuIcon size={16} />} {active ? <XIcon size={16} /> : <MenuIcon size={16} />}
</Button> </Button>
</div> </div>
<div className="flex h-16 shrink-0 items-center gap-2 border-b border-border px-4"> <div className="flex h-16 shrink-0 items-center gap-2 border-border border-b px-4">
<Link to="/"> <Link to="/">
<LogoSquare className="max-h-8" /> <LogoSquare className="max-h-8" />
</Link> </Link>
<ProjectSelector <ProjectSelector
align="start" align="start"
projects={projects}
organizations={organizations} organizations={organizations}
projects={projects}
/> />
</div> </div>
<div <div
className={cn([ className={cn([
'flex flex-grow col gap-1 overflow-auto p-4 hide-scrollbar', 'hide-scrollbar flex-1 overflow-auto p-4',
"[&_a[data-status='active']]:bg-def-200", "[&_a[data-status='active']]:bg-def-200",
])} ])}
> >
{children} {children}
</div>
<div className="mt-auto w-full pt-6"> <div className="relative">
<div className="row gap-2 justify-between"> <div className="pointer-events-none absolute right-0 bottom-full left-0 h-8 bg-gradient-to-t from-card to-card/0" />
<FeedbackButton /> <div className="border-border border-t bg-card">
<ProfileToggle /> <div className="flex items-center">
<FeedbackButton className="h-12 flex-1 whitespace-nowrap rounded-none border-border border-r px-4 text-muted-foreground outline-0 hover:bg-accent hover:text-accent-foreground" />
<a
className="flex h-12 flex-1 items-center justify-center gap-2 border-border border-r font-medium text-muted-foreground text-sm transition-colors hover:bg-accent hover:text-accent-foreground"
href="https://openpanel.dev/docs"
rel="noopener noreferrer"
target="_blank"
>
Docs
</a>
<ProfileToggle className="h-12 flex-1 rounded-none hover:bg-accent hover:text-accent-foreground" />
</div> </div>
{isSelfHosted && ( {isSelfHosted && (
<a <a
className="center-center flex h-12 cursor-pointer gap-2 border-border border-t px-4 font-medium text-muted-foreground text-sm transition-colors hover:bg-accent hover:text-accent-foreground"
href="https://openpanel.dev/supporter" href="https://openpanel.dev/supporter"
className="text-center text-sm w-full mt-2 border rounded p-2 font-medium block hover:underline hover:text-primary outline-none"
> >
Self-hosted instance, support us! <span>Support Us</span>
<span>Pay What You Want</span>
</a> </a>
)} )}
</div> </div>
</div> </div>
<div className="fixed bottom-0 left-0 right-0 pointer-events-none">
<div className="h-8 w-full bg-gradient-to-t from-card to-card/0" />
</div>
</div> </div>
</> </>
); );

View File

@@ -1,3 +1,5 @@
import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute, Link, redirect } from '@tanstack/react-router';
import FullPageLoadingState from '@/components/full-page-loading-state'; import FullPageLoadingState from '@/components/full-page-loading-state';
import { LogoSquare } from '@/components/logo'; import { LogoSquare } from '@/components/logo';
import { PageHeader } from '@/components/page-header'; import { PageHeader } from '@/components/page-header';
@@ -6,11 +8,9 @@ import { useLogout } from '@/hooks/use-logout';
import { useNumber } from '@/hooks/use-numer-formatter'; import { useNumber } from '@/hooks/use-numer-formatter';
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { createTitle } from '@/utils/title'; import { createTitle } from '@/utils/title';
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
import { Link, createFileRoute, redirect } from '@tanstack/react-router';
export const Route = createFileRoute('/')({ export const Route = createFileRoute('/')({
beforeLoad: async ({ context }) => { beforeLoad: ({ context }) => {
if (!context.session.session) { if (!context.session.session) {
throw redirect({ to: '/login' }); throw redirect({ to: '/login' });
} }
@@ -28,7 +28,7 @@ export const Route = createFileRoute('/')({
context.trpc.organization.list.queryOptions(undefined, { context.trpc.organization.list.queryOptions(undefined, {
staleTime: 0, staleTime: 0,
gcTime: 0, gcTime: 0,
}), })
) )
.catch(() => []); .catch(() => []);
@@ -50,28 +50,28 @@ function LandingPage() {
const trpc = useTRPC(); const trpc = useTRPC();
const logout = useLogout(); const logout = useLogout();
const { data: organizations } = useSuspenseQuery( const { data: organizations } = useSuspenseQuery(
trpc.organization.list.queryOptions(), trpc.organization.list.queryOptions()
); );
const number = useNumber(); const number = useNumber();
return ( return (
<div className="min-h-screen flex flex-col items-center justify-center"> <div className="flex min-h-screen flex-col items-center justify-center">
<div className="max-w-2xl mx-auto px-4 col gap-12"> <div className="col mx-auto max-w-2xl gap-12 px-4 py-8">
<div className="col gap-4"> <div className="col gap-4">
<LogoSquare className="w-full max-w-24" /> <LogoSquare className="w-full max-w-14 md:max-w-24" />
<PageHeader <PageHeader
title="Welcome to OpenPanel.dev"
description="The best web and product analytics tool out there (our honest opinion)." description="The best web and product analytics tool out there (our honest opinion)."
title="Welcome to OpenPanel.dev"
/> />
</div> </div>
<div className="col gap-2"> <div className="col gap-2">
{organizations?.map((org) => ( {organizations?.map((org) => (
<Link <Link
className="row items-center justify-between rounded-lg border bg-card p-3 transition-all hover:translate-x-1 hover:border-primary hover:shadow-md"
key={org.id} key={org.id}
to={'/$organizationId'}
params={{ organizationId: org.id }} params={{ organizationId: org.id }}
className="row justify-between items-center p-3 rounded-lg border bg-card hover:border-primary hover:shadow-md transition-all hover:translate-x-1" to={'/$organizationId'}
> >
<div className="col gap-2"> <div className="col gap-2">
<span className="font-medium text-lg">{org.name}</span> <span className="font-medium text-lg">{org.name}</span>
@@ -89,7 +89,7 @@ function LandingPage() {
</div> </div>
<div className="row gap-4"> <div className="row gap-4">
<Button onClick={() => logout.mutate()} loading={logout.isPending}> <Button loading={logout.isPending} onClick={() => logout.mutate()}>
Log out Log out
</Button> </Button>
</div> </div>