xertica-ui 1.9.3 → 1.9.5

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/components/assistant/xertica-assistant/xertica-assistant.tsx +21 -21
  3. package/components/brand/branding/branding.mdx +1 -1
  4. package/components/brand/branding/branding.stories.tsx +4 -4
  5. package/components/brand/xertica-logo/XerticaLogo.stories.tsx +82 -0
  6. package/components/brand/xertica-logo/xertica-logo.mdx +56 -0
  7. package/components/brand/xertica-logo/xertica-logo.test.tsx +1 -1
  8. package/components/brand/xertica-provider/XerticaProvider.tsx +4 -3
  9. package/components/brand/xertica-provider/xertica-provider.mdx +7 -3
  10. package/components/brand/xertica-xlogo/XerticaXLogo.stories.tsx +79 -0
  11. package/components/brand/xertica-xlogo/xertica-xlogo.mdx +55 -0
  12. package/components/layout/header/header.stories.tsx +29 -1
  13. package/components/layout/header/header.tsx +20 -0
  14. package/components/layout/sidebar/sidebar.stories.tsx +72 -0
  15. package/components/layout/sidebar/sidebar.tsx +169 -190
  16. package/components/media/FloatingMediaWrapper.tsx +9 -33
  17. package/components/media/floating-media-wrapper.mdx +74 -0
  18. package/components/pages/forgot-password-page/ForgotPasswordPage.stories.tsx +24 -0
  19. package/components/pages/forgot-password-page/forgot-password-page.mdx +60 -0
  20. package/components/pages/home-content/HomeContent.stories.tsx +39 -0
  21. package/components/pages/home-content/home-content.mdx +63 -0
  22. package/components/pages/home-page/HomePage.tsx +4 -4
  23. package/components/pages/home-page/home-page.test.tsx +1 -0
  24. package/components/pages/reset-password-page/ResetPasswordPage.stories.tsx +24 -0
  25. package/components/pages/reset-password-page/reset-password-page.mdx +59 -0
  26. package/components/pages/template-content/TemplateContent.stories.tsx +39 -0
  27. package/components/pages/template-content/template-content.mdx +62 -0
  28. package/components/pages/template-page/template-page.test.tsx +1 -0
  29. package/components/pages/verify-email-page/VerifyEmailPage.stories.tsx +41 -0
  30. package/components/pages/verify-email-page/verify-email-page.mdx +55 -0
  31. package/components/shared/assistant-utils.test.ts +1 -1
  32. package/components/shared/assistant-utils.ts +9 -9
  33. package/components/ui/assistant-chart/AssistantChart.tsx +58 -23
  34. package/components/ui/assistant-chart/assistant-chart.stories.tsx +1 -1
  35. package/components/ui/assistant-chart/assistant-chart.test.tsx +1 -1
  36. package/components/ui/avatar/avatar.stories.tsx +11 -4
  37. package/components/ui/badge/badge.stories.tsx +16 -1
  38. package/components/ui/button/button.stories.tsx +13 -1
  39. package/components/ui/button/button.tsx +7 -1
  40. package/components/ui/dialog/dialog.stories.tsx +61 -20
  41. package/components/ui/dialog/dialog.tsx +33 -7
  42. package/components/ui/drawer/drawer.test.tsx +2 -2
  43. package/components/ui/file-upload/file-upload.tsx +47 -16
  44. package/components/ui/form/form.test.tsx +1 -1
  45. package/components/ui/google-maps-loader/google-maps-loader.mdx +68 -0
  46. package/components/ui/index.ts +9 -4
  47. package/components/ui/input/input.stories.tsx +10 -0
  48. package/components/ui/notification-badge/notification-badge.stories.tsx +1 -1
  49. package/components/ui/notification-badge/notification-badge.tsx +29 -15
  50. package/components/ui/page-header/page-header.test.tsx +1 -1
  51. package/components/ui/page-header/page-header.tsx +39 -29
  52. package/components/ui/progress/progress.stories.tsx +16 -0
  53. package/components/ui/progress/progress.tsx +31 -6
  54. package/components/ui/rating/rating.stories.tsx +2 -2
  55. package/components/ui/rating/rating.test.tsx +1 -1
  56. package/components/ui/rating/rating.tsx +68 -38
  57. package/components/ui/rich-text-editor/rich-text-editor.mdx +2 -0
  58. package/components/ui/rich-text-editor/rich-text-editor.stories.tsx +37 -1
  59. package/components/ui/rich-text-editor/rich-text-editor.test.tsx +35 -0
  60. package/components/ui/rich-text-editor/rich-text-editor.tsx +483 -99
  61. package/components/ui/search/search.test.tsx +4 -4
  62. package/components/ui/search/search.tsx +34 -17
  63. package/components/ui/select/select.stories.tsx +11 -3
  64. package/components/ui/simple-map/simple-map.tsx +1 -1
  65. package/components/ui/stats-card/stats-card.tsx +3 -3
  66. package/components/ui/stepper/stepper.tsx +67 -61
  67. package/components/ui/timeline/timeline.stories.tsx +11 -2
  68. package/components/ui/timeline/timeline.tsx +10 -6
  69. package/components/ui/tree-view/tree-view.tsx +156 -44
  70. package/components.json +1 -1
  71. package/contexts/LanguageContext.test.tsx +6 -6
  72. package/dist/components/assistant/xertica-assistant/xertica-assistant.d.ts +5 -5
  73. package/dist/components/brand/xertica-provider/XerticaProvider.d.ts +1 -1
  74. package/dist/components/layout/header/header.d.ts +14 -1
  75. package/dist/components/layout/sidebar/sidebar.d.ts +2 -0
  76. package/dist/components/ui/alert/alert.d.ts +1 -1
  77. package/dist/components/ui/assistant-chart/AssistantChart.d.ts +20 -3
  78. package/dist/components/ui/badge/badge.d.ts +1 -1
  79. package/dist/components/ui/button/button.d.ts +2 -2
  80. package/dist/components/ui/dialog/dialog.d.ts +14 -1
  81. package/dist/components/ui/file-upload/file-upload.d.ts +5 -2
  82. package/dist/components/ui/index.d.ts +9 -3
  83. package/dist/components/ui/notification-badge/notification-badge.d.ts +4 -2
  84. package/dist/components/ui/page-header/page-header.d.ts +19 -18
  85. package/dist/components/ui/progress/progress.d.ts +9 -3
  86. package/dist/components/ui/rating/rating.d.ts +12 -3
  87. package/dist/components/ui/rich-text-editor/rich-text-editor.d.ts +22 -1
  88. package/dist/components/ui/search/search.d.ts +4 -0
  89. package/dist/components/ui/simple-map/simple-map.d.ts +1 -2
  90. package/dist/components/ui/stepper/stepper.d.ts +9 -4
  91. package/dist/components/ui/timeline/timeline.d.ts +2 -2
  92. package/dist/components/ui/tree-view/tree-view.d.ts +11 -3
  93. package/dist/index.es.js +1177 -568
  94. package/dist/index.umd.js +1174 -565
  95. package/dist/xertica-ui.css +2 -2
  96. package/docs/components/badge.md +12 -3
  97. package/docs/components/button.md +13 -19
  98. package/docs/components/dialog.md +54 -29
  99. package/docs/components/header.md +31 -70
  100. package/docs/components/notification-badge.md +30 -13
  101. package/docs/components/progress.md +24 -1
  102. package/docs/components/rating.md +4 -4
  103. package/docs/components/rich-text-editor.md +13 -0
  104. package/docs/components/search.md +21 -11
  105. package/docs/components/sidebar.md +72 -15
  106. package/docs/components/timeline.md +87 -51
  107. package/llms-full.txt +272 -95
  108. package/llms.txt +2 -2
  109. package/package.json +2 -2
  110. package/styles/xertica/theme-map.css +9 -1
  111. package/templates/package.json +14 -11
  112. package/templates/src/app/App.d.ts +1 -1
  113. package/templates/src/app/App.js +70 -70
  114. package/templates/src/app/pages/CrudTemplate.d.ts +1 -1
  115. package/templates/src/app/pages/CrudTemplate.js +6 -6
  116. package/templates/src/app/pages/DashboardTemplate.d.ts +1 -1
  117. package/templates/src/app/pages/DashboardTemplate.js +9 -9
  118. package/templates/src/app/pages/ForgotPassword/ForgotPasswordContent.d.ts +1 -1
  119. package/templates/src/app/pages/ForgotPassword/ForgotPasswordContent.js +21 -21
  120. package/templates/src/app/pages/ForgotPasswordPage.d.ts +1 -1
  121. package/templates/src/app/pages/ForgotPasswordPage.js +5 -5
  122. package/templates/src/app/pages/FormTemplate.d.ts +1 -1
  123. package/templates/src/app/pages/FormTemplate.js +23 -23
  124. package/templates/src/app/pages/Home/HomeContent.d.ts +1 -1
  125. package/templates/src/app/pages/Home/HomeContent.js +24 -24
  126. package/templates/src/app/pages/HomePage.d.ts +8 -8
  127. package/templates/src/app/pages/HomePage.js +24 -24
  128. package/templates/src/app/pages/Login/LoginContent.d.ts +5 -5
  129. package/templates/src/app/pages/Login/LoginContent.js +28 -28
  130. package/templates/src/app/pages/LoginPage.d.ts +5 -5
  131. package/templates/src/app/pages/LoginPage.js +5 -5
  132. package/templates/src/app/pages/LoginTemplate.d.ts +1 -1
  133. package/templates/src/app/pages/LoginTemplate.js +6 -6
  134. package/templates/src/app/pages/ResetPassword/ResetPasswordContent.d.ts +1 -1
  135. package/templates/src/app/pages/ResetPassword/ResetPasswordContent.js +73 -73
  136. package/templates/src/app/pages/ResetPasswordPage.d.ts +1 -1
  137. package/templates/src/app/pages/ResetPasswordPage.js +5 -5
  138. package/templates/src/app/pages/Template/TemplateContent.d.ts +1 -1
  139. package/templates/src/app/pages/Template/TemplateContent.js +75 -75
  140. package/templates/src/app/pages/TemplatePage.d.ts +8 -8
  141. package/templates/src/app/pages/TemplatePage.js +11 -11
  142. package/templates/src/app/pages/VerifyEmail/VerifyEmailContent.d.ts +1 -1
  143. package/templates/src/app/pages/VerifyEmail/VerifyEmailContent.js +24 -24
  144. package/templates/src/app/pages/VerifyEmailPage.d.ts +1 -1
  145. package/templates/src/app/pages/VerifyEmailPage.js +5 -5
  146. package/templates/src/app/routes.d.ts +10 -10
  147. package/templates/src/app/routes.js +22 -22
  148. package/templates/src/main.d.ts +1 -1
  149. package/templates/src/main.js +6 -6
  150. package/templates/src/styles/index.css +2 -2
  151. package/templates/vite.config.d.ts +2 -2
  152. package/templates/vite.config.js +6 -6
