@axzydev/axzy_ui_system 1.2.6 → 1.2.8

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 (185) hide show
  1. package/dist/index.cjs +777 -535
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.css.map +1 -1
  5. package/dist/index.d.cts +1470 -87
  6. package/dist/index.d.ts +1470 -87
  7. package/dist/index.js +799 -555
  8. package/dist/index.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/App.tsx +19 -54
  11. package/src/components/alert/alert.doc.mdx +48 -0
  12. package/src/components/alert/alert.props.ts +7 -0
  13. package/src/components/alert/alert.tsx +8 -0
  14. package/src/components/avatar/avatar.doc.mdx +48 -0
  15. package/src/components/avatar/avatar.props.ts +8 -0
  16. package/src/components/avatar/avatar.tsx +25 -5
  17. package/src/components/badget/badget.doc.mdx +46 -0
  18. package/src/components/badget/badget.props.ts +6 -0
  19. package/src/components/badget/badget.tsx +11 -0
  20. package/src/components/breadcrumbs/breadcrumbs.doc.mdx +57 -0
  21. package/src/components/breadcrumbs/breadcrumbs.props.ts +6 -0
  22. package/src/components/breadcrumbs/breadcrumbs.tsx +12 -0
  23. package/src/components/button/button.doc.mdx +59 -0
  24. package/src/components/button/button.props.ts +12 -0
  25. package/src/components/button/button.tsx +11 -0
  26. package/src/components/calendar/calendar.doc.mdx +75 -0
  27. package/src/components/calendar/calendar.props.ts +27 -7
  28. package/src/components/calendar/calendar.tsx +13 -0
  29. package/src/components/card/card.doc.mdx +54 -0
  30. package/src/components/card/card.props.ts +11 -0
  31. package/src/components/card/card.tsx +13 -0
  32. package/src/components/checkbox/checkbox.doc.mdx +54 -0
  33. package/src/components/checkbox/checkbox.props.ts +7 -0
  34. package/src/components/checkbox/checkbox.tsx +9 -0
  35. package/src/components/confirm-dialog/confirm-dialog.doc.mdx +60 -0
  36. package/src/components/confirm-dialog/confirm-dialog.props.ts +9 -0
  37. package/src/components/confirm-dialog/confirm-dialog.tsx +19 -0
  38. package/src/components/data-table/ITDataTable.doc.mdx +59 -0
  39. package/src/components/data-table/dataTable.props.ts +15 -0
  40. package/src/components/data-table/dataTable.tsx +178 -73
  41. package/src/components/date-picker/date-picker.doc.mdx +65 -0
  42. package/src/components/date-picker/date-picker.props.ts +17 -0
  43. package/src/components/date-picker/datePicker.tsx +31 -1
  44. package/src/components/dialog/dialog.doc.mdx +54 -0
  45. package/src/components/dialog/dialog.props.ts +7 -0
  46. package/src/components/dialog/dialog.tsx +26 -0
  47. package/src/components/divider/divider.doc.mdx +42 -0
  48. package/src/components/divider/divider.props.ts +5 -0
  49. package/src/components/divider/divider.tsx +16 -0
  50. package/src/components/drawer/drawer.doc.mdx +59 -0
  51. package/src/components/drawer/drawer.props.ts +9 -0
  52. package/src/components/drawer/drawer.tsx +20 -0
  53. package/src/components/dropfile/dropfile.doc.mdx +59 -0
  54. package/src/components/dropfile/dropfile.props.ts +41 -0
  55. package/src/components/dropfile/dropfile.tsx +21 -33
  56. package/src/components/empty-state/empty-state.doc.mdx +50 -0
  57. package/src/components/empty-state/empty-state.props.ts +5 -0
  58. package/src/components/empty-state/empty-state.tsx +16 -0
  59. package/src/components/flex/flex.doc.mdx +59 -0
  60. package/src/components/flex/flex.props.ts +13 -0
  61. package/src/components/flex/flex.tsx +15 -0
  62. package/src/components/form-builder/fieldRenderer.tsx +52 -2
  63. package/src/components/form-builder/formBuilder.doc.mdx +124 -0
  64. package/src/components/form-builder/formBuilder.props.ts +12 -2
  65. package/src/components/form-builder/formBuilder.tsx +31 -0
  66. package/src/components/form-header/form-header.doc.mdx +38 -0
  67. package/src/components/form-header/form-header.props.ts +3 -0
  68. package/src/components/form-header/form-header.stories.tsx +53 -0
  69. package/src/components/form-header/form-header.tsx +11 -0
  70. package/src/components/grid/grid.doc.mdx +54 -0
  71. package/src/components/grid/grid.props.ts +13 -0
  72. package/src/components/grid/grid.tsx +26 -2
  73. package/src/components/image/image.doc.mdx +44 -0
  74. package/src/components/image/image.props.ts +5 -0
  75. package/src/components/image/image.stories.tsx +49 -0
  76. package/src/components/image/image.tsx +19 -0
  77. package/src/components/input/input.doc.mdx +70 -0
  78. package/src/components/input/input.props.ts +34 -2
  79. package/src/components/input/input.tsx +29 -0
  80. package/src/components/layout/layout.doc.mdx +51 -0
  81. package/src/components/layout/layout.props.ts +5 -0
  82. package/src/components/layout/layout.tsx +41 -17
  83. package/src/components/loader/loader.doc.mdx +43 -0
  84. package/src/components/loader/loader.props.ts +4 -0
  85. package/src/components/loader/loader.tsx +17 -0
  86. package/src/components/navbar/navbar.doc.mdx +77 -0
  87. package/src/components/navbar/navbar.props.ts +37 -1
  88. package/src/components/navbar/navbar.stories.tsx +84 -0
  89. package/src/components/navbar/navbar.tsx +78 -46
  90. package/src/components/page/page.doc.mdx +80 -0
  91. package/src/components/page/page.props.ts +25 -0
  92. package/src/components/page/page.tsx +35 -7
  93. package/src/components/page-header/page-header.doc.mdx +54 -0
  94. package/src/components/page-header/page-header.props.ts +11 -0
  95. package/src/components/page-header/page-header.stories.tsx +14 -0
  96. package/src/components/page-header/page-header.tsx +50 -15
  97. package/src/components/pagination/pagination.doc.mdx +62 -0
  98. package/src/components/pagination/pagination.props.ts +11 -32
  99. package/src/components/pagination/pagination.tsx +17 -0
  100. package/src/components/popover/popover.doc.mdx +53 -0
  101. package/src/components/popover/popover.props.ts +8 -0
  102. package/src/components/popover/popover.tsx +13 -0
  103. package/src/components/progress/progress.doc.mdx +48 -0
  104. package/src/components/progress/progress.props.ts +8 -0
  105. package/src/components/progress/progress.tsx +9 -0
  106. package/src/components/radio/radio.doc.mdx +62 -0
  107. package/src/components/radio/radio.props.ts +11 -0
  108. package/src/components/radio/radio.tsx +18 -0
  109. package/src/components/search-select/search-select.doc.mdx +72 -0
  110. package/src/components/search-select/search-select.props.ts +23 -18
  111. package/src/components/search-select/search-select.tsx +27 -2
  112. package/src/components/searchTable/searchTable.doc.mdx +79 -0
  113. package/src/components/searchTable/searchTable.props.ts +42 -3
  114. package/src/components/searchTable/searchTable.stories.tsx +74 -0
  115. package/src/components/searchTable/searchTable.tsx +23 -0
  116. package/src/components/segmented-control/segmented-control.doc.mdx +60 -0
  117. package/src/components/segmented-control/segmented-control.props.ts +12 -0
  118. package/src/components/segmented-control/segmented-control.tsx +15 -0
  119. package/src/components/select/select.doc.mdx +75 -0
  120. package/src/components/select/select.props.ts +22 -0
  121. package/src/components/select/select.tsx +2 -5
  122. package/src/components/sidebar/sidebar.doc.mdx +86 -0
  123. package/src/components/sidebar/sidebar.props.ts +22 -0
  124. package/src/components/sidebar/sidebar.tsx +22 -0
  125. package/src/components/skeleton/skeleton.doc.mdx +43 -0
  126. package/src/components/skeleton/skeleton.props.ts +8 -0
  127. package/src/components/skeleton/skeleton.tsx +10 -0
  128. package/src/components/slide/slide.doc.mdx +46 -0
  129. package/src/components/slide/slide.props.ts +11 -24
  130. package/src/components/slide/slide.tsx +10 -1
  131. package/src/components/slider/slider.doc.mdx +49 -0
  132. package/src/components/slider/slider.props.ts +9 -0
  133. package/src/components/slider/slider.tsx +15 -0
  134. package/src/components/stack/stack.doc.mdx +126 -0
  135. package/src/components/stack/stack.props.ts +18 -0
  136. package/src/components/stack/stack.stories.tsx +221 -16
  137. package/src/components/stack/stack.tsx +21 -0
  138. package/src/components/stat-card/stat-card.doc.mdx +48 -0
  139. package/src/components/stat-card/stat-card.props.ts +9 -0
  140. package/src/components/stat-card/stat-card.tsx +10 -0
  141. package/src/components/stepper/stepper.doc.mdx +54 -0
  142. package/src/components/stepper/stepper.props.ts +11 -1
  143. package/src/components/stepper/stepper.tsx +15 -0
  144. package/src/components/table/table.doc.mdx +58 -0
  145. package/src/components/table/table.props.ts +17 -0
  146. package/src/components/table/table.tsx +199 -84
  147. package/src/components/tabs/tabs.doc.mdx +52 -0
  148. package/src/components/tabs/tabs.props.ts +11 -0
  149. package/src/components/tabs/tabs.tsx +14 -0
  150. package/src/components/text/text.doc.mdx +41 -0
  151. package/src/components/text/text.props.ts +5 -0
  152. package/src/components/text/text.stories.tsx +67 -0
  153. package/src/components/text/text.tsx +10 -0
  154. package/src/components/textarea/textarea.doc.mdx +64 -0
  155. package/src/components/textarea/textarea.props.ts +11 -0
  156. package/src/components/textarea/textarea.tsx +16 -0
  157. package/src/components/theme-provider/themeProvider.doc.mdx +75 -0
  158. package/src/components/theme-provider/themeProvider.props.ts +3 -0
  159. package/src/components/theme-provider/themeProvider.stories.tsx +59 -0
  160. package/src/components/theme-provider/themeProvider.tsx +14 -0
  161. package/src/components/time-picker/timePicker.doc.mdx +68 -0
  162. package/src/components/time-picker/timePicker.props.ts +14 -0
  163. package/src/components/time-picker/timePicker.tsx +22 -1
  164. package/src/components/toast/toast.doc.mdx +50 -0
  165. package/src/components/toast/toast.props.ts +5 -0
  166. package/src/components/toast/toast.tsx +21 -0
  167. package/src/components/tooltip/tooltip.doc.mdx +47 -0
  168. package/src/components/tooltip/tooltip.props.ts +6 -0
  169. package/src/components/tooltip/tooltip.tsx +19 -0
  170. package/src/components/topbar/topbar.doc.mdx +69 -0
  171. package/src/components/topbar/topbar.props.ts +15 -0
  172. package/src/components/topbar/topbar.tsx +38 -0
  173. package/src/components/triple-filter/tripleFilter.doc.mdx +62 -0
  174. package/src/components/triple-filter/tripleFilter.props.ts +7 -0
  175. package/src/components/triple-filter/tripleFilter.tsx +32 -0
  176. package/src/index.css +17 -0
  177. package/src/showcases/DataShowcases.tsx +529 -45
  178. package/src/showcases/FormShowcases.tsx +399 -29
  179. package/src/showcases/HomeShowcase.tsx +252 -272
  180. package/src/showcases/LayoutPrimitivesShowcases.tsx +1224 -248
  181. package/src/showcases/PageShowcases.tsx +868 -151
  182. package/src/showcases/ShowcaseLayout.tsx +237 -73
  183. package/src/showcases/StructureShowcases.tsx +1039 -97
  184. package/src/types/table.types.ts +1 -1
  185. package/src/utils/styles.ts +2 -1
