Skip to content

WIP POC for new assistant styling #551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: feat/simplify-assistant
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions apps/web/app/(app)/[emailAccountId]/automation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { Button } from "@/components/ui/button";
import { PremiumAlertWithData } from "@/components/PremiumAlert";
import { checkUserOwnsEmailAccount } from "@/utils/email-account";
import { SettingsTab } from "@/app/(app)/[emailAccountId]/assistant/SettingsTab";
import { PageHeading } from "@/components/Typography";
import { TabSelect } from "@/components/TabSelect";

export const maxDuration = 300; // Applies to the actions

Expand Down Expand Up @@ -71,10 +73,39 @@ export default async function AutomationPage({
/>
</div> */}

<PageHeading className="content-container">Assistant</PageHeading>

<PremiumAlertWithData className="content-container mt-2" />

<div className="max-w-screen-xl">
<div className="content-container">
<div className="border-b border-neutral-200">
<TabSelect
options={[
{
id: "settings",
label: "Settings",
href: `/${emailAccountId}/automation/settings`,
},
{
id: "test",
label: "Test",
href: `/${emailAccountId}/automation/test`,
},
{
id: "history",
label: "History",
href: `/${emailAccountId}/automation/history`,
},
]}
selected="settings"
/>
</div>
</div>
</div>

<Tabs defaultValue="settings">
<TabsToolbar>
{/* <TabsToolbar>
<div className="w-full overflow-x-auto">
<TabsList>
<TabsTrigger value="settings">Settings</TabsTrigger>
Expand Down Expand Up @@ -117,7 +148,7 @@ export default async function AutomationPage({
</Link>
</Button>
</div>
</TabsToolbar>
</TabsToolbar> */}

<TabsContent value="settings" className="content-container mb-10">
<SettingsTab />
Expand Down
101 changes: 101 additions & 0 deletions apps/web/components/TabSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"use client";

/*
* Adapted from: https://github.com/dubinc/dub
*
* Original work Copyright (c) 2023 Dub, Inc.
* Licensed under AGPL-3.0
*
* This file may have been modified from the original.
*/
import { cn } from "@/utils";
import { cva, type VariantProps } from "class-variance-authority";
import { LayoutGroup, motion } from "framer-motion";
import Link from "next/link";
import { type Dispatch, type SetStateAction, useId } from "react";
import { ArrowUpRight } from "lucide-react";

const tabSelectButtonVariants = cva("p-4 transition-colors duration-75", {
variants: {
variant: {
default:
"text-content-subtle data-[selected=true]:text-content-emphasis data-[selected=false]:hover:text-content-default",
accent:
"text-content-subtle transition-[color,font-weight] data-[selected=true]:text-blue-600 data-[selected=false]:hover:text-content-default data-[selected=true]:font-medium",
},
},
defaultVariants: {
variant: "default",
},
});

const tabSelectIndicatorVariants = cva("absolute bottom-0 w-full px-1.5", {
variants: {
variant: {
default: "text-bg-inverted",
accent: "text-blue-600",
},
},
defaultVariants: {
variant: "default",
},
});

export function TabSelect<T extends string>({
variant,
options,
selected,
onSelect,
className,
}: VariantProps<typeof tabSelectButtonVariants> & {
options: { id: T; label: string; href?: string; target?: string }[];
selected: string | null;
onSelect?: Dispatch<SetStateAction<T>> | ((id: T) => void);
className?: string;
}) {
const layoutGroupId = useId();

return (
<div className={cn("flex text-sm", className)}>
<LayoutGroup id={layoutGroupId}>
{options.map(({ id, label, href, target }) => {
const isSelected = id === selected;
const As = href ? Link : "div";
return (
<As
key={id}
className="relative"
href={href ?? "#"}
target={target ?? undefined}
>
<button
type="button"
{...(onSelect && !href && { onClick: () => onSelect(id) })}
className={cn(
tabSelectButtonVariants({ variant }),
target === "_blank" && "group flex items-center gap-1.5",
)}
data-selected={isSelected}
aria-selected={isSelected}
>
{label}
{target === "_blank" && <ArrowUpRight className="size-2.5" />}
</button>
{isSelected && (
<motion.div
layoutId="indicator"
transition={{
duration: 0.1,
}}
className={tabSelectIndicatorVariants({ variant })}
>
<div className="h-0.5 rounded-t-full bg-current" />
</motion.div>
)}
</As>
);
})}
</LayoutGroup>
</div>
);
}
2 changes: 1 addition & 1 deletion apps/web/components/TopNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { ProfileImage } from "@/components/ProfileImage";

export function TopNav({ trigger }: { trigger: React.ReactNode }) {
return (
<div className="content-container flex h-16 shrink-0 items-center gap-x-4 border-b border-border bg-background shadow-sm sm:gap-x-6">
<div className="content-container flex h-16 shrink-0 items-center gap-x-4 bg-background sm:gap-x-6">
{trigger}

<div className="flex flex-1 gap-x-4 self-stretch lg:gap-x-6">
Expand Down