@axzydev/axzy_ui_system 1.4.7 → 1.5.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.
Files changed (226) hide show
  1. package/README.md +2 -11
  2. package/dist/index.cjs +2174 -1570
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +1 -1
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.cts +232 -19
  7. package/dist/index.d.ts +232 -19
  8. package/dist/index.js +1838 -1238
  9. package/dist/index.js.map +1 -1
  10. package/dist/layered.css +1 -1
  11. package/package.json +3 -16
  12. package/src/App.tsx +90 -73
  13. package/src/components/atoms/badget/badget.tsx +23 -5
  14. package/src/components/atoms/chip/chip.tsx +3 -1
  15. package/src/components/atoms/image/image.tsx +3 -1
  16. package/src/components/atoms/input/input.tsx +8 -5
  17. package/src/components/atoms/loader/loader.tsx +3 -1
  18. package/src/components/atoms/slide/slide.props.ts +12 -0
  19. package/src/components/atoms/slide/slide.tsx +3 -0
  20. package/src/components/molecules/alert/alert.tsx +3 -1
  21. package/src/components/molecules/breadcrumbs/breadcrumbs.tsx +3 -1
  22. package/src/components/molecules/calendar/calendar.tsx +9 -6
  23. package/src/components/molecules/card/card.tsx +5 -2
  24. package/src/components/molecules/chip-input/chip-input.tsx +9 -7
  25. package/src/components/molecules/date-picker/datePicker.tsx +9 -9
  26. package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +1 -1
  27. package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +6 -3
  28. package/src/components/molecules/field/field.tsx +3 -1
  29. package/src/components/molecules/form-header/form-header.tsx +3 -1
  30. package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +2 -2
  31. package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +20 -15
  32. package/src/components/molecules/masked-input/masked-input.tsx +3 -1
  33. package/src/components/molecules/multi-select/multi-select.tsx +12 -9
  34. package/src/components/molecules/pagination/pagination.tsx +11 -5
  35. package/src/components/molecules/search-select/search-select.tsx +11 -9
  36. package/src/components/molecules/select/select.tsx +6 -4
  37. package/src/components/molecules/stepper/stepper.tsx +6 -4
  38. package/src/components/molecules/table/table.props.ts +10 -2
  39. package/src/components/molecules/table/table.tsx +163 -114
  40. package/src/components/molecules/time-picker/timePicker.tsx +8 -6
  41. package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
  42. package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
  43. package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
  44. package/src/components/organisms/data-table/dataTable.props.ts +3 -2
  45. package/src/components/organisms/data-table/dataTable.tsx +149 -81
  46. package/src/components/organisms/dialog/dialog.tsx +3 -0
  47. package/src/components/organisms/drawer/drawer.tsx +3 -0
  48. package/src/components/organisms/dropfile/dropfile.tsx +19 -17
  49. package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
  50. package/src/components/organisms/navbar/navbar.tsx +4 -2
  51. package/src/components/organisms/page-header/page-header.tsx +3 -1
  52. package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
  53. package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
  54. package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
  55. package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
  56. package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
  57. package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
  58. package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
  59. package/src/components/organisms/searchTable/searchTable.tsx +4 -2
  60. package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
  61. package/src/components/organisms/sidebar/sidebar.tsx +9 -4
  62. package/src/components/organisms/toast/toast.tsx +3 -1
  63. package/src/components/organisms/topbar/topbar.tsx +4 -2
  64. package/src/components/templates/page/page.props.ts +4 -4
  65. package/src/components/templates/page/page.tsx +6 -4
  66. package/src/components/theme-provider/themeProvider.tsx +28 -17
  67. package/src/dev.css +77 -2
  68. package/src/global.d.ts +10 -0
  69. package/src/i18n/context.ts +9 -0
  70. package/src/i18n/index.ts +22 -0
  71. package/src/i18n/locales/en.ts +163 -0
  72. package/src/i18n/locales/es.ts +165 -0
  73. package/src/i18n/provider.tsx +44 -0
  74. package/src/i18n/translator.ts +82 -0
  75. package/src/i18n/types.ts +54 -0
  76. package/src/i18n/useITTranslation.ts +20 -0
  77. package/src/index.css +0 -1
  78. package/src/index.ts +9 -3
  79. package/src/sandbox/LandingShowcase.tsx +224 -580
  80. package/src/sandbox/NotFoundShowcase.tsx +51 -36
  81. package/src/sandbox/TopbarSearch.tsx +6 -4
  82. package/src/sandbox/controls.tsx +180 -0
  83. package/src/sandbox/i18n.ts +1929 -0
  84. package/src/sandbox/icons.tsx +25 -0
  85. package/src/sandbox/locale.tsx +72 -0
  86. package/src/sandbox/ui.tsx +377 -0
  87. package/src/sandbox/useHashRoute.ts +46 -10
  88. package/src/showcases/DataShowcases.tsx +201 -80
  89. package/src/showcases/FeedbackShowcases.tsx +37 -30
  90. package/src/showcases/FormShowcases.tsx +302 -214
  91. package/src/showcases/GettingStartedShowcase.tsx +151 -145
  92. package/src/showcases/HelpShowcase.tsx +126 -128
  93. package/src/showcases/HomeShowcase.tsx +678 -482
  94. package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
  95. package/src/showcases/NavigationShowcases.tsx +45 -37
  96. package/src/showcases/PageShowcases.tsx +171 -152
  97. package/src/showcases/ProductoDetalle.tsx +272 -129
  98. package/src/showcases/ShowcaseLayout.tsx +270 -216
  99. package/src/showcases/SizesShowcase.tsx +123 -64
  100. package/src/showcases/StructureShowcases.tsx +157 -131
  101. package/src/showcases/portfolioUi.tsx +153 -0
  102. package/src/showcases/techIcons.ts +3 -0
  103. package/src/types/table.types.ts +110 -0
  104. package/src/utils/table.utils.ts +10 -2
  105. package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
  106. package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
  107. package/src/components/atoms/badget/badget.doc.mdx +0 -46
  108. package/src/components/atoms/badget/badget.stories.tsx +0 -75
  109. package/src/components/atoms/button/button.doc.mdx +0 -59
  110. package/src/components/atoms/button/button.stories.tsx +0 -173
  111. package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
  112. package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
  113. package/src/components/atoms/chip/chip.doc.mdx +0 -47
  114. package/src/components/atoms/chip/chip.stories.tsx +0 -64
  115. package/src/components/atoms/divider/divider.doc.mdx +0 -42
  116. package/src/components/atoms/divider/divider.stories.tsx +0 -33
  117. package/src/components/atoms/flex/flex.doc.mdx +0 -59
  118. package/src/components/atoms/flex/flex.stories.tsx +0 -70
  119. package/src/components/atoms/grid/grid.doc.mdx +0 -54
  120. package/src/components/atoms/grid/grid.stories.tsx +0 -71
  121. package/src/components/atoms/image/image.doc.mdx +0 -44
  122. package/src/components/atoms/image/image.stories.tsx +0 -48
  123. package/src/components/atoms/input/input.doc.mdx +0 -70
  124. package/src/components/atoms/input/input.stories.tsx +0 -113
  125. package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
  126. package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
  127. package/src/components/atoms/loader/loader.doc.mdx +0 -43
  128. package/src/components/atoms/loader/loader.stories.tsx +0 -104
  129. package/src/components/atoms/popover/popover.doc.mdx +0 -53
  130. package/src/components/atoms/popover/popover.stories.tsx +0 -24
  131. package/src/components/atoms/progress/progress.doc.mdx +0 -48
  132. package/src/components/atoms/progress/progress.stories.tsx +0 -39
  133. package/src/components/atoms/radio/radio.doc.mdx +0 -62
  134. package/src/components/atoms/radio/radio.stories.tsx +0 -48
  135. package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
  136. package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
  137. package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
  138. package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
  139. package/src/components/atoms/slide/slide.doc.mdx +0 -46
  140. package/src/components/atoms/slide/slide.stories.tsx +0 -120
  141. package/src/components/atoms/slider/slider.doc.mdx +0 -49
  142. package/src/components/atoms/slider/slider.stories.tsx +0 -29
  143. package/src/components/atoms/stack/stack.doc.mdx +0 -126
  144. package/src/components/atoms/stack/stack.stories.tsx +0 -283
  145. package/src/components/atoms/text/text.doc.mdx +0 -41
  146. package/src/components/atoms/text/text.stories.tsx +0 -66
  147. package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
  148. package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
  149. package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
  150. package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
  151. package/src/components/isolation/isolation.stories.tsx +0 -202
  152. package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
  153. package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
  154. package/src/components/molecules/alert/alert.doc.mdx +0 -48
  155. package/src/components/molecules/alert/alert.stories.tsx +0 -40
  156. package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
  157. package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
  158. package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
  159. package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
  160. package/src/components/molecules/card/card.doc.mdx +0 -54
  161. package/src/components/molecules/card/card.stories.tsx +0 -57
  162. package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
  163. package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
  164. package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
  165. package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
  166. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
  167. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
  168. package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
  169. package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
  170. package/src/components/molecules/field/field.doc.mdx +0 -43
  171. package/src/components/molecules/field/field.stories.tsx +0 -42
  172. package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
  173. package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
  174. package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
  175. package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
  176. package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
  177. package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
  178. package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
  179. package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
  180. package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
  181. package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
  182. package/src/components/molecules/select/select.doc.mdx +0 -75
  183. package/src/components/molecules/select/select.stories.tsx +0 -85
  184. package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
  185. package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
  186. package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
  187. package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
  188. package/src/components/molecules/table/table.doc.mdx +0 -123
  189. package/src/components/molecules/table/table.stories.tsx +0 -402
  190. package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
  191. package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
  192. package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
  193. package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
  194. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
  195. package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
  196. package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
  197. package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -115
  198. package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
  199. package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
  200. package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
  201. package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
  202. package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
  203. package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
  204. package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
  205. package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
  206. package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
  207. package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
  208. package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
  209. package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
  210. package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
  211. package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
  212. package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
  213. package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
  214. package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
  215. package/src/components/organisms/toast/toast.doc.mdx +0 -50
  216. package/src/components/organisms/toast/toast.stories.tsx +0 -137
  217. package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
  218. package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
  219. package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
  220. package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
  221. package/src/components/templates/layout/layout.doc.mdx +0 -53
  222. package/src/components/templates/layout/layout.stories.tsx +0 -113
  223. package/src/components/templates/page/page.doc.mdx +0 -86
  224. package/src/components/templates/page/page.stories.tsx +0 -97
  225. package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
  226. package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