package/CHANGELOG.md CHANGED
@@ -7,6 +7,33 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ---
9
9
 
10
+ ## [1.10.0] — 2026-05-08
11
+
12
+ ### Added
13
+
14
+ - **Semantic Variants** — Added `success`, `info`, and `warning` variants to components that lacked them:
15
+ - **Button** — now supports 9 variants: `default`, `secondary`, `outline`, `ghost`, `destructive`, `link`, `success`, `info`, `warning`.
16
+ - **Progress** — new `variant` prop (`default`, `success`, `info`, `warning`, `destructive`) colors both the track and the indicator.
17
+ - **NotificationBadge** — added `secondary`, `outline`, `success`, `info`, `warning`; standardized `default` to primary color for consistency with Badge and Button.
18
+ - **TimelineDot** — added `info` and `outline` variants; replaced hardcoded `rgb()` values with semantic CSS tokens (`bg-success`, `bg-warning`).
19
+ - **DialogBody** — new sub-component for the Dialog. When used, `DialogHeader` and `DialogFooter` stay pinned while `DialogBody` scrolls independently. Exported from `xertica-ui`.
20
+ - **Dialog height management** — `DialogContent` now has `max-h-[calc(100dvh-2rem)] overflow-hidden`. The close button (×) is pinned and never scrolls with content. `size="full"` fills the full viewport height.
21
+ - **Header `breadcrumbSlot`** — new prop accepting any `ReactNode` rendered immediately after the breadcrumb/title area (badges, buttons, status chips, etc.).
22
+ - **Sidebar default variant groups** — `variant="default"` now renders `navigationGroups` with labeled group headers. Each `RouteConfig` supports a `children` field (sub-routes shown in a contextual `DropdownMenu` via a `ChevronRight` button at the end of the item).
23
+
24
+ ### Fixed
25
+
26
+ - **Search double clear icon** — `type="search"` caused browsers to inject a native clear button on top of the custom × icon. Changed to `type="text"`.
27
+ - **CSS `@source` path** — CLI template `src/styles/index.css` had `../node_modules/xertica-ui` (one level short); corrected to `../../node_modules/xertica-ui/components`.
28
+ - **`theme-map.css` incomplete** — `--color-success`, `--color-info`, `--color-warning` and their `foreground` variants were missing, preventing `bg-success`, `text-info`, etc. from being generated in the compiled library CSS.
29
+
30
+ ### Changed
31
+
32
+ - **Storybook argTypes** — Multiple components had controls missing from the Storybook panel: Badge (`success`/`info`/`warning` options), Select (`size`), Avatar (`size`), Rating (`readonly` casing), Timeline (`dotVariant`), Dialog (`size` available in all stories). All corrected.
33
+ - **LLM documentation** (`llms-full.txt`) — Updated Badge, Button, Dialog, Header, NotificationBadge, Progress, Search, Sidebar, and Timeline sections to reflect current APIs.
34
+
35
+ ---
36
+
10
37
  ## [1.9.0] — 2026-05-05
