feat: redesign superadmin agencies list, implement flat design, add date filters, and fix UI bugs
This commit is contained in:
149
1. docs/nova-interface.md
Normal file
149
1. docs/nova-interface.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# System Instruction: Arquitetura de Layout com Sidebar Expansível
|
||||
|
||||
**Role:** Senior React Developer & UI Specialist
|
||||
**Tech Stack:** React, Tailwind CSS (Sem bibliotecas de ícones ou fontes externas).
|
||||
|
||||
**Objetivo:**
|
||||
Implementar um sistema de layout "Dashboard" composto por um **Menu Lateral (Sidebar)** que expande e colapsa suavemente e uma área de conteúdo principal.
|
||||
|
||||
**Requisitos Críticos de Animação:**
|
||||
1. A transição de largura da sidebar deve ser suave (transition-all duration-300).
|
||||
2. O texto dos botões **não deve quebrar** ou desaparecer bruscamente. Use a técnica de transição de `max-width` e `opacity` para que o texto deslize suavemente para fora.
|
||||
3. Não utilize bibliotecas de animação (Framer Motion, etc), apenas Tailwind CSS puro.
|
||||
|
||||
---
|
||||
|
||||
## 1. Componente: `DashboardLayout.tsx` (Container Principal)
|
||||
|
||||
Este componente deve gerenciar o estado global do menu (aberto/fechado) para evitar "prop drilling" desnecessário.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { SidebarRail } from './SidebarRail';
|
||||
|
||||
interface DashboardLayoutProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
// Estado centralizado do layout
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
const [activeTab, setActiveTab] = useState('home');
|
||||
|
||||
return (
|
||||
<div className="flex h-screen w-full bg-gray-900 text-slate-900 overflow-hidden p-3 gap-3">
|
||||
{/* Sidebar controla seu próprio estado visual via props */}
|
||||
<SidebarRail
|
||||
activeTab={activeTab}
|
||||
onTabChange={setActiveTab}
|
||||
isExpanded={isExpanded}
|
||||
onToggle={() => setIsExpanded(!isExpanded)}
|
||||
/>
|
||||
|
||||
{/* Área de Conteúdo (Children) */}
|
||||
<main className="flex-1 h-full min-w-0 overflow-hidden flex flex-col bg-white rounded-3xl shadow-xl relative">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## 2. Componente: `SidebarRail.tsx` (Lógica de Animação)
|
||||
|
||||
Aqui reside a lógica visual. Substitua os ícones por `<span>Icon</span>` ou SVGs genéricos para manter o código agnóstico.
|
||||
|
||||
**Pontos de atenção no código abaixo:**
|
||||
* `w-[220px]` vs `w-[72px]`: Define a largura física.
|
||||
* `max-w-[150px]` vs `max-w-0`: Define a animação do texto.
|
||||
* `whitespace-nowrap`: Impede que o texto pule de linha enquanto fecha.
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
|
||||
interface SidebarRailProps {
|
||||
activeTab: string;
|
||||
onTabChange: (tab: string) => void;
|
||||
isExpanded: boolean;
|
||||
onToggle: () => void;
|
||||
}
|
||||
|
||||
export const SidebarRail: React.FC<SidebarRailProps> = ({ activeTab, onTabChange, isExpanded, onToggle }) => {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
h-full bg-zinc-900 rounded-3xl flex flex-col py-6 gap-4 text-gray-400 shrink-0 border border-white/10 shadow-xl
|
||||
transition-[width] duration-300 ease-[cubic-bezier(0.25,0.1,0.25,1)] px-3
|
||||
${isExpanded ? 'w-[220px]' : 'w-[72px]'}
|
||||
`}
|
||||
>
|
||||
{/* Header / Toggle */}
|
||||
<div className={`flex items-center w-full relative transition-all duration-300 mb-4 ${isExpanded ? 'justify-between px-1' : 'justify-center'}`}>
|
||||
<div className="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center text-white font-bold shrink-0 z-10">
|
||||
Logo
|
||||
</div>
|
||||
|
||||
{/* Título com animação de opacidade e largura */}
|
||||
<div className={`overflow-hidden transition-all duration-300 ease-in-out whitespace-nowrap absolute left-14 ${isExpanded ? 'opacity-100 max-w-[100px]' : 'opacity-0 max-w-0'}`}>
|
||||
<span className="font-bold text-white text-lg">App Name</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navegação */}
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<RailButton
|
||||
label="Dashboard"
|
||||
active={activeTab === 'home'}
|
||||
onClick={() => onTabChange('home')}
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
<RailButton
|
||||
label="Settings"
|
||||
active={activeTab === 'settings'}
|
||||
onClick={() => onTabChange('settings')}
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Footer / Toggle Button */}
|
||||
<div className="mt-auto">
|
||||
<button
|
||||
onClick={onToggle}
|
||||
className="w-full p-2 rounded-xl hover:bg-white/10 text-gray-400 hover:text-white transition-colors flex items-center justify-center"
|
||||
>
|
||||
{/* Ícone de Toggle Genérico */}
|
||||
<span>{isExpanded ? '<<' : '>>'}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Subcomponente do Botão (Essencial para a animação do texto)
|
||||
const RailButton = ({ label, active, onClick, isExpanded }: any) => (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className={`
|
||||
flex items-center p-2.5 rounded-xl transition-all duration-300 group relative overflow-hidden
|
||||
${active ? 'bg-white/10 text-white' : 'hover:bg-white/5 hover:text-gray-200'}
|
||||
${isExpanded ? '' : 'justify-center'}
|
||||
`}
|
||||
>
|
||||
{/* Placeholder do Ícone */}
|
||||
<div className="shrink-0 flex items-center justify-center w-6 h-6 bg-gray-700/50 rounded text-[10px]">Icon</div>
|
||||
|
||||
{/* Lógica Mágica do Texto: Max-Width Transition */}
|
||||
<div className={`
|
||||
overflow-hidden whitespace-nowrap transition-all duration-300 ease-in-out
|
||||
${isExpanded ? 'max-w-[150px] opacity-100 ml-3' : 'max-w-0 opacity-0 ml-0'}
|
||||
`}>
|
||||
<span className="font-medium text-sm">{label}</span>
|
||||
</div>
|
||||
|
||||
{/* Indicador de Ativo (Barra lateral pequena quando fechado) */}
|
||||
{active && !isExpanded && (
|
||||
<div className="absolute left-0 top-1/2 -translate-y-1/2 w-1 h-3 bg-white rounded-r-full -ml-3" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
```
|
||||
Reference in New Issue
Block a user