@@ -6,6 +6,7 @@ import ITText from "@/components/atoms/text/text";
6
6
  import ITButton from "@/components/atoms/button/button";
7
7
  import ITDialog from "@/components/organisms/dialog/dialog";
8
8
  import { ITDropfileProps, FileTypeEnum, UploadStatus } from "./dropfile.props";
9
+ import { useITTranslation } from "@/i18n";
9
10
  export { FileTypeEnum, UploadStatus } from "./dropfile.props";
10
11
 
11
12
  /**
@@ -50,9 +51,10 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
50
51
  onStatusChange,
51
52
  initialPreviewUrl,
52
53
  view = "drop",
53
- buttonLabel = "Subir archivo",
54
+ buttonLabel,
54
55
  modalTitle,
55
56
  }) => {
57
+ const { t } = useITTranslation();
56
58
  const [isModalOpen, setIsModalOpen] = useState(false);
57
59
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
58
60
  const [fileType, setFileType] = useState<string | null>(null);
@@ -172,22 +174,22 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
172
174
  const StatusBadge = ({ status }: { status: UploadStatus }) => {
173
175
  const config = {
174
176
  [UploadStatus.PENDING]: {
175
- label: "Pendiente",
177
+ label: t("dropfile.status.pending"),
176
178
  color: "bg-warning-100 text-warning-800 border-warning-200",
177
179
  dotColor: "bg-warning-400",
178
180
  },
179
181
  [UploadStatus.UPLOADING]: {
180
- label: "Subiendo...",
182
+ label: t("dropfile.status.uploading"),
181
183
  color: "bg-primary-100 text-primary-800 border-primary-200",
182
184
  dotColor: "bg-primary-400 animate-pulse",
183
185
  },
184
186
  [UploadStatus.UPLOADED]: {
185
- label: "Subido",
187
+ label: t("dropfile.status.uploaded"),
186
188
  color: "bg-success-100 text-success-800 border-success-200",
187
189
  dotColor: "bg-success-400",
188
190
  },
189
191
  [UploadStatus.ERROR]: {
190
- label: "Error",
192
+ label: t("dropfile.status.error"),
191
193
  color: "bg-danger-100 text-danger-800 border-danger-200",
192
194
  dotColor: "bg-danger-400",
193
195
  },
@@ -223,7 +225,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
223
225
  setImagePreview(previewUrl);
224
226
  }
225
227
  } else {
226
- alert(`Tipo de archivo no permitido.`);
228
+ alert(t("dropfile.fileTypeNotAllowed"));
227
229
  setSelectedFile(null);
228
230
  setFileType(null);
229
231
  setImagePreview(null);
@@ -318,7 +320,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
318
320
  const headerRow = (
319
321
  <div className="flex items-center justify-between mb-2">
320
322
  <label className="block text-sm font-semibold text-secondary-700">
321
- <ITText as="span">Subir archivo </ITText><ITText as="span" className="text-secondary-400 font-normal text-xs">({getFileExtensions()})</ITText>
323
+ <ITText as="span">{t("dropfile.upload")} </ITText><ITText as="span" className="text-secondary-400 font-normal text-xs">({getFileExtensions()})</ITText>
322
324
  </label>
323
325
 
324
326
  {showStatusBadge && selectedFile && (
@@ -355,7 +357,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
355
357
 
356
358
  <div className="text-center space-y-1">
357
359
  <ITText as="p" className={`text-sm font-medium transition-colors duration-300 ${isDragActive ? 'text-primary-700' : 'text-secondary-700'}`}>
358
- {isDragActive ? "¡Suelta aquí!" : "Haz clic o arrastra"}
360
+ {isDragActive ? t("dropfile.dropHere") : t("dropfile.clickOrDrag")}
359
361
  </ITText>
360
362
  </div>
361
363
  </div>
@@ -375,8 +377,8 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
375
377
  )}
376
378
  </div>
377
379
  <div className="min-w-0">
378
- <ITText as="p" className="text-xs font-medium text-secondary-900 truncate" title={selectedFile?.name || "Imagen cargada"}>
379
- {selectedFile?.name || "Imagen cargada"}
380
+ <ITText as="p" className="text-xs font-medium text-secondary-900 truncate" title={selectedFile?.name || t("dropfile.imageLoaded")}>
381
+ {selectedFile?.name || t("dropfile.imageLoaded")}
380
382
  </ITText>
381
383
  <ITText as="p" className="text-[10px] text-secondary-500">
382
384
  {selectedFile ? (selectedFile.size / 1024 / 1024).toFixed(2) + " MB" : ""}
@@ -389,7 +391,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
389
391
  {((selectedFile && fileType?.startsWith('image/')) || (!selectedFile && imagePreview)) ? (
390
392
  <img
391
393
  src={imagePreview}
392
- alt="Vista previa"
394
+ alt={t("dropfile.previewAlt")}
393
395
  className="w-full h-full object-contain max-h-[200px]"
394
396
  />
395
397
  ) : (
@@ -397,7 +399,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
397
399
  <svg className="w-10 h-10 mb-2 opacity-50" fill="none" viewBox="0 0 24 24" stroke="currentColor">
398
400
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
399
401
  </svg>
400
- <ITText as="span" className="text-xs">Sin vista previa</ITText>
402
+ <ITText as="span" className="text-xs">{t("dropfile.noPreview")}</ITText>
401
403
  </div>
402
404
  )}
403
405
  </div>
@@ -412,7 +414,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
412
414
  size="sm"
413
415
  onClick={handleCancel}
414
416
  >
415
- <ITText>Cancelar</ITText>
417
+ <ITText>{t("common.cancel")}</ITText>
416
418
  </ITButton>
417
419
  <ITButton
418
420
  type="button"
@@ -422,7 +424,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
422
424
  onClick={handleConfirm}
423
425
  >
424
426
  <div className="flex items-center gap-2">
425
- <ITText>Confirmar</ITText>
427
+ <ITText>{t("common.confirm")}</ITText>
426
428
  <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
427
429
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
428
430
  </svg>
@@ -440,7 +442,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
440
442
  <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
441
443
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
442
444
  </svg>
443
- <ITText>Eliminar</ITText>
445
+ <ITText>{t("common.delete")}</ITText>
444
446
  </ITButton>
445
447
  )}
446
448
  </div>
@@ -479,13 +481,13 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
479
481
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
480
482
  </svg>
481
483
  <ITText className="truncate">
482
- {selectedFile?.name || (hasFile ? "Archivo cargado" : buttonLabel)}
484
+ {selectedFile?.name || (hasFile ? t("dropfile.fileLoaded") : (buttonLabel ?? t("dropfile.upload")))}
483
485
  </ITText>
484
486
  {showStatusBadge && hasFile && <StatusBadge status={uploadStatus} />}
485
487
  </div>
486
488
  </ITButton>
487
489
 
488
- <ITDialog isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title={modalTitle ?? buttonLabel}>
490
+ <ITDialog isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title={modalTitle ?? buttonLabel ?? t("dropfile.upload")}>
489
491
  <div className="w-full transition-all duration-300">
490
492
  {headerRow}
491
493
  {dropZoneOrPreview}
@@ -11,6 +11,7 @@ import { useFieldRules } from "./useFormBuilder";
11
11
  import { getColSpanClass, getGridColsClass } from "@/utils/styles";
12
12
  import ITText from "@/components/atoms/text/text";
13
13
  import { FaSpinner } from "react-icons/fa";
14
+ import { useITTranslation } from "@/i18n";
14
15
 
15
16
  /**
16
17
  * Resolves `FieldConfigV2["options"]` to a stable `{ value, label }[]` array,
@@ -123,6 +124,7 @@ const ITFieldRenderer = ({
123
124
  dependentValues = {},
124
125
  }: ITFieldRendererProps) => {
125
126
  const context = useITFormBuilderContext();
127
+ const { t } = useITTranslation();
126
128
  const { isVisible, isRequired, isDisabled, dynamicProps } = useFieldRules(
127
129
  config,
128
130
  dependentValues,
@@ -220,7 +222,7 @@ const ITFieldRenderer = ({
220
222
  >
221
223
  <FaSpinner className="animate-spin text-primary-500" />
222
224
  <ITText as="span" className="text-sm text-slate-500">
223
- Cargando opciones...
225
+ {t("formBuilder.loadingOptions")}
224
226
  </ITText>
225
227
  </div>
226
228
  );
@@ -366,7 +368,7 @@ const ITFieldRenderer = ({
366
368
  return (
367
369
  <div className="p-4 border-2 border-dashed border-secondary-200 rounded-xl">
368
370
  <ITText as="p" className="text-sm text-secondary-500 text-center">
369
- Array Field: {label}
371
+ {t("formBuilder.arrayField", { label: label ?? "" })}
370
372
  </ITText>
371
373
  </div>
372
374
  );
@@ -4,6 +4,7 @@ import { FaChevronDown, FaChevronRight, FaUserCircle } from "react-icons/fa";
4
4
  import { ITNavbarProps, ITNavigationItem } from "./navbar.props";
5
5
  import ITText from "@/components/atoms/text/text";
6
6
  import { theme } from "@/theme/theme";
7
+ import { useITTranslation } from "@/i18n";
7
8
 
8
9
  /**
9
10
  * Full sidebar navigation shell with collapsible submenus, user menu dropdown, and themed styling.
@@ -44,6 +45,7 @@ export default function ITNavbar({
44
45
  showSidebarOnMobile = false,
45
46
  sidebarItems,
46
47
  }: ITNavbarProps) {
48
+ const { t } = useITTranslation();
47
49
  const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
48
50
  const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
49
51
 
@@ -106,7 +108,7 @@ export default function ITNavbar({
106
108
  <img
107
109
  className="w-8 h-8 rounded-full"
108
110
  src={userMenu.userImage}
109
- alt="user photo"
111
+ alt={t("common.userAvatar")}
110
112
  />
111
113
  ) : (
112
114
  <FaUserCircle className="w-8 h-8 text-secondary-500" />
@@ -290,7 +292,7 @@ export default function ITNavbar({
290
292
  <img
291
293
  className="w-10 h-10 rounded-full border-2 transition-colors"
292
294
  src={userMenu.userImage}
293
- alt="user photo"
295
+ alt={t("common.userAvatar")}
294
296
  style={{ borderColor: sidebar.borderColor }}
295
297
  />
296
298
  ) : (
@@ -3,6 +3,7 @@ import { ITPageHeaderProps } from "./page-header.props";
3
3
  import ITBreadcrumbs from "@/components/molecules/breadcrumbs/breadcrumbs";
4
4
  import ITText from "@/components/atoms/text/text";
5
5
  import { useITFlatAppearance } from "@/theme/theme-context";
6
+ import { useITTranslation } from "@/i18n";
6
7
 
7
8
  /**
8
9
  * Page title bar with breadcrumbs, description, back button, and action buttons.
@@ -29,6 +30,7 @@ export default function ITPageHeader({
29
30
  iconColor,
30
31
  className,
31
32
  }: ITPageHeaderProps) {
33
+ const { t } = useITTranslation();
32
34
  const showTopRow = breadcrumbs?.length || backAction;
33
35
  // Flat appearance: compact title, no decorative icon tile.
34
36
  const flat = useITFlatAppearance();
@@ -43,7 +45,7 @@ export default function ITPageHeader({
43
45
  <button
44
46
  onClick={backAction}
45
47
  className="flex items-center justify-center w-9 h-9 rounded-full border border-slate-200 dark:border-slate-700 text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:border-slate-300 dark:hover:border-slate-600 hover:bg-slate-50 dark:hover:bg-slate-800/60 transition-all duration-200 flex-shrink-0"
46
- aria-label="Volver"
48
+ aria-label={t("pageHeader.back")}
47
49
  >
48
50
  <FaChevronLeft size={14} />
49
51
  </button>
@@ -4,6 +4,7 @@ import PaginationInfo from "./PaginationInfo";
4
4
  import ITSelect from "@/components/molecules/select/select";
5
5
  import ITButton from "@/components/atoms/button/button";
6
6
  import ITText from "@/components/atoms/text/text";
7
+ import { useITTranslation } from "@/i18n";
7
8
 
8
9
  interface PaginationControlsProps {
9
10
  pageIndex: number;
@@ -30,13 +31,14 @@ export default function PaginationControls({
30
31
  currentCount,
31
32
  totalCount,
32
33
  }: PaginationControlsProps) {
34
+ const { t } = useITTranslation();
33
35
  return (
34
36
  <div className="flex flex-col sm:flex-row justify-between items-center gap-4">
35
37
  <div className="flex items-center space-x-4">
36
38
  <PaginationInfo currentCount={currentCount} totalCount={totalCount} />
37
39
 
38
40
  <div className="flex items-center space-x-2">
39
- <ITText as="span" className="text-sm text-secondary-700">Mostrar:</ITText>
41
+ <ITText as="span" className="text-sm text-secondary-700">{t("searchTable.showLabel")}</ITText>
40
42
  <ITSelect
41
43
  name="itemsPerPage"
42
44
  options={itemsPerPageOptions.map((option) => ({
@@ -59,14 +61,14 @@ export default function PaginationControls({
59
61
  onClick={() => onPageChange(pageIndex - 1)}
60
62
  disabled={!hasPreviousPage}
61
63
  className="min-w-[32px]"
62
- ariaLabel="Página anterior"
63
- title="Ir a la página anterior"
64
+ ariaLabel={t("searchTable.prev")}
65
+ title={t("searchTable.prev")}
64
66
  >
65
67
  <FaArrowLeft aria-hidden="true" />
66
68
  </ITButton>
67
69
 
68
70
  <ITText as="span" className="px-4 py-2 text-sm text-secondary-700" aria-live="polite">
69
- Página {pageIndex} de {totalPages}
71
+ {t("searchTable.pageOf", { current: pageIndex, total: totalPages })}
70
72
  </ITText>
71
73
 
72
74
  <ITButton
@@ -75,8 +77,8 @@ export default function PaginationControls({
75
77
  onClick={() => onPageChange(pageIndex + 1)}
76
78
  disabled={!hasNextPage}
77
79
  className="min-w-[32px]"
78
- ariaLabel="Página siguiente"
79
- title="Ir a la página siguiente"
80
+ ariaLabel={t("searchTable.next")}
81
+ title={t("searchTable.next")}
80
82
  >
81
83
  <FaArrowRight aria-hidden="true" />
82
84
  </ITButton>
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import ITText from "@/components/atoms/text/text";
3
+ import { useITTranslation } from "@/i18n";
3
4
 
4
5
  interface PaginationInfoProps {
5
6
  currentCount: number;
@@ -12,9 +13,10 @@ export default function PaginationInfo({
12
13
  totalCount,
13
14
  className = "",
14
15
  }: PaginationInfoProps) {
16
+ const { t } = useITTranslation();
15
17
  return (
16
18
  <ITText as="span" className={`text-sm text-secondary-700 ${className}`}>
17
- Mostrando {currentCount} de {totalCount} resultados
19
+ {t("searchTable.showingCount", { from: currentCount, total: totalCount })}
18
20
  </ITText>
19
21
  );
20
22
  }
@@ -3,6 +3,7 @@ import SearchInput from "./SearchInput";
3
3
  import SortButton from "./SortButton";
4
4
  import ITButton from "@/components/atoms/button/button";
5
5
  import ITText from "@/components/atoms/text/text";
6
+ import { useITTranslation } from "@/i18n";
6
7
 
7
8
  interface SearchAndSortBarProps {
8
9
  searchTerm: string;
@@ -22,13 +23,14 @@ export default function SearchAndSortBar({
22
23
  onClearSearch,
23
24
  onGlobalSort,
24
25
  sortConfig,
25
- searchInputPlaceholder = "Buscar en todos los campos...",
26
+ searchInputPlaceholder,
26
27
  }: SearchAndSortBarProps) {
28
+ const { t } = useITTranslation();
27
29
  return (
28
30
  <div className="bg-secondary-50 px-6 py-4 border-b border-secondary-200">
29
31
  <div className="flex items-center gap-4">
30
32
  <SearchInput
31
- placeholder={searchInputPlaceholder}
33
+ placeholder={searchInputPlaceholder ?? t("searchTable.searchPlaceholder")}
32
34
  value={searchTerm}
33
35
  onChange={onSearchChange}
34
36
  />
@@ -41,10 +43,10 @@ export default function SearchAndSortBar({
41
43
  variant="outlined"
42
44
  color="danger"
43
45
  onClick={onClearSearch}
44
- ariaLabel="Limpiar búsqueda"
45
- title="Limpiar búsqueda"
46
+ ariaLabel={t("searchTable.clearSearch")}
47
+ title={t("searchTable.clearSearch")}
46
48
  >
47
- <ITText as="span">Limpiar</ITText>
49
+ <ITText as="span">{t("common.clear")}</ITText>
48
50
  </ITButton>
49
51
  )}
50
52
  </div>
@@ -1,6 +1,7 @@
1
1
  import ITInput from "@/components/atoms/input/input";
2
2
  import React from "react";
3
3
  import { FaSearch } from "react-icons/fa";
4
+ import { useITTranslation } from "@/i18n";
4
5
 
5
6
  interface SearchInputProps {
6
7
  placeholder?: string;
@@ -10,11 +11,12 @@ interface SearchInputProps {
10
11
  }
11
12
 
12
13
  export default function SearchInput({
13
- placeholder = "Buscar en todos los campos...",
14
+ placeholder,
14
15
  value,
15
16
  onChange,
16
17
  className = "",
17
18
  }: SearchInputProps) {
19
+ const { t } = useITTranslation();
18
20
  return (
19
21
  <div className={`relative flex-1 ${className}`}>
20
22
  <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
@@ -22,7 +24,7 @@ export default function SearchInput({
22
24
  </div>
23
25
  <ITInput
24
26
  name="global-search"
25
- placeholder={placeholder}
27
+ placeholder={placeholder ?? t("searchTable.searchPlaceholder")}
26
28
  value={value}
27
29
  onChange={(e) => onChange(e.target.value)}
28
30
  onBlur={() => {}}
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
3
3
  import ITText from "@/components/atoms/text/text";
4
+ import { useITTranslation } from "@/i18n";
4
5
 
5
6
  interface SortButtonProps {
6
7
  sortConfig?: {
@@ -16,18 +17,19 @@ export default function SortButton({
16
17
  onClick,
17
18
  className = "",
18
19
  }: SortButtonProps) {
20
+ const { t } = useITTranslation();
21
+ const directionLabel = sortConfig
22
+ ? sortConfig.direction === "asc"
23
+ ? t("searchTable.sortDescending")
24
+ : t("searchTable.sortAscending")
25
+ : t("searchTable.sortAscending");
26
+
19
27
  return (
20
28
  <button
21
29
  onClick={onClick}
22
30
  className={`p-3 rounded-lg bg-white border border-secondary-300 hover:bg-secondary-50 transition-colors duration-200 flex items-center gap-2 min-w-[120px] ${className}`}
23
- aria-label={`Ordenar tabla ${
24
- sortConfig
25
- ? sortConfig.direction === "asc"
26
- ? "descendente"
27
- : "ascendente"
28
- : "ascendente"
29
- }`}
30
- title="Ordenar tabla"
31
+ aria-label={t("searchTable.sortAria", { direction: directionLabel })}
32
+ title={t("searchTable.sortTable")}
31
33
  >
32
34
  {sortConfig ? (
33
35
  sortConfig.direction === "asc" ? (
@@ -41,9 +43,9 @@ export default function SortButton({
41
43
  <ITText as="span" className="text-sm font-medium text-secondary-700">
42
44
  {sortConfig
43
45
  ? sortConfig.direction === "asc"
44
- ? "Asc ↑"
45
- : "Desc ↓"
46
- : "Ordenar"}
46
+ ? t("searchTable.sortAsc")
47
+ : t("searchTable.sortDesc")
48
+ : t("searchTable.sort")}
47
49
  </ITText>
48
50
  </button>
49
51
  );
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import ITText from "@/components/atoms/text/text";
3
+ import { useITTranslation } from "@/i18n";
3
4
 
4
5
  interface TableEmptyStateProps {
5
6
  colSpan: number;
@@ -10,12 +11,13 @@ export default function TableEmptyState({
10
11
  colSpan,
11
12
  searchTerm,
12
13
  }: TableEmptyStateProps) {
14
+ const { t } = useITTranslation();
13
15
  return (
14
16
  <tr>
15
17
  <td colSpan={colSpan} className="px-6 py-4 text-center">
16
18
  {searchTerm
17
- ? <ITText as="span">No se encontraron resultados para tu búsqueda</ITText>
18
- : <ITText as="span">No se encontraron resultados</ITText>}
19
+ ? <ITText as="span">{t("searchTable.emptySearch")}</ITText>
20
+ : <ITText as="span">{t("searchTable.empty")}</ITText>}
19
21
  </td>
20
22
  </tr>
21
23
  );
@@ -6,6 +6,7 @@ import { FaCheck, FaTimes } from "react-icons/fa";
6
6
  import { SearchColumn } from "../searchTable.props";
7
7
  import EditableCell from "./EditableCell";
8
8
  import * as yup from "yup";
9
+ import { useITTranslation, toIntlLocale } from "@/i18n";
9
10
 
10
11
  interface TableRowProps<T> {
11
12
  row: T;
@@ -31,6 +32,7 @@ export default function TableRow<T>({
31
32
  isEditing = false,
32
33
  onEdit,
33
34
  }: TableRowProps<T>) {
35
+ const { t, locale } = useITTranslation();
34
36
  const {
35
37
  editedRow,
36
38
  errors,
@@ -55,18 +57,18 @@ export default function TableRow<T>({
55
57
  switch (col.type) {
56
58
  case "number":
57
59
  return typeof value === "number" && col.currencyMX
58
- ? formatCurrencyMX(value)
60
+ ? formatCurrencyMX(value, toIntlLocale(locale))
59
61
  : (value as React.ReactNode);
60
62
 
61
63
  case "boolean":
62
64
  return value ? (
63
65
  <FaCheck
64
66
  className="text-green-500"
65
- aria-label="Verdadero"
66
- title="Verdadero"
67
+ aria-label={t("common.true")}
68
+ title={t("common.true")}
67
69
  />
68
70
  ) : (
69
- <FaTimes className="text-danger-500" aria-label="Falso" title="Falso" />
71
+ <FaTimes className="text-danger-500" aria-label={t("common.false")} title={t("common.false")} />
70
72
  );
71
73
 
72
74
  case "actions":
@@ -11,6 +11,7 @@ import { getNestedValue } from "@/utils/table.utils";
11
11
  import TableEmptyState from "./components/TableEmptyState";
12
12
  import PaginationControls from "./components/PaginationControls";
13
13
  import ITText from "@/components/atoms/text/text";
14
+ import { useITTranslation } from "@/i18n";
14
15
 
15
16
  interface CustomITSearchTableProps<T> extends ITSearchTableProps<T> {
16
17
  editingRow?: number | null;
@@ -53,7 +54,7 @@ export default function ITSearchTable<T extends Record<string, unknown>>({
53
54
  data,
54
55
  containerClassName,
55
56
  searchTermInitial = "",
56
- searchInputPlaceholder = "Buscar en todos los campos...",
57
+ searchInputPlaceholder,
57
58
  variant = "default",
58
59
  size = "md",
59
60
  itemsPerPageOptions = [10, 20, 50, 100],
@@ -76,6 +77,7 @@ export default function ITSearchTable<T extends Record<string, unknown>>({
76
77
  onSave,
77
78
  onCancel,
78
79
  }: CustomITSearchTableProps<T>) {
80
+ const { t } = useITTranslation();
79
81
  const [itemsPerPage, setItemsPerPage] = useState(defaultItemsPerPage);
80
82
 
81
83
  const { searchTerm, handleSearchChange, handleClearSearch } = useDebouncedSearch({
@@ -145,7 +147,7 @@ return (
145
147
  onClearSearch={handleClearSearchWithClear}
146
148
  onGlobalSort={handleGlobalSort}
147
149
  sortConfig={sortConfig}
148
- searchInputPlaceholder={searchInputPlaceholder}
150
+ searchInputPlaceholder={searchInputPlaceholder ?? t("searchTable.searchPlaceholder")}
149
151
  />
150
152
  </div>
151
153
 
@@ -75,7 +75,7 @@ export interface ITSidebarNotification {
75
75
  count: number;
76
76
  /** Icon rendered left of the label (e.g. a bell). Omit for a count-only pill. */
