xertica-ui 2.6.0 → 2.8.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/CHANGELOG.md +34 -0
- package/README.md +20 -12
- package/bin/generate-tokens.ts +25 -9
- package/components/assistant/xertica-assistant/use-assistant.ts +5 -6
- package/components/assistant/xertica-assistant/xertica-assistant.tsx +1 -1
- package/{templates/src/features/auth/ui → components/blocks/auth}/AuthPageShell.tsx +8 -3
- package/components/blocks/auth/PasswordStrengthMeter.tsx +41 -0
- package/components/blocks/auth/SocialLoginButtons.tsx +95 -0
- package/components/blocks/auth/index.ts +11 -0
- package/components/blocks/auth/usePasswordStrength.ts +13 -0
- package/components/blocks/index.ts +1 -0
- package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +45 -139
- package/components/pages/login-page/LoginPage.tsx +52 -145
- package/components/pages/reset-password-page/ResetPasswordPage.tsx +79 -169
- package/components/pages/verify-email-page/VerifyEmailPage.tsx +48 -150
- package/components/ui/button/button.test.tsx +2 -2
- package/components/ui/button/button.tsx +6 -6
- package/components/ui/card/card.tsx +14 -2
- package/components/ui/input/input.tsx +1 -1
- package/components/ui/input-otp/input-otp.tsx +1 -1
- package/components/ui/search/search.tsx +1 -1
- package/components/ui/select/select.tsx +2 -2
- package/components/ui/switch/switch.tsx +1 -1
- package/components/ui/textarea/textarea.tsx +1 -1
- package/contexts/BrandColorsContext.tsx +50 -2
- package/contexts/theme-data.ts +100 -3
- package/dist/AssistantChart-BFBJXVcm.js +3383 -0
- package/dist/AssistantChart-BTnE94FR.cjs +3551 -0
- package/dist/AssistantChart-BvccsQMx.cjs +3551 -0
- package/dist/AssistantChart-CImCNLfD.cjs +3551 -0
- package/dist/AssistantChart-CkskcBVD.js +3383 -0
- package/dist/AssistantChart-CrPkO9ip.js +3383 -0
- package/dist/AssistantChart-DKz2O1R8.cjs +3551 -0
- package/dist/AssistantChart-DYL6UEvo.cjs +3551 -0
- package/dist/AssistantChart-DfdIfmQr.js +3383 -0
- package/dist/AssistantChart-keo-ogKi.js +3383 -0
- package/dist/AudioPlayer-AoU5MTiM.cjs +1282 -0
- package/dist/AudioPlayer-Bx1vrblm.js +1278 -0
- package/dist/AudioPlayer-D0-I6J3J.cjs +1282 -0
- package/dist/AudioPlayer-DIWX_Yg7.cjs +1282 -0
- package/dist/AudioPlayer-DrWJnS7c.js +1278 -0
- package/dist/AudioPlayer-_P-Z7pAK.js +1278 -0
- package/dist/BrandColorsContext-B25Bpr3b.cjs +819 -0
- package/dist/BrandColorsContext-BCieATdW.js +812 -0
- package/dist/BrandColorsContext-DP0DXAXS.js +824 -0
- package/dist/BrandColorsContext-DjpC9wR_.cjs +798 -0
- package/dist/BrandColorsContext-MpXFhte7.cjs +831 -0
- package/dist/BrandColorsContext-V3tOc-Zw.js +791 -0
- package/dist/CodeBlock-CK4rO6lM.js +221 -0
- package/dist/CodeBlock-CKXamfVd.cjs +223 -0
- package/dist/CodeBlock-CVmE7isS.cjs +223 -0
- package/dist/CodeBlock-D7i5-cMv.js +221 -0
- package/dist/CodeBlock-Dg56j2ut.cjs +223 -0
- package/dist/CodeBlock-Dt6nUQoo.js +221 -0
- package/dist/CustomTooltipContent-Bxynuq7T.js +33 -0
- package/dist/CustomTooltipContent-BzjOSA0P.cjs +54 -0
- package/dist/CustomTooltipContent-C-ZeCNsf.js +33 -0
- package/dist/CustomTooltipContent-CON_QrXm.cjs +54 -0
- package/dist/CustomTooltipContent-UR_n2QfW.js +33 -0
- package/dist/CustomTooltipContent-v1SXjoFn.cjs +54 -0
- package/dist/FeatureCard-4n_8a63v.cjs +497 -0
- package/dist/FeatureCard-BLiAWT3w.js +485 -0
- package/dist/FeatureCard-BXRW97Ef.cjs +497 -0
- package/dist/FeatureCard-BhpfmPPx.js +485 -0
- package/dist/FeatureCard-CDgLlWE2.js +485 -0
- package/dist/FeatureCard-CgQ8lq-I.cjs +497 -0
- package/dist/FeatureCard-Cp8cVC6T.cjs +497 -0
- package/dist/FeatureCard-D-5yS_OD.cjs +497 -0
- package/dist/FeatureCard-D0MwrTRP.js +485 -0
- package/dist/FeatureCard-uE5i0in_.js +485 -0
- package/dist/ImageWithFallback-BOh1FM3I.js +98 -0
- package/dist/ImageWithFallback-BQO7952C.js +98 -0
- package/dist/ImageWithFallback-BkMXHCvV.cjs +122 -0
- package/dist/ImageWithFallback-C72nwszA.cjs +122 -0
- package/dist/ImageWithFallback-CCUMDuEC.cjs +122 -0
- package/dist/ImageWithFallback-CfkAkctC.cjs +122 -0
- package/dist/ImageWithFallback-DQD5TTlY.js +98 -0
- package/dist/ImageWithFallback-bw-CxxDc.js +98 -0
- package/dist/LanguageContext-CX_zdxre.js +1912 -0
- package/dist/LanguageContext-CjhSSqJT.cjs +1917 -0
- package/dist/LanguageSelector-1XhM7R1i.cjs +48 -0
- package/dist/LanguageSelector-B3ZVNc55.js +46 -0
- package/dist/LanguageSelector-BR3Ss0k_.js +46 -0
- package/dist/LanguageSelector-CHOLPmHr.cjs +48 -0
- package/dist/LanguageSelector-Cj6zl0CM.js +46 -0
- package/dist/LanguageSelector-DK1zD4VH.cjs +48 -0
- package/dist/LanguageSelector-DseCAa0p.cjs +48 -0
- package/dist/LanguageSelector-Du09anfM.js +46 -0
- package/dist/LanguageSelector-PZHlFfEs.cjs +48 -0
- package/dist/LanguageSelector-SB-NJSmx.js +46 -0
- package/dist/PasswordStrengthMeter-B3S6i_k4.cjs +179 -0
- package/dist/PasswordStrengthMeter-B8ky1nJI.js +173 -0
- package/dist/PasswordStrengthMeter-C5VEopH-.cjs +179 -0
- package/dist/PasswordStrengthMeter-C8irs0G1.js +173 -0
- package/dist/PasswordStrengthMeter-CIm7_jNT.js +173 -0
- package/dist/PasswordStrengthMeter-DKSAbQzu.js +173 -0
- package/dist/PasswordStrengthMeter-DxLu54p-.cjs +179 -0
- package/dist/PasswordStrengthMeter-MLzhax-d.cjs +179 -0
- package/dist/PasswordStrengthMeter-k-e9Pole.cjs +179 -0
- package/dist/PasswordStrengthMeter-pAi2viq5.js +173 -0
- package/dist/ThemeContext-CEY9pCn-.cjs +86 -0
- package/dist/ThemeContext-Dk3tH7Ym.js +83 -0
- package/dist/ThemeToggle-4pQbVkpK.js +215 -0
- package/dist/ThemeToggle-B6rIVLvC.cjs +219 -0
- package/dist/ThemeToggle-BUOTps5l.cjs +219 -0
- package/dist/ThemeToggle-BpM_iHh8.js +215 -0
- package/dist/ThemeToggle-CO5mPl6e.js +215 -0
- package/dist/ThemeToggle-CZRlv0d4.cjs +219 -0
- package/dist/ThemeToggle-DbZQ0JSV.cjs +219 -0
- package/dist/ThemeToggle-vLXEq2TS.js +215 -0
- package/dist/VerifyEmailPage-BKiaw2YK.js +2954 -0
- package/dist/VerifyEmailPage-BTjI2c9n.js +2954 -0
- package/dist/VerifyEmailPage-Beaicc6V.cjs +2963 -0
- package/dist/VerifyEmailPage-BehPBp0F.cjs +2963 -0
- package/dist/VerifyEmailPage-CJGfDSOx.js +2954 -0
- package/dist/VerifyEmailPage-DOlZUNc0.cjs +2963 -0
- package/dist/VerifyEmailPage-DQPRl_RJ.js +2954 -0
- package/dist/VerifyEmailPage-Djb6hthM.js +2954 -0
- package/dist/VerifyEmailPage-DrdqMbLC.cjs +2963 -0
- package/dist/VerifyEmailPage-hyDfeCRa.cjs +2963 -0
- package/dist/VerifyEmailPage-kKSXl8vu.cjs +2963 -0
- package/dist/VerifyEmailPage-w4N-bDhU.js +2954 -0
- package/dist/XerticaOrbe-B9tegV1n.js +1925 -0
- package/dist/XerticaOrbe-BQ_NjwPS.cjs +1927 -0
- package/dist/XerticaOrbe-BdUX171Q.cjs +1927 -0
- package/dist/XerticaOrbe-BdlKXRHU.cjs +1927 -0
- package/dist/XerticaOrbe-CByPAFE5.js +1925 -0
- package/dist/XerticaOrbe-Ccu9eFMu.js +1925 -0
- package/dist/XerticaProvider-BVid1oqn.cjs +46 -0
- package/dist/XerticaProvider-BijpC_py.cjs +46 -0
- package/dist/XerticaProvider-Bz_YfNY4.js +44 -0
- package/dist/XerticaProvider-C2wDRQhT.js +44 -0
- package/dist/XerticaProvider-CtvYfRbZ.cjs +46 -0
- package/dist/XerticaProvider-DMiyExQS.js +44 -0
- package/dist/XerticaProvider-DP2lzKip.cjs +46 -0
- package/dist/XerticaProvider-De79hhgp.js +44 -0
- package/dist/XerticaProvider-Dkk1Vbsy.js +44 -0
- package/dist/XerticaProvider-EdzH9Nrw.cjs +46 -0
- package/dist/alert-dialog-9XYAn5z5.js +819 -0
- package/dist/alert-dialog-B281hud0.cjs +872 -0
- package/dist/alert-dialog-BVWbrcrw.cjs +872 -0
- package/dist/alert-dialog-B_Ko1xpu.js +819 -0
- package/dist/alert-dialog-BzIcTKn_.cjs +872 -0
- package/dist/alert-dialog-CIxE8T-J.cjs +872 -0
- package/dist/alert-dialog-DW-_iPuf.js +819 -0
- package/dist/alert-dialog-kty5pxQp.js +819 -0
- package/dist/assistant.cjs.js +2 -2
- package/dist/assistant.es.js +2 -2
- package/dist/avatar-BJwIMbZ_.js +54 -0
- package/dist/avatar-C4Zh5fAJ.cjs +77 -0
- package/dist/avatar-CTEUKZUT.js +54 -0
- package/dist/avatar-D1bZhlhL.cjs +77 -0
- package/dist/avatar-DKIxHeKG.cjs +77 -0
- package/dist/avatar-v16eZC8p.js +54 -0
- package/dist/blocks.cjs.js +7 -3
- package/dist/blocks.es.js +2 -2
- package/dist/brand.cjs.js +8 -7
- package/dist/brand.es.js +4 -3
- package/dist/breadcrumb-B1mUiaWB.cjs +98 -0
- package/dist/breadcrumb-BIRgmem-.js +90 -0
- package/dist/breadcrumb-BSng-oUf.cjs +98 -0
- package/dist/breadcrumb-CES7furU.js +90 -0
- package/dist/breadcrumb-CP275kbF.cjs +98 -0
- package/dist/breadcrumb-D7hr1EvJ.js +90 -0
- package/dist/button-BYtQygX5.cjs +85 -0
- package/dist/button-BnAW-a_w.js +62 -0
- package/dist/button-CUPDQews.js +62 -0
- package/dist/button-DFa-rtPy.js +62 -0
- package/dist/button-DV1G6XrI.cjs +85 -0
- package/dist/button-Kd9Fj53S.cjs +85 -0
- package/dist/cli.js +94 -10
- package/dist/components/blocks/auth/AuthPageShell.d.ts +12 -0
- package/dist/components/blocks/auth/PasswordStrengthMeter.d.ts +7 -0
- package/dist/components/blocks/auth/SocialLoginButtons.d.ts +8 -0
- package/dist/components/blocks/auth/index.d.ts +8 -0
- package/dist/components/blocks/auth/usePasswordStrength.d.ts +3 -0
- package/dist/components/blocks/index.d.ts +1 -0
- package/dist/components/pages/reset-password-page/ResetPasswordPage.d.ts +1 -1
- package/dist/components/ui/card/card.d.ts +11 -1
- package/dist/contexts/theme-data.d.ts +15 -1
- package/dist/dropdown-menu-B9wTZ0uX.cjs +225 -0
- package/dist/dropdown-menu-BeBtZOrs.cjs +225 -0
- package/dist/dropdown-menu-D7mRDGis.js +190 -0
- package/dist/dropdown-menu-D8ZmqHB7.js +190 -0
- package/dist/dropdown-menu-_AWBeOts.cjs +225 -0
- package/dist/dropdown-menu-qGzLO_HO.js +190 -0
- package/dist/hooks.cjs.js +6 -5
- package/dist/hooks.es.js +3 -2
- package/dist/index.cjs.js +42 -37
- package/dist/index.es.js +25 -24
- package/dist/input-B53E6K8G.js +65 -0
- package/dist/input-B7Q7vcoG.cjs +91 -0
- package/dist/input-BysqLMK1.js +65 -0
- package/dist/input-CStdFsaH.cjs +91 -0
- package/dist/input-CXYth6nW.cjs +91 -0
- package/dist/input-CX_fWE2D.cjs +91 -0
- package/dist/input-CitUVnEn.js +65 -0
- package/dist/input-wkBYTp-B.js +65 -0
- package/dist/layout.cjs.js +1 -1
- package/dist/layout.es.js +1 -1
- package/dist/media.cjs.js +1 -1
- package/dist/media.es.js +1 -1
- package/dist/pages.cjs.js +1 -1
- package/dist/pages.es.js +1 -1
- package/dist/rich-text-editor-BHiRUzWZ.js +2894 -0
- package/dist/rich-text-editor-BWMRUMJ2.js +2894 -0
- package/dist/rich-text-editor-BoE6Ks5x.cjs +2968 -0
- package/dist/rich-text-editor-BzuEwR_X.js +2894 -0
- package/dist/rich-text-editor-CcopGbQ-.js +2894 -0
- package/dist/rich-text-editor-CmxSRJIi.cjs +2968 -0
- package/dist/rich-text-editor-DyYAu28v.cjs +2968 -0
- package/dist/rich-text-editor-JS_eMQCC.cjs +2968 -0
- package/dist/select-BNfFJwYp.js +130 -0
- package/dist/select-CN8IDjGB.js +130 -0
- package/dist/select-CwRzQHA7.cjs +161 -0
- package/dist/select-CwgD3nMD.js +130 -0
- package/dist/select-DEHUm_AC.cjs +161 -0
- package/dist/select-DJDgpVm3.cjs +161 -0
- package/dist/select-DSLWQLmo.cjs +161 -0
- package/dist/select-YFx0wCYT.js +130 -0
- package/dist/sidebar-B7YzwAp3.js +1151 -0
- package/dist/sidebar-BF7JEL7U.js +1151 -0
- package/dist/sidebar-Bjr2doX5.cjs +1154 -0
- package/dist/sidebar-CMrNCmhb.cjs +1154 -0
- package/dist/sidebar-CO9x8AVn.cjs +1154 -0
- package/dist/sidebar-Cb0U7NsV.cjs +1154 -0
- package/dist/sidebar-Cn_KB4c6.js +1151 -0
- package/dist/sidebar-Db_C30ph.cjs +1154 -0
- package/dist/sidebar-miPHsRz4.js +1151 -0
- package/dist/sidebar-pZF8mLLu.js +1151 -0
- package/dist/skeleton-BX2XTjMO.cjs +87 -0
- package/dist/skeleton-BoLK0iV7.js +78 -0
- package/dist/skeleton-Bysq8yeB.js +79 -0
- package/dist/skeleton-C7nspYnC.cjs +87 -0
- package/dist/skeleton-DL4V5Vub.cjs +87 -0
- package/dist/skeleton-DSMhdqp1.js +78 -0
- package/dist/skeleton-DhJswvTW.cjs +88 -0
- package/dist/skeleton-DicUfozA.js +78 -0
- package/dist/slider-77T_Eqw4.js +56 -0
- package/dist/slider-B6puMLXS.cjs +78 -0
- package/dist/slider-B785N7lZ.js +56 -0
- package/dist/slider-C6yssKyZ.cjs +78 -0
- package/dist/slider-CKZO9gVh.cjs +78 -0
- package/dist/slider-Cn-ImSze.js +56 -0
- package/dist/tooltip-BiJVGob3.cjs +72 -0
- package/dist/tooltip-D2OPn-1v.cjs +72 -0
- package/dist/tooltip-DlCHQuh1.js +48 -0
- package/dist/tooltip-fQ2Va0G8.cjs +72 -0
- package/dist/tooltip-oAw00FX2.js +48 -0
- package/dist/tooltip-u147L0wD.js +48 -0
- package/dist/ui.cjs.js +17 -17
- package/dist/ui.es.js +13 -13
- package/dist/xertica-assistant-8fh8KA2K.js +2173 -0
- package/dist/xertica-assistant-BjfG3zyL.cjs +2180 -0
- package/dist/xertica-assistant-C2A0R94j.js +2173 -0
- package/dist/xertica-assistant-CSUprvTR.js +2173 -0
- package/dist/xertica-assistant-Caubm0HR.js +2173 -0
- package/dist/xertica-assistant-DEexPM2u.cjs +2180 -0
- package/dist/xertica-assistant-Dh1dmEx3.cjs +2180 -0
- package/dist/xertica-assistant-GGcyHEZG.cjs +2180 -0
- package/dist/xertica-assistant-USefPe2L.js +2173 -0
- package/dist/xertica-assistant-cwSHFwfv.cjs +2180 -0
- package/dist/xertica-ui.css +1 -1
- package/docs/i18n.md +2 -0
- package/package.json +3 -2
- package/styles/xertica/base.css +38 -0
- package/styles/xertica/tokens.css +9 -0
- package/templates/package.json +2 -2
- package/templates/src/app/App.tsx +5 -1
- package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +1 -2
- package/templates/src/features/auth/ui/LoginContent.tsx +1 -2
- package/templates/src/features/auth/ui/ResetPasswordContent.tsx +3 -57
- package/templates/src/features/auth/ui/VerifyEmailContent.tsx +1 -2
- package/templates/src/features/home/index.ts +0 -10
- package/templates/src/features/home/ui/HomeContent.tsx +19 -74
- package/templates/src/features/template/index.ts +0 -4
- package/templates/src/features/template/ui/TemplateContent.tsx +397 -1107
- package/templates/src/locales/en/pages/templates.json +70 -270
- package/templates/src/locales/es/pages/templates.json +77 -277
- package/templates/src/locales/pt-BR/pages/templates.json +77 -277
- package/templates/src/styles/xertica/tokens.css +9 -0
- package/templates/vite.config.ts +25 -0
- package/templates/src/features/auth/ui/SocialLoginButtons.tsx +0 -78
- package/templates/src/features/home/data/mock.ts +0 -41
- package/templates/src/features/home/hooks/useFeatureCards.ts +0 -20
- package/templates/src/features/home/store/dashboardStore.ts +0 -25
- package/templates/src/features/template/ui/CrudTemplate.tsx +0 -112
- package/templates/src/features/template/ui/DashboardTemplate.tsx +0 -110
- package/templates/src/features/template/ui/FormTemplate.tsx +0 -117
- package/templates/src/features/template/ui/LoginTemplate.tsx +0 -59
- package/templates/src/locales/en/pages/crudTemplate.json +0 -25
- package/templates/src/locales/en/pages/dashboardTemplate.json +0 -20
- package/templates/src/locales/en/pages/formTemplate.json +0 -16
- package/templates/src/locales/en/pages/loginTemplate.json +0 -9
- package/templates/src/locales/es/pages/crudTemplate.json +0 -25
- package/templates/src/locales/es/pages/dashboardTemplate.json +0 -20
- package/templates/src/locales/es/pages/formTemplate.json +0 -16
- package/templates/src/locales/es/pages/loginTemplate.json +0 -9
- package/templates/src/locales/pt-BR/pages/crudTemplate.json +0 -25
- package/templates/src/locales/pt-BR/pages/dashboardTemplate.json +0 -20
- package/templates/src/locales/pt-BR/pages/formTemplate.json +0 -16
- package/templates/src/locales/pt-BR/pages/loginTemplate.json +0 -9
- package/templates/vite.config.d.ts +0 -2
- package/templates/vite.config.js +0 -20
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { Button } from '../../ui/button';
|
|
3
3
|
import { XerticaLogo } from '../../brand/xertica-logo';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { ArrowLeft, Mail, CheckCircle2, Lock } from 'lucide-react';
|
|
4
|
+
import { AuthPageShell, SocialLoginButtons } from '../../blocks/auth';
|
|
5
|
+
import { ArrowLeft, Mail, CheckCircle2 } from 'lucide-react';
|
|
7
6
|
import { useNavigate, useLocation } from 'react-router-dom';
|
|
8
7
|
import { useTranslation } from 'react-i18next';
|
|
9
8
|
|
|
@@ -47,160 +46,59 @@ export function VerifyEmailPage() {
|
|
|
47
46
|
};
|
|
48
47
|
|
|
49
48
|
return (
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
className="absolute inset-0 w-full h-full object-cover"
|
|
58
|
-
/>
|
|
59
|
-
|
|
60
|
-
{/* Gradient overlay */}
|
|
61
|
-
<div className="absolute inset-0 bg-[image:var(--gradient-diagonal)] opacity-80" />
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
{/* Right side - Content */}
|
|
65
|
-
<div className="flex-1 flex items-center justify-center px-4 sm:px-6 lg:px-8 lg:flex-none lg:w-1/2 relative bg-muted">
|
|
66
|
-
{/* Language selector in the top right corner */}
|
|
67
|
-
<div className="absolute top-4 right-4 z-20">
|
|
68
|
-
<LanguageSelector variant="minimal" showIcon={false} />
|
|
49
|
+
<AuthPageShell
|
|
50
|
+
imageSrc="https://images.unsplash.com/photo-1563986768609-322da13575f3?w=1200&h=800&fit=crop&auto=format"
|
|
51
|
+
imageAlt={t('verifyEmail.heroImageAlt')}
|
|
52
|
+
>
|
|
53
|
+
<div className="text-center">
|
|
54
|
+
<div className="flex items-center justify-center mb-4">
|
|
55
|
+
<XerticaLogo className="h-12 w-auto text-primary dark:text-foreground" variant="theme" />
|
|
69
56
|
</div>
|
|
70
57
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<div className="w-full max-w-sm space-y-6 relative z-10">
|
|
75
|
-
{/* Form header */}
|
|
76
|
-
<div className="text-center">
|
|
77
|
-
<div className="flex items-center justify-center mb-4">
|
|
78
|
-
<XerticaLogo
|
|
79
|
-
className="h-12 w-auto text-primary dark:text-foreground"
|
|
80
|
-
variant="theme"
|
|
81
|
-
/>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
|
-
{/* Email icon */}
|
|
85
|
-
<div className="flex items-center justify-center mb-4">
|
|
86
|
-
<div className="p-4 bg-primary/10 rounded-[var(--radius)]">
|
|
87
|
-
<Mail className="w-12 h-12 text-primary" />
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<h2 className="text-sm text-muted-foreground">{t('verifyEmail.heading')}</h2>
|
|
92
|
-
<p className="mt-2 text-muted-foreground">{t('verifyEmail.instructionsSent')}</p>
|
|
93
|
-
<p className="mt-1 text-primary">{email}</p>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
{/* Instructions */}
|
|
97
|
-
<div className="bg-accent rounded-[var(--radius)] p-4 space-y-3">
|
|
98
|
-
<p className="text-muted-foreground">{t('verifyEmail.instructions')}</p>
|
|
99
|
-
<div className="flex items-start gap-2 text-muted-foreground">
|
|
100
|
-
<CheckCircle2 className="w-4 h-4 mt-0.5 flex-shrink-0 text-[var(--chart-2)]" />
|
|
101
|
-
<span className="text-sm">{t('verifyEmail.checkSpam')}</span>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
{/* Success message on resend */}
|
|
106
|
-
{resendSuccess && (
|
|
107
|
-
<div className="bg-[var(--chart-2)]/10 border border-[var(--chart-2)]/20 rounded-[var(--radius)] p-3 flex items-center gap-2">
|
|
108
|
-
<CheckCircle2 className="w-5 h-5 text-[var(--chart-2)] flex-shrink-0" />
|
|
109
|
-
<span className="text-sm text-[var(--chart-2)]">
|
|
110
|
-
{t('verifyEmail.resentSuccess')}
|
|
111
|
-
</span>
|
|
112
|
-
</div>
|
|
113
|
-
)}
|
|
114
|
-
|
|
115
|
-
{/* Action buttons */}
|
|
116
|
-
<div className="space-y-3">
|
|
117
|
-
<p className="text-center text-muted-foreground">{t('verifyEmail.notReceived')}</p>
|
|
118
|
-
<Button
|
|
119
|
-
variant="outline"
|
|
120
|
-
className="w-full"
|
|
121
|
-
onClick={handleResend}
|
|
122
|
-
disabled={isResending}
|
|
123
|
-
>
|
|
124
|
-
{isResending ? t('verifyEmail.resending') : t('verifyEmail.resend')}
|
|
125
|
-
</Button>
|
|
126
|
-
|
|
127
|
-
<Button
|
|
128
|
-
type="button"
|
|
129
|
-
onClick={() => navigate('/login')}
|
|
130
|
-
variant="outline"
|
|
131
|
-
className="w-full text-muted-foreground hover:text-foreground"
|
|
132
|
-
>
|
|
133
|
-
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
134
|
-
{t('verifyEmail.backToLogin')}
|
|
135
|
-
</Button>
|
|
136
|
-
</div>
|
|
137
|
-
|
|
138
|
-
{/* Divider */}
|
|
139
|
-
<div className="relative">
|
|
140
|
-
<div className="absolute inset-0 flex items-center">
|
|
141
|
-
<div className="w-full border-t border-border"></div>
|
|
142
|
-
</div>
|
|
143
|
-
<div className="relative flex justify-center text-sm">
|
|
144
|
-
<span className="bg-muted px-2 text-muted-foreground">
|
|
145
|
-
{t('login.orContinueWith')}
|
|
146
|
-
</span>
|
|
147
|
-
</div>
|
|
58
|
+
<div className="flex items-center justify-center mb-4">
|
|
59
|
+
<div className="p-4 bg-primary/10 rounded-[var(--radius)]">
|
|
60
|
+
<Mail className="w-12 h-12 text-primary" />
|
|
148
61
|
</div>
|
|
62
|
+
</div>
|
|
149
63
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
type="button"
|
|
155
|
-
variant="outline"
|
|
156
|
-
className="w-full justify-center"
|
|
157
|
-
onClick={() => handleSocialLogin('Google')}
|
|
158
|
-
>
|
|
159
|
-
<svg className="w-5 h-5 mr-2" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
|
160
|
-
<path
|
|
161
|
-
fill="#EA4335"
|
|
162
|
-
d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"
|
|
163
|
-
></path>
|
|
164
|
-
<path
|
|
165
|
-
fill="#4285F4"
|
|
166
|
-
d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"
|
|
167
|
-
></path>
|
|
168
|
-
<path
|
|
169
|
-
fill="#FBBC05"
|
|
170
|
-
d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"
|
|
171
|
-
></path>
|
|
172
|
-
<path
|
|
173
|
-
fill="#34A853"
|
|
174
|
-
d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"
|
|
175
|
-
></path>
|
|
176
|
-
<path fill="none" d="M0 0h48v48H0z"></path>
|
|
177
|
-
</svg>
|
|
178
|
-
<span>{t('login.signInWithGoogle')}</span>
|
|
179
|
-
</Button>
|
|
64
|
+
<h2 className="text-sm text-muted-foreground">{t('verifyEmail.heading')}</h2>
|
|
65
|
+
<p className="mt-2 text-muted-foreground">{t('verifyEmail.instructionsSent')}</p>
|
|
66
|
+
<p className="mt-1 text-primary">{email}</p>
|
|
67
|
+
</div>
|
|
180
68
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
<Lock className="w-5 h-5 mr-2 text-[var(--chart-4)]" />
|
|
189
|
-
<span>{t('login.signInWithMTLogin')}</span>
|
|
190
|
-
</Button>
|
|
69
|
+
<div className="bg-accent rounded-[var(--radius)] p-4 space-y-3">
|
|
70
|
+
<p className="text-muted-foreground">{t('verifyEmail.instructions')}</p>
|
|
71
|
+
<div className="flex items-start gap-2 text-muted-foreground">
|
|
72
|
+
<CheckCircle2 className="w-4 h-4 mt-0.5 flex-shrink-0 text-[var(--chart-2)]" />
|
|
73
|
+
<span className="text-sm">{t('verifyEmail.checkSpam')}</span>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
191
76
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
className="w-full justify-center font-normal"
|
|
197
|
-
onClick={() => handleSocialLogin('gov.br')}
|
|
198
|
-
>
|
|
199
|
-
<span>{t('login.signInWithGovBr')}</span>
|
|
200
|
-
</Button>
|
|
201
|
-
</div>
|
|
77
|
+
{resendSuccess && (
|
|
78
|
+
<div className="bg-[var(--chart-2)]/10 border border-[var(--chart-2)]/20 rounded-[var(--radius)] p-3 flex items-center gap-2">
|
|
79
|
+
<CheckCircle2 className="w-5 h-5 text-[var(--chart-2)] flex-shrink-0" />
|
|
80
|
+
<span className="text-sm text-[var(--chart-2)]">{t('verifyEmail.resentSuccess')}</span>
|
|
202
81
|
</div>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
<div className="space-y-3">
|
|
85
|
+
<p className="text-center text-muted-foreground">{t('verifyEmail.notReceived')}</p>
|
|
86
|
+
<Button variant="outline" className="w-full" onClick={handleResend} disabled={isResending}>
|
|
87
|
+
{isResending ? t('verifyEmail.resending') : t('verifyEmail.resend')}
|
|
88
|
+
</Button>
|
|
89
|
+
|
|
90
|
+
<Button
|
|
91
|
+
type="button"
|
|
92
|
+
onClick={() => navigate('/login')}
|
|
93
|
+
variant="outline"
|
|
94
|
+
className="w-full text-muted-foreground hover:text-foreground"
|
|
95
|
+
>
|
|
96
|
+
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
97
|
+
{t('verifyEmail.backToLogin')}
|
|
98
|
+
</Button>
|
|
203
99
|
</div>
|
|
204
|
-
|
|
100
|
+
|
|
101
|
+
<SocialLoginButtons onSocialLogin={handleSocialLogin} />
|
|
102
|
+
</AuthPageShell>
|
|
205
103
|
);
|
|
206
104
|
}
|
|
@@ -8,7 +8,7 @@ describe('Button', () => {
|
|
|
8
8
|
render(<Button>Click me</Button>);
|
|
9
9
|
const button = screen.getByRole('button', { name: /click me/i });
|
|
10
10
|
expect(button).toBeInTheDocument();
|
|
11
|
-
expect(button).toHaveClass('bg-primary');
|
|
11
|
+
expect(button).toHaveClass('bg-button-primary');
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
it('renders correctly with different variants', () => {
|
|
@@ -59,6 +59,6 @@ describe('Button', () => {
|
|
|
59
59
|
);
|
|
60
60
|
const link = screen.getByRole('link', { name: /link button/i });
|
|
61
61
|
expect(link).toBeInTheDocument();
|
|
62
|
-
expect(link).toHaveClass('bg-primary'); // Should still have button styles
|
|
62
|
+
expect(link).toHaveClass('bg-button-primary'); // Should still have button styles
|
|
63
63
|
});
|
|
64
64
|
});
|
|
@@ -10,18 +10,18 @@ const buttonVariants = cva(
|
|
|
10
10
|
{
|
|
11
11
|
variants: {
|
|
12
12
|
variant: {
|
|
13
|
-
default: 'bg-primary text-
|
|
13
|
+
default: 'border-button-stroke bg-button-primary text-button-primary',
|
|
14
14
|
destructive:
|
|
15
|
-
'bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',
|
|
15
|
+
'border-button-stroke bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',
|
|
16
16
|
outline: 'border border-border bg-background hover:bg-accent hover:text-accent-foreground',
|
|
17
|
-
secondary: 'bg-secondary text-
|
|
17
|
+
secondary: 'border-button-stroke bg-button-secondary text-button-secondary',
|
|
18
18
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
19
19
|
link: 'text-primary underline-offset-4 hover:underline',
|
|
20
20
|
success:
|
|
21
|
-
'bg-success text-success-foreground hover:bg-success/90 focus-visible:ring-success/20 dark:focus-visible:ring-success/40',
|
|
22
|
-
info: 'bg-info text-info-foreground hover:bg-info/90 focus-visible:ring-info/20 dark:focus-visible:ring-info/40',
|
|
21
|
+
'border-button-stroke bg-success text-success-foreground hover:bg-success/90 focus-visible:ring-success/20 dark:focus-visible:ring-success/40',
|
|
22
|
+
info: 'border-button-stroke bg-info text-info-foreground hover:bg-info/90 focus-visible:ring-info/20 dark:focus-visible:ring-info/40',
|
|
23
23
|
warning:
|
|
24
|
-
'bg-warning text-warning-foreground hover:bg-warning/90 focus-visible:ring-warning/20 dark:focus-visible:ring-warning/40',
|
|
24
|
+
'border-button-stroke bg-warning text-warning-foreground hover:bg-warning/90 focus-visible:ring-warning/20 dark:focus-visible:ring-warning/40',
|
|
25
25
|
},
|
|
26
26
|
size: {
|
|
27
27
|
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
|
@@ -2,6 +2,16 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { cn } from '../../shared/utils';
|
|
4
4
|
|
|
5
|
+
export interface CardProps extends React.ComponentProps<'div'> {
|
|
6
|
+
/**
|
|
7
|
+
* Background variant.
|
|
8
|
+
* - `default`: uses the theme's `--card` token (e.g. Marfim on the Xertica theme).
|
|
9
|
+
* - `white`: forces a solid white background regardless of the active theme,
|
|
10
|
+
* for cards that should stand out from the theme's own card tone.
|
|
11
|
+
*/
|
|
12
|
+
variant?: 'default' | 'white';
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
/**
|
|
6
16
|
* Primary content container surface.
|
|
7
17
|
*
|
|
@@ -13,13 +23,15 @@ import { cn } from '../../shared/utils';
|
|
|
13
23
|
* 1. NEVER create raw divs with `bg-white dark:bg-black rounded border shadow` — use `<Card>`.
|
|
14
24
|
* 2. Compose with the semantic order: `CardHeader > CardTitle + CardDescription > CardContent > CardFooter`.
|
|
15
25
|
* 3. For inline action buttons in the header, use `<CardAction>` (rendered right-aligned automatically).
|
|
26
|
+
* 4. Use `variant="white"` for cards that need a solid white background instead of the theme's card tone.
|
|
16
27
|
*/
|
|
17
|
-
function Card({ className, ...props }:
|
|
28
|
+
function Card({ className, variant = 'default', ...props }: CardProps) {
|
|
18
29
|
return (
|
|
19
30
|
<div
|
|
20
31
|
data-slot="card"
|
|
21
32
|
className={cn(
|
|
22
|
-
'
|
|
33
|
+
'text-card-foreground flex flex-col gap-6 rounded-[var(--radius-card)]',
|
|
34
|
+
variant === 'white' ? 'bg-white' : 'bg-card',
|
|
23
35
|
className
|
|
24
36
|
)}
|
|
25
37
|
{...props}
|
|
@@ -38,7 +38,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
|
38
38
|
type={type}
|
|
39
39
|
data-slot="input"
|
|
40
40
|
className={cn(
|
|
41
|
-
'flex w-full min-w-0 bg-background rounded-[var(--radius)] border border-
|
|
41
|
+
'flex w-full min-w-0 bg-background rounded-[var(--radius)] border border-input-stroke transition-colors outline-none text-foreground',
|
|
42
42
|
'placeholder:text-muted-foreground',
|
|
43
43
|
'focus:ring-2 focus:ring-primary focus:border-transparent',
|
|
44
44
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
@@ -74,7 +74,7 @@ function InputOTPSlot({
|
|
|
74
74
|
data-slot="input-otp-slot"
|
|
75
75
|
data-active={isActive}
|
|
76
76
|
className={cn(
|
|
77
|
-
'data-[active=true]:border-primary data-[active=true]:ring-primary/20 data-[active=true]:aria-invalid:ring-destructive/20 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive relative flex items-center justify-center border border-
|
|
77
|
+
'data-[active=true]:border-primary data-[active=true]:ring-primary/20 data-[active=true]:aria-invalid:ring-destructive/20 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive relative flex items-center justify-center border border-input-stroke rounded-[var(--radius)] bg-background transition-all outline-none data-[active=true]:z-10 data-[active=true]:ring-2',
|
|
78
78
|
sizeClasses[size],
|
|
79
79
|
className
|
|
80
80
|
)}
|
|
@@ -109,7 +109,7 @@ const Search = React.forwardRef<HTMLInputElement, SearchProps>(
|
|
|
109
109
|
onChange={handleChange}
|
|
110
110
|
onKeyDown={handleKeyDown}
|
|
111
111
|
className={cn(
|
|
112
|
-
'flex w-full rounded-[var(--radius)] border border-
|
|
112
|
+
'flex w-full rounded-[var(--radius)] border border-input-stroke bg-background text-foreground transition-colors outline-none',
|
|
113
113
|
'placeholder:text-muted-foreground',
|
|
114
114
|
'focus:ring-2 focus:ring-primary focus:border-transparent',
|
|
115
115
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
@@ -48,7 +48,7 @@ const SelectTrigger = React.forwardRef<
|
|
|
48
48
|
data-slot="select-trigger"
|
|
49
49
|
data-size={size}
|
|
50
50
|
className={cn(
|
|
51
|
-
'flex w-full items-center justify-between gap-2 bg-background rounded-[var(--radius)] border border-
|
|
51
|
+
'flex w-full items-center justify-between gap-2 bg-background rounded-[var(--radius)] border border-input-stroke transition-colors outline-none whitespace-nowrap text-foreground',
|
|
52
52
|
'data-[placeholder]:text-muted-foreground',
|
|
53
53
|
'focus:ring-2 focus:ring-primary focus:border-transparent',
|
|
54
54
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
@@ -107,7 +107,7 @@ const SelectContent = React.forwardRef<
|
|
|
107
107
|
ref={ref}
|
|
108
108
|
data-slot="select-content"
|
|
109
109
|
className={cn(
|
|
110
|
-
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--radius)] border border-
|
|
110
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--radius)] border border-input-stroke shadow-md',
|
|
111
111
|
position === 'popper' &&
|
|
112
112
|
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
113
113
|
className
|
|
@@ -45,7 +45,7 @@ const Switch = React.forwardRef<
|
|
|
45
45
|
<SwitchPrimitive.Root
|
|
46
46
|
className={cn(
|
|
47
47
|
'peer inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
48
|
-
'data-[state=checked]:bg-primary',
|
|
48
|
+
'data-[state=checked]:bg-button-primary',
|
|
49
49
|
'data-[state=unchecked]:bg-muted',
|
|
50
50
|
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
|
51
51
|
trackClasses[size],
|
|
@@ -43,7 +43,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
|
43
43
|
<textarea
|
|
44
44
|
data-slot="textarea"
|
|
45
45
|
className={cn(
|
|
46
|
-
'flex min-h-16 w-full bg-background rounded-[var(--radius)] border border-
|
|
46
|
+
'flex min-h-16 w-full bg-background rounded-[var(--radius)] border border-input-stroke transition-colors outline-none resize-none text-foreground',
|
|
47
47
|
'placeholder:text-muted-foreground',
|
|
48
48
|
'focus:ring-2 focus:ring-primary focus:border-transparent',
|
|
49
49
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
@@ -132,6 +132,10 @@ export const BrandColorsProvider: React.FC<BrandColorsProviderProps> = ({
|
|
|
132
132
|
// 3. Radius
|
|
133
133
|
cssVars.push(`--radius: ${radius}rem`);
|
|
134
134
|
|
|
135
|
+
// 3b. Button shape overrides (identical in both modes; theme-specific, always emitted)
|
|
136
|
+
cssVars.push(`--radius-button: ${colors.buttonRadius || '12px'}`);
|
|
137
|
+
cssVars.push(`--button-stroke-width: ${colors.buttonStrokeWidth || '0px'}`);
|
|
138
|
+
|
|
135
139
|
// 4. Charts
|
|
136
140
|
cssVars.push(`--chart-1: ${colors.chart1}`);
|
|
137
141
|
cssVars.push(`--chart-2: ${colors.chart2}`);
|
|
@@ -193,6 +197,48 @@ export const BrandColorsProvider: React.FC<BrandColorsProviderProps> = ({
|
|
|
193
197
|
darkSurfaceVars.push(`--input-background: ${colors.darkMuted}`);
|
|
194
198
|
}
|
|
195
199
|
|
|
200
|
+
// 7b. Button stroke/secondary tokens + light-mode page background.
|
|
201
|
+
// Always emitted (with fallbacks matching the pre-existing look) so
|
|
202
|
+
// switching away from a theme that defines them never leaves a stale value.
|
|
203
|
+
const lightModeVars: string[] = [
|
|
204
|
+
`--button-stroke-color: ${colors.buttonStrokeColor || 'transparent'}`,
|
|
205
|
+
`--button-secondary-bg: ${colors.buttonSecondaryBg || 'var(--secondary)'}`,
|
|
206
|
+
`--button-secondary-foreground: ${colors.buttonSecondaryForeground || 'var(--secondary-foreground)'}`,
|
|
207
|
+
`--button-primary-bg: ${colors.buttonPrimaryBg || 'var(--primary)'}`,
|
|
208
|
+
`--button-primary-foreground: ${colors.buttonPrimaryForeground || 'var(--primary-foreground)'}`,
|
|
209
|
+
];
|
|
210
|
+
if (colors.backgroundLight) {
|
|
211
|
+
// The app shell backdrop (e.g. AppLayout's `bg-muted` wrapper behind the
|
|
212
|
+
// sidebar/content) reads `--muted`, not `--background` — mirror the
|
|
213
|
+
// override so the shell matches the page background instead of falling
|
|
214
|
+
// back to the neutral gray every other theme uses.
|
|
215
|
+
lightModeVars.push(`--background: ${colors.backgroundLight}`);
|
|
216
|
+
lightModeVars.push(`--muted: ${colors.backgroundLight}`);
|
|
217
|
+
}
|
|
218
|
+
if (colors.cardLight) {
|
|
219
|
+
lightModeVars.push(`--card: ${colors.cardLight}`);
|
|
220
|
+
lightModeVars.push(`--popover: ${colors.cardLight}`);
|
|
221
|
+
}
|
|
222
|
+
if (colors.inputBorderColor) {
|
|
223
|
+
lightModeVars.push(`--input-border: ${colors.inputBorderColor}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
darkSurfaceVars.push(
|
|
227
|
+
`--button-stroke-color: ${colors.buttonStrokeColorDark || colors.buttonStrokeColor || 'transparent'}`
|
|
228
|
+
);
|
|
229
|
+
darkSurfaceVars.push(
|
|
230
|
+
`--button-secondary-bg: ${colors.buttonSecondaryBgDark || colors.buttonSecondaryBg || 'var(--secondary)'}`
|
|
231
|
+
);
|
|
232
|
+
darkSurfaceVars.push(
|
|
233
|
+
`--button-secondary-foreground: ${colors.buttonSecondaryForegroundDark || colors.buttonSecondaryForeground || 'var(--secondary-foreground)'}`
|
|
234
|
+
);
|
|
235
|
+
darkSurfaceVars.push(
|
|
236
|
+
`--button-primary-bg: ${colors.buttonPrimaryBgDark || colors.buttonPrimaryBg || 'var(--primary)'}`
|
|
237
|
+
);
|
|
238
|
+
darkSurfaceVars.push(
|
|
239
|
+
`--button-primary-foreground: ${colors.buttonPrimaryForegroundDark || colors.buttonPrimaryForeground || 'var(--primary-foreground)'}`
|
|
240
|
+
);
|
|
241
|
+
|
|
196
242
|
// Apply primary-related tokens directly as inline styles on <html>.
|
|
197
243
|
// Inline styles have the highest possible specificity and always win over
|
|
198
244
|
// any stylesheet rule, regardless of order or selector specificity.
|
|
@@ -216,13 +262,15 @@ export const BrandColorsProvider: React.FC<BrandColorsProviderProps> = ({
|
|
|
216
262
|
document.head.appendChild(styleEl);
|
|
217
263
|
}
|
|
218
264
|
|
|
265
|
+
const lightModeBlock = `:root:not(.dark) {\n ${lightModeVars.join(';\n ')};\n}`;
|
|
266
|
+
|
|
219
267
|
const darkSurfaceBlock =
|
|
220
268
|
darkSurfaceVars.length > 0
|
|
221
269
|
? `\n:root[data-mode='dark'], .dark {\n ${darkSurfaceVars.join(';\n ')};\n}`
|
|
222
270
|
: '';
|
|
223
271
|
|
|
224
|
-
// The style tag handles
|
|
225
|
-
styleEl.innerHTML = darkSurfaceBlock
|
|
272
|
+
// The style tag handles the surface/button tokens that vary per theme per mode.
|
|
273
|
+
styleEl.innerHTML = `${lightModeBlock}${darkSurfaceBlock}`.trim();
|
|
226
274
|
}, [colors, currentTheme, radius, useCustomTokens]);
|
|
227
275
|
|
|
228
276
|
// Aplicar cores quando elas mudarem
|
package/contexts/theme-data.ts
CHANGED
|
@@ -31,8 +31,44 @@ export interface BrandColors {
|
|
|
31
31
|
chart4: string;
|
|
32
32
|
chart5: string;
|
|
33
33
|
|
|
34
|
-
// Optional:
|
|
35
|
-
|
|
34
|
+
// Optional: light-mode page/shell background override (defaults to white
|
|
35
|
+
// when unset). Drives --background and --muted (the app-shell backdrop).
|
|
36
|
+
backgroundLight?: string;
|
|
37
|
+
|
|
38
|
+
// Optional: light-mode surface override for cards, popovers, the header,
|
|
39
|
+
// and the assistant panel (defaults to white when unset). Drives --card
|
|
40
|
+
// and --popover — kept distinct from backgroundLight so a theme can use a
|
|
41
|
+
// different tone for "page" vs "elevated surface".
|
|
42
|
+
cardLight?: string;
|
|
43
|
+
|
|
44
|
+
// Optional: light-mode stroke color for form fields only (Input, Select,
|
|
45
|
+
// Textarea, Search, InputOTP) — defaults to the shared --border token when
|
|
46
|
+
// unset. Deliberately scoped away from --border/--sidebar-border so
|
|
47
|
+
// structural strokes (header divider, sidebar popovers, <Separator>) keep
|
|
48
|
+
// their normal subtle look; only actual form controls need a stronger,
|
|
49
|
+
// always-visible stroke regardless of the surrounding background.
|
|
50
|
+
inputBorderColor?: string;
|
|
51
|
+
|
|
52
|
+
// Optional: Button shape & stroke overrides (defaults preserve current look when unset)
|
|
53
|
+
buttonRadius?: string;
|
|
54
|
+
buttonStrokeWidth?: string;
|
|
55
|
+
buttonStrokeColor?: string;
|
|
56
|
+
buttonStrokeColorDark?: string;
|
|
57
|
+
|
|
58
|
+
// Optional: Button `secondary` variant colors (defaults to the shared --secondary token when unset)
|
|
59
|
+
buttonSecondaryBg?: string;
|
|
60
|
+
buttonSecondaryBgDark?: string;
|
|
61
|
+
buttonSecondaryForeground?: string;
|
|
62
|
+
buttonSecondaryForegroundDark?: string;
|
|
63
|
+
|
|
64
|
+
// Optional: accent used by the Button `default` variant and Switch's checked
|
|
65
|
+
// state only (defaults to the shared --primary token when unset). Lets a
|
|
66
|
+
// theme use a vibrant color for these two controls without it bleeding into
|
|
67
|
+
// links, focus rings, radio buttons, the logo, etc. via --primary.
|
|
68
|
+
buttonPrimaryBg?: string;
|
|
69
|
+
buttonPrimaryBgDark?: string;
|
|
70
|
+
buttonPrimaryForeground?: string;
|
|
71
|
+
buttonPrimaryForegroundDark?: string;
|
|
36
72
|
}
|
|
37
73
|
|
|
38
74
|
export interface ColorTheme {
|
|
@@ -66,7 +102,7 @@ export const PALETTE = {
|
|
|
66
102
|
export const colorThemes: ColorTheme[] = [
|
|
67
103
|
{
|
|
68
104
|
id: 'xertica-original',
|
|
69
|
-
name: 'Xertica
|
|
105
|
+
name: 'Xertica Classic',
|
|
70
106
|
description: 'A identidade visual clássica da Xertica com o gradiente original',
|
|
71
107
|
colors: {
|
|
72
108
|
primary: '#2C275B',
|
|
@@ -100,6 +136,67 @@ export const colorThemes: ColorTheme[] = [
|
|
|
100
136
|
accent: '#72CDFD',
|
|
101
137
|
},
|
|
102
138
|
},
|
|
139
|
+
{
|
|
140
|
+
id: 'xertica',
|
|
141
|
+
name: 'Xertica',
|
|
142
|
+
description: 'A nova identidade visual da Xertica: papel quente, tintas vivas e botões em estilo serigrafia',
|
|
143
|
+
colors: {
|
|
144
|
+
// General-purpose brand accent (logo, links, radio buttons, focus rings,
|
|
145
|
+
// sidebar active state, badges, etc). Kept as Negro Xertica / Crema so it
|
|
146
|
+
// stays legible everywhere — yellow is reserved for buttonPrimaryBg below.
|
|
147
|
+
primary: '#1E1E1E', // Negro Xertica
|
|
148
|
+
primaryForeground: '#FFFEF8', // Marfim
|
|
149
|
+
primaryLight: '#1E1E1E',
|
|
150
|
+
primaryDarkMode: '#F2EDD8', // Crema
|
|
151
|
+
primaryForegroundDark: '#1E1E1E',
|
|
152
|
+
|
|
153
|
+
sidebarLight: '#1E1E1E', // Negro Xertica
|
|
154
|
+
sidebarDark: '#1E1E1E',
|
|
155
|
+
|
|
156
|
+
darkBackground: '#141311',
|
|
157
|
+
darkCard: '#1E1E1E',
|
|
158
|
+
darkMuted: '#26241f',
|
|
159
|
+
darkBorder: '#38352c',
|
|
160
|
+
|
|
161
|
+
gradientStart: '#1899AF', // Celeste
|
|
162
|
+
gradientEnd: '#C45BAA', // Magenta
|
|
163
|
+
gradientStartDark: '#126578',
|
|
164
|
+
gradientEndDark: '#8F3F7D',
|
|
165
|
+
|
|
166
|
+
chart1: '#3D63AC', // Azul
|
|
167
|
+
chart2: '#1899AF', // Celeste
|
|
168
|
+
chart3: '#FAF338', // Amarillo
|
|
169
|
+
chart4: '#DE5B48', // Rojo Coral
|
|
170
|
+
chart5: '#2E8B5A', // Verde
|
|
171
|
+
|
|
172
|
+
backgroundLight: '#E9E6DC', // page/shell background
|
|
173
|
+
cardLight: '#FFFEF8', // Marfim — cards, header, assistant panel
|
|
174
|
+
inputBorderColor: 'rgba(30, 30, 30, 0.4)', // Negro Xertica stroke — form fields only
|
|
175
|
+
|
|
176
|
+
buttonRadius: '9999px',
|
|
177
|
+
buttonStrokeWidth: '2px',
|
|
178
|
+
buttonStrokeColor: '#1E1E1E',
|
|
179
|
+
buttonStrokeColorDark: '#F2EDD8', // Crema
|
|
180
|
+
|
|
181
|
+
buttonSecondaryBg: '#1E1E1E',
|
|
182
|
+
buttonSecondaryBgDark: '#1E1E1E',
|
|
183
|
+
buttonSecondaryForeground: '#FFFEF8',
|
|
184
|
+
buttonSecondaryForegroundDark: '#FFFEF8',
|
|
185
|
+
|
|
186
|
+
// Amarillo stays vibrant, but only here — Button `default` variant and
|
|
187
|
+
// Switch's checked track, per the brand rule that yellow is the one
|
|
188
|
+
// accent allowed to dominate, and only in those two contexts.
|
|
189
|
+
buttonPrimaryBg: '#FAF338',
|
|
190
|
+
buttonPrimaryBgDark: '#FAF338',
|
|
191
|
+
buttonPrimaryForeground: '#1E1E1E',
|
|
192
|
+
buttonPrimaryForegroundDark: '#1E1E1E',
|
|
193
|
+
},
|
|
194
|
+
preview: {
|
|
195
|
+
primary: '#FAF338',
|
|
196
|
+
secondary: '#1E1E1E',
|
|
197
|
+
accent: '#1899AF',
|
|
198
|
+
},
|
|
199
|
+
},
|
|
103
200
|
{
|
|
104
201
|
id: 'zinc',
|
|
105
202
|
name: 'Zinc',
|