Skip to content

Commit

Permalink
Account popover (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeSaterlay authored Jul 19, 2024
1 parent 4e8909b commit dd2fe75
Show file tree
Hide file tree
Showing 6 changed files with 7,311 additions and 4,003 deletions.
59 changes: 51 additions & 8 deletions packages/frontpage/app/(app)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ import { Button } from "@/lib/components/ui/button";
import { isBetaUser } from "@/lib/data/user";
import { OpenInNewWindowIcon } from "@radix-ui/react-icons";
import { ThemeToggle } from "./_components/theme-toggle";
import { getDidFromHandleOrDid } from "@/lib/data/atproto/did";

import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
} from "@/lib/components/ui/dropdown-menu";
import { DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
import { UserAvatar } from "@/lib/components/user-avatar";

export default async function Layout({
children,
Expand Down Expand Up @@ -86,15 +97,47 @@ export default async function Layout({
async function LoginOrLogout() {
const session = await getSession();
if (session) {
const did = await getDidFromHandleOrDid(session.user.name as string);
return (
<form
action={async () => {
"use server";
await signOut();
}}
>
<button type="submit">Logout ({session.user.name})</button>
</form>
<DropdownMenu>
<DropdownMenuTrigger>
{did ? (
<UserAvatar did={did} size="smedium" />
) : (
<span>{session.user.name}</span>
)}
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" side="bottom" align="end">
<DropdownMenuLabel className="truncate">
{session.user.name}
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
href={`/profile/${session.user.name}`}
className="cursor-pointer"
>
Profile
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<form
action={async () => {
"use server";
await signOut();
}}
>
<DropdownMenuItem asChild>
<button
type="submit"
className="w-full text-start cursor-pointer"
>
Logout
</button>
</DropdownMenuItem>
</form>
</DropdownMenuContent>
</DropdownMenu>
);
}

Expand Down
41 changes: 41 additions & 0 deletions packages/frontpage/lib/components/ui/popover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use client";

import * as React from "react";
import * as PopoverPrimitive from "@radix-ui/react-popover";

import { cn } from "@/lib/utils";

const Popover = PopoverPrimitive.Root;

const PopoverTrigger = PopoverPrimitive.Trigger;

const PopoverAnchor = PopoverPrimitive.Anchor;

export type PopoverContentProps = React.ComponentPropsWithoutRef<
typeof PopoverPrimitive.Content
>;

function PopoverContent({
className,
align = "center",
sideOffset = 4,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
</PopoverPrimitive.Portal>
);
}

PopoverContent.displayName = PopoverPrimitive.Content.displayName;

export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
84 changes: 45 additions & 39 deletions packages/frontpage/lib/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,55 @@ import { cn } from "@/lib/utils";

const Tabs = TabsPrimitive.Root;

const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
className,
)}
{...props}
/>
));
function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
className={cn(
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
className,
)}
{...props}
/>
);
}

TabsList.displayName = TabsPrimitive.List.displayName;

const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
className,
)}
{...props}
/>
));
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
className,
)}
{...props}
/>
);
}

TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;

const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className,
)}
{...props}
/>
));
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className,
)}
{...props}
/>
);
}

TabsContent.displayName = TabsPrimitive.Content.displayName;

export { Tabs, TabsList, TabsTrigger, TabsContent };
1 change: 1 addition & 0 deletions packages/frontpage/lib/components/user-avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { DID } from "../data/atproto/did";

const userAvatarSizes = {
small: 22,
smedium: 50,
medium: 100,
large: 150,
};
Expand Down
1 change: 1 addition & 0 deletions packages/frontpage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@radix-ui/react-hover-card": "^1.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
Expand Down
Loading

0 comments on commit dd2fe75

Please sign in to comment.