77
77
  icon?: React.ReactNode;
78
- /** Accessible label and tooltip for the notification button. @default "Notificaciones" */
78
+ /** Accessible label and tooltip for the notification button. @default i18n `sidebar.notifications` ("Notificaciones") */
79
79
  label?: string;
80
80
  /** Click handler for the notification button. */
81
81
  onClick?: () => void;
@@ -11,6 +11,7 @@ import {
11
11
  import ITBadget from "@/components/atoms/badget/badget";
12
12
  import ITText from "@/components/atoms/text/text";
13
13
  import { useITFlatAppearance } from "@/theme/theme-context";
14
+ import { useITTranslation } from "@/i18n";
14
15
 
15
16
  /** Narrows a submenu entry to a titled group. */
16
17
  function isSubItemGroup(
@@ -73,6 +74,7 @@ export default function ITSidebar({
73
74
  }: ITSidebarProps) {
74
75
  // Flat appearance: plain surface, no glow/accent bar, narrower panel.
75
76
  const flat = useITFlatAppearance();
77
+ const { t } = useITTranslation();
76
78
  const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
77
79
  const [isHovering, setIsHovering] = useState(false);
78
80
  const sidebarRef = useRef<HTMLDivElement>(null);
@@ -251,7 +253,7 @@ export default function ITSidebar({
251
253
  const {
252
254
  count,
253
255
  icon,
254
- label = "Notificaciones",
256
+ label = t("sidebar.notifications"),
255
257
  onClick,
256
258
  badgeProps,
257
259
  } = notification;
@@ -371,11 +373,14 @@ export default function ITSidebar({
371
373
  )}
372
374
 
373
375
  {/* Navigation Items */}
374
- <nav aria-label="Componentes de la librería" className={`flex-1 py-4 custom-scrollbar ${fixedRail ? "overflow-visible" : "overflow-y-auto overflow-x-hidden"} ${flat && isSidebarCollapsed ? "px-3" : "px-4"}`}>
376
+ <nav aria-label={t("sidebar.navAria")} className={`flex-1 py-4 custom-scrollbar ${fixedRail ? "overflow-visible" : "overflow-y-auto overflow-x-hidden"} ${flat && isSidebarCollapsed ? "px-3" : "px-4"}`}>
375
377
  <ul className="space-y-1">
376
378
  {navigationItems.map((item) => {
377
379
  const hasSubmenu = !!item.subitems && item.subitems.length > 0;
378
380
  const submenuId = `it-sidebar-submenu-${item.id}`;
381
+ // El submenú solo existe en el DOM cuando la barra está expandida:
382
+ // `aria-controls` a un id inexistente es un valor ARIA inválido.
383
+ const hasRenderedSubmenu = hasSubmenu && !isSidebarCollapsed;
379
384
  const { className: badgeClassName, ...badgeRest } = item.badgeProps ?? {};
380
385
  // Flat + expanded: a parent whose subitem is active stays plain; the
381
386
  // subitem carries the highlight. Collapsed, the parent icon shows it.
@@ -387,7 +392,7 @@ export default function ITSidebar({
387
392
  tabIndex={0}
388
393
  aria-label={item.label}
389
394
  aria-expanded={hasSubmenu ? expandedItems.has(item.id) : undefined}
390
- aria-controls={hasSubmenu ? submenuId : undefined}
395
+ aria-controls={hasRenderedSubmenu ? submenuId : undefined}
391
396
  className={`flex items-center cursor-pointer
392
397
  transition-all duration-300 ease-[cubic-bezier(0.2,0,0,1)]
393
398
  rounded-xl relative overflow-visible
@@ -525,7 +530,7 @@ export default function ITSidebar({
525
530
  ))}
526
531
  </div>
527
532
  ) : (
528
- <ITText as="div" className="px-5 py-3 text-sm italic" style={{ color: "var(--it-sidebar-label-color, var(--color-secondary-400))" }}>No hay submenú</ITText>
533
+ <ITText as="div" className="px-5 py-3 text-sm italic" style={{ color: "var(--it-sidebar-label-color, var(--color-secondary-400))" }}>{t("sidebar.noSubmenu")}</ITText>
529
534
  )}
530
535
  </div>
531
536
  )}
@@ -5,6 +5,7 @@ import { useEffect, useState } from "react";
5
5
  import { ITToastProps } from "./toast.props";
6
6
  import { FaTimesCircle, FaCheckCircle, FaExclamationTriangle, FaInfoCircle, FaTimes } from "react-icons/fa";
7
7
  import ITText from "@/components/atoms/text/text";
8
+ import { useITTranslation } from "@/i18n";
8
9
 
9
10
  /**
10
11
  * ITToast — floating notification with automatic dismiss and severity-based styling.
@@ -34,6 +35,7 @@ export default function ITToast({
34
35
  position = "top-right",
35
36
  onClose,
36
37
  }: ITToastProps) {
38
+ const { t } = useITTranslation();
37
39
  const [isVisible, setIsVisible] = useState(true);
38
40
 
39
41
  useEffect(() => {
@@ -98,7 +100,7 @@ export default function ITToast({
98
100
  <button
99
101
  onClick={handleClose}
100
102
  className="p-1.5 rounded-full hover:bg-black/15 transition-colors focus:outline-none focus:ring-2 focus:ring-white/50"
101
- aria-label="Close notification"
103
+ aria-label={t("common.closeNotification")}
102
104
  >
103
105
  <FaTimes className="w-4 h-4" />
104
106
  </button>
@@ -4,6 +4,7 @@ import { useRef, useState } from "react";
4
4
  import { ITTopBarProps } from "./topbar.props";
5
5
  import ITText from "@/components/atoms/text/text";
6
6
  import { useITFlatAppearance } from "@/theme/theme-context";
7
+ import { useITTranslation } from "@/i18n";
7
8
 
8
9
  /**
9
10
  * ITTopBar — sticky top navigation bar with logo, nav items, and user avatar dropdown.
@@ -73,6 +74,7 @@ export default function ITTopBar({
73
74
  }: ITTopBarProps) {
74
75
  // Flat appearance: plain bar (no shadow/blur), initials avatar, name before it.
75
76
  const flat = useITFlatAppearance();
77
+ const { t } = useITTranslation();
76
78
  const initials = (userMenu?.userName ?? "")
77
79
  .trim()
78
80
  .split(/\s+/)
@@ -102,7 +104,7 @@ export default function ITTopBar({
102
104
  {showMobileMenuButton && (
103
105
  <button
104
106
  type="button"
105
- aria-label="Menú"
107
+ aria-label={t("common.menu")}
106
108
  className={`${showDesktopMenuButton ? "" : "lg:hidden"} p-2.5 -ml-2.5 rounded-xl transition-colors duration-200`}
107
109
  style={{
108
110
  color: "var(--it-topbar-icon, #64748b)",
@@ -200,7 +202,7 @@ export default function ITTopBar({
200
202
  <img
201
203
  className="w-9 h-9 rounded-full object-cover ring-2 ring-white shadow-sm"
202
204
  src={userMenu.userImage}
203
- alt="Current user"
205
+ alt={t("common.userAvatar")}
204
206
  />
205
207
  ) : flat && initials ? (
206
208
  <div