Pular para o conteúdo principal

Componentes UI Base

Esta página documenta os componentes UI base disponíveis no APAH Assistant, todos baseados no shadcn/ui.

Button

Botão com múltiplas variantes e tamanhos.

Importação

import { Button } from "@/components/ui/button";

Variantes

<Button variant="default">Default</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

Tamanhos

<Button size="sm">Pequeno</Button>
<Button size="default">Normal</Button>
<Button size="lg">Grande</Button>
<Button size="icon"><IconComponent /></Button>

Com Ícone

import { Loader2, Mail } from "lucide-react";

<Button>
<Mail className="mr-2 h-4 w-4" />
Email
</Button>

<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
A carregar
</Button>

Props

PropTipoDefaultDescrição
variant"default" | "destructive" | "outline" | "secondary" | "ghost" | "link""default"Estilo visual
size"default" | "sm" | "lg" | "icon""default"Tamanho
asChildbooleanfalseRenderizar como slot

Input

Campo de entrada de texto.

Importação

import { Input } from "@/components/ui/input";

Uso Básico

<Input type="email" placeholder="Email" />
<Input type="password" placeholder="Password" />
<Input disabled placeholder="Desativado" />

Com Label

import { Label } from "@/components/ui/label";

<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="nome@exemplo.com" />
</div>

Com Ícone

<div className="relative">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input className="pl-10" placeholder="Pesquisar..." />
</div>

Dialog

Modal dialog para interações focadas.

Importação

import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
DialogClose,
} from "@/components/ui/dialog";

Uso Básico

<Dialog>
<DialogTrigger asChild>
<Button>Abrir Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Título</DialogTitle>
<DialogDescription>
Descrição do que este dialog faz.
</DialogDescription>
</DialogHeader>
<div className="py-4">
{/* Conteúdo */}
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancelar</Button>
</DialogClose>
<Button>Confirmar</Button>
</DialogFooter>
</DialogContent>
</Dialog>

Controlado

const [open, setOpen] = useState(false);

<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>
{/* ... */}
<Button onClick={() => setOpen(false)}>Fechar</Button>
</DialogContent>
</Dialog>

// Abrir programaticamente
<Button onClick={() => setOpen(true)}>Abrir</Button>

Card

Container com estilo para agrupar conteúdo.

Importação

import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";

Uso

<Card className="w-[350px]">
<CardHeader>
<CardTitle>Título do Card</CardTitle>
<CardDescription>Descrição ou subtítulo</CardDescription>
</CardHeader>
<CardContent>
<p>Conteúdo principal do card.</p>
</CardContent>
<CardFooter className="flex justify-between">
<Button variant="outline">Cancelar</Button>
<Button>Confirmar</Button>
</CardFooter>
</Card>

Select

Lista de seleção dropdown.

Importação

import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";

Uso

<Select>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Selecionar..." />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Frutas</SelectLabel>
<SelectItem value="apple">Maçã</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="orange">Laranja</SelectItem>
</SelectGroup>
</SelectContent>
</Select>

Controlado

const [value, setValue] = useState("apple");

<Select value={value} onValueChange={setValue}>
{/* ... */}
</Select>

Avatar

Imagem de perfil de utilizador.

Importação

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";

Uso

<Avatar>
<AvatarImage src="https://example.com/avatar.jpg" alt="@username" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>

Tamanhos Customizados

<Avatar className="h-16 w-16">
<AvatarImage src="/avatar.jpg" />
<AvatarFallback className="text-2xl">JD</AvatarFallback>
</Avatar>

Menu dropdown para ações.

Importação

import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

Uso

<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Ações</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => handleEdit()}>
<Edit className="mr-2 h-4 w-4" />
Editar
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleDelete()}
className="text-destructive"
>
<Trash className="mr-2 h-4 w-4" />
Eliminar
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

Tooltip

Dica contextual ao hover.

Importação

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";

Uso

// TooltipProvider deve envolver a app ou a área que usa tooltips
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon">
<Info className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Informação adicional</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>

ScrollArea

Área com scroll customizado.

Importação

import { ScrollArea } from "@/components/ui/scroll-area";

Uso

<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
{longContent.map((item) => (
<div key={item.id} className="py-2">
{item.content}
</div>
))}
</ScrollArea>

Switch

Toggle on/off.

Importação

import { Switch } from "@/components/ui/switch";

Uso

<div className="flex items-center space-x-2">
<Switch id="airplane-mode" />
<Label htmlFor="airplane-mode">Modo avião</Label>
</div>

Controlado

const [enabled, setEnabled] = useState(false);

<Switch checked={enabled} onCheckedChange={setEnabled} />

Alert

Mensagem de alerta ou feedback.

Importação

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

Variantes

// Default
<Alert>
<Info className="h-4 w-4" />
<AlertTitle>Informação</AlertTitle>
<AlertDescription>
Esta é uma mensagem informativa.
</AlertDescription>
</Alert>

// Destructive
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Erro</AlertTitle>
<AlertDescription>
Ocorreu um erro ao processar o pedido.
</AlertDescription>
</Alert>

Separator

Linha separadora visual.

Importação

import { Separator } from "@/components/ui/separator";

Uso

<div>
<h2>Título</h2>
<Separator className="my-4" />
<p>Conteúdo abaixo do separador</p>
</div>

{/* Vertical */}
<div className="flex h-5 items-center space-x-4">
<div>Item 1</div>
<Separator orientation="vertical" />
<div>Item 2</div>
</div>

Recursos Adicionais