mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
refactor(navbar): extrair NavbarShell e adicionar variante navbar no Button
Unifica a estrutura da navbar entre o app e a landing page via novo componente NavbarShell. Centraliza estilos de botões da navbar na variante `navbar` do Button, eliminando nav-styles.ts e as classes inline duplicadas. AnimatedThemeToggler, RefreshPageButton e MobileNav passam a aceitar prop `variant` para adaptar ao contexto. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,6 @@ import {
|
|||||||
extraFeatures,
|
extraFeatures,
|
||||||
getMetricsItems,
|
getMetricsItems,
|
||||||
mainFeatures,
|
mainFeatures,
|
||||||
navbarActionClassName,
|
|
||||||
navLinks,
|
navLinks,
|
||||||
pwaHighlights,
|
pwaHighlights,
|
||||||
stackItems,
|
stackItems,
|
||||||
@@ -27,6 +26,7 @@ import { landingImages } from "@/features/landing/images";
|
|||||||
import { fetchGitHubStats } from "@/features/landing/queries";
|
import { fetchGitHubStats } from "@/features/landing/queries";
|
||||||
import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler";
|
import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler";
|
||||||
import { Logo } from "@/shared/components/logo";
|
import { Logo } from "@/shared/components/logo";
|
||||||
|
import { NavbarShell } from "@/shared/components/navigation/navbar/navbar-shell";
|
||||||
import { Badge } from "@/shared/components/ui/badge";
|
import { Badge } from "@/shared/components/ui/badge";
|
||||||
import { Button } from "@/shared/components/ui/button";
|
import { Button } from "@/shared/components/ui/button";
|
||||||
import { Card, CardContent } from "@/shared/components/ui/card";
|
import { Card, CardContent } from "@/shared/components/ui/card";
|
||||||
@@ -50,65 +50,60 @@ export default async function Page() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen flex-col">
|
<div className="flex min-h-screen flex-col">
|
||||||
{/* Navigation */}
|
{/* Navigation */}
|
||||||
<header className="sticky top-0 z-50 flex h-16 shrink-0 items-center bg-primary">
|
<NavbarShell>
|
||||||
<div className="relative z-10 max-w-8xl mx-auto px-4 w-full flex h-full items-center justify-between">
|
{/* Center Navigation Links */}
|
||||||
<Logo variant="compact" invertTextOnDark={false} />
|
<nav className="hidden md:flex items-center gap-1 absolute left-1/2 -translate-x-1/2">
|
||||||
|
{navLinks.map(({ href, label }) => (
|
||||||
|
<a
|
||||||
|
key={href}
|
||||||
|
href={href}
|
||||||
|
className="rounded-md px-2 py-1.5 text-sm font-medium text-black/75 hover:text-black hover:bg-black/10 transition-colors"
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
|
||||||
{/* Center Navigation Links */}
|
<nav className="ml-auto flex items-center gap-2 md:gap-3">
|
||||||
<nav className="hidden md:flex items-center gap-1 absolute left-1/2 -translate-x-1/2">
|
<AnimatedThemeToggler variant="navbar" />
|
||||||
{navLinks.map(({ href, label }) => (
|
{!isPublicDomain &&
|
||||||
<a
|
(session?.user ? (
|
||||||
key={href}
|
<Link prefetch href="/dashboard" className="hidden md:block">
|
||||||
href={href}
|
<Button
|
||||||
className="rounded-md px-2 py-1.5 text-sm font-medium text-black/75 hover:text-black hover:bg-black/10 transition-colors"
|
variant="outline"
|
||||||
>
|
size="sm"
|
||||||
{label}
|
className="border-black/20 text-black/80 bg-transparent hover:bg-black/10 hover:text-black shadow-none"
|
||||||
</a>
|
>
|
||||||
))}
|
Dashboard
|
||||||
</nav>
|
</Button>
|
||||||
|
</Link>
|
||||||
<nav className="flex items-center gap-2 md:gap-3">
|
) : (
|
||||||
<AnimatedThemeToggler className={navbarActionClassName} />
|
<div className="hidden md:flex items-center gap-2">
|
||||||
{!isPublicDomain &&
|
<Link href="/login">
|
||||||
(session?.user ? (
|
|
||||||
<Link prefetch href="/dashboard" className="hidden md:block">
|
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="border-black/20 text-black/80 bg-transparent hover:bg-black/10 hover:text-black shadow-none"
|
className="text-black/75 hover:bg-black/10 hover:text-black shadow-none"
|
||||||
>
|
>
|
||||||
Dashboard
|
Entrar
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
<Link href="/signup">
|
||||||
<div className="hidden md:flex items-center gap-2">
|
<Button
|
||||||
<Link href="/login">
|
size="sm"
|
||||||
<Button
|
className="bg-black/10 border border-black/20 text-black shadow-none hover:bg-black/20 gap-2"
|
||||||
variant="ghost"
|
>
|
||||||
size="sm"
|
Começar
|
||||||
className="text-black/75 hover:bg-black/10 hover:text-black shadow-none"
|
</Button>
|
||||||
>
|
</Link>
|
||||||
Entrar
|
</div>
|
||||||
</Button>
|
))}
|
||||||
</Link>
|
<MobileNav
|
||||||
<Link href="/signup">
|
isPublicDomain={isPublicDomain}
|
||||||
<Button
|
isLoggedIn={!!session?.user}
|
||||||
size="sm"
|
/>
|
||||||
className="bg-black/10 border border-black/20 text-black shadow-none hover:bg-black/20 gap-2"
|
</nav>
|
||||||
>
|
</NavbarShell>
|
||||||
Começar
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
<MobileNav
|
|
||||||
isPublicDomain={isPublicDomain}
|
|
||||||
isLoggedIn={!!session?.user}
|
|
||||||
triggerClassName="border border-black/10 text-black/75 shadow-none hover:border-black/20 hover:bg-black/10 hover:text-black focus-visible:ring-black/20"
|
|
||||||
/>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="relative overflow-hidden pt-14 md:pt-20 lg:pt-24 pb-0">
|
<section className="relative overflow-hidden pt-14 md:pt-20 lg:pt-24 pb-0">
|
||||||
|
|||||||
@@ -24,24 +24,18 @@ const navLinks = [
|
|||||||
interface MobileNavProps {
|
interface MobileNavProps {
|
||||||
isPublicDomain: boolean;
|
isPublicDomain: boolean;
|
||||||
isLoggedIn: boolean;
|
isLoggedIn: boolean;
|
||||||
triggerClassName?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MobileNav({
|
export function MobileNav({ isPublicDomain, isLoggedIn }: MobileNavProps) {
|
||||||
isPublicDomain,
|
|
||||||
isLoggedIn,
|
|
||||||
triggerClassName,
|
|
||||||
}: MobileNavProps) {
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="md:hidden">
|
<div className="md:hidden">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="navbar"
|
||||||
size="icon"
|
size="icon-sm"
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => setOpen(true)}
|
||||||
aria-label="Abrir menu"
|
aria-label="Abrir menu"
|
||||||
className={triggerClassName}
|
|
||||||
>
|
>
|
||||||
<RiMenuLine className="size-5" />
|
<RiMenuLine className="size-5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -35,9 +35,6 @@ export type FeatureItem = {
|
|||||||
colorVar: string;
|
colorVar: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const navbarActionClassName =
|
|
||||||
"border-black/10 bg-transparent text-black/75 shadow-none hover:border-black/20 hover:bg-black/10 hover:text-black focus-visible:ring-black/20 data-[state=open]:bg-black/10 data-[state=open]:text-black";
|
|
||||||
|
|
||||||
export const navLinks = [
|
export const navLinks = [
|
||||||
{ href: "#telas", label: "conheça as telas" },
|
{ href: "#telas", label: "conheça as telas" },
|
||||||
{ href: "#funcionalidades", label: "funcionalidades" },
|
{ href: "#funcionalidades", label: "funcionalidades" },
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { RiMoonClearLine, RiSunLine } from "@remixicon/react";
|
import { RiMoonClearLine, RiSunLine } from "@remixicon/react";
|
||||||
|
import type { VariantProps } from "class-variance-authority";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { flushSync } from "react-dom";
|
import { flushSync } from "react-dom";
|
||||||
import { buttonVariants } from "@/shared/components/ui/button";
|
import { buttonVariants } from "@/shared/components/ui/button";
|
||||||
@@ -13,11 +14,13 @@ import { cn } from "@/shared/utils/ui";
|
|||||||
interface AnimatedThemeTogglerProps
|
interface AnimatedThemeTogglerProps
|
||||||
extends React.ComponentPropsWithoutRef<"button"> {
|
extends React.ComponentPropsWithoutRef<"button"> {
|
||||||
duration?: number;
|
duration?: number;
|
||||||
|
variant?: VariantProps<typeof buttonVariants>["variant"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AnimatedThemeToggler = ({
|
export const AnimatedThemeToggler = ({
|
||||||
className,
|
className,
|
||||||
duration = 400,
|
duration = 400,
|
||||||
|
variant = "ghost",
|
||||||
...props
|
...props
|
||||||
}: AnimatedThemeTogglerProps) => {
|
}: AnimatedThemeTogglerProps) => {
|
||||||
const [isDark, setIsDark] = useState(false);
|
const [isDark, setIsDark] = useState(false);
|
||||||
@@ -84,10 +87,10 @@ export const AnimatedThemeToggler = ({
|
|||||||
onClick={toggleTheme}
|
onClick={toggleTheme}
|
||||||
data-state={isDark ? "dark" : "light"}
|
data-state={isDark ? "dark" : "light"}
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({ variant: "ghost", size: "icon-sm" }),
|
buttonVariants({ variant, size: "icon-sm" }),
|
||||||
"group relative text-muted-foreground transition-all duration-200",
|
"group relative transition-all duration-200",
|
||||||
"hover:text-foreground focus-visible:ring-2 focus-visible:ring-primary/40",
|
variant === "ghost" &&
|
||||||
"data-[state=open]:bg-accent/60 data-[state=open]:text-foreground",
|
"text-muted-foreground hover:text-foreground focus-visible:ring-2 focus-visible:ring-primary/40 data-[state=open]:bg-accent/60 data-[state=open]:text-foreground",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import Link from "next/link";
|
|
||||||
import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler";
|
import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler";
|
||||||
import { Logo } from "@/shared/components/logo";
|
|
||||||
import { NotificationBell } from "@/shared/components/navigation/navbar/notification-bell";
|
import { NotificationBell } from "@/shared/components/navigation/navbar/notification-bell";
|
||||||
import { RefreshPageButton } from "@/shared/components/refresh-page-button";
|
import { RefreshPageButton } from "@/shared/components/refresh-page-button";
|
||||||
import type { DashboardNotificationsSnapshot } from "@/shared/lib/types/notifications";
|
import type { DashboardNotificationsSnapshot } from "@/shared/lib/types/notifications";
|
||||||
import { NavMenu } from "./nav-menu";
|
import { NavMenu } from "./nav-menu";
|
||||||
|
import { NavbarShell } from "./navbar-shell";
|
||||||
import { NavbarUser } from "./navbar-user";
|
import { NavbarUser } from "./navbar-user";
|
||||||
|
|
||||||
type AppNavbarProps = {
|
type AppNavbarProps = {
|
||||||
@@ -19,9 +18,6 @@ type AppNavbarProps = {
|
|||||||
notificationsSnapshot: DashboardNotificationsSnapshot;
|
notificationsSnapshot: DashboardNotificationsSnapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
const navbarActionClassName =
|
|
||||||
"border-black/10 bg-transparent text-black/75 shadow-none hover:border-black/20 hover:bg-black/10 hover:text-black focus-visible:ring-black/20 data-[state=open]:bg-black/10 data-[state=open]:text-black";
|
|
||||||
|
|
||||||
export function AppNavbar({
|
export function AppNavbar({
|
||||||
user,
|
user,
|
||||||
pagadorAvatarUrl,
|
pagadorAvatarUrl,
|
||||||
@@ -29,28 +25,20 @@ export function AppNavbar({
|
|||||||
notificationsSnapshot,
|
notificationsSnapshot,
|
||||||
}: AppNavbarProps) {
|
}: AppNavbarProps) {
|
||||||
return (
|
return (
|
||||||
<header className="fixed top-0 left-0 right-0 z-50 flex h-16 shrink-0 items-center bg-primary">
|
<NavbarShell logoHref="/dashboard" fixed>
|
||||||
<div className="relative z-10 mx-auto flex h-full w-full max-w-8xl items-center gap-4 px-4">
|
<NavMenu />
|
||||||
<Link href="/dashboard" className="shrink-0 mr-1">
|
<div className="ml-auto flex items-center gap-2">
|
||||||
<Logo variant="compact" invertTextOnDark={false} />
|
<NotificationBell
|
||||||
</Link>
|
notifications={notificationsSnapshot.notifications}
|
||||||
|
unreadCount={notificationsSnapshot.unreadCount}
|
||||||
<NavMenu />
|
visibleCount={notificationsSnapshot.visibleCount}
|
||||||
|
budgetNotifications={notificationsSnapshot.budgetNotifications}
|
||||||
<div className="ml-auto flex items-center gap-2">
|
preLancamentosCount={preLancamentosCount}
|
||||||
<NotificationBell
|
/>
|
||||||
notifications={notificationsSnapshot.notifications}
|
<RefreshPageButton variant="navbar" />
|
||||||
unreadCount={notificationsSnapshot.unreadCount}
|
<AnimatedThemeToggler variant="navbar" />
|
||||||
visibleCount={notificationsSnapshot.visibleCount}
|
|
||||||
budgetNotifications={notificationsSnapshot.budgetNotifications}
|
|
||||||
preLancamentosCount={preLancamentosCount}
|
|
||||||
/>
|
|
||||||
<RefreshPageButton className={navbarActionClassName} />
|
|
||||||
<AnimatedThemeToggler className={navbarActionClassName} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<NavbarUser user={user} pagadorAvatarUrl={pagadorAvatarUrl} />
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
<NavbarUser user={user} pagadorAvatarUrl={pagadorAvatarUrl} />
|
||||||
|
</NavbarShell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,18 @@ import {
|
|||||||
SheetTitle,
|
SheetTitle,
|
||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from "@/shared/components/ui/sheet";
|
} from "@/shared/components/ui/sheet";
|
||||||
|
import { cn } from "@/shared/utils/ui";
|
||||||
import { MobileLink, MobileSectionLabel } from "./mobile-link";
|
import { MobileLink, MobileSectionLabel } from "./mobile-link";
|
||||||
import { NavDropdown } from "./nav-dropdown";
|
import { NavDropdown } from "./nav-dropdown";
|
||||||
import { NAV_SECTIONS } from "./nav-items";
|
import { NAV_SECTIONS } from "./nav-items";
|
||||||
import { NavPill } from "./nav-pill";
|
import { NavPill } from "./nav-pill";
|
||||||
import { triggerActiveClass, triggerClass } from "./nav-styles";
|
|
||||||
import { MobileTools, NavToolsDropdown } from "./nav-tools";
|
import { MobileTools, NavToolsDropdown } from "./nav-tools";
|
||||||
|
|
||||||
|
const triggerClass =
|
||||||
|
"h-8! rounded-md! px-2! py-0! text-sm! font-medium! bg-transparent! shadow-none! lowercase! [&_svg]:text-current! text-black/75! hover:text-black! hover:bg-black/10! focus:text-black! focus:bg-black/10! focus-visible:ring-black/20! data-[state=open]:text-black! data-[state=open]:bg-black/10!";
|
||||||
|
|
||||||
|
const triggerActiveClass = "bg-black/15! text-black!";
|
||||||
|
|
||||||
export function NavMenu() {
|
export function NavMenu() {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const [sheetOpen, setSheetOpen] = useState(false);
|
const [sheetOpen, setSheetOpen] = useState(false);
|
||||||
@@ -55,7 +60,10 @@ export function NavMenu() {
|
|||||||
return (
|
return (
|
||||||
<NavigationMenuItem key={section.label}>
|
<NavigationMenuItem key={section.label}>
|
||||||
<NavigationMenuTrigger
|
<NavigationMenuTrigger
|
||||||
className={`${triggerClass} ${isSectionActive ? triggerActiveClass : ""}`}
|
className={cn(
|
||||||
|
triggerClass,
|
||||||
|
isSectionActive && triggerActiveClass,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{section.label}
|
{section.label}
|
||||||
</NavigationMenuTrigger>
|
</NavigationMenuTrigger>
|
||||||
@@ -82,9 +90,9 @@ export function NavMenu() {
|
|||||||
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
|
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="navbar"
|
||||||
size="icon"
|
size="icon-sm"
|
||||||
className="-order-1 border border-black/10 text-black/75 shadow-none md:hidden hover:border-black/20 hover:bg-black/10 hover:text-black focus-visible:ring-black/20"
|
className="-order-1 md:hidden"
|
||||||
>
|
>
|
||||||
<RiMenuLine className="size-5" />
|
<RiMenuLine className="size-5" />
|
||||||
<span className="sr-only">Abrir menu</span>
|
<span className="sr-only">Abrir menu</span>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
|
import { buttonVariants } from "@/shared/components/ui/button";
|
||||||
import { cn } from "@/shared/utils/ui";
|
import { cn } from "@/shared/utils/ui";
|
||||||
import { NavLink } from "./nav-link";
|
import { NavLink } from "./nav-link";
|
||||||
import { linkActive, linkBase, linkIdle } from "./nav-styles";
|
|
||||||
|
|
||||||
type NavPillProps = {
|
type NavPillProps = {
|
||||||
href: string;
|
href: string;
|
||||||
@@ -23,7 +23,11 @@ export function NavPill({ href, preservePeriod, children }: NavPillProps) {
|
|||||||
<NavLink
|
<NavLink
|
||||||
href={href}
|
href={href}
|
||||||
preservePeriod={preservePeriod}
|
preservePeriod={preservePeriod}
|
||||||
className={cn(linkBase, isActive ? linkActive : linkIdle)}
|
className={cn(
|
||||||
|
buttonVariants({ variant: "navbar", size: "sm" }),
|
||||||
|
"lowercase",
|
||||||
|
isActive && "bg-black/15 text-black",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
export const linkBase =
|
|
||||||
"inline-flex h-8 items-center justify-center rounded-md px-2 text-sm font-medium transition-all lowercase";
|
|
||||||
|
|
||||||
export const linkIdle = "text-black/75 hover:bg-black/10 hover:text-black";
|
|
||||||
|
|
||||||
export const linkActive = "bg-black/15 text-black";
|
|
||||||
|
|
||||||
export const triggerActiveClass = ["bg-black/15!", "text-black!"].join(" ");
|
|
||||||
|
|
||||||
export const triggerClass = [
|
|
||||||
"h-8!",
|
|
||||||
"rounded-md!",
|
|
||||||
"px-2!",
|
|
||||||
"py-0!",
|
|
||||||
"text-sm!",
|
|
||||||
"font-medium!",
|
|
||||||
"bg-transparent!",
|
|
||||||
"text-black/75!",
|
|
||||||
"hover:text-black!",
|
|
||||||
"hover:bg-black/10!",
|
|
||||||
"focus:text-black!",
|
|
||||||
"focus:bg-black/10!",
|
|
||||||
"focus-visible:ring-black/20!",
|
|
||||||
"data-[state=open]:text-black!",
|
|
||||||
"data-[state=open]:bg-black/10!",
|
|
||||||
"shadow-none!",
|
|
||||||
"[&_svg]:text-current!",
|
|
||||||
"lowercase!",
|
|
||||||
].join(" ");
|
|
||||||
33
src/shared/components/navigation/navbar/navbar-shell.tsx
Normal file
33
src/shared/components/navigation/navbar/navbar-shell.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
import { Logo } from "@/shared/components/logo";
|
||||||
|
|
||||||
|
type NavbarShellProps = {
|
||||||
|
logoHref?: string;
|
||||||
|
fixed?: boolean;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function NavbarShell({
|
||||||
|
logoHref,
|
||||||
|
fixed = false,
|
||||||
|
children,
|
||||||
|
}: NavbarShellProps) {
|
||||||
|
const positionClass = fixed ? "fixed top-0 left-0 right-0" : "sticky top-0";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header
|
||||||
|
className={`${positionClass} z-50 flex h-16 shrink-0 items-center bg-primary`}
|
||||||
|
>
|
||||||
|
<div className="relative z-10 mx-auto flex h-full w-full max-w-8xl items-center gap-4 px-4">
|
||||||
|
{logoHref ? (
|
||||||
|
<Link href={logoHref} className="shrink-0">
|
||||||
|
<Logo variant="compact" invertTextOnDark={false} />
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Logo variant="compact" invertTextOnDark={false} />
|
||||||
|
)}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { RiRefreshLine } from "@remixicon/react";
|
import { RiRefreshLine } from "@remixicon/react";
|
||||||
|
import type { VariantProps } from "class-variance-authority";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useTransition } from "react";
|
import { useTransition } from "react";
|
||||||
import { buttonVariants } from "@/shared/components/ui/button";
|
import { buttonVariants } from "@/shared/components/ui/button";
|
||||||
@@ -11,10 +12,12 @@ import {
|
|||||||
} from "@/shared/components/ui/tooltip";
|
} from "@/shared/components/ui/tooltip";
|
||||||
import { cn } from "@/shared/utils/ui";
|
import { cn } from "@/shared/utils/ui";
|
||||||
|
|
||||||
type RefreshPageButtonProps = React.ComponentPropsWithoutRef<"button">;
|
type RefreshPageButtonProps = React.ComponentPropsWithoutRef<"button"> &
|
||||||
|
Pick<VariantProps<typeof buttonVariants>, "variant">;
|
||||||
|
|
||||||
export function RefreshPageButton({
|
export function RefreshPageButton({
|
||||||
className,
|
className,
|
||||||
|
variant = "ghost",
|
||||||
...props
|
...props
|
||||||
}: RefreshPageButtonProps) {
|
}: RefreshPageButtonProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -36,10 +39,10 @@ export function RefreshPageButton({
|
|||||||
aria-label="Atualizar página"
|
aria-label="Atualizar página"
|
||||||
title="Atualizar página"
|
title="Atualizar página"
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({ variant: "ghost", size: "icon-sm" }),
|
buttonVariants({ variant, size: "icon-sm" }),
|
||||||
"size-8 text-muted-foreground transition-all duration-200",
|
"transition-all duration-200",
|
||||||
"hover:text-foreground focus-visible:ring-2 focus-visible:ring-primary/40",
|
variant === "ghost" &&
|
||||||
"disabled:pointer-events-none disabled:opacity-50",
|
"text-muted-foreground hover:text-foreground focus-visible:ring-2 focus-visible:ring-primary/40",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ const buttonVariants = cva(
|
|||||||
ghost:
|
ghost:
|
||||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
|
navbar:
|
||||||
|
"bg-transparent text-black/75 shadow-none hover:bg-black/10 hover:text-black focus-visible:ring-black/20",
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||||
|
|||||||
Reference in New Issue
Block a user