@gvaz/gvaz-ui
v0.2.3
Published
Design system e biblioteca de componentes React com Tailwind CSS
Maintainers
Readme
@gvaz/gvaz-ui
Design system e biblioteca de componentes React com Tailwind CSS.
Instalação
npm install @gvaz/gvaz-uiSetup (Next.js)
1. Configurar o Tailwind
No tailwind.config.ts, adicione o preset da lib e inclua os arquivos do dist no content:
import type { Config } from "tailwindcss";
import gvazPreset from "@gvaz/gvaz-ui/tailwind-preset";
const config: Config = {
presets: [gvazPreset],
content: [
"./src/**/*.{js,ts,jsx,tsx,mdx}",
"./node_modules/@gvaz/gvaz-ui/dist/**/*.{js,mjs}",
],
};
export default config;2. Adicionar as variáveis CSS
No seu globals.css (ou qualquer CSS global), cole as variáveis de tema:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}
@layer base {
* { @apply border-border; }
body { @apply bg-background text-foreground; }
}As cores usam variáveis CSS em formato HSL. Você pode customizar qualquer cor sobrescrevendo as variáveis no seu CSS.
Layout com Sidebar
A lib fornece um layout completo com sidebar colapsável, contexto de estado e header de página.
Estrutura recomendada
app/
layout.tsx ← SidebarProvider + MainLayout aqui
page.tsx ← PageHeader + conteúdo aqui
components/
layout/
sidebar.tsx ← wrapper com Link do seu router
page-header.tsx ← wrapper com toggle da sidebarlayout.tsx
import { SidebarProvider, MainLayout } from "@gvaz/gvaz-ui";
import { Sidebar } from "@/components/layout/sidebar";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="pt-BR">
<body>
<SidebarProvider>
<div className="flex min-h-screen">
<Sidebar />
<MainLayout>
<main className="flex-1 p-8">{children}</main>
</MainLayout>
</div>
</SidebarProvider>
</body>
</html>
);
}components/layout/sidebar.tsx
Crie um wrapper que conecta o Link do seu router e o estado de colapso:
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Sidebar as GvazSidebar, useSidebar, type SidebarNavItem } from "@gvaz/gvaz-ui";
import { LayoutDashboard, Settings, Users } from "lucide-react";
const navItems: Omit<SidebarNavItem, "isActive">[] = [
{ title: "Dashboard", href: "/", icon: LayoutDashboard },
{ title: "Usuários", href: "/users", icon: Users },
{ title: "Configurações", href: "/settings", icon: Settings },
];
export function Sidebar() {
const pathname = usePathname();
const { open } = useSidebar();
const withActive = (items: Omit<SidebarNavItem, "isActive">[]): SidebarNavItem[] =>
items.map((item) => ({
...item,
isActive: pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href)),
}));
return (
<GvazSidebar
collapsed={!open}
logo={{ name: "Meu App" }}
navItems={withActive(navItems)}
user={{ name: "Usuário", role: "Admin", fallback: "US" }}
LinkComponent={Link}
/>
);
}components/layout/page-header.tsx
"use client";
import { PageHeader as GvazPageHeader, useSidebar, type PageHeaderProps } from "@gvaz/gvaz-ui";
import Link from "next/link";
type Props = Omit<PageHeaderProps, "onMenuToggle" | "LinkComponent">;
export function PageHeader(props: Props) {
const { toggle } = useSidebar();
return <GvazPageHeader {...props} onMenuToggle={toggle} LinkComponent={Link} />;
}Usando nas páginas
import { PageHeader } from "@/components/layout/page-header";
export default function DashboardPage() {
return (
<div>
<PageHeader
title="Dashboard"
breadcrumbs={[{ label: "Início", href: "/" }]}
actions={<Button>Nova ação</Button>}
/>
{/* conteúdo */}
</div>
);
}Componentes disponíveis
Todos importados direto de @gvaz/gvaz-ui:
UI
| Componente | Descrição |
|---|---|
| Button | Botão com variantes: default, destructive, outline, secondary, ghost, link |
| Input | Campo de texto |
| Textarea | Campo de texto multilinha |
| Label | Label de formulário |
| Select + SelectTrigger SelectContent SelectItem SelectValue | Select nativo Radix |
| Switch | Toggle on/off |
| Badge | Etiqueta com variantes |
| Avatar | Avatar com imagem ou fallback de iniciais |
| Progress | Barra de progresso |
| Separator | Divisor horizontal ou vertical |
Layout
| Componente | Descrição |
|---|---|
| Card + CardHeader CardTitle CardDescription CardContent CardFooter | Card container |
| Tabs + TabsList TabsTrigger TabsContent | Abas com estilo underline |
| Table + TableHeader TableBody TableRow TableHead TableCell | Tabela |
Overlays
| Componente | Descrição |
|---|---|
| Dialog + DialogTrigger DialogContent DialogHeader DialogTitle DialogDescription DialogFooter DialogClose | Modal |
| DropdownMenu + DropdownMenuTrigger DropdownMenuContent DropdownMenuItem DropdownMenuSeparator DropdownMenuLabel | Menu dropdown |
Navegação / App shell
| Componente / Hook | Descrição |
|---|---|
| Sidebar | Sidebar colapsável com logo, nav, notificações e usuário |
| PageHeader | Header de página com toggle, breadcrumb e slot de ações |
| SidebarProvider | Context provider para estado open/collapsed |
| MainLayout | Wrapper do conteúdo principal que se adapta ao estado da sidebar |
| useSidebar() | Hook para ler open e chamar toggle() de qualquer componente |
Utilitário
| Export | Descrição |
|---|---|
| cn(...classes) | Merge de classes Tailwind (clsx + tailwind-merge) |
Customizando o tema
As cores são totalmente customizáveis via variáveis CSS. Exemplo — trocar a cor primária para roxo:
:root {
--primary: 262 80% 50%;
--primary-foreground: 0 0% 100%;
}Você pode alterar qualquer variável do tema sem reconstruir a lib.
Publicando uma atualização
# ajuste a versão no package.json (ex: 0.1.0 → 0.2.0)
npm run build
npm publish --access publicInstalação
npm install gvaz-uiUso
1. Adicionar o preset do Tailwind
No tailwind.config.ts do seu projeto:
import type { Config } from "tailwindcss";
import gvazPreset from "gvaz-ui/tailwind-preset";
const config: Config = {
presets: [gvazPreset],
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/gvaz-ui/dist/**/*.{js,mjs}",
],
// ...
};
export default config;2. Importar os estilos base
No seu globals.css ou layout:
@import "gvaz-ui/styles";Ou importe diretamente no layout:
import "gvaz-ui/styles";3. Usar os componentes
import { Button, Card, CardHeader, CardTitle, CardContent, Input, Label, Badge } from "gvaz-ui";
export default function Page() {
return (
<Card>
<CardHeader>
<CardTitle>Login</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="[email protected]" />
</div>
<Button>Entrar</Button>
<Badge variant="secondary">Novo</Badge>
</CardContent>
</Card>
);
}Componentes disponíveis
- Button — botão com variantes (default, destructive, outline, secondary, ghost, link)
- Input — campo de input estilizado
- Label — label para formulários
- Badge — badge/tag com variantes
- Card — card container com Header, Title, Description, Content e Footer
Tema
O tema é baseado em CSS variables (HSL). Edite as variáveis em globals.css para customizar cores. Suporte a dark mode via classe .dark.
Scripts
npm run build # build da lib
npm run dev # build em watch mode
npm run typecheck # checar tipos
npm run clean # limpar dist/