@ffid-br/tailor-ui 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -1
- package/dist/index.es.js +545 -185
- package/dist/index.umd.js +1 -1
- package/dist/types/components/TailorSidebar.d.ts +140 -0
- package/dist/types/index.d.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ffid-br/tailor-ui
|
|
2
2
|
|
|
3
|
-
Primitivos de marca da Tailor.ia em React: a fita métrica de carregamento, a abertura cinematográfica, o ponto com a malha Fibonacci, a transição login → app
|
|
3
|
+
Primitivos de marca da Tailor.ia em React: a fita métrica de carregamento, a abertura cinematográfica, o ponto com a malha Fibonacci, a transição login → app, o lockup do produto e a barra lateral padrão dos apps. Antes, cada app mantinha uma cópia desses componentes. Agora todos vêm deste pacote.
|
|
4
4
|
|
|
5
5
|
## Instalação
|
|
6
6
|
|
|
@@ -79,6 +79,93 @@ Lockup: wordmark com 21px de arte e o nome do produto em 18px semibold (tailor-i
|
|
|
79
79
|
|
|
80
80
|
`logoTailor` e `logoTailorBranco` também são exportados (data URI) para outros usos.
|
|
81
81
|
|
|
82
|
+
### `TailorSidebar`
|
|
83
|
+
|
|
84
|
+
Barra lateral padrão do accounts, CRM, BI e Pilot. **Uma lista de itens desenha as duas formas**: a barra fixa a partir do breakpoint (expandida com 288px ou recolhida em trilho de 80px, só ícones) e a gaveta no celular. O app não mantém mais uma nav para o `<aside>` e outra para o drawer.
|
|
85
|
+
|
|
86
|
+
- Estrutura: marca + recolher (55px) · seletor de contas + apps · grupos · `rodape` · "Powered by" opcional.
|
|
87
|
+
- Item com 34px de altura (44px na gaveta, alvo de toque), ícone de linha 18px (traço 1,5), texto 14px. Ativo: fundo `neutral-100`, barra verde de 2px à esquerda e texto preto; no escuro, `white/10` e texto branco. Ícone não ganha cor.
|
|
88
|
+
- Badge: chip quadrado preto (branco no escuro) com números tabulares; `badgeTom: 'alerta'` pinta de vermelho. Acima de 99 vira `99+`. No trilho vira um ponto e a contagem vai para o `aria-label`.
|
|
89
|
+
- `filhos`: o item pai vira um botão que abre e fecha a lista (abre sozinho se um filho está ativo). Quer link para a página do pai? Ponha um filho "Visão geral". No trilho, clicar no pai expande a barra.
|
|
90
|
+
- `superficie`: `auto` (branco no claro, `neutral-950` no escuro), `clara` ou `escura` (preto fixo, para o admin do accounts).
|
|
91
|
+
- A barra fixa usa `max-lg:hidden!` e a gaveta/barra do celular `lg:hidden!` (ou `md`, via `breakpoint`). O `!` é de propósito: o CSS do account-selector-component carrega depois do app e o `.flex` dele venceria um `hidden` comum.
|
|
92
|
+
- O `<aside>` é `sticky top-0 h-screen`: funciona num layout `flex` com a página ao lado. Quem usa `fixed` + `ml-72` passa a posição por `className`.
|
|
93
|
+
- Acessibilidade: `<nav aria-label>`, `aria-current="page"` no ativo, `title` + `aria-label` no trilho, anel de foco `tailor-green/60`, `motion-reduce`. A gaveta é um `role="dialog"`: prende o foco, fecha no Esc, no fundo (preto 55%) e ao navegar, e devolve o foco a quem abriu.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { NavLink, useLocation } from 'react-router-dom';
|
|
97
|
+
import { Home, MessageCircle, LayoutDashboard, LogOut, UserCog } from 'lucide-react';
|
|
98
|
+
import { TailorSidebar, TailorMobileBar, TailorUserMenu, type TailorSidebarGrupo } from '@ffid-br/tailor-ui';
|
|
99
|
+
|
|
100
|
+
function Layout() {
|
|
101
|
+
const { pathname } = useLocation();
|
|
102
|
+
const [aberto, setAberto] = useState(false);
|
|
103
|
+
const [recolhido, setRecolhido] = useState(() => localStorage.getItem('sidebar_collapsed') === '1');
|
|
104
|
+
const recolher = (v: boolean) => { setRecolhido(v); localStorage.setItem('sidebar_collapsed', v ? '1' : '0'); };
|
|
105
|
+
|
|
106
|
+
const grupos: TailorSidebarGrupo[] = [
|
|
107
|
+
{
|
|
108
|
+
rotulo: 'Geral',
|
|
109
|
+
itens: [
|
|
110
|
+
{ id: 'inicio', rotulo: 'Início', icone: Home, href: '/', ativo: pathname === '/' },
|
|
111
|
+
{ id: 'msg', rotulo: 'Mensagens', icone: MessageCircle, href: '/mensagens', ativo: pathname.startsWith('/mensagens'), badge: pendentes },
|
|
112
|
+
{
|
|
113
|
+
id: 'painel', rotulo: 'Painel', icone: LayoutDashboard,
|
|
114
|
+
filhos: [{ id: 'painel-geral', rotulo: 'Visão geral', icone: LayoutDashboard, href: '/painel', ativo: pathname === '/painel' }],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div className="flex min-h-screen">
|
|
122
|
+
<TailorSidebar
|
|
123
|
+
produto="Conta"
|
|
124
|
+
logoClaro={logos?.claro} // whitelabel: substitui o wordmark...
|
|
125
|
+
logoEscuro={logos?.escuro}
|
|
126
|
+
poweredBy={Boolean(logos)} // ...e aí o "Powered by Tailor.ia" aparece
|
|
127
|
+
superficie={pathname.startsWith('/admin') ? 'escura' : 'auto'}
|
|
128
|
+
grupos={grupos}
|
|
129
|
+
accountSelector={<AccountSelector {...} />}
|
|
130
|
+
apps={<AppLauncher />}
|
|
131
|
+
recolhido={recolhido}
|
|
132
|
+
onRecolher={recolher}
|
|
133
|
+
aberto={aberto}
|
|
134
|
+
onFechar={() => setAberto(false)}
|
|
135
|
+
renderLink={(item, props) => <NavLink to={item.href!} {...props} />}
|
|
136
|
+
rodape={
|
|
137
|
+
<TailorUserMenu
|
|
138
|
+
nome={usuario.nome}
|
|
139
|
+
detalhe={usuario.email}
|
|
140
|
+
papel="Administrador"
|
|
141
|
+
avatarUrl={usuario.avatar}
|
|
142
|
+
acoes={[
|
|
143
|
+
{ rotulo: 'Meu perfil', icone: UserCog, href: '/perfil' },
|
|
144
|
+
{ rotulo: 'Sair', icone: LogOut, tom: 'perigo', onSelect: sair },
|
|
145
|
+
]}
|
|
146
|
+
>
|
|
147
|
+
<ThemeToggle /> {/* conteúdo livre: tema, notificações push */}
|
|
148
|
+
</TailorUserMenu>
|
|
149
|
+
}
|
|
150
|
+
/>
|
|
151
|
+
<div className="min-w-0 flex-1">
|
|
152
|
+
<TailorMobileBar produto="Conta" onAbrirMenu={() => setAberto(true)} menuAberto={aberto} apps={<AppLauncher />} />
|
|
153
|
+
<main>...</main>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Notas para quem migra:
|
|
161
|
+
|
|
162
|
+
- `renderLink` recebe `className`, `children`, `aria-current`, `onClick` (fecha a gaveta) e, no trilho, `title`/`aria-label`. Repasse tudo. `ativo` continua vindo do app (ele sabe a regra de rota, ex.: `startsWith`). Sem `renderLink`, sai um `<a href>`.
|
|
163
|
+
- Item sem `href` e com `onSelect` vira botão de ação. `desabilitado` mostra o item apagado e sem clique (o "Em breve" do Pilot).
|
|
164
|
+
- Casos especiais (a sub-nav do Orchestrator, o aviso de status) entram como `grupos` próprios ou como `children`, montados com `SidebarGroup` e `SidebarItem`, que também são exportados.
|
|
165
|
+
- `marca` troca o lockup inteiro (ex.: logo do cliente com link para o início). `marcaRecolhida` aparece no trilho, acima do botão de expandir.
|
|
166
|
+
- Sem `onRecolher`, o botão de recolher não aparece.
|
|
167
|
+
- As classes novas estão no `dist`, então o `@source` da configuração já as cobre.
|
|
168
|
+
|
|
82
169
|
## Receita: transição login → app
|
|
83
170
|
|
|
84
171
|
1. **No login**: marque a entrada ao enviar, desmarque se der erro e mostre o preto crescendo do botão.
|
|
@@ -146,6 +233,15 @@ npm run build # dist/: index.es.js, index.umd.js, types/, style.css, theme.cs
|
|
|
146
233
|
|
|
147
234
|
## Mudanças
|
|
148
235
|
|
|
236
|
+
### 0.2.0
|
|
237
|
+
- `TailorSidebar`: barra lateral padrão (marca, seletor de contas + apps, grupos, badges, subitens, trilho recolhido, gaveta no celular com a mesma lista, superfície `auto`/`clara`/`escura`, `renderLink` para o roteador).
|
|
238
|
+
- `TailorUserMenu`: menu do usuário para o rodapé, com conteúdo livre (tema) e ações.
|
|
239
|
+
- `TailorMobileBar`: barra do topo no celular (hambúrguer, marca, apps).
|
|
240
|
+
- `SidebarGroup` e `SidebarItem` exportados para montar navs especiais.
|
|
241
|
+
|
|
242
|
+
### 0.1.2
|
|
243
|
+
- `EntradaApp` toca sempre depois de um login e só depois de um login (marca pendente). Saiu o disparo na primeira visita da aba: reload e link direto entram sem o preto. A `CinematicIntro` segue sendo uma vez só, por cookie no app.
|
|
244
|
+
|
|
149
245
|
### 0.1.1
|
|
150
246
|
- A entrada em sequência (`data-tailor-entrada-alvo`) começa em 1,5s, enquanto o preto da `EntradaApp` recolhe. Na 0.1.0 os blocos terminavam de entrar ainda cobertos. Quem sobrescreveu `animation-delay` no app pode tirar a sobrescrita.
|
|
151
247
|
- `TailorLoader`: variante `caixa` (régua numa caixa de 377px com fundo e borda, para chat e painéis estreitos) e prop `semRespiro`.
|