mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
chore: navbar refinements
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import {
|
||||
ArrowBottomRightIcon,
|
||||
QuestionMarkCircledIcon,
|
||||
} from "@radix-ui/react-icons";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
|
||||
import { LibraryPageStateProvider } from "./components/state-provider";
|
||||
import LibraryActionHeader from "./components/LibraryActionHeader/LibraryActionHeader";
|
||||
import LibraryAgentList from "./components/LibraryAgentList/LibraryAgentList";
|
||||
import { LibraryPageStateProvider } from "./components/state-provider";
|
||||
|
||||
/**
|
||||
* LibraryPage Component
|
||||
@@ -17,7 +17,7 @@ import LibraryAgentList from "./components/LibraryAgentList/LibraryAgentList";
|
||||
*/
|
||||
export default function LibraryPage() {
|
||||
return (
|
||||
<main className="container min-h-screen space-y-4 pb-20 sm:px-8 md:px-12">
|
||||
<main className="pt-160sm:px-8 container min-h-screen space-y-4 pb-20 pt-16 md:px-12">
|
||||
<LibraryPageStateProvider>
|
||||
<LibraryActionHeader />
|
||||
<LibraryAgentList />
|
||||
|
||||
@@ -1,82 +1,78 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CircleNotchIcon } from "@phosphor-icons/react/dist/ssr";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import Link, { type LinkProps } from "next/link";
|
||||
import React from "react";
|
||||
import { ButtonProps, extendedButtonVariants } from "./helpers";
|
||||
|
||||
// Extended button variants based on our design system
|
||||
const extendedButtonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 font-sans leading-snug border",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
primary:
|
||||
"bg-zinc-800 border-zinc-800 text-white hover:bg-zinc-900 hover:border-zinc-900 rounded-full disabled:text-white disabled:bg-zinc-200 disabled:border-zinc-200 disabled:opacity-1",
|
||||
secondary:
|
||||
"bg-zinc-100 border-zinc-100 text-black hover:bg-zinc-300 hover:border-zinc-300 rounded-full disabled:text-zinc-300 disabled:bg-zinc-50 disabled:border-zinc-50 disabled:opacity-1",
|
||||
destructive:
|
||||
"bg-red-500 border-red-500 text-white hover:bg-red-600 hover:border-red-600 rounded-full disabled:text-white disabled:bg-zinc-200 disabled:border-zinc-200 disabled:opacity-1",
|
||||
outline:
|
||||
"bg-transparent border-zinc-700 text-black hover:bg-zinc-100 hover:border-zinc-700 rounded-full disabled:border-zinc-200 disabled:text-zinc-200 disabled:opacity-1",
|
||||
ghost:
|
||||
"bg-transparent border-transparent text-black hover:bg-zinc-50 hover:border-zinc-50 rounded-full disabled:text-zinc-200 disabled:opacity-1",
|
||||
icon: "bg-white text-black border border-zinc-600 hover:bg-zinc-100 rounded-[96px] disabled:opacity-1",
|
||||
},
|
||||
size: {
|
||||
small: "px-3 py-2 text-sm gap-1.5 h-[2.25rem]",
|
||||
large: "min-w-20 px-4 py-3 text-sm gap-2",
|
||||
icon: "p-3",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "primary",
|
||||
size: "large",
|
||||
},
|
||||
},
|
||||
);
|
||||
export function Button(props: ButtonProps) {
|
||||
const {
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
loading = false,
|
||||
leftIcon,
|
||||
rightIcon,
|
||||
children,
|
||||
as = "button",
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof extendedButtonVariants> {
|
||||
loading?: boolean;
|
||||
leftIcon?: React.ReactNode;
|
||||
rightIcon?: React.ReactNode;
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
loading = false,
|
||||
leftIcon,
|
||||
rightIcon,
|
||||
children,
|
||||
disabled,
|
||||
...props
|
||||
}: ButtonProps) {
|
||||
const disabled = "disabled" in props ? props.disabled : false;
|
||||
const isDisabled = disabled;
|
||||
|
||||
const buttonContent = (
|
||||
<>
|
||||
{loading && (
|
||||
<CircleNotchIcon className="h-4 w-4 animate-spin" weight="bold" />
|
||||
)}
|
||||
{!loading && leftIcon}
|
||||
{children}
|
||||
{!loading && rightIcon}
|
||||
</>
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return variant === "ghost" ? (
|
||||
<button
|
||||
const loadingClassName =
|
||||
variant === "ghost"
|
||||
? cn(
|
||||
extendedButtonVariants({ variant, size, className }),
|
||||
"pointer-events-none",
|
||||
)
|
||||
: cn(
|
||||
extendedButtonVariants({ variant: "primary", size, className }),
|
||||
"pointer-events-none border-zinc-500 bg-zinc-500 text-white",
|
||||
);
|
||||
|
||||
return as === "NextLink" ? (
|
||||
<Link
|
||||
{...(restProps as LinkProps)}
|
||||
className={loadingClassName}
|
||||
aria-disabled="true"
|
||||
>
|
||||
<CircleNotchIcon className="h-4 w-4 animate-spin" weight="bold" />
|
||||
{children}
|
||||
</Link>
|
||||
) : (
|
||||
<button className={loadingClassName} disabled>
|
||||
<CircleNotchIcon className="h-4 w-4 animate-spin" weight="bold" />
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
if (as === "NextLink") {
|
||||
return (
|
||||
<Link
|
||||
{...(restProps as LinkProps)}
|
||||
className={cn(
|
||||
extendedButtonVariants({ variant, size, className }),
|
||||
"pointer-events-none",
|
||||
loading && "pointer-events-none",
|
||||
isDisabled && "pointer-events-none opacity-50",
|
||||
)}
|
||||
aria-disabled={isDisabled}
|
||||
>
|
||||
<CircleNotchIcon className="h-4 w-4 animate-spin" weight="bold" />
|
||||
{children}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className={cn(
|
||||
extendedButtonVariants({ variant: "primary", size, className }),
|
||||
"pointer-events-none border-zinc-500 bg-zinc-500 text-white",
|
||||
)}
|
||||
>
|
||||
<CircleNotchIcon className="h-4 w-4 animate-spin" weight="bold" />
|
||||
{children}
|
||||
</button>
|
||||
{buttonContent}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,18 +83,9 @@ function Button({
|
||||
loading && "pointer-events-none",
|
||||
)}
|
||||
disabled={isDisabled}
|
||||
{...props}
|
||||
{...(restProps as React.ButtonHTMLAttributes<HTMLButtonElement>)}
|
||||
>
|
||||
{loading && (
|
||||
<CircleNotchIcon className="h-4 w-4 animate-spin" weight="bold" />
|
||||
)}
|
||||
{!loading && leftIcon}
|
||||
{children}
|
||||
{!loading && rightIcon}
|
||||
{buttonContent}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Button.displayName = "Button";
|
||||
|
||||
export { Button, extendedButtonVariants };
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { cva, VariantProps } from "class-variance-authority";
|
||||
import { LinkProps } from "next/link";
|
||||
|
||||
// Extended button variants based on our design system
|
||||
export const extendedButtonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 font-sans leading-snug border",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
primary:
|
||||
"bg-zinc-800 border-zinc-800 text-white hover:bg-zinc-900 hover:border-zinc-900 rounded-full disabled:text-white disabled:bg-zinc-200 disabled:border-zinc-200 disabled:opacity-1",
|
||||
secondary:
|
||||
"bg-zinc-100 border-zinc-100 text-black hover:bg-zinc-300 hover:border-zinc-300 rounded-full disabled:text-zinc-300 disabled:bg-zinc-50 disabled:border-zinc-50 disabled:opacity-1",
|
||||
destructive:
|
||||
"bg-red-500 border-red-500 text-white hover:bg-red-600 hover:border-red-600 rounded-full disabled:text-white disabled:bg-zinc-200 disabled:border-zinc-200 disabled:opacity-1",
|
||||
outline:
|
||||
"bg-transparent border-zinc-700 text-black hover:bg-zinc-100 hover:border-zinc-700 rounded-full disabled:border-zinc-200 disabled:text-zinc-200 disabled:opacity-1",
|
||||
ghost:
|
||||
"bg-transparent border-transparent text-black hover:bg-zinc-50 hover:border-zinc-50 rounded-full disabled:text-zinc-200 disabled:opacity-1",
|
||||
icon: "bg-white text-black border border-zinc-600 hover:bg-zinc-100 rounded-[96px] disabled:opacity-1",
|
||||
},
|
||||
size: {
|
||||
small: "px-3 py-2 text-sm gap-1.5 h-[2.25rem]",
|
||||
large: "min-w-20 px-4 py-3 text-sm gap-2",
|
||||
icon: "p-3",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "primary",
|
||||
size: "large",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
type BaseButtonProps = {
|
||||
loading?: boolean;
|
||||
leftIcon?: React.ReactNode;
|
||||
rightIcon?: React.ReactNode;
|
||||
asChild?: boolean;
|
||||
} & VariantProps<typeof extendedButtonVariants>;
|
||||
|
||||
type ButtonAsButton = BaseButtonProps &
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||
as?: "button";
|
||||
href?: never;
|
||||
};
|
||||
|
||||
type ButtonAsLink = BaseButtonProps &
|
||||
Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> &
|
||||
LinkProps & {
|
||||
as: "NextLink";
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type ButtonProps = ButtonAsButton | ButtonAsLink;
|
||||
@@ -1,16 +1,14 @@
|
||||
import { IconAutoGPTLogo, IconType } from "@/components/ui/icons";
|
||||
import { ProfileDetails } from "@/lib/autogpt-server-api/types";
|
||||
import Link from "next/link";
|
||||
import { MobileNavBar } from "../../agptui/MobileNavBar";
|
||||
import Wallet from "../../agptui/Wallet";
|
||||
import { AccountMenu } from "./components/AccountMenu/AccountMenu";
|
||||
import { MobileNavBar } from "./components/MobileNavbar/MobileNavBar";
|
||||
import { NavbarLink } from "./components/NavbarLink";
|
||||
import { ProfilePopoutMenu } from "./components/ProfilePopoutMenu";
|
||||
|
||||
import BackendAPI from "@/lib/autogpt-server-api";
|
||||
import { getServerUser } from "@/lib/supabase/server/getServerUser";
|
||||
import { SignInIcon } from "@phosphor-icons/react/dist/ssr";
|
||||
import { Button } from "../../atoms/Button/Button";
|
||||
import { accountMeunItems, loggedInLinks } from "./helpers";
|
||||
import { LoginButton } from "./components/LoginButton";
|
||||
import { accountMenuItems, loggedInLinks, loggedOutLinks } from "./helpers";
|
||||
|
||||
async function getProfileData() {
|
||||
const api = new BackendAPI();
|
||||
@@ -31,12 +29,16 @@ export async function Navbar() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className="sticky top-0 z-40 mx-[16px] hidden h-16 items-center rounded-bl-2xl rounded-br-2xl border border-white/50 bg-white/5 py-3 pl-6 pr-3 backdrop-blur-[26px] dark:border-gray-700 dark:bg-gray-900 md:inline-flex">
|
||||
<nav className="sticky top-0 z-40 mx-[16px] hidden h-16 items-center rounded-bl-2xl rounded-br-2xl border border-white/50 bg-white/5 p-3 backdrop-blur-[26px] dark:border-gray-700 dark:bg-gray-900 md:inline-flex">
|
||||
{/* Left section */}
|
||||
<div className="flex flex-1 items-center gap-6">
|
||||
{loggedInLinks.map((link) => (
|
||||
<NavbarLink key={link.name} name={link.name} href={link.href} />
|
||||
))}
|
||||
{isLoggedIn
|
||||
? loggedInLinks.map((link) => (
|
||||
<NavbarLink key={link.name} name={link.name} href={link.href} />
|
||||
))
|
||||
: loggedOutLinks.map((link) => (
|
||||
<NavbarLink key={link.name} name={link.name} href={link.href} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Centered logo */}
|
||||
@@ -49,24 +51,15 @@ export async function Navbar() {
|
||||
{isLoggedIn ? (
|
||||
<div className="flex items-center gap-4">
|
||||
{profile && <Wallet />}
|
||||
<ProfilePopoutMenu
|
||||
menuItemGroups={accountMeunItems}
|
||||
<AccountMenu
|
||||
userName={profile?.username}
|
||||
userEmail={profile?.name}
|
||||
avatarSrc={profile?.avatar_url}
|
||||
menuItemGroups={accountMenuItems}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Link href="/login">
|
||||
<Button
|
||||
size="small"
|
||||
className="flex items-center justify-end space-x-2"
|
||||
leftIcon={<SignInIcon className="h-5 w-5" />}
|
||||
variant="secondary"
|
||||
>
|
||||
Log In
|
||||
</Button>
|
||||
</Link>
|
||||
<LoginButton />
|
||||
)}
|
||||
{/* <ThemeToggle /> */}
|
||||
</div>
|
||||
@@ -80,7 +73,7 @@ export async function Navbar() {
|
||||
menuItemGroups={[
|
||||
{
|
||||
groupName: "Navigation",
|
||||
items: links.map((link) => ({
|
||||
items: loggedInLinks.map((link) => ({
|
||||
icon:
|
||||
link.name === "Marketplace"
|
||||
? IconType.Marketplace
|
||||
@@ -95,27 +88,13 @@ export async function Navbar() {
|
||||
href: link.href,
|
||||
})),
|
||||
},
|
||||
...menuItemGroups,
|
||||
...accountMenuItems,
|
||||
]}
|
||||
userEmail={profile?.name}
|
||||
avatarSrc={profile?.avatar_url}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Link
|
||||
href="/login"
|
||||
className="fixed right-4 top-4 z-50 mt-4 inline-flex h-8 items-center justify-end rounded-lg pr-4 md:hidden"
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
className="flex items-center justify-end space-x-2"
|
||||
leftIcon={<SignInIcon className="h-5 w-5" />}
|
||||
variant="secondary"
|
||||
>
|
||||
Log In
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
) : null}
|
||||
</>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -6,22 +6,11 @@ import {
|
||||
} from "@/components/ui/popover";
|
||||
import Link from "next/link";
|
||||
import * as React from "react";
|
||||
import { ProfilePopoutMenuLogoutButton } from "../../../agptui/ProfilePopoutMenuLogoutButton";
|
||||
import { PublishAgentPopout } from "../../../agptui/composite/PublishAgentPopout";
|
||||
import {
|
||||
IconBuilder,
|
||||
IconEdit,
|
||||
IconLayoutDashboard,
|
||||
IconLibrary,
|
||||
IconLogOut,
|
||||
IconMarketplace,
|
||||
IconRefresh,
|
||||
IconSettings,
|
||||
IconType,
|
||||
IconUploadCloud,
|
||||
} from "../../../ui/icons";
|
||||
import { ProfilePopoutMenuLogoutButton } from "../../../../agptui/ProfilePopoutMenuLogoutButton";
|
||||
import { PublishAgentPopout } from "../../../../agptui/composite/PublishAgentPopout";
|
||||
import { getAccountMenuOptionIcon, MenuItemGroup } from "../../helpers";
|
||||
|
||||
interface ProfilePopoutMenuProps {
|
||||
interface Props {
|
||||
userName?: string;
|
||||
userEmail?: string;
|
||||
avatarSrc?: string;
|
||||
@@ -29,38 +18,14 @@ interface ProfilePopoutMenuProps {
|
||||
menuItemGroups: MenuItemGroup[];
|
||||
}
|
||||
|
||||
export function ProfilePopoutMenu({
|
||||
export function AccountMenu({
|
||||
userName,
|
||||
userEmail,
|
||||
avatarSrc,
|
||||
menuItemGroups,
|
||||
}: ProfilePopoutMenuProps) {
|
||||
}: Props) {
|
||||
const popupId = React.useId();
|
||||
|
||||
const getIcon = (icon: IconType) => {
|
||||
const iconClass = "w-6 h-6";
|
||||
switch (icon) {
|
||||
case IconType.LayoutDashboard:
|
||||
return <IconLayoutDashboard className={iconClass} />;
|
||||
case IconType.UploadCloud:
|
||||
return <IconUploadCloud className={iconClass} />;
|
||||
case IconType.Edit:
|
||||
return <IconEdit className={iconClass} />;
|
||||
case IconType.Settings:
|
||||
return <IconSettings className={iconClass} />;
|
||||
case IconType.LogOut:
|
||||
return <IconLogOut className={iconClass} />;
|
||||
case IconType.Marketplace:
|
||||
return <IconMarketplace className={iconClass} />;
|
||||
case IconType.Library:
|
||||
return <IconLibrary className={iconClass} />;
|
||||
case IconType.Builder:
|
||||
return <IconBuilder className={iconClass} />;
|
||||
default:
|
||||
return <IconRefresh className={iconClass} />;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
@@ -119,7 +84,7 @@ export function ProfilePopoutMenu({
|
||||
className="inline-flex w-full items-center justify-start gap-2.5"
|
||||
>
|
||||
<div className="relative h-6 w-6">
|
||||
{getIcon(item.icon)}
|
||||
{getAccountMenuOptionIcon(item.icon)}
|
||||
</div>
|
||||
<div className="font-sans text-base font-medium leading-normal text-neutral-800 dark:text-neutral-200">
|
||||
{item.text}
|
||||
@@ -135,7 +100,7 @@ export function ProfilePopoutMenu({
|
||||
trigger={
|
||||
<div className="inline-flex w-full items-center justify-start gap-2.5">
|
||||
<div className="relative h-6 w-6">
|
||||
{getIcon(item.icon)}
|
||||
{getAccountMenuOptionIcon(item.icon)}
|
||||
</div>
|
||||
<div className="font-sans text-base font-medium leading-normal text-neutral-800 dark:text-neutral-200">
|
||||
{item.text}
|
||||
@@ -157,7 +122,7 @@ export function ProfilePopoutMenu({
|
||||
tabIndex={0}
|
||||
>
|
||||
<div className="relative h-6 w-6">
|
||||
{getIcon(item.icon)}
|
||||
{getAccountMenuOptionIcon(item.icon)}
|
||||
</div>
|
||||
<div className="font-sans text-base font-medium leading-normal text-neutral-800 dark:text-neutral-200">
|
||||
{item.text}
|
||||
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/components/atoms/Button/Button";
|
||||
import { SignInIcon } from "@phosphor-icons/react/dist/ssr";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
export function LoginButton() {
|
||||
const pathname = usePathname();
|
||||
const isLoginPage = pathname.includes("/login");
|
||||
|
||||
if (isLoginPage) return null;
|
||||
|
||||
return (
|
||||
<Button
|
||||
as="NextLink"
|
||||
href="/login"
|
||||
size="small"
|
||||
className="flex items-center justify-end space-x-2"
|
||||
leftIcon={<SignInIcon className="h-5 w-5" />}
|
||||
variant="secondary"
|
||||
>
|
||||
Log In
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -1,45 +1,26 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import Link from "next/link";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
PopoverContent,
|
||||
PopoverPortal,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
IconType,
|
||||
IconMenu,
|
||||
IconChevronUp,
|
||||
IconEdit,
|
||||
IconLayoutDashboard,
|
||||
IconUploadCloud,
|
||||
IconSettings,
|
||||
IconLogOut,
|
||||
IconMarketplace,
|
||||
IconLibrary,
|
||||
IconBuilder,
|
||||
} from "../ui/icons";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { usePathname } from "next/navigation";
|
||||
import * as React from "react";
|
||||
import { IconChevronUp, IconMenu } from "../../../../ui/icons";
|
||||
import { MenuItemGroup } from "../../helpers";
|
||||
import { MobileNavbarMenuItem } from "./components/MobileNavbarMenuItem";
|
||||
|
||||
interface MobileNavBarProps {
|
||||
userName?: string;
|
||||
userEmail?: string;
|
||||
avatarSrc?: string;
|
||||
menuItemGroups: {
|
||||
groupName?: string;
|
||||
items: {
|
||||
icon: IconType;
|
||||
text: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
}[];
|
||||
}[];
|
||||
menuItemGroups: MenuItemGroup[];
|
||||
}
|
||||
|
||||
const Overlay = React.forwardRef<HTMLDivElement, { children: React.ReactNode }>(
|
||||
@@ -49,76 +30,15 @@ const Overlay = React.forwardRef<HTMLDivElement, { children: React.ReactNode }>(
|
||||
</div>
|
||||
),
|
||||
);
|
||||
|
||||
Overlay.displayName = "Overlay";
|
||||
|
||||
const PopoutMenuItem: React.FC<{
|
||||
icon: IconType;
|
||||
isActive: boolean;
|
||||
text: React.ReactNode;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
}> = ({ icon, isActive, text, href, onClick }) => {
|
||||
const getIcon = (iconType: IconType) => {
|
||||
const iconClass = "w-6 h-6 relative";
|
||||
switch (iconType) {
|
||||
case IconType.Marketplace:
|
||||
return <IconMarketplace className={iconClass} />;
|
||||
case IconType.Library:
|
||||
return <IconLibrary className={iconClass} />;
|
||||
case IconType.Builder:
|
||||
return <IconBuilder className={iconClass} />;
|
||||
case IconType.Edit:
|
||||
return <IconEdit className={iconClass} />;
|
||||
case IconType.LayoutDashboard:
|
||||
return <IconLayoutDashboard className={iconClass} />;
|
||||
case IconType.UploadCloud:
|
||||
return <IconUploadCloud className={iconClass} />;
|
||||
case IconType.Settings:
|
||||
return <IconSettings className={iconClass} />;
|
||||
case IconType.LogOut:
|
||||
return <IconLogOut className={iconClass} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const content = (
|
||||
<div className="inline-flex w-full items-center justify-start gap-4 hover:rounded hover:bg-[#e0e0e0] dark:hover:bg-[#3a3a3a]">
|
||||
{getIcon(icon)}
|
||||
<div className="relative">
|
||||
<div
|
||||
className={`font-sans text-base font-normal leading-7 text-[#474747] dark:text-[#cfcfcf] ${isActive ? "font-semibold text-[#272727] dark:text-[#ffffff]" : "text-[#474747] dark:text-[#cfcfcf]"}`}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
{isActive && (
|
||||
<div className="absolute bottom-[-4px] left-0 h-[2px] w-full bg-[#272727] dark:bg-[#ffffff]"></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (onClick)
|
||||
return (
|
||||
<div className="w-full" onClick={onClick}>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
if (href)
|
||||
return (
|
||||
<Link href={href} className="w-full">
|
||||
{content}
|
||||
</Link>
|
||||
);
|
||||
return content;
|
||||
};
|
||||
|
||||
export const MobileNavBar: React.FC<MobileNavBarProps> = ({
|
||||
export function MobileNavBar({
|
||||
userName,
|
||||
userEmail,
|
||||
avatarSrc,
|
||||
menuItemGroups,
|
||||
}) => {
|
||||
}: MobileNavBarProps) {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
const pathname = usePathname();
|
||||
const parts = pathname.split("/");
|
||||
@@ -173,7 +93,7 @@ export const MobileNavBar: React.FC<MobileNavBarProps> = ({
|
||||
{menuItemGroups.map((group, groupIndex) => (
|
||||
<React.Fragment key={groupIndex}>
|
||||
{group.items.map((item, itemIndex) => (
|
||||
<PopoutMenuItem
|
||||
<MobileNavbarMenuItem
|
||||
key={itemIndex}
|
||||
icon={item.icon}
|
||||
isActive={item.href === activeLink}
|
||||
@@ -194,4 +114,4 @@ export const MobileNavBar: React.FC<MobileNavBarProps> = ({
|
||||
</AnimatePresence>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { IconType } from "@/components/ui/icons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Link from "next/link";
|
||||
import { getAccountMenuOptionIcon } from "../../../helpers";
|
||||
|
||||
interface Props {
|
||||
icon: IconType;
|
||||
isActive: boolean;
|
||||
text: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export function MobileNavbarMenuItem({
|
||||
icon,
|
||||
isActive,
|
||||
text,
|
||||
href,
|
||||
onClick,
|
||||
}: Props) {
|
||||
const content = (
|
||||
<div className="inline-flex w-full items-center justify-start gap-4 hover:rounded hover:bg-[#e0e0e0] dark:hover:bg-[#3a3a3a]">
|
||||
{getAccountMenuOptionIcon(icon)}
|
||||
<div className="relative">
|
||||
<div
|
||||
className={cn(
|
||||
"font-sans text-base font-normal leading-7",
|
||||
isActive
|
||||
? "font-semibold text-[#272727] dark:text-[#ffffff]"
|
||||
: "text-[#474747] dark:text-[#cfcfcf]",
|
||||
)}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
{isActive && (
|
||||
<div className="absolute bottom-[-4px] left-0 h-[2px] w-full bg-[#272727] dark:bg-[#ffffff]"></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (onClick)
|
||||
return (
|
||||
<div className="w-full" onClick={onClick}>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
if (href)
|
||||
return (
|
||||
<Link href={href} className="w-full">
|
||||
{content}
|
||||
</Link>
|
||||
);
|
||||
return content;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { IconLaptop } from "@/components/ui/icons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
CubeIcon,
|
||||
HouseIcon,
|
||||
@@ -9,15 +11,16 @@ import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Text } from "../../../atoms/Text/Text";
|
||||
|
||||
interface NavbarLinkProps {
|
||||
interface Props {
|
||||
name: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
export const NavbarLink = ({ name, href }: NavbarLinkProps) => {
|
||||
export function NavbarLink({ name, href }: Props) {
|
||||
const pathname = usePathname();
|
||||
const parts = pathname.split("/");
|
||||
const activeLink = "/" + (parts.length > 2 ? parts[2] : parts[1]);
|
||||
const isActive = activeLink === href;
|
||||
|
||||
return (
|
||||
<Link
|
||||
@@ -26,43 +29,42 @@ export const NavbarLink = ({ name, href }: NavbarLinkProps) => {
|
||||
className="font-poppins text-[20px] leading-[28px]"
|
||||
>
|
||||
<div
|
||||
className={`p-2 ${
|
||||
activeLink === href
|
||||
? "rounded-2xl bg-neutral-800 dark:bg-neutral-200"
|
||||
: ""
|
||||
} flex items-center justify-start gap-1`}
|
||||
className={cn(
|
||||
"flex items-center justify-start gap-1 p-2",
|
||||
isActive &&
|
||||
"rounded-small bg-neutral-800 p-2 transition-all duration-300 dark:bg-neutral-200",
|
||||
)}
|
||||
>
|
||||
{href === "/marketplace" && (
|
||||
<StorefrontIcon
|
||||
className={`h-6 w-6 ${activeLink === href ? "text-white dark:text-black" : ""}`}
|
||||
className={cn("h-6 w-6", isActive && "text-white dark:text-black")}
|
||||
/>
|
||||
)}
|
||||
{href === "/build" && (
|
||||
<CubeIcon
|
||||
className={`h-6 w-6 ${activeLink === href ? "text-white dark:text-black" : ""}`}
|
||||
className={cn("h-6 w-6", isActive && "text-white dark:text-black")}
|
||||
/>
|
||||
)}
|
||||
{href === "/monitor" && (
|
||||
<IconLaptop
|
||||
className={`h-6 w-6 ${activeLink === href ? "text-white dark:text-black" : ""}`}
|
||||
className={cn("h-6 w-6", isActive && "text-white dark:text-black")}
|
||||
/>
|
||||
)}
|
||||
{href === "/library" && (
|
||||
<HouseIcon
|
||||
className={`h-6 w-6 ${activeLink === href ? "text-white dark:text-black" : ""}`}
|
||||
className={cn("h-6 w-6", isActive && "text-white dark:text-black")}
|
||||
/>
|
||||
)}
|
||||
<Text
|
||||
variant="body-medium"
|
||||
className={`hidden lg:block ${
|
||||
activeLink === href
|
||||
? "text-neutral-50 dark:text-neutral-900"
|
||||
: "text-neutral-900 dark:text-neutral-50"
|
||||
}`}
|
||||
className={cn(
|
||||
"hidden lg:block",
|
||||
isActive ? "!text-white" : "!text-black",
|
||||
)}
|
||||
>
|
||||
{name}
|
||||
</Text>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import { Icon } from "@phosphor-icons/react";
|
||||
import {
|
||||
CloudArrowUp,
|
||||
GearIcon,
|
||||
SignOut,
|
||||
SquaresFourIcon,
|
||||
UserSquareIcon,
|
||||
} from "@phosphor-icons/react/dist/ssr";
|
||||
|
||||
type Link = {
|
||||
name: string;
|
||||
href: string;
|
||||
};
|
||||
|
||||
export const loggedInLinks: Link[] = [
|
||||
{
|
||||
name: "Home",
|
||||
href: "/library",
|
||||
},
|
||||
{
|
||||
name: "Marketplace",
|
||||
href: "/marketplace",
|
||||
},
|
||||
{
|
||||
name: "Build",
|
||||
href: "/build",
|
||||
},
|
||||
];
|
||||
|
||||
export const loggedOutLinks: Link[] = [
|
||||
{
|
||||
name: "Marketplace",
|
||||
href: "/marketplace",
|
||||
},
|
||||
];
|
||||
|
||||
type MenuItemGroup = {
|
||||
items: {
|
||||
icon: Icon;
|
||||
text: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const accountMeunItems: MenuItemGroup[] = [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: UserSquareIcon,
|
||||
text: "Edit profile",
|
||||
href: "/profile",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: SquaresFourIcon,
|
||||
text: "Creator Dashboard",
|
||||
href: "/profile/dashboard",
|
||||
},
|
||||
{
|
||||
icon: CloudArrowUp,
|
||||
text: "Publish an agent",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: GearIcon,
|
||||
text: "Settings",
|
||||
href: "/profile/settings",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: SignOut,
|
||||
text: "Log out",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,115 @@
|
||||
import {
|
||||
IconBuilder,
|
||||
IconEdit,
|
||||
IconLayoutDashboard,
|
||||
IconLibrary,
|
||||
IconLogOut,
|
||||
IconMarketplace,
|
||||
IconRefresh,
|
||||
IconSettings,
|
||||
IconType,
|
||||
IconUploadCloud,
|
||||
} from "@/components/ui/icons";
|
||||
|
||||
type Link = {
|
||||
name: string;
|
||||
href: string;
|
||||
};
|
||||
|
||||
export const loggedInLinks: Link[] = [
|
||||
{
|
||||
name: "Marketplace",
|
||||
href: "/marketplace",
|
||||
},
|
||||
{
|
||||
name: "Library",
|
||||
href: "/library",
|
||||
},
|
||||
{
|
||||
name: "Build",
|
||||
href: "/build",
|
||||
},
|
||||
];
|
||||
|
||||
export const loggedOutLinks: Link[] = [
|
||||
{
|
||||
name: "Marketplace",
|
||||
href: "/marketplace",
|
||||
},
|
||||
];
|
||||
|
||||
export type MenuItemGroup = {
|
||||
groupName?: string;
|
||||
items: {
|
||||
icon: IconType;
|
||||
text: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const accountMenuItems: MenuItemGroup[] = [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: IconType.Edit,
|
||||
text: "Edit profile",
|
||||
href: "/profile",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: IconType.LayoutDashboard,
|
||||
text: "Creator Dashboard",
|
||||
href: "/profile/dashboard",
|
||||
},
|
||||
{
|
||||
icon: IconType.UploadCloud,
|
||||
text: "Publish an agent",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: IconType.Settings,
|
||||
text: "Settings",
|
||||
href: "/profile/settings",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{
|
||||
icon: IconType.LogOut,
|
||||
text: "Log out",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function getAccountMenuOptionIcon(icon: IconType) {
|
||||
const iconClass = "w-6 h-6";
|
||||
switch (icon) {
|
||||
case IconType.LayoutDashboard:
|
||||
return <IconLayoutDashboard className={iconClass} />;
|
||||
case IconType.UploadCloud:
|
||||
return <IconUploadCloud className={iconClass} />;
|
||||
case IconType.Edit:
|
||||
return <IconEdit className={iconClass} />;
|
||||
case IconType.Settings:
|
||||
return <IconSettings className={iconClass} />;
|
||||
case IconType.LogOut:
|
||||
return <IconLogOut className={iconClass} />;
|
||||
case IconType.Marketplace:
|
||||
return <IconMarketplace className={iconClass} />;
|
||||
case IconType.Library:
|
||||
return <IconLibrary className={iconClass} />;
|
||||
case IconType.Builder:
|
||||
return <IconBuilder className={iconClass} />;
|
||||
default:
|
||||
return <IconRefresh className={iconClass} />;
|
||||
}
|
||||
}
|
||||
@@ -14,30 +14,30 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
|
||||
// Border radius scale data based on Figma design tokens
|
||||
// Custom naming convention: xs, s, m, l, xl, 2xl, full
|
||||
// Custom naming convention: xsmall, small, medium, large, xlarge, 2xlarge, full
|
||||
const borderRadiusScale = [
|
||||
{
|
||||
name: "xs",
|
||||
name: "xsmall",
|
||||
value: "0.25rem",
|
||||
rem: "0.25rem",
|
||||
px: "4px",
|
||||
class: "rounded-xs",
|
||||
class: "rounded-xsmall",
|
||||
description: "Extra small - for subtle rounding",
|
||||
},
|
||||
{
|
||||
name: "s",
|
||||
name: "small",
|
||||
value: "0.5rem",
|
||||
rem: "0.5rem",
|
||||
px: "8px",
|
||||
class: "rounded-s",
|
||||
class: "rounded-small",
|
||||
description: "Small - for cards and containers",
|
||||
},
|
||||
{
|
||||
name: "m",
|
||||
name: "medium",
|
||||
value: "0.75rem",
|
||||
rem: "0.75rem",
|
||||
px: "12px",
|
||||
class: "rounded-m",
|
||||
class: "rounded-medium",
|
||||
description: "Medium - for buttons and inputs",
|
||||
},
|
||||
{
|
||||
@@ -49,19 +49,19 @@ const borderRadiusScale = [
|
||||
description: "Large - for panels and modals",
|
||||
},
|
||||
{
|
||||
name: "xl",
|
||||
name: "xlarge",
|
||||
value: "1.25rem",
|
||||
rem: "1.25rem",
|
||||
px: "20px",
|
||||
class: "rounded-xl",
|
||||
class: "rounded-xlarge",
|
||||
description: "Extra large - for hero sections",
|
||||
},
|
||||
{
|
||||
name: "2xl",
|
||||
name: "2xlarge",
|
||||
value: "1.5rem",
|
||||
rem: "1.5rem",
|
||||
px: "24px",
|
||||
class: "rounded-2xl",
|
||||
class: "rounded-2xlarge",
|
||||
description: "2X large - for major containers",
|
||||
},
|
||||
{
|
||||
@@ -84,10 +84,11 @@ export function AllVariants() {
|
||||
Border Radius
|
||||
</Text>
|
||||
<Text variant="large" className="text-zinc-600">
|
||||
Our border radius system uses a simplified naming convention (xs, s,
|
||||
m, large, xl, 2xl, full) based on our Figma design tokens. This
|
||||
creates visual hierarchy and maintains design consistency across all
|
||||
components.
|
||||
Our border radius system uses a descriptive naming convention
|
||||
(xsmall, small, medium, large, xlarge, 2xlarge, full) based on our
|
||||
Figma design tokens. This creates visual hierarchy and maintains
|
||||
design consistency across all components while avoiding conflicts
|
||||
with Tailwind's built-in classes.
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
@@ -137,9 +138,10 @@ export function AllVariants() {
|
||||
</div>
|
||||
<Text variant="body" className="mb-4 text-zinc-600">
|
||||
We use a custom border radius system based on our Figma design
|
||||
tokens, with simplified naming (xs, s, m, large, xl, 2xl, full)
|
||||
that provides consistent radius values optimized for our design
|
||||
system.
|
||||
tokens, with descriptive naming (xsmall, small, medium, large,
|
||||
xlarge, 2xlarge, full) that provides consistent radius values
|
||||
optimized for our design system while avoiding conflicts with
|
||||
Tailwind's built-in classes.
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,7 +190,8 @@ export function AllVariants() {
|
||||
<Text variant="body" className="mb-6 text-zinc-600">
|
||||
All border radius values from our Figma design tokens. Each value
|
||||
can be applied to all corners or specific corners/sides using our
|
||||
simplified naming convention (xs, s, m, large, xl, 2xl, full).
|
||||
descriptive naming convention (xsmall, small, medium, large, xlarge,
|
||||
2xlarge, full).
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
@@ -232,30 +235,30 @@ export function AllVariants() {
|
||||
|
||||
<StoryCode
|
||||
code={`// Border radius examples - Design System Tokens
|
||||
<div className="rounded-xs">Extra small rounding (4px)</div>
|
||||
<div className="rounded-s">Small rounding (8px)</div>
|
||||
<div className="rounded-m">Medium rounding (12px)</div>
|
||||
<div className="rounded-xsmall">Extra small rounding (4px)</div>
|
||||
<div className="rounded-small">Small rounding (8px)</div>
|
||||
<div className="rounded-medium">Medium rounding (12px)</div>
|
||||
<div className="rounded-large">Large rounding (16px)</div>
|
||||
<div className="rounded-xl">Extra large rounding (20px)</div>
|
||||
<div className="rounded-2xl">2X large rounding (24px)</div>
|
||||
<div className="rounded-xlarge">Extra large rounding (20px)</div>
|
||||
<div className="rounded-2xlarge">2X large rounding (24px)</div>
|
||||
<div className="rounded-full">Pill buttons (circular)</div>
|
||||
|
||||
// Directional rounding (works with all sizes)
|
||||
<div className="rounded-t-m">Top corners only</div>
|
||||
<div className="rounded-r-m">Right corners only</div>
|
||||
<div className="rounded-b-m">Bottom corners only</div>
|
||||
<div className="rounded-l-m">Left corners only</div>
|
||||
<div className="rounded-t-medium">Top corners only</div>
|
||||
<div className="rounded-r-medium">Right corners only</div>
|
||||
<div className="rounded-b-medium">Bottom corners only</div>
|
||||
<div className="rounded-l-medium">Left corners only</div>
|
||||
|
||||
// Individual corners
|
||||
<div className="rounded-tl-m">Top-left corner</div>
|
||||
<div className="rounded-tr-m">Top-right corner</div>
|
||||
<div className="rounded-bl-m">Bottom-left corner</div>
|
||||
<div className="rounded-br-m">Bottom-right corner</div>
|
||||
<div className="rounded-tl-medium">Top-left corner</div>
|
||||
<div className="rounded-tr-medium">Top-right corner</div>
|
||||
<div className="rounded-bl-medium">Bottom-left corner</div>
|
||||
<div className="rounded-br-medium">Bottom-right corner</div>
|
||||
|
||||
// Usage recommendations
|
||||
<button className="rounded-full">Pill Button</button>
|
||||
<div className="rounded-m">Card Container</div>
|
||||
<input className="rounded-s">Input Field</input>`}
|
||||
<div className="rounded-medium">Card Container</div>
|
||||
<input className="rounded-small">Input Field</input>`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,56 +73,56 @@ const config = {
|
||||
},
|
||||
spacing: {
|
||||
// Tailwind spacing + custom sizes
|
||||
0: "0rem",
|
||||
0.5: "0.125rem",
|
||||
1: "0.25rem",
|
||||
1.5: "0.375rem",
|
||||
2: "0.5rem",
|
||||
2.5: "0.625rem",
|
||||
3: "0.75rem",
|
||||
3.5: "0.875rem",
|
||||
4: "1rem",
|
||||
5: "1.25rem",
|
||||
6: "1.5rem",
|
||||
7: "1.75rem",
|
||||
7.5: "1.875rem",
|
||||
8: "2rem",
|
||||
8.5: "2.125rem",
|
||||
9: "2.25rem",
|
||||
10: "2.5rem",
|
||||
11: "2.75rem",
|
||||
12: "3rem",
|
||||
14: "3.5rem",
|
||||
16: "4rem",
|
||||
18: "4.5rem",
|
||||
20: "5rem",
|
||||
24: "6rem",
|
||||
28: "7rem",
|
||||
32: "8rem",
|
||||
36: "9rem",
|
||||
40: "10rem",
|
||||
44: "11rem",
|
||||
48: "12rem",
|
||||
52: "13rem",
|
||||
56: "14rem",
|
||||
60: "15rem",
|
||||
64: "16rem",
|
||||
68: "17rem",
|
||||
70: "17.5rem",
|
||||
71: "17.75rem",
|
||||
72: "18rem",
|
||||
76: "19rem",
|
||||
80: "20rem",
|
||||
96: "24rem",
|
||||
0: "0rem", // 0px
|
||||
0.5: "0.125rem", // 2px
|
||||
1: "0.25rem", // 4px
|
||||
1.5: "0.375rem", // 6px
|
||||
2: "0.5rem", // 8px
|
||||
2.5: "0.625rem", // 10px
|
||||
3: "0.75rem", // 12px
|
||||
3.5: "0.875rem", // 14px
|
||||
4: "1rem", // 16px
|
||||
5: "1.25rem", // 20px
|
||||
6: "1.5rem", // 24px
|
||||
7: "1.75rem", // 28px
|
||||
7.5: "1.875rem", // 30px
|
||||
8: "2rem", // 32px
|
||||
8.5: "2.125rem", // 34px
|
||||
9: "2.25rem", // 36px
|
||||
10: "2.5rem", // 40px
|
||||
11: "2.75rem", // 44px
|
||||
12: "3rem", // 48px
|
||||
14: "3.5rem", // 56px
|
||||
16: "4rem", // 64px
|
||||
18: "4.5rem", // 72px
|
||||
20: "5rem", // 80px
|
||||
24: "6rem", // 96px
|
||||
28: "7rem", // 112px
|
||||
32: "8rem", // 128px
|
||||
36: "9rem", // 144px
|
||||
40: "10rem", // 160px
|
||||
44: "11rem", // 176px
|
||||
48: "12rem", // 192px
|
||||
52: "13rem", // 208px
|
||||
56: "14rem", // 224px
|
||||
60: "15rem", // 240px
|
||||
64: "16rem", // 256px
|
||||
68: "17rem", // 272px
|
||||
70: "17.5rem", // 280px
|
||||
71: "17.75rem", // 284px
|
||||
72: "18rem", // 288px
|
||||
76: "19rem", // 304px
|
||||
80: "20rem", // 320px
|
||||
96: "24rem", // 384px
|
||||
},
|
||||
borderRadius: {
|
||||
// Design system border radius tokens from Figma
|
||||
xs: "0.25rem", // 4px
|
||||
s: "0.5rem", // 8px
|
||||
m: "0.75rem", // 12px
|
||||
large: "1rem", // 16px (renamed from 'l' to avoid conflict with directional 'left')
|
||||
xl: "1.25rem", // 20px
|
||||
"2xl": "1.5rem", // 24px
|
||||
xsmall: "0.25rem", // 4px
|
||||
small: "0.5rem", // 8px
|
||||
medium: "0.75rem", // 12px
|
||||
large: "1rem", // 16px
|
||||
xlarge: "1.25rem", // 20px
|
||||
"2xlarge": "1.5rem", // 24px
|
||||
full: "9999px", // For pill buttons
|
||||
|
||||
// Legacy values - kept for backward compatibility
|
||||
|
||||
Reference in New Issue
Block a user