Kanban
Board Kanban com Drag & Drop de itens e colunas via dnd-kit — pronto pra usar ou compondo os primitivos.
1. Em Análise CTM
Inspeção Obrigatória Rotor Principal S-76C++
ANAC ADAtualização de Aviônicos Primários AW139
Leonardo SB2. FAPT Criado
Troca de Selos do Sistema Hidráulico AW139
FAA DRSimport { useState } from "react";
import { Kanban } from "@vincisys/eyeson";
export function KanbanBasicDemo() {
const [value, setValue] = useState(INITIAL_VALUE);
return (
<div className="w-full rounded-eds-sm border border-eds-outline-border bg-white p-4">
<Kanban
columns={COLUMNS}
items={value}
getItemValue={(ticket) => ticket.id}
onValueChange={setValue}
renderItem={(ticket) => (
<div className="rounded-eds-xs border border-eds-outline-border bg-white p-3 shadow-sm">
<span className="font-mono text-xs font-bold text-eds-blue-main">
{ticket.code}
</span>
<h4 className="mt-1 text-xs font-bold text-eds-neutral-main">
{ticket.title}
</h4>
<span className="mt-2 block text-[10.5px] text-eds-neutral-elements">
{ticket.source}
</span>
</div>
)}
/>
</div>
);
} Instalação
import { Kanban } from '@vincisys/eyeson'; Uso
Kanban recebe columns + items e monta board, colunas, alças de arrasto
e cards por baixo — mesmo espírito de DataTable sobre Table.
function Example() {
const [value, setValue] = useState(initialValue); // Record<string, Ticket[]>
return (
<Kanban
columns={[
{ id: 'col-1', title: 'Em Análise' },
{ id: 'col-2', title: 'FAPT Criado' },
]}
items={value}
getItemValue={(ticket) => ticket.id}
onValueChange={setValue}
renderItem={(ticket) => <TicketCard ticket={ticket} />}
/>
);
} Composição manual
Para layout de coluna/card totalmente customizado (múltiplas linhas por
card, filtros no cabeçalho da coluna, etc.), componha os primitivos
diretamente em vez de usar <Kanban columns={...} items={...} />:
<Kanban.Root value={value} onValueChange={setValue} getItemValue={(t) => t.id}>
<Kanban.Board>
{Object.entries(value).map(([columnId, tickets]) => (
<Kanban.Column key={columnId} value={columnId}>
<div className="flex items-center justify-between pb-3">
<h3>{columnId}</h3>
<Kanban.ColumnHandle>
<GripVertical size={14} />
</Kanban.ColumnHandle>
</div>
<Kanban.ColumnContent items={tickets.map((t) => t.id)}>
{tickets.map((ticket) => (
<Kanban.Item key={ticket.id} value={ticket.id}>
<TicketCard ticket={ticket} />
</Kanban.Item>
))}
</Kanban.ColumnContent>
</Kanban.Column>
))}
</Kanban.Board>
<Kanban.Overlay>
{({ id, type }) =>
type === 'item' ? <TicketCard ticket={findTicket(id)} /> : null
}
</Kanban.Overlay>
</Kanban.Root> API
Kanban
Versão pronta pra usar. Props: columns ({id, title, className?}[]),
items (Record<string, T[]>), getItemValue, renderItem,
renderColumnBadge?, onValueChange (preview em tempo real durante o
arrasto), onValueCommit (uma vez, ao soltar), onColumnOrderChange.
Kanban.Root
Raiz dos primitivos: dona do estado de drag & drop, sem layout próprio.
Mesmas props de dados que Kanban (value, getItemValue,
onValueChange, onValueCommit, columnOrder, onColumnOrderChange).
Kanban.Board
Container em grid responsivo. Também é o SortableContext de reordenação
das colunas.
Kanban.Column
Coluna individual. Props: value (id da coluna). Corpo livre via
children.
Kanban.ColumnHandle
Alça de arrasto da coluna. Sem ela, a coluna não é reordenável.
Kanban.ColumnContent
Envolve a lista de Kanban.Item de uma coluna. Props: items (ids dos
itens, na ordem exibida).
Kanban.Item
Card arrastável. Props: value (id do item). Por padrão o card inteiro é a
alça de arrasto; passe asHandle={false} para usar um Kanban.ItemHandle
dedicado.
Kanban.ItemHandle
Alça de arrasto explícita do item, para usar com <Kanban.Item asHandle={false}>.
Kanban.Overlay
Portal com o “fantasma” do item sendo arrastado. children recebe
{ id, type } do elemento ativo (type é 'item' ou 'column').