rharuow-ds 1.8.2 → 1.10.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 +512 -25
- package/dist/rharuow-ds.cjs.js +1 -1
- package/dist/rharuow-ds.es.js +1298 -963
- package/dist/styles.css +1 -1
- package/dist/types/src/components/Modal.d.ts +16 -0
- package/dist/types/src/components/Toaster.d.ts +31 -0
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/stories/Modal.stories.d.ts +13 -0
- package/dist/types/src/stories/Toaster.stories.d.ts +13 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ Um Design System moderno em React com integração completa ao React Hook Form,
|
|
|
44
44
|
## 🌟 Características
|
|
45
45
|
|
|
46
46
|
- ⚛️ **React 18+** com TypeScript
|
|
47
|
-
- 🧩 **
|
|
47
|
+
- 🧩 **17 componentes** prontos para uso (Input, Textarea, Select, AsyncSelect, MultiSelect, MultiAsyncSelect, RadioGroup, Button, Card, Table, Tooltip, Accordion, AsideSheet, Modal, Toaster, ImageInput)
|
|
48
48
|
- 💡 **Filtro digitável** em componentes Select - Digite para encontrar opções rapidamente
|
|
49
49
|
- 🔗 **Integração nativa** com React Hook Form
|
|
50
50
|
- 🎨 **Customização via CSS Variables** - Mude o tema facilmente
|
|
@@ -112,6 +112,8 @@ npm install react-hook-form
|
|
|
112
112
|
Tooltip,
|
|
113
113
|
Accordion,
|
|
114
114
|
AsideSheet,
|
|
115
|
+
Modal,
|
|
116
|
+
Toaster,
|
|
115
117
|
ImageInput,
|
|
116
118
|
} from "rharuow-ds";
|
|
117
119
|
|
|
@@ -199,6 +201,8 @@ npm install react-hook-form
|
|
|
199
201
|
Tooltip,
|
|
200
202
|
Accordion,
|
|
201
203
|
AsideSheet,
|
|
204
|
+
Modal,
|
|
205
|
+
Toaster,
|
|
202
206
|
ImageInput,
|
|
203
207
|
} from "rharuow-ds";
|
|
204
208
|
|
|
@@ -582,7 +586,373 @@ Veja a story do componente no Storybook para demonstrações e variações (left
|
|
|
582
586
|
|
|
583
587
|
[Storybook — AsideSheet](https://rharuow.github.io/rharuow-ds-docs/?path=/story/asidesheet--default)
|
|
584
588
|
|
|
585
|
-
###
|
|
589
|
+
### 🎭 **Modal**
|
|
590
|
+
|
|
591
|
+
Componente de diálogo modal para exibir conteúdo sobreposto à página principal.
|
|
592
|
+
|
|
593
|
+
- ✅ Overlay com transparência configurável
|
|
594
|
+
- ✅ Múltiplos tamanhos: sm, md, lg, xl, full
|
|
595
|
+
- ✅ Controle de fechamento via overlay, ESC ou botão X
|
|
596
|
+
- ✅ Prevenção de scroll do body quando aberto
|
|
597
|
+
- ✅ Animações suaves de entrada/saída
|
|
598
|
+
- ✅ Sub-componentes para estruturação: Header, Body, Footer
|
|
599
|
+
- ✅ Renderização via Portal (React Portal)
|
|
600
|
+
- ✅ Acessível: role="dialog", aria-modal
|
|
601
|
+
|
|
602
|
+
Props principais:
|
|
603
|
+
|
|
604
|
+
- `open: boolean` — controla visibilidade do modal
|
|
605
|
+
- `onClose: () => void` — callback chamado ao fechar
|
|
606
|
+
- `size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'` — tamanho do modal (padrão: 'md')
|
|
607
|
+
- `closeOnOverlayClick?: boolean` — fecha ao clicar fora (padrão: true)
|
|
608
|
+
- `closeOnEscape?: boolean` — fecha ao pressionar ESC (padrão: true)
|
|
609
|
+
- `showCloseButton?: boolean` — exibe botão X de fechar (padrão: true)
|
|
610
|
+
- `className?: string` — classes adicionais para o container do modal
|
|
611
|
+
|
|
612
|
+
Exemplo de uso básico:
|
|
613
|
+
|
|
614
|
+
```tsx
|
|
615
|
+
import React from 'react';
|
|
616
|
+
import { Modal, Button } from 'rharuow-ds';
|
|
617
|
+
|
|
618
|
+
function Example() {
|
|
619
|
+
const [open, setOpen] = React.useState(false);
|
|
620
|
+
|
|
621
|
+
return (
|
|
622
|
+
<div>
|
|
623
|
+
<Button onClick={() => setOpen(true)}>Abrir Modal</Button>
|
|
624
|
+
|
|
625
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
626
|
+
<h2>Título do Modal</h2>
|
|
627
|
+
<p>Conteúdo do modal aqui.</p>
|
|
628
|
+
</Modal>
|
|
629
|
+
</div>
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
Exemplo com estrutura completa:
|
|
635
|
+
|
|
636
|
+
```tsx
|
|
637
|
+
import React from 'react';
|
|
638
|
+
import { Modal, Button } from 'rharuow-ds';
|
|
639
|
+
|
|
640
|
+
function Example() {
|
|
641
|
+
const [open, setOpen] = React.useState(false);
|
|
642
|
+
|
|
643
|
+
return (
|
|
644
|
+
<div>
|
|
645
|
+
<Button onClick={() => setOpen(true)}>Confirmar Ação</Button>
|
|
646
|
+
|
|
647
|
+
<Modal
|
|
648
|
+
open={open}
|
|
649
|
+
onClose={() => setOpen(false)}
|
|
650
|
+
size="md"
|
|
651
|
+
>
|
|
652
|
+
<Modal.Header>
|
|
653
|
+
<h2 className="text-2xl font-bold">Confirmar Exclusão</h2>
|
|
654
|
+
<p className="text-sm text-gray-500">Esta ação não pode ser desfeita</p>
|
|
655
|
+
</Modal.Header>
|
|
656
|
+
|
|
657
|
+
<Modal.Body>
|
|
658
|
+
<p className="text-gray-700">
|
|
659
|
+
Você tem certeza que deseja excluir este item?
|
|
660
|
+
Todos os dados associados serão removidos permanentemente.
|
|
661
|
+
</p>
|
|
662
|
+
</Modal.Body>
|
|
663
|
+
|
|
664
|
+
<Modal.Footer>
|
|
665
|
+
<Button variant="outline" onClick={() => setOpen(false)}>
|
|
666
|
+
Cancelar
|
|
667
|
+
</Button>
|
|
668
|
+
<Button onClick={() => {
|
|
669
|
+
// Executar ação
|
|
670
|
+
setOpen(false);
|
|
671
|
+
}}>
|
|
672
|
+
Confirmar
|
|
673
|
+
</Button>
|
|
674
|
+
</Modal.Footer>
|
|
675
|
+
</Modal>
|
|
676
|
+
</div>
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
Exemplo com formulário integrado:
|
|
682
|
+
|
|
683
|
+
```tsx
|
|
684
|
+
import React from 'react';
|
|
685
|
+
import { Modal, Button, Input } from 'rharuow-ds';
|
|
686
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
687
|
+
|
|
688
|
+
function FormModal() {
|
|
689
|
+
const [open, setOpen] = React.useState(false);
|
|
690
|
+
const methods = useForm();
|
|
691
|
+
|
|
692
|
+
const onSubmit = (data: any) => {
|
|
693
|
+
console.log('Form data:', data);
|
|
694
|
+
setOpen(false);
|
|
695
|
+
methods.reset();
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
return (
|
|
699
|
+
<div>
|
|
700
|
+
<Button onClick={() => setOpen(true)}>Novo Cadastro</Button>
|
|
701
|
+
|
|
702
|
+
<Modal
|
|
703
|
+
open={open}
|
|
704
|
+
onClose={() => setOpen(false)}
|
|
705
|
+
size="lg"
|
|
706
|
+
closeOnOverlayClick={false}
|
|
707
|
+
>
|
|
708
|
+
<FormProvider {...methods}>
|
|
709
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
710
|
+
<Modal.Header>
|
|
711
|
+
<h2 className="text-2xl font-bold">Cadastrar Usuário</h2>
|
|
712
|
+
</Modal.Header>
|
|
713
|
+
|
|
714
|
+
<Modal.Body>
|
|
715
|
+
<div className="space-y-4">
|
|
716
|
+
<Input label="Nome completo" name="name" required />
|
|
717
|
+
<Input label="E-mail" name="email" type="email" required />
|
|
718
|
+
<Input label="Telefone" name="phone" />
|
|
719
|
+
</div>
|
|
720
|
+
</Modal.Body>
|
|
721
|
+
|
|
722
|
+
<Modal.Footer>
|
|
723
|
+
<Button
|
|
724
|
+
type="button"
|
|
725
|
+
variant="outline"
|
|
726
|
+
onClick={() => setOpen(false)}
|
|
727
|
+
>
|
|
728
|
+
Cancelar
|
|
729
|
+
</Button>
|
|
730
|
+
<Button type="submit">Salvar</Button>
|
|
731
|
+
</Modal.Footer>
|
|
732
|
+
</form>
|
|
733
|
+
</FormProvider>
|
|
734
|
+
</Modal>
|
|
735
|
+
</div>
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
Veja a story do componente no Storybook para mais exemplos e variações:
|
|
741
|
+
|
|
742
|
+
[Storybook — Modal](https://rharuow.github.io/rharuow-ds-docs/?path=/story/components-modal--basic)
|
|
743
|
+
|
|
744
|
+
### � **Toaster**
|
|
745
|
+
|
|
746
|
+
Sistema completo de notificações toast para feedback ao usuário com múltiplas variantes e posicionamento flexível.
|
|
747
|
+
|
|
748
|
+
- ✅ 5 variantes de toast: success, error, warning, info, default
|
|
749
|
+
- ✅ 6 posições configuráveis na tela
|
|
750
|
+
- ✅ Auto-dismiss com duração customizável
|
|
751
|
+
- ✅ Toast permanente (duration: 0)
|
|
752
|
+
- ✅ Ícones automáticos por variante
|
|
753
|
+
- ✅ Animações suaves de entrada e saída
|
|
754
|
+
- ✅ Limite de toasts simultâneos (padrão: 5)
|
|
755
|
+
- ✅ Callbacks ao fechar
|
|
756
|
+
- ✅ Hook `useToast` para uso simplificado
|
|
757
|
+
- ✅ Gerenciamento via Context API
|
|
758
|
+
|
|
759
|
+
**Configuração inicial:**
|
|
760
|
+
|
|
761
|
+
O Toaster precisa ser configurado uma única vez no nível superior da aplicação:
|
|
762
|
+
|
|
763
|
+
```tsx
|
|
764
|
+
import React from 'react';
|
|
765
|
+
import { ToasterProvider } from 'rharuow-ds';
|
|
766
|
+
|
|
767
|
+
function App() {
|
|
768
|
+
return (
|
|
769
|
+
<ToasterProvider position="top-right" maxToasts={5}>
|
|
770
|
+
{/* Sua aplicação aqui */}
|
|
771
|
+
<YourApp />
|
|
772
|
+
</ToasterProvider>
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
Props do `ToasterProvider`:
|
|
778
|
+
|
|
779
|
+
- `position?: ToastPosition` - Posição dos toasts na tela (padrão: 'top-right')
|
|
780
|
+
- Opções: 'top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'
|
|
781
|
+
- `maxToasts?: number` - Número máximo de toasts simultâneos (padrão: 5)
|
|
782
|
+
|
|
783
|
+
**Uso básico com hook `useToast`:**
|
|
784
|
+
|
|
785
|
+
```tsx
|
|
786
|
+
import React from 'react';
|
|
787
|
+
import { useToast, Button } from 'rharuow-ds';
|
|
788
|
+
|
|
789
|
+
function MyComponent() {
|
|
790
|
+
const toast = useToast();
|
|
791
|
+
|
|
792
|
+
return (
|
|
793
|
+
<div>
|
|
794
|
+
<Button onClick={() => toast.success('Operação realizada com sucesso!')}>
|
|
795
|
+
Success
|
|
796
|
+
</Button>
|
|
797
|
+
|
|
798
|
+
<Button onClick={() => toast.error('Erro ao processar requisição')}>
|
|
799
|
+
Error
|
|
800
|
+
</Button>
|
|
801
|
+
|
|
802
|
+
<Button onClick={() => toast.warning('Atenção: verifique os dados')}>
|
|
803
|
+
Warning
|
|
804
|
+
</Button>
|
|
805
|
+
|
|
806
|
+
<Button onClick={() => toast.info('Você tem 3 novas mensagens')}>
|
|
807
|
+
Info
|
|
808
|
+
</Button>
|
|
809
|
+
</div>
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
**Toasts com duração customizada:**
|
|
815
|
+
|
|
816
|
+
```tsx
|
|
817
|
+
import React from 'react';
|
|
818
|
+
import { useToast, Button } from 'rharuow-ds';
|
|
819
|
+
|
|
820
|
+
function CustomDuration() {
|
|
821
|
+
const toast = useToast();
|
|
822
|
+
|
|
823
|
+
return (
|
|
824
|
+
<div>
|
|
825
|
+
{/* Toast rápido - 2 segundos */}
|
|
826
|
+
<Button onClick={() => toast.success('Toast rápido', 2000)}>
|
|
827
|
+
2 Segundos
|
|
828
|
+
</Button>
|
|
829
|
+
|
|
830
|
+
{/* Toast longo - 10 segundos */}
|
|
831
|
+
<Button onClick={() => toast.info('Toast longo', 10000)}>
|
|
832
|
+
10 Segundos
|
|
833
|
+
</Button>
|
|
834
|
+
|
|
835
|
+
{/* Toast permanente - não fecha automaticamente */}
|
|
836
|
+
<Button
|
|
837
|
+
onClick={() => toast.toast('Toast permanente', { duration: 0 })}
|
|
838
|
+
>
|
|
839
|
+
Permanente
|
|
840
|
+
</Button>
|
|
841
|
+
</div>
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
**Toast com callback ao fechar:**
|
|
847
|
+
|
|
848
|
+
```tsx
|
|
849
|
+
import React from 'react';
|
|
850
|
+
import { useToaster, Button } from 'rharuow-ds';
|
|
851
|
+
|
|
852
|
+
function WithCallback() {
|
|
853
|
+
const { addToast } = useToaster();
|
|
854
|
+
|
|
855
|
+
const handleAction = () => {
|
|
856
|
+
addToast({
|
|
857
|
+
message: 'Processando dados...',
|
|
858
|
+
variant: 'info',
|
|
859
|
+
duration: 3000,
|
|
860
|
+
onClose: () => {
|
|
861
|
+
console.log('Toast fechado!');
|
|
862
|
+
// Executar ação após fechamento
|
|
863
|
+
performNextAction();
|
|
864
|
+
},
|
|
865
|
+
});
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
return <Button onClick={handleAction}>Iniciar Processo</Button>;
|
|
869
|
+
}
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
**Exemplo completo em um formulário:**
|
|
873
|
+
|
|
874
|
+
```tsx
|
|
875
|
+
import React from 'react';
|
|
876
|
+
import { useForm, FormProvider } from 'react-hook-form';
|
|
877
|
+
import { Input, Button, useToast } from 'rharuow-ds';
|
|
878
|
+
|
|
879
|
+
function FormWithToast() {
|
|
880
|
+
const methods = useForm();
|
|
881
|
+
const toast = useToast();
|
|
882
|
+
|
|
883
|
+
const onSubmit = async (data: any) => {
|
|
884
|
+
try {
|
|
885
|
+
// Simular chamada à API
|
|
886
|
+
await saveData(data);
|
|
887
|
+
|
|
888
|
+
toast.success('Dados salvos com sucesso!');
|
|
889
|
+
methods.reset();
|
|
890
|
+
} catch (error) {
|
|
891
|
+
toast.error('Erro ao salvar dados. Tente novamente.');
|
|
892
|
+
console.error(error);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
return (
|
|
897
|
+
<FormProvider {...methods}>
|
|
898
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
899
|
+
<Input label="Nome" name="name" required />
|
|
900
|
+
<Input label="E-mail" name="email" type="email" required />
|
|
901
|
+
|
|
902
|
+
<Button type="submit">Salvar</Button>
|
|
903
|
+
</form>
|
|
904
|
+
</FormProvider>
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
**API do hook `useToast`:**
|
|
910
|
+
|
|
911
|
+
```typescript
|
|
912
|
+
const toast = useToast();
|
|
913
|
+
|
|
914
|
+
// Métodos disponíveis:
|
|
915
|
+
toast.success(message: string, duration?: number)
|
|
916
|
+
toast.error(message: string, duration?: number)
|
|
917
|
+
toast.warning(message: string, duration?: number)
|
|
918
|
+
toast.info(message: string, duration?: number)
|
|
919
|
+
toast.toast(message: string, options?: ToastOptions)
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
**API avançada com `useToaster`:**
|
|
923
|
+
|
|
924
|
+
```typescript
|
|
925
|
+
const { addToast, removeToast, clearAll, toasts } = useToaster();
|
|
926
|
+
|
|
927
|
+
// Adicionar toast com controle total
|
|
928
|
+
const id = addToast({
|
|
929
|
+
message: 'Mensagem personalizada',
|
|
930
|
+
variant: 'success',
|
|
931
|
+
duration: 5000,
|
|
932
|
+
onClose: () => console.log('Fechado'),
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
// Remover toast específico
|
|
936
|
+
removeToast(id);
|
|
937
|
+
|
|
938
|
+
// Limpar todos os toasts
|
|
939
|
+
clearAll();
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
**Dicas de uso:**
|
|
943
|
+
|
|
944
|
+
- Use `success` para operações bem-sucedidas (save, delete, update)
|
|
945
|
+
- Use `error` para falhas e erros
|
|
946
|
+
- Use `warning` para avisos que requerem atenção
|
|
947
|
+
- Use `info` para informações gerais
|
|
948
|
+
- Configure `duration: 0` para toasts que precisam de ação manual do usuário
|
|
949
|
+
- Posicione toasts conforme o contexto: top para notificações gerais, bottom para ações específicas
|
|
950
|
+
|
|
951
|
+
Veja a story do componente no Storybook para demonstrações interativas:
|
|
952
|
+
|
|
953
|
+
[Storybook — Toaster](https://rharuow.github.io/rharuow-ds-docs/?path=/story/components-toaster--top-right)
|
|
954
|
+
|
|
955
|
+
### �📷 **ImageInput**
|
|
586
956
|
|
|
587
957
|
Componente para seleção e upload de imagens com preview e ações de confirmação/remoção:
|
|
588
958
|
|
|
@@ -692,51 +1062,168 @@ Veja a story do componente no Storybook para demonstrações completas:
|
|
|
692
1062
|
|
|
693
1063
|
## 🎨 Customização de Tema
|
|
694
1064
|
|
|
695
|
-
O rharuow-ds utiliza **
|
|
1065
|
+
O rharuow-ds utiliza um **sistema de cores baseado em brand colors** (cores da marca) que permite criar uma experiência visual coesa em toda a sua aplicação. Todos os componentes (Card, Table, Select, Tooltip) derivam suas cores das variáveis primárias e secundárias que você define.
|
|
1066
|
+
|
|
1067
|
+
### 🌈 Sistema de Cores
|
|
1068
|
+
|
|
1069
|
+
#### Variáveis Principais
|
|
1070
|
+
|
|
1071
|
+
```css
|
|
1072
|
+
:root {
|
|
1073
|
+
/* Cores Primárias - Personalizáveis */
|
|
1074
|
+
--primary: #2563eb; /* Cor principal da marca */
|
|
1075
|
+
--primary-hover: #1d4ed8; /* Hover da cor principal */
|
|
1076
|
+
--primary-light: #dbeafe; /* Versão clara para fundos */
|
|
1077
|
+
|
|
1078
|
+
/* Cores Secundárias - Personalizáveis */
|
|
1079
|
+
--secondary: #64748b; /* Cor secundária */
|
|
1080
|
+
--secondary-hover: #475569; /* Hover da cor secundária */
|
|
1081
|
+
--secondary-light: #f1f5f9; /* Versão clara para fundos */
|
|
1082
|
+
}
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
#### Como os Componentes Usam as Cores
|
|
1086
|
+
|
|
1087
|
+
Os componentes **derivam automaticamente** suas cores das variáveis primárias:
|
|
1088
|
+
|
|
1089
|
+
- **Card Header**: Mescla 5% da cor primária com fundo neutro
|
|
1090
|
+
- **Table Header**: Mescla 8% da cor primária com fundo neutro
|
|
1091
|
+
- **Table Hover**: Mescla 10% da cor primária com fundo neutro
|
|
1092
|
+
- **Select Selected**: Usa diretamente `--primary-light`
|
|
1093
|
+
- **Elementos Selecionados**: Consistentemente usam a cor primária clara
|
|
696
1094
|
|
|
697
|
-
###
|
|
1095
|
+
### 💡 Como Personalizar
|
|
1096
|
+
|
|
1097
|
+
#### Método 1: CSS Global (Recomendado)
|
|
1098
|
+
|
|
1099
|
+
No seu arquivo CSS principal (`index.css` ou `App.css`):
|
|
698
1100
|
|
|
699
1101
|
```css
|
|
1102
|
+
/* Importar o DS primeiro */
|
|
1103
|
+
@import 'rharuow-ds/dist/styles.css';
|
|
1104
|
+
|
|
1105
|
+
/* Depois sobrescrever as cores da marca */
|
|
700
1106
|
:root {
|
|
701
|
-
--primary: #
|
|
702
|
-
--primary-hover: #
|
|
703
|
-
--primary-
|
|
704
|
-
|
|
705
|
-
--
|
|
1107
|
+
--primary: #8b5cf6; /* Roxo */
|
|
1108
|
+
--primary-hover: #7c3aed;
|
|
1109
|
+
--primary-light: #ede9fe;
|
|
1110
|
+
|
|
1111
|
+
--secondary: #ec4899; /* Rosa */
|
|
1112
|
+
--secondary-hover: #db2777;
|
|
1113
|
+
--secondary-light: #fce7f3;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/* Para dark mode, customize também */
|
|
1117
|
+
[data-theme="dark"], .dark {
|
|
1118
|
+
--primary: #a78bfa; /* Roxo mais claro para dark */
|
|
1119
|
+
--primary-hover: #8b5cf6;
|
|
1120
|
+
--primary-light: #4c1d95;
|
|
1121
|
+
|
|
1122
|
+
--secondary: #f472b6;
|
|
1123
|
+
--secondary-hover: #ec4899;
|
|
1124
|
+
--secondary-light: #831843;
|
|
706
1125
|
}
|
|
707
1126
|
```
|
|
708
1127
|
|
|
709
|
-
|
|
1128
|
+
#### Método 2: JavaScript/React
|
|
1129
|
+
|
|
1130
|
+
```typescript
|
|
1131
|
+
// App.tsx ou main.tsx
|
|
1132
|
+
useEffect(() => {
|
|
1133
|
+
const root = document.documentElement;
|
|
1134
|
+
|
|
1135
|
+
root.style.setProperty('--primary', '#f59e0b');
|
|
1136
|
+
root.style.setProperty('--primary-hover', '#d97706');
|
|
1137
|
+
root.style.setProperty('--primary-light', '#fef3c7');
|
|
1138
|
+
}, []);
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
### 🎯 Exemplos de Paletas
|
|
710
1142
|
|
|
711
1143
|
```css
|
|
712
|
-
/*
|
|
1144
|
+
/* Paleta Corporativa (Azul) */
|
|
1145
|
+
:root {
|
|
1146
|
+
--primary: #0ea5e9;
|
|
1147
|
+
--primary-hover: #0284c7;
|
|
1148
|
+
--primary-light: #e0f2fe;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/* Paleta Moderna (Roxo/Rosa) */
|
|
713
1152
|
:root {
|
|
714
|
-
--primary: #
|
|
715
|
-
--primary-hover: #
|
|
716
|
-
--primary-
|
|
1153
|
+
--primary: #8b5cf6;
|
|
1154
|
+
--primary-hover: #7c3aed;
|
|
1155
|
+
--primary-light: #ede9fe;
|
|
1156
|
+
--secondary: #ec4899;
|
|
717
1157
|
}
|
|
718
1158
|
|
|
719
|
-
/*
|
|
1159
|
+
/* Paleta Natureza (Verde) */
|
|
720
1160
|
:root {
|
|
721
|
-
--primary: #
|
|
722
|
-
--primary-hover: #
|
|
723
|
-
--primary-
|
|
1161
|
+
--primary: #10b981;
|
|
1162
|
+
--primary-hover: #059669;
|
|
1163
|
+
--primary-light: #d1fae5;
|
|
724
1164
|
}
|
|
725
1165
|
|
|
726
|
-
/*
|
|
1166
|
+
/* Paleta Minimalista (Cinza) */
|
|
1167
|
+
:root {
|
|
1168
|
+
--primary: #6b7280;
|
|
1169
|
+
--primary-hover: #4b5563;
|
|
1170
|
+
--primary-light: #f3f4f6;
|
|
1171
|
+
}
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
### 🔧 Customização Avançada
|
|
1175
|
+
|
|
1176
|
+
Para controle total, você pode sobrescrever variáveis específicas:
|
|
1177
|
+
|
|
1178
|
+
```css
|
|
727
1179
|
:root {
|
|
728
|
-
|
|
729
|
-
--primary
|
|
730
|
-
|
|
1180
|
+
/* Cores base da marca */
|
|
1181
|
+
--primary: #8b5cf6;
|
|
1182
|
+
|
|
1183
|
+
/* Customização específica de Card */
|
|
1184
|
+
--card-header-bg: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
1185
|
+
--card-header-border: #8b5cf6;
|
|
1186
|
+
|
|
1187
|
+
/* Customização específica de Table */
|
|
1188
|
+
--table-header-bg: #f3e8ff;
|
|
1189
|
+
--table-row-selected: #ede9fe;
|
|
731
1190
|
}
|
|
732
1191
|
```
|
|
733
1192
|
|
|
1193
|
+
### 📚 Variáveis Disponíveis por Componente
|
|
1194
|
+
|
|
1195
|
+
#### Card
|
|
1196
|
+
- `--card-bg`, `--card-border`, `--card-text`
|
|
1197
|
+
- `--card-header-bg`, `--card-header-border`
|
|
1198
|
+
- `--card-footer-bg`, `--card-footer-border`
|
|
1199
|
+
|
|
1200
|
+
#### Table
|
|
1201
|
+
- `--table-bg`, `--table-border`, `--table-text`
|
|
1202
|
+
- `--table-header-bg`, `--table-row-hover`, `--table-row-selected`
|
|
1203
|
+
|
|
1204
|
+
#### Select/AsyncSelect/MultiSelect
|
|
1205
|
+
- `--select-dropdown-bg`, `--select-dropdown-border`
|
|
1206
|
+
- `--select-dropdown-hover`, `--select-dropdown-selected`
|
|
1207
|
+
|
|
1208
|
+
#### Tooltip
|
|
1209
|
+
- `--tooltip-bg`, `--tooltip-text`
|
|
1210
|
+
|
|
1211
|
+
### 🌓 Dark Mode
|
|
1212
|
+
|
|
1213
|
+
O sistema ajusta automaticamente as cores no dark mode:
|
|
1214
|
+
|
|
1215
|
+
```css
|
|
1216
|
+
/* Ative o dark mode adicionando o atributo */
|
|
1217
|
+
<html data-theme="dark">
|
|
1218
|
+
<!-- ou -->
|
|
1219
|
+
<html class="dark">
|
|
1220
|
+
```
|
|
1221
|
+
|
|
734
1222
|
### No Storybook
|
|
735
1223
|
|
|
736
|
-
Na documentação do Storybook, você pode testar diferentes temas
|
|
1224
|
+
Na [documentação do Storybook](https://rharuow.github.io/rharuow-ds-docs/), você pode testar diferentes temas na story **"Theme Customization"**.
|
|
737
1225
|
|
|
738
|
-
|
|
739
|
-
- 🌈 **Primary Hover**: Muda a cor de hover/background
|
|
1226
|
+
Para mais detalhes, consulte [THEME_CUSTOMIZATION.md](./THEME_CUSTOMIZATION.md).
|
|
740
1227
|
|
|
741
1228
|
---
|
|
742
1229
|
|