11
38
 
12
39
  ### Added
@@ -211,11 +211,11 @@ export interface Message {
211
211
  */
212
212
  export interface Conversation {
213
213
  id: string;
214
- titulo: string;
215
- ultimaMensagem?: string;
214
+ title: string;
215
+ lastMessage?: string;
216
216
  timestamp: string;
217
- favorita: boolean;
218
- mensagens: Message[];
217
+ isFavorite: boolean;
218
+ messages: Message[];
219
219
  }
220
220
 
221
221
  /**
@@ -223,7 +223,7 @@ export interface Conversation {
223
223
  */
224
224
  export interface Suggestion {
225
225
  id: string;
226
- texto: string;
226
+ text: string;
227
227
  icon?: React.ReactNode;
228
228
  }
229
229
 
@@ -550,10 +550,10 @@ export function XerticaAssistant({
550
550
  // ============================================================================
551
551
 
552
552
  const defaultSuggestions: Suggestion[] = [
553
- { id: '1', texto: 'Me ajude a criar um documento profissional' },
554
- { id: '2', texto: 'Buscar nos meus arquivos por "relatório"' },
555
- { id: '3', texto: 'Resuma as conversas importantes desta semana' },
556
- { id: '4', texto: 'Crie um podcast sobre o último projeto' },
553
+ { id: '1', text: 'Me ajude a criar um documento profissional' },
554
+ { id: '2', text: 'Buscar nos meus arquivos por "relatório"' },
555
+ { id: '3', text: 'Resuma as conversas importantes desta semana' },
556
+ { id: '4', text: 'Crie um podcast sobre o último projeto' },
557
557
  ];
558
558
 
559
559
  const sugestoes = propSuggestions ?? defaultSuggestions;
@@ -765,7 +765,7 @@ export function XerticaAssistant({
765
765
  const handleSelecionarConversa = (conversaId: string) => {
766
766
  const conversa = conversas.find(c => c.id === conversaId);
767
767
  if (conversa) {
768
- setMensagens(conversa.mensagens);
768
+ setMensagens(conversa.messages);
769
769
  setConversaAtual(conversaId);
770
770
  setAbaSelecionada('chat');
771
771
  }
@@ -774,7 +774,7 @@ export function XerticaAssistant({
774
774
  const handleToggleFavoritaConversa = (conversaId: string) => {
775
775
  setConversas(prev =>
776
776
  prev.map(conv =>
777
- conv.id === conversaId ? { ...conv, favorita: !conv.favorita } : conv
777
+ conv.id === conversaId ? { ...conv, isFavorite: !conv.isFavorite } : conv
778
778
  )
779
779
  );
780
780
  };
@@ -803,10 +803,10 @@ export function XerticaAssistant({
803
803
 
804
804
  const handleRichSuggestionClick = (suggestion: Suggestion) => {
805
805
  if (onRichAction) {
806
- onRichAction(suggestion.id, suggestion.texto);
806
+ onRichAction(suggestion.id, suggestion.text);
807
807
  } else {
808
808
  // Fallback: send as message
809
- handleEnviarMensagem(suggestion.texto);
809
+ handleEnviarMensagem(suggestion.text);
810
810
  }
811
811
  setShowMoreSuggestions(false);
812
812
  };
@@ -853,7 +853,7 @@ export function XerticaAssistant({
853
853
 
854
854
  const conversasFiltradas = conversas.filter(conversa => {
855
855
  if (abaSelecionada === 'favoritos') {
856
- return conversa.favorita;
856
+ return conversa.isFavorite;
857
857
  }
858
858
  return true;
859
859
  });
@@ -1197,10 +1197,10 @@ export function XerticaAssistant({
1197
1197
  {sugestoes.map((sugestao) => (
1198
1198
  <button
1199
1199
  key={sugestao.id}
1200
- onClick={() => handleEnviarMensagem(sugestao.texto)}
1200
+ onClick={() => handleEnviarMensagem(sugestao.text)}
1201
1201
  className="w-full p-3 text-left rounded-[var(--radius-card)] bg-muted text-foreground transition-colors duration-200 hover:bg-muted/80"
1202
1202
  >
1203
- {sugestao.texto}
1203
+ {sugestao.text}
1204
1204
  </button>
1205
1205
  ))}
1206
1206
 
@@ -1226,7 +1226,7 @@ export function XerticaAssistant({
1226
1226
  <div className="flex items-center gap-2">
1227
1227
  {sugestao.id.includes('chart') && <BarChart3 className="w-4 h-4 text-primary" />}
1228
1228
  {sugestao.id.includes('table') && <TableIcon className="w-4 h-4 text-primary" />}
1229
- <span className="font-medium">{sugestao.texto}</span>
1229
+ <span className="font-medium">{sugestao.text}</span>
1230
1230
  </div>
1231
1231
  </button>
1232
1232
  ))
@@ -1767,7 +1767,7 @@ export function XerticaAssistant({
1767
1767
  >
1768
1768
  <div className="flex items-start justify-between mb-1">
1769
1769
  <h4 className="text-sm font-medium text-foreground truncate flex-1">
1770
- {conversa.titulo}
1770
+ {conversa.title}
1771
1771
  </h4>
1772
1772
  <Button
1773
1773
  variant="ghost"
@@ -1781,14 +1781,14 @@ export function XerticaAssistant({
1781
1781
  <Heart
1782
1782
  className={cn(
1783
1783
  "w-3 h-3",
1784
- conversa.favorita ? "text-destructive fill-current" : "text-muted-foreground"
1784
+ conversa.isFavorite ? "text-destructive fill-current" : "text-muted-foreground"
1785
1785
  )}
1786
1786
  />
1787
1787
  </Button>
1788
1788
  </div>
1789
- {conversa.ultimaMensagem && (
1789
+ {conversa.lastMessage && (
1790
1790
  <p className="text-sm text-muted-foreground truncate mb-1">
1791
- {conversa.ultimaMensagem}
1791
+ {conversa.lastMessage}
1792
1792
  </p>
1793
1793
  )}
1794
1794
  <p className="text-sm text-muted-foreground">
@@ -22,6 +22,6 @@ The standard Xertica.ai logo, available in multiple color variants to suit diffe
22
22
  ## AI Best Practices
23
23
 
24
24
  > [!IMPORTANT]
25
- > - **Variants** — Use the `white` variant on dark backgrounds and the `dark` or `brand` variant on light backgrounds. Use `theme` for automatic adjustment.
25
+ > - **Variants** — Use `default` on light/neutral backgrounds, `white` on dark or colored backgrounds, and `theme` to inherit the surrounding text color. There is no `brand` or `dark` variant.
26
26
  > - **Scaling** — Always specify a height (`h-*`) and use `w-auto` to maintain the correct aspect ratio.
27
27
  > - **Icon Usage** — Use `XerticaXLogo` for favicon-like placements, profile avatars, or collapsed sidebars where horizontal space is limited.
@@ -19,12 +19,12 @@ export const Logos: StoryObj = {
19
19
  <h3 className="text-lg font-semibold text-muted-foreground border-b pb-2">Full Logo</h3>
20
20
  <div className="flex flex-wrap gap-8 items-center bg-muted/20 p-8 rounded-xl">
21
21
  <div className="space-y-2 text-center">
22
- <XerticaLogo variant="brand" className="h-10 w-auto" />
23
- <span className="text-xs text-muted-foreground">Brand</span>
22
+ <XerticaLogo variant="default" className="h-10 w-auto" />
23
+ <span className="text-xs text-muted-foreground">Default</span>
24
24
  </div>
25
25
  <div className="space-y-2 text-center">
26
- <XerticaLogo variant="dark" className="h-10 w-auto" />
27
- <span className="text-xs text-muted-foreground">Dark</span>
26
+ <XerticaLogo variant="theme" className="h-10 w-auto" />
27
+ <span className="text-xs text-muted-foreground">Theme</span>
28
28
  </div>
29
29
  <div className="space-y-2 text-center bg-slate-900 p-4 rounded-lg">
30
30
  <XerticaLogo variant="white" className="h-10 w-auto" />
@@ -0,0 +1,82 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { XerticaLogo } from './XerticaLogo';
3
+ import React from 'react';
4
+
5
+ const meta: Meta<typeof XerticaLogo> = {
6
+ title: 'Brand/XerticaLogo',
7
+ component: XerticaLogo,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ argTypes: {
12
+ variant: {
13
+ control: 'select',
14
+ options: ['default', 'white', 'theme'],
15
+ },
16
+ },
17
+ };
18
+
19
+ export default meta;
20
+ type Story = StoryObj<typeof XerticaLogo>;
21
+
22
+ export const Default: Story = {
23
+ args: {
24
+ variant: 'default',
25
+ className: 'h-10 w-auto',
26
+ },
27
+ };
28
+
29
+ export const White: Story = {
30
+ args: {
31
+ variant: 'white',
32
+ className: 'h-10 w-auto',
33
+ },
34
+ decorators: [
35
+ (Story) => (
36
+ <div className="bg-slate-900 p-8 rounded-xl">
37
+ <Story />
38
+ </div>
39
+ ),
40
+ ],
41
+ };
42
+
43
+ export const Theme: Story = {
44
+ args: {
45
+ variant: 'theme',
46
+ className: 'h-10 w-auto text-blue-600',
47
+ },
48
+ };
49
+
50
+ export const AllVariants: Story = {
51
+ render: () => (
52
+ <div className="space-y-8 p-6">
53
+ <div className="space-y-2">
54
+ <p className="text-xs text-muted-foreground font-mono">variant="default"</p>
55
+ <XerticaLogo variant="default" className="h-10 w-auto" />
56
+ </div>
57
+ <div className="space-y-2 bg-slate-900 p-6 rounded-xl">
58
+ <p className="text-xs text-slate-400 font-mono">variant="white"</p>
59
+ <XerticaLogo variant="white" className="h-10 w-auto" />
60
+ </div>
61
+ <div className="space-y-2">
62
+ <p className="text-xs text-muted-foreground font-mono">variant="theme" (text-blue-600)</p>
63
+ <XerticaLogo variant="theme" className="h-10 w-auto text-blue-600" />
64
+ </div>
65
+ <div className="space-y-2">
66
+ <p className="text-xs text-muted-foreground font-mono">color="#e11d48" (direct override)</p>
67
+ <XerticaLogo color="#e11d48" className="h-10 w-auto" />
68
+ </div>
69
+ </div>
70
+ ),
71
+ };
72
+
73
+ export const Sizes: Story = {
74
+ render: () => (
75
+ <div className="flex flex-col gap-6 p-6 items-start">
76
+ <XerticaLogo className="h-6 w-auto" />
77
+ <XerticaLogo className="h-8 w-auto" />
78
+ <XerticaLogo className="h-10 w-auto" />
79
+ <XerticaLogo className="h-14 w-auto" />
80
+ </div>
81
+ ),
82
+ };
@@ -0,0 +1,56 @@
1
+ import { Meta, Title, Subtitle, Description } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Brand/XerticaLogo" />
4
+
5
+ <Title>XerticaLogo</Title>
6
+ <Subtitle>Full Xertica.ai wordmark (X-symbol + text) as a responsive SVG.</Subtitle>
7
+
8
+ ---
9
+
10
+ ## Overview
11
+
12
+ `XerticaLogo` renders the complete Xertica brand identity — the X symbol alongside the wordmark text. It adapts to different backgrounds through its `variant` prop and supports a direct `color` override for edge cases.
13
+
14
+ ```tsx
15
+ import { XerticaLogo } from 'xertica-ui';
16
+
17
+ <XerticaLogo className="h-8 w-auto" />
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Props
23
+
24
+ | Prop | Type | Default | Description |
25
+ |---|---|---|---|
26
+ | `variant` | `'default' \| 'white' \| 'theme'` | `'default'` | Color variant. `default` uses `var(--primary)`, `white` forces white fill, `theme` inherits `currentColor`. |
27
+ | `color` | `string` | — | Direct color override (CSS color value). Overrides `variant`. |
28
+ | `className` | `string` | `'w-auto h-8'` | Additional CSS classes applied to the SVG element. |
29
+
30
+ ---
31
+
32
+ ## Variants
33
+
34
+ ```tsx
35
+ // Light background — primary brand color
36
+ <XerticaLogo variant="default" className="h-8 w-auto" />
37
+
38
+ // Dark background — white fill
39
+ <XerticaLogo variant="white" className="h-8 w-auto" />
40
+
41
+ // Inherits text color from parent (useful on colored backgrounds)
42
+ <XerticaLogo variant="theme" className="h-8 w-auto" />
43
+
44
+ // Direct color override
45
+ <XerticaLogo color="#1D4ED8" className="h-8 w-auto" />
46
+ ```
47
+
48
+ ---
49
+
50
+ ## AI Best Practices
51
+
52
+ > [!IMPORTANT]
53
+ > - **Variant selection** — Use `default` on light/neutral backgrounds, `white` on dark or colored backgrounds, and `theme` when the logo should inherit the surrounding text color.
54
+ > - **Sizing** — Always set a height (`h-*`) and use `w-auto` to preserve the correct aspect ratio. Never set both width and height to fixed values.
55
+ > - **Icon-only contexts** — Use `XerticaXLogo` instead of `XerticaLogo` in compact spaces such as collapsed sidebars, favicons, or avatars.
56
+ > - **No `dark` or `brand` variants** — These are not valid. Use `default` for brand-color rendering.
@@ -20,7 +20,7 @@ describe('XerticaLogo', () => {
20
20
  // Verification depends on implementation (e.g. fill color)
21
21
  expect(container.querySelector('svg')).toBeInTheDocument();
22
22
 
23
- rerender(<XerticaLogo variant="brand" />);
23
+ rerender(<XerticaLogo variant="theme" />);
24
24
  expect(container.querySelector('svg')).toBeInTheDocument();
25
25
  });
26
26
  });
@@ -31,11 +31,12 @@ interface XerticaProviderProps {
31
31
  * This component aggregates all necessary context providers. It should be placed at the
32
32
  * root of your application, ideally inside the App component.
33
33
  */
34
- export function XerticaProvider({
35
- children
34
+ export function XerticaProvider({
35
+ children,
36
+ googleMapsApiKey,
36
37
  }: XerticaProviderProps) {
37
38
  return (
38
- <GoogleMapsLoaderProvider>
39
+ <GoogleMapsLoaderProvider apiKey={googleMapsApiKey}>
39
40
  <LayoutProvider>
40
41
  <TooltipProvider>
41
42
  {children}
@@ -32,9 +32,13 @@ function App() {
32
32
 
33
33
  | Prop | Type | Default | Description |
34
34
  |---|---|---|---|
35
- | `children` | `ReactNode` | **Required** | The application content |
36
-
37
- > **Note**: As of version 1.6+, brand colors, API keys, and language state are managed independently or via CSS tokens to increase modularity and performance.
35
+ | `children` | `ReactNode` | **Required** | The application content to be wrapped by all providers. |
36
+ | `googleMapsApiKey` | `string` | — | Google Maps JavaScript API key. Passed to `GoogleMapsLoaderProvider` to enable map components (`SimpleMap`, `MapShowcase`, etc.). |
37
+ | `apiKey` | `string` | | Gemini / AI service API key for AI-powered features. Accepted by the provider but not yet wired to a default context — pass explicitly to AI components that require it. |
38
+ | `defaultBrandTheme` | `string` | — | Initial theme name (e.g., `'default'`, `'dark'`). Intended for future theme-switching support. |
39
+ | `primaryColor` | `string` | — | Hex color override for the primary brand token. When set, updates `--primary` at runtime. |
40
+ | `useCustomTokens` | `boolean` | `false` | When `true`, skips injecting the library's default CSS token set, relying entirely on the host application's tokens. |
41
+ | `disableDarkMode` | `boolean` | `false` | When `true`, prevents the library from applying dark-mode class or media-query overrides. |
38
42
 
39
43
  ---
40
44
 
@@ -0,0 +1,79 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { XerticaXLogo } from './XerticaXLogo';
3
+ import React from 'react';
4
+
5
+ const meta: Meta<typeof XerticaXLogo> = {
6
+ title: 'Brand/XerticaXLogo',
7
+ component: XerticaXLogo,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ argTypes: {
12
+ variant: {
13
+ control: 'select',
14
+ options: ['default', 'white', 'theme'],
15
+ },
16
+ },
17
+ };
18
+
19
+ export default meta;
20
+ type Story = StoryObj<typeof XerticaXLogo>;
21
+
22
+ export const Default: Story = {
23
+ args: {
24
+ variant: 'default',
25
+ className: 'h-12 w-12',
26
+ },
27
+ };
28
+
29
+ export const White: Story = {
30
+ args: {
31
+ variant: 'white',
32
+ className: 'h-12 w-12',
33
+ },
34
+ decorators: [
35
+ (Story) => (
36
+ <div className="bg-slate-900 p-8 rounded-xl">
37
+ <Story />
38
+ </div>
39
+ ),
40
+ ],
41
+ };
42
+
43
+ export const Theme: Story = {
44
+ args: {
45
+ variant: 'theme',
46
+ className: 'h-12 w-12 text-blue-600',
47
+ },
48
+ };
49
+
50
+ export const AllVariants: Story = {
51
+ render: () => (
52
+ <div className="flex flex-wrap gap-10 p-6 items-end">
53
+ <div className="space-y-2 text-center">
54
+ <XerticaXLogo variant="default" className="h-12 w-12" />
55
+ <p className="text-xs text-muted-foreground">default</p>
56
+ </div>
57
+ <div className="space-y-2 text-center bg-slate-900 p-4 rounded-xl">
58
+ <XerticaXLogo variant="white" className="h-12 w-12" />
59
+ <p className="text-xs text-slate-400">white</p>
60
+ </div>
61
+ <div className="space-y-2 text-center">
62
+ <XerticaXLogo variant="theme" className="h-12 w-12 text-blue-600" />
63
+ <p className="text-xs text-muted-foreground">theme</p>
64
+ </div>
65
+ <div className="space-y-2 text-center">
66
+ <XerticaXLogo color="#e11d48" className="h-12 w-12" />
67
+ <p className="text-xs text-muted-foreground">color override</p>
68
+ </div>
69
+ </div>
70
+ ),
71
+ };
72
+
73
+ export const CollapsedSidebarSlot: Story = {
74
+ render: () => (
75
+ <div className="flex items-center justify-center w-20 h-16 bg-sidebar border-r border-border">
76
+ <XerticaXLogo className="h-7 w-7" />
77
+ </div>
78
+ ),
79
+ };
@@ -0,0 +1,55 @@
1
+ import { Meta, Title, Subtitle } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Brand/XerticaXLogo" />
4
+
5
+ <Title>XerticaXLogo</Title>
6
+ <Subtitle>Compact X-symbol mark for favicons, avatars, and collapsed sidebar slots.</Subtitle>
7
+
8
+ ---
9
+
10
+ ## Overview
11
+
12
+ `XerticaXLogo` renders only the X-symbol portion of the Xertica identity. It shares the same prop API as `XerticaLogo` and is the preferred choice wherever horizontal space is constrained.
13
+
14
+ ```tsx
15
+ import { XerticaXLogo } from 'xertica-ui';
16
+
17
+ <XerticaXLogo className="h-8 w-8" />
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Props
23
+
24
+ | Prop | Type | Default | Description |
25
+ |---|---|---|---|
26
+ | `variant` | `'default' \| 'white' \| 'theme'` | `'default'` | Color variant. `default` uses `var(--primary)`, `white` forces white fill, `theme` inherits `currentColor`. |
27
+ | `color` | `string` | — | Direct color override. Overrides `variant`. |
28
+ | `className` | `string` | `'w-auto h-8'` | Additional CSS classes applied to the SVG element. |
29
+
30
+ ---
31
+
32
+ ## Usage Examples
33
+
34
+ ```tsx
35
+ // Default — primary color
36
+ <XerticaXLogo className="h-10 w-10" />
37
+
38
+ // On a dark background
39
+ <XerticaXLogo variant="white" className="h-10 w-10" />
40
+
41
+ // Inherits current text color
42
+ <XerticaXLogo variant="theme" className="h-10 w-10 text-blue-600" />
43
+
44
+ // Collapsed sidebar icon slot
45
+ <XerticaXLogo className="h-6 w-6 shrink-0" />
46
+ ```
47
+
48
+ ---
49
+
50
+ ## AI Best Practices
51
+
52
+ > [!IMPORTANT]
53
+ > - **Square sizing** — Unlike the full logo, set both width and height to the same value (e.g., `h-10 w-10`) since the X symbol has a near-square aspect ratio (viewBox `0 0 258 282`).
54
+ > - **Favicon** — Export as a PNG at 32×32 and 192×192 for web manifest icons; do not use the SVG component directly in `<link rel="icon">`.
55
+ > - **Collapsed sidebar** — Replace the full `XerticaLogo` with `XerticaXLogo` when `sidebarExpanded === false` to avoid clipping.
@@ -1,8 +1,10 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { Header } from './header';
3
3
  import { BrowserRouter, Link } from 'react-router-dom';
4
- import { Home, Bell, Mail, User, Settings, LogOut, Users, FileText, FolderOpen } from 'lucide-react';
4
+ import { Home, Bell, Mail, User, Settings, LogOut, Users, FileText, FolderOpen, RefreshCw } from 'lucide-react';
5
5
  import React from 'react';
6
+ import { Badge } from '../../ui/badge';
7
+ import { Button } from '../../ui/button';
6
8
 
7
9
  const meta: Meta<typeof Header> = {
8
10
  title: 'Layout/Header',
@@ -144,6 +146,32 @@ export const CustomUserMenu: Story = {
144
146
  }
145
147
  };
146
148
 
149
+ /**
150
+ * Breadcrumb slot: custom element rendered right after the breadcrumb area.
151
+ * Accepts any React node — badges, buttons, status chips, etc.
152
+ */
153
+ export const WithBreadcrumbSlot: Story = {
154
+ args: {
155
+ breadcrumbs: [
156
+ { label: 'Home', href: '/', icon: <Home className="size-4" /> },
157
+ { label: 'Deployments' },
158
+ ],
159
+ breadcrumbSlot: (
160
+ <div className="flex items-center gap-2">
161
+ <Badge variant="warning">Beta</Badge>
162
+ <Button variant="outline" size="sm">
163
+ <RefreshCw className="size-3.5" />
164
+ Sync
165
+ </Button>
166
+ </div>
167
+ ),
168
+ user: {
169
+ name: 'Pedro Duarte',
170
+ email: 'pedro@example.com',
171
+ },
172
+ },
173
+ };
174
+
147
175
  /**
148
176
  * SPA Navigation: uses `renderLink` with React Router's `Link` component
149
177
  * to prevent full-page reloads when navigating breadcrumbs.
@@ -94,6 +94,19 @@ export interface HeaderProps {
94
94
  showLogout?: boolean;
95
95
  /** Click handler for logout */
96
96
  onLogoutClick?: () => void;
97
+ /**
98
+ * Custom element rendered immediately after the breadcrumb / title area.
99
+ * Accepts any React node — badges, buttons, status chips, etc.
100
+ *
101
+ * @example
102
+ * ```tsx
103
+ * <Header
104
+ * breadcrumbs={[...]}
105
+ * breadcrumbSlot={<Badge variant="warning">Beta</Badge>}
106
+ * />
107
+ * ```
108
+ */
109
+ breadcrumbSlot?: React.ReactNode;
97
110
  /**
98
111
  * Custom link renderer for breadcrumb navigation.
99
112
  * Use this to integrate with client-side routers (e.g., React Router, Next.js Link)
@@ -147,6 +160,7 @@ export function Header({
147
160
  showLogout,
148
161
  onLogoutClick,
149
162
  renderLink,
163
+ breadcrumbSlot,
150
164
  }: HeaderProps) {
151
165
  const { sidebarExpanded, toggleSidebar } = useLayout();
152
166
 
@@ -209,6 +223,12 @@ export function Header({
209
223
  </BreadcrumbList>
210
224
  </Breadcrumb>
211
225
  )}
226
+ {/* Breadcrumb slot */}
227
+ {breadcrumbSlot && (
228
+ <div className="flex items-center shrink-0">
229
+ {breadcrumbSlot}
230
+ </div>
231
+ )}
212
232
  </div>
213
233
 
214
234
  {/* User controls */}