@@ -3,7 +3,35 @@ import { useRef, useState } from "react";
3
3
  import { FaChevronDown, FaChevronRight, FaUserCircle } from "react-icons/fa";
4
4
  import { ITNavbarProps, ITNavigationItem } from "./navbar.props";
5
5
  import ITText from "@/components/text/text";
6
+ import { theme } from "@/theme/theme";
6
7
 
8
+ /**
9
+ * Full sidebar navigation shell with collapsible submenus, user menu dropdown, and themed styling.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <ITNavbar
14
+ * logo={<LogoIcon />}
15
+ * logoText="My App"
16
+ * navigationItems={[
17
+ * { id: 'home', label: 'Home', icon: <FaHome />, isActive: true },
18
+ * {
19
+ * id: 'settings',
20
+ * label: 'Settings',
21
+ * icon: <FaCog />,
22
+ * subitems: [{ id: 'profile', label: 'Profile', action: () => {} }],
23
+ * },
24
+ * ]}
25
+ * userMenu={{
26
+ * userName: 'John Doe',
27
+ * userEmail: 'john@example.com',
28
+ * menuItems: [{ label: 'Logout', onClick: () => {} }],
29
+ * }}
30
+ * >
31
+ * <ITPage title="Dashboard">...</ITPage>
32
+ * </ITNavbar>
33
+ * ```
34
+ */
7
35
  export default function ITNavbar({
8
36
  logo,
9
37
  logoText,
@@ -139,15 +167,21 @@ export default function ITNavbar({
139
167
  }
140
168
 
141
169
  // New sidebar design
170
+ const sidebar = theme.sidebar;
171
+ const topbar = theme.topbar;
172
+
142
173
  return (
143
- <div className="flex h-screen font-sans" style={{ backgroundColor: "var(--layout-bg, #f8fafc)" }}>
174
+ <div className="flex h-screen font-sans" style={{ backgroundColor: theme.layout.backgroundColor }}>
144
175
  {/* Sidebar */}
145
- <aside className="w-72 shadow-xl flex flex-col transition-all duration-300 ease-in-out" style={{ backgroundColor: "var(--sidebar-bg, #0f172a)", borderRight: "1px solid var(--sidebar-border, #1e293b)" }}>
176
+ <aside
177
+ className="w-72 shadow-xl flex flex-col transition-all duration-300 ease-in-out"
178
+ style={{ backgroundColor: sidebar.backgroundColor, borderRight: `1px solid ${sidebar.borderColor}` }}
179
+ >
146
180
  {/* Logo Section */}
147
- <div className="p-6 flex items-center gap-3" style={{ borderBottom: "1px solid var(--sidebar-border, #1e293b)" }}>
181
+ <div className="p-6 flex items-center gap-3" style={{ borderBottom: `1px solid ${sidebar.borderColor}` }}>
148
182
  {logo && <div className="h-8 w-auto object-contain transition-transform hover:scale-105">{logo}</div>}
149
183
  {logoText && (
150
- <ITText as="span" className="text-lg font-bold tracking-wide" style={{ color: "var(--sidebar-active-color, #ffffff)" }}>
184
+ <ITText as="span" className="text-lg font-bold tracking-wide" style={{ color: sidebar.active.color }}>
151
185
  {logoText}
152
186
  </ITText>
153
187
  )}
@@ -160,46 +194,42 @@ export default function ITNavbar({
160
194
  <li key={item.id}>
161
195
  <div
162
196
  className={`group flex items-center justify-between px-4 py-3 rounded-xl cursor-pointer transition-all duration-200 border-l-4 ${
163
- item.isActive
164
- ? 'shadow-sm'
197
+ item.isActive
198
+ ? 'shadow-sm'
165
199
  : 'hover:shadow-sm'
166
200
  }`}
167
201
  onClick={() => handleItemClick(item)}
168
202
  style={{
169
- backgroundColor: item.isActive ? "var(--sidebar-active-bg, rgba(255,255,255,0.1))" : "transparent",
170
- borderColor: item.isActive ? "var(--sidebar-active-icon, #3b82f6)" : "transparent",
171
- color: item.isActive ? "var(--sidebar-active-color, #ffffff)" : "var(--sidebar-label-color, #94a3b8)"
203
+ backgroundColor: item.isActive ? sidebar.active.backgroundColor : "transparent",
204
+ borderColor: item.isActive ? sidebar.active.iconColor : "transparent",
205
+ color: item.isActive ? sidebar.active.color : sidebar.label.color
172
206
  }}
173
207
  onMouseEnter={(e) => {
174
208
  if (!item.isActive) {
175
- e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, rgba(255,255,255,0.05))";
176
- e.currentTarget.style.color = "var(--sidebar-active-color, #ffffff)";
209
+ e.currentTarget.style.backgroundColor = sidebar.hover.backgroundColor;
210
+ e.currentTarget.style.color = sidebar.active.color;
177
211
  }
178
212
  }}
179
213
  onMouseLeave={(e) => {
180
214
  if (!item.isActive) {
181
215
  e.currentTarget.style.backgroundColor = "transparent";
182
- e.currentTarget.style.color = "var(--sidebar-label-color, #94a3b8)";
216
+ e.currentTarget.style.color = sidebar.label.color;
183
217
  }
184
218
  }}
185
219
  >
186
220
  <div className="flex items-center gap-3">
187
- {/* Icon */}
188
221
  {item.icon && (
189
222
  <div className="text-xl transition-colors" style={{
190
- color: item.isActive ? "var(--sidebar-active-icon, #3b82f6)" : "var(--sidebar-icon-color, #64748b)"
223
+ color: item.isActive ? sidebar.active.iconColor : sidebar.icon.color
191
224
  }}>
192
225
  {item.icon}
193
226
  </div>
194
227
  )}
195
-
196
- {/* Label */}
197
228
  <ITText as="span" className={`font-medium text-sm ${item.isActive ? 'font-semibold' : ''}`}>{item.label}</ITText>
198
229
  </div>
199
230
 
200
- {/* Chevron for expandable items */}
201
231
  {item.subitems && item.subitems.length > 0 && (
202
- <div className="transition-transform" style={{ color: "var(--sidebar-icon-color, #64748b)" }}>
232
+ <div className="transition-transform" style={{ color: sidebar.icon.color }}>
203
233
  {expandedItems.has(item.id) ? (
204
234
  <FaChevronDown className="w-3 h-3" />
205
235
  ) : (
@@ -209,23 +239,22 @@ export default function ITNavbar({
209
239
  )}
210
240
  </div>
211
241
 
212
- {/* Submenu */}
213
- {item.subitems &&
214
- item.subitems.length > 0 &&
242
+ {item.subitems &&
243
+ item.subitems.length > 0 &&
215
244
  expandedItems.has(item.id) && (
216
- <ul className="mt-1 ml-4 pl-4 space-y-1" style={{ borderLeft: "1px solid var(--sidebar-border, #1e293b)" }}>
245
+ <ul className="mt-1 ml-4 pl-4 space-y-1" style={{ borderLeft: `1px solid ${sidebar.borderColor}` }}>
217
246
  {item.subitems.map((subitem) => (
218
247
  <li key={subitem.id}>
219
248
  <button
220
249
  onClick={subitem.action}
221
250
  className="block w-full text-left px-4 py-2.5 rounded-lg text-sm transition-all duration-200"
222
251
  style={{
223
- color: subitem.isActive ? "var(--sidebar-active-color, #ffffff)" : "var(--sidebar-label-color, #94a3b8)",
224
- backgroundColor: subitem.isActive ? "var(--sidebar-active-bg, rgba(255,255,255,0.1))" : "transparent"
252
+ color: subitem.isActive ? sidebar.active.color : sidebar.label.color,
253
+ backgroundColor: subitem.isActive ? sidebar.active.backgroundColor : "transparent"
225
254
  }}
226
255
  onMouseEnter={(e) => {
227
256
  if (!subitem.isActive) {
228
- e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, rgba(255,255,255,0.05))";
257
+ e.currentTarget.style.backgroundColor = sidebar.hover.backgroundColor;
229
258
  }
230
259
  }}
231
260
  onMouseLeave={(e) => {
@@ -247,14 +276,14 @@ export default function ITNavbar({
247
276
 
248
277
  {/* User Menu */}
249
278
  {userMenu && (
250
- <div className="p-4" style={{ borderTop: "1px solid var(--sidebar-border, #1e293b)" }}>
279
+ <div className="p-4" style={{ borderTop: `1px solid ${sidebar.borderColor}` }}>
251
280
  <div className="relative">
252
281
  <button
253
282
  type="button"
254
283
  className="flex items-center gap-3 w-full p-3 rounded-xl transition-colors duration-200 group"
255
- style={{ color: "var(--sidebar-label-color, #94a3b8)" }}
256
- onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, rgba(255,255,255,0.05))"; e.currentTarget.style.color = "var(--sidebar-active-color, #ffffff)"; }}
257
- onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = "transparent"; e.currentTarget.style.color = "var(--sidebar-label-color, #94a3b8)"; }}
284
+ style={{ color: sidebar.label.color }}
285
+ onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = sidebar.hover.backgroundColor; e.currentTarget.style.color = sidebar.active.color; }}
286
+ onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = "transparent"; e.currentTarget.style.color = sidebar.label.color; }}
258
287
  onClick={toggleUserMenu}
259
288
  >
260
289
  {userMenu.userImage ? (
@@ -262,37 +291,40 @@ export default function ITNavbar({
262
291
  className="w-10 h-10 rounded-full border-2 transition-colors"
263
292
  src={userMenu.userImage}
264
293
  alt="user photo"
265
- style={{ borderColor: "var(--sidebar-border, #1e293b)" }}
294
+ style={{ borderColor: sidebar.borderColor }}
266
295
  />
267
296
  ) : (
268
- <div className="w-10 h-10 rounded-full flex items-center justify-center transition-colors" style={{ backgroundColor: "var(--sidebar-hover-bg, rgba(255,255,255,0.1))", color: "var(--sidebar-icon-color, #64748b)" }}>
269
- <FaUserCircle className="w-6 h-6" />
297
+ <div
298
+ className="w-10 h-10 rounded-full flex items-center justify-center transition-colors"
299
+ style={{ backgroundColor: sidebar.hover.backgroundColor, color: sidebar.icon.color }}
300
+ >
301
+ <FaUserCircle className="w-6 h-6" />
270
302
  </div>
271
303
  )}
272
304
  <div className="flex-1 text-left overflow-hidden">
273
- <ITText as="div" className="font-medium text-sm truncate" style={{ color: "var(--sidebar-active-color, #ffffff)" }}>
305
+ <ITText as="div" className="font-medium text-sm truncate" style={{ color: sidebar.active.color }}>
274
306
  {userMenu.userName}
275
307
  </ITText>
276
- <ITText as="div" className="text-xs truncate" style={{ color: "var(--sidebar-label-color, #94a3b8)" }}>
308
+ <ITText as="div" className="text-xs truncate" style={{ color: sidebar.label.color }}>
277
309
  {userMenu.userEmail}
278
310
  </ITText>
279
311
  </div>
280
- <FaChevronRight className="w-3 h-3" style={{ color: "var(--sidebar-icon-color, #64748b)" }} />
312
+ <FaChevronRight className="w-3 h-3" style={{ color: sidebar.icon.color }} />
281
313
  </button>
282
314
 
283
315
  {isUserMenuOpen && (
284
316
  <div
285
317
  ref={userMenuRef}
286
318
  className="absolute bottom-full left-0 mb-3 w-full rounded-xl shadow-2xl overflow-hidden transform transition-all duration-200 origin-bottom"
287
- style={{ backgroundColor: "var(--topbar-user-dropdown-bg, #ffffff)", border: "1px solid var(--topbar-user-dropdown-border, #e2e8f0)" }}
319
+ style={{ backgroundColor: topbar.userMenu.dropdown.backgroundColor, border: `1px solid ${topbar.userMenu.dropdown.borderColor}` }}
288
320
  >
289
- <div className="px-4 py-3" style={{ backgroundColor: "var(--topbar-user-bg, #f8fafc)", borderBottom: "1px solid var(--topbar-user-dropdown-border, #e2e8f0)" }}>
290
- <ITText as="span" className="block text-sm font-semibold" style={{ color: "var(--topbar-user-text, #0f172a)" }}>
291
- {userMenu.userName}
292
- </ITText>
293
- <ITText as="span" className="block text-xs truncate" style={{ color: "var(--topbar-user-subtitle, #64748b)" }}>
294
- {userMenu.userEmail}
295
- </ITText>
321
+ <div className="px-4 py-3" style={{ backgroundColor: topbar.userMenu.backgroundColor, borderBottom: `1px solid ${topbar.userMenu.dropdown.borderColor}` }}>
322
+ <ITText as="span" className="block text-sm font-semibold" style={{ color: topbar.userMenu.textColor }}>
323
+ {userMenu.userName}
324
+ </ITText>
325
+ <ITText as="span" className="block text-xs truncate" style={{ color: topbar.userMenu.subtitleColor }}>
326
+ {userMenu.userEmail}
327
+ </ITText>
296
328
  </div>
297
329
  <ul className="py-1">
298
330
  {userMenu.menuItems.map((item, index) => (
@@ -303,8 +335,8 @@ export default function ITNavbar({
303
335
  setIsUserMenuOpen(false);
304
336
  }}
305
337
  className="flex items-center w-full px-4 py-2.5 text-sm transition-colors"
306
- style={{ color: "var(--topbar-user-text, #334155)" }}
307
- onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = "var(--topbar-user-item-hover, #f8fafc)"; }}
338
+ style={{ color: topbar.userMenu.textColor }}
339
+ onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = topbar.userMenu.dropdown.itemHoverBackground; }}
308
340
  onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = "transparent"; }}
309
341
  >
310
342
  <ITText as="span">{item.label}</ITText>
@@ -320,7 +352,7 @@ export default function ITNavbar({
320
352
  </aside>
321
353
 
322
354
  {/* Main Content */}
323
- <main className="flex-1 overflow-y-auto relative" style={{ backgroundColor: "var(--layout-bg, #f8fafc)" }}>
355
+ <main className="flex-1 overflow-y-auto relative" style={{ backgroundColor: theme.layout.backgroundColor }}>
324
356
  {children}
325
357
  </main>
326
358
  </div>
@@ -0,0 +1,80 @@
1
+ import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
+ import * as Stories from './page.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # ITPage
7
+
8
+ A page template component that wraps an ITPageHeader with content area and built-in state handling for loading, error, and empty states. Provides automatic skeleton placeholders during loading, an error boundary with retry action, and a customizable empty state with action.
9
+
10
+ ## Props
11
+
12
+ | Prop | Type | Default | Description |
13
+ |------|------|---------|-------------|
14
+ | `title` | `string` | `undefined` | Page title passed to the header. |
15
+ | `description` | `string` | `undefined` | Description text shown below the title. |
16
+ | `breadcrumbs` | `ITBreadcrumbItem[]` | `undefined` | Breadcrumb navigation items. |
17
+ | `actions` | `ReactNode` | `undefined` | Action buttons rendered in the header. |
18
+ | `backAction` | `() => void` | `undefined` | Callback for the back button. |
19
+ | `icon` | `ReactNode` | `undefined` | Icon displayed next to the title. |
20
+ | `iconColor` | `string` | `undefined` | Custom color for the icon. |
21
+ | `loading` | `boolean` | `false` | When true, shows skeleton placeholders instead of content. |
22
+ | `error` | `string \| null` | `null` | Error message. When provided, shows an error state with retry button. |
23
+ | `errorTitle` | `string` | `'Error'` | Custom title for the error state. |
24
+ | `errorActionLabel` | `string` | `'Reintentar'` | Label for the retry button in the error state. |
25
+ | `onRetry` | `() => void` | `undefined` | Callback when the retry button is clicked. |
26
+ | `empty` | `boolean` | `false` | When true, shows an empty state placeholder. |
27
+ | `emptyTitle` | `string` | `'Sin datos'` | Custom title for the empty state. |
28
+ | `emptyDescription` | `string` | `undefined` | Custom description for the empty state. |
29
+ | `emptyAction` | `ReactNode` | `undefined` | Custom action element for the empty state. |
30
+ | `children` | `ReactNode` | required | Content rendered when no special state (loading/error/empty) is active. |
31
+ | `maxWidth` | `'2xl' \| '3xl' \| '4xl' \| '5xl' \| '6xl' \| '7xl'` | `'7xl'` | Maximum width of the page content container. |
32
+ | `noPadding` | `boolean` | `false` | When true, removes default padding from the page wrapper. |
33
+ | `className` | `string` | `undefined` | Additional CSS classes for the page wrapper. |
34
+
35
+ ## Usage
36
+
37
+ ```tsx
38
+ import { ITPage } from '@axzydev/axzy_ui_system';
39
+
40
+ <ITPage title="Users" description="Manage system users" actions={<ITButton label="Add" />}>
41
+ <p>Your page content</p>
42
+ </ITPage>
43
+
44
+ <ITPage title="Dashboard" loading>
45
+ <p>Content not shown while loading</p>
46
+ </ITPage>
47
+
48
+ <ITPage
49
+ title="Orders"
50
+ error="Failed to load orders"
51
+ onRetry={() => refetch()}
52
+ >
53
+ <p>Content not shown while error</p>
54
+ </ITPage>
55
+
56
+ <ITPage
57
+ title="Notifications"
58
+ empty
59
+ emptyTitle="No notifications"
60
+ emptyAction={<ITButton label="Refresh" />}
61
+ >
62
+ <p>Content not shown while empty</p>
63
+ </ITPage>
64
+ ```
65
+
66
+ ## Notes
67
+
68
+ - State priority: `error` > `loading` > `empty` > `children`.
69
+ - The loading state renders animated skeleton blocks matching common page patterns.
70
+ - The error state renders a centered error icon, message, and a retry button.
71
+ - The empty state renders a centered placeholder with optional title, description, and action.
72
+ - All header props (`title`, `description`, `breadcrumbs`, `actions`, `backAction`, `icon`) are forwarded to ITPageHeader.
73
+ - Content maximum width is controlled by Tailwind max-width classes via `maxWidth`.
74
+ - `noPadding` is useful for full-bleed layouts like dashboards.
75
+
76
+ ## Stories
77
+
78
+ <Primary />
79
+ <Controls />
80
+ <Stories />
@@ -1,21 +1,46 @@
1
1
  import { ReactNode } from "react";
2
2
  import { ITBreadcrumbItem } from "../breadcrumbs/breadcrumbs.props";
3
3
 
4
+ /** Props for the ITPage component. */
4
5
  export interface ITPageProps {
6
+ /** Page title passed to the header. */
5
7
  title?: string;
8
+ /** Description text shown below the title. */
6
9
  description?: string;
10
+ /** Array of breadcrumb items for navigation context. */
7
11
  breadcrumbs?: ITBreadcrumbItem[];
12
+ /** Action buttons rendered in the header. */
8
13
  actions?: ReactNode;
14
+ /** Callback fired when the back button is clicked. */
9
15
  backAction?: () => void;
16
+ /** Optional icon displayed next to the title. */
17
+ icon?: ReactNode;
18
+ /** Custom color for the icon. Accepts any valid CSS color value. */
19
+ iconColor?: string;
20
+ /** Whether the page is in a loading state. Shows skeleton placeholders when true. */
10
21
  loading?: boolean;
22
+ /** Error message to display. Shows an error state with retry button when provided. */
11
23
  error?: string | null;
24
+ /** Custom title for the error state. Default: "Error". */
12
25
  errorTitle?: string;
26
+ /** Label for the retry button in the error state. Default: "Reintentar". */
13
27
  errorActionLabel?: string;
28
+ /** Callback fired when the retry button is clicked in the error state. */
14
29
  onRetry?: () => void;
30
+ /** Whether the page is in an empty state. Shows a placeholder when true. */
15
31
  empty?: boolean;
32
+ /** Custom title for the empty state. Default: "Sin datos". */
16
33
  emptyTitle?: string;
34
+ /** Custom description for the empty state. */
17
35
  emptyDescription?: string;
36
+ /** Custom action element for the empty state. */
18
37
  emptyAction?: ReactNode;
38
+ /** Additional CSS classes for the page wrapper. */
19
39
  className?: string;
40
+ /** Content rendered inside the page wrapper. */
20
41
  children: ReactNode;
42
+ /** Maximum width of the page content. Options: "2xl", "3xl", "4xl", "5xl", "6xl", "7xl". Default: "7xl". */
43
+ maxWidth?: "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "7xl";
44
+ /** Whether to remove default padding from the page wrapper. */
45
+ noPadding?: boolean;
21
46
  }
@@ -7,7 +7,7 @@ import ITButton from "../button/button";
7
7
  import ITStack from "../stack/stack";
8
8
 
9
9
  const hasHeader = (props: ITPageProps) =>
10
- !!(props.title || props.description || props.breadcrumbs || props.actions || props.backAction);
10
+ !!(props.title || props.description || props.breadcrumbs || props.actions || props.backAction || props.icon);
11
11
 
12
12
  const renderHeader = (props: ITPageProps) => {
13
13
  if (!hasHeader(props)) return null;
@@ -18,10 +18,30 @@ const renderHeader = (props: ITPageProps) => {
18
18
  breadcrumbs={props.breadcrumbs}
19
19
  actions={props.actions}
20
20
  backAction={props.backAction}
21
+ icon={props.icon}
22
+ iconColor={props.iconColor}
21
23
  />
22
24
  );
23
25
  };
24
26
 
27
+ /**
28
+ * Page template combining a page header and content area with built-in states for loading, error, and empty.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * <ITPage
33
+ * title="Dashboard"
34
+ * description="Overview of your account"
35
+ * breadcrumbs={[{ label: 'Home' }, { label: 'Dashboard' }]}
36
+ * actions={<ITButton label="Refresh" />}
37
+ * loading={isLoading}
38
+ * error={errorMessage}
39
+ * onRetry={fetchData}
40
+ * >
41
+ * <ITCard>Dashboard content</ITCard>
42
+ * </ITPage>
43
+ * ```
44
+ */
25
45
  export default function ITPage(props: ITPageProps) {
26
46
  const {
27
47
  loading = false,
@@ -35,18 +55,26 @@ export default function ITPage(props: ITPageProps) {
35
55
  emptyAction,
36
56
  className,
37
57
  children,
58
+ maxWidth = "7xl",
59
+ noPadding = false,
38
60
  } = props;
39
61
 
40
- const wrapperClass = clsx("space-y-6", className);
62
+ const wrapperClass = clsx(
63
+ "mx-auto w-full",
64
+ !noPadding && "px-4 sm:px-6 lg:px-8 py-6",
65
+ `max-w-${maxWidth}`,
66
+ "space-y-8",
67
+ className
68
+ );
41
69
 
42
70
  if (loading) {
43
71
  return (
44
72
  <div className={wrapperClass}>
45
73
  {renderHeader(props)}
46
- <ITStack spacing={4}>
47
- <ITSkeleton variant="rectangular" height={40} width="40%" />
48
- <ITSkeleton variant="rectangular" height={200} />
49
- <ITSkeleton variant="rectangular" height={200} />
74
+ <ITStack spacing={6}>
75
+ <ITSkeleton variant="rectangular" height={40} width="40%" className="rounded-lg" />
76
+ <ITSkeleton variant="rectangular" height={200} className="rounded-lg" />
77
+ <ITSkeleton variant="rectangular" height={200} className="rounded-lg" />
50
78
  </ITStack>
51
79
  </div>
52
80
  );
@@ -92,4 +120,4 @@ export default function ITPage(props: ITPageProps) {
92
120
  {children}
93
121
  </div>
94
122
  );
95
- }
123
+ }
@@ -0,0 +1,54 @@
1
+ import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
+ import * as Stories from './page-header.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # ITPageHeader
7
+
8
+ A page title bar component that displays a heading with optional breadcrumbs, description text, action buttons, and a back navigation button. Designed to sit at the top of page content for consistent page-level navigation.
9
+
10
+ ## Props
11
+
12
+ | Prop | Type | Default | Description |
13
+ |------|------|---------|-------------|
14
+ | `title` | `string` | required | Page title displayed as the main heading. |
15
+ | `description` | `string` | `undefined` | Optional description text shown below the title. |
16
+ | `breadcrumbs` | `ITBreadcrumbItem[]` | `undefined` | Breadcrumb navigation items above the title. |
17
+ | `actions` | `ReactNode` | `undefined` | Action buttons or elements rendered on the right side. |
18
+ | `backAction` | `() => void` | `undefined` | Callback fired when the back button is clicked. |
19
+ | `icon` | `ReactNode` | `undefined` | Optional icon displayed next to the title. |
20
+ | `iconColor` | `string` | `undefined` | Custom CSS color value for the icon. |
21
+ | `className` | `string` | `undefined` | Additional CSS classes for the container. |
22
+
23
+ ## Usage
24
+
25
+ ```tsx
26
+ import { ITPageHeader } from '@axzydev/axzy_ui_system';
27
+ import { FaUsers } from 'react-icons/fa';
28
+
29
+ <ITPageHeader
30
+ title="Users"
31
+ description="Manage system users"
32
+ breadcrumbs={[{ label: 'Dashboard', href: '#' }, { label: 'Users' }]}
33
+ actions={<ITButton label="Add User" />}
34
+ />
35
+ <ITPageHeader
36
+ title="Edit User"
37
+ backAction={() => navigate(-1)}
38
+ breadcrumbs={[{ label: 'Users', href: '/users' }, { label: 'Edit' }]}
39
+ />
40
+ ```
41
+
42
+ ## Notes
43
+
44
+ - Breadcrumbs render above the title using the ITBreadcrumbs component.
45
+ - `backAction` renders a left-arrow button before the content; breadcrumbs shift to the right of the back button.
46
+ - The `icon` slot places an icon beside the title, colored by `iconColor` or the primary theme color.
47
+ - Actions area accepts any React nodes; typically ITButton components with `small` sizing.
48
+ - The component uses a flex layout: breadcrumbs + back button on the left, actions on the right.
49
+
50
+ ## Stories
51
+
52
+ <Primary />
53
+ <Controls />
54
+ <Stories />
@@ -1,11 +1,22 @@
1
1
  import { ReactNode } from "react";
2
2
  import { ITBreadcrumbItem } from "../breadcrumbs/breadcrumbs.props";
3
3
 
4
+ /** Props for the ITPageHeader component. */
4
5
  export interface ITPageHeaderProps {
6
+ /** Page title displayed as the main heading. */
5
7
  title: string;
8
+ /** Optional description text shown below the title. */
6
9
  description?: string;
10
+ /** Array of breadcrumb items for navigation context. */
7
11
  breadcrumbs?: ITBreadcrumbItem[];
12
+ /** Action buttons or elements rendered on the right side. */
8
13
  actions?: ReactNode;
14
+ /** Callback fired when the back button is clicked. */
9
15
  backAction?: () => void;
16
+ /** Optional icon displayed next to the title. */
17
+ icon?: ReactNode;
18
+ /** Custom color for the icon. Accepts any valid CSS color value. */
19
+ iconColor?: string;
20
+ /** Additional CSS classes for the container. */
10
21
  className?: string;
11
22
  }
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { FaUsers } from "react-icons/fa";
2
3
  import ITPageHeader from "./page-header";
3
4
  import ITButton from "../button/button";
4
5
 
@@ -59,3 +60,16 @@ export const WithBackAction: Story = {
59
60
  actions: <ITButton label="Editar" size="small" />,
60
61
  },
61
62
  };
63
+
64
+ export const WithIcon: Story = {
65
+ args: {
66
+ title: "Usuarios",
67
+ description: "Gestiona los usuarios del sistema",
68
+ icon: <FaUsers size={20} />,
69
+ iconColor: "#6366f1",
70
+ breadcrumbs: [
71
+ { label: "Inicio", href: "#" },
72
+ { label: "Usuarios" },
73
+ ],
74
+ },
75
+ };