@open-mercato/ui 0.5.1-develop.2860.07af3a6a9d → 0.5.1-develop.2874.77704bccbd

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 (246) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +204 -121
  3. package/dist/backend/AppShell.js +25 -28
  4. package/dist/backend/AppShell.js.map +2 -2
  5. package/dist/backend/ContextHelp.js +1 -1
  6. package/dist/backend/ContextHelp.js.map +1 -1
  7. package/dist/backend/CrudForm.js +12 -15
  8. package/dist/backend/CrudForm.js.map +2 -2
  9. package/dist/backend/DataTable.js +9 -10
  10. package/dist/backend/DataTable.js.map +2 -2
  11. package/dist/backend/FilterBar.js +6 -8
  12. package/dist/backend/FilterBar.js.map +2 -2
  13. package/dist/backend/FilterOverlay.js +10 -10
  14. package/dist/backend/FilterOverlay.js.map +2 -2
  15. package/dist/backend/FlashMessages.js +1 -1
  16. package/dist/backend/FlashMessages.js.map +2 -2
  17. package/dist/backend/JsonBuilder.js +6 -6
  18. package/dist/backend/JsonBuilder.js.map +1 -1
  19. package/dist/backend/NextStepCallout.js +1 -1
  20. package/dist/backend/NextStepCallout.js.map +1 -1
  21. package/dist/backend/PerspectiveSidebar.js +2 -2
  22. package/dist/backend/PerspectiveSidebar.js.map +2 -2
  23. package/dist/backend/ProfileDropdown.js +1 -1
  24. package/dist/backend/ProfileDropdown.js.map +1 -1
  25. package/dist/backend/RowActions.js +1 -1
  26. package/dist/backend/RowActions.js.map +1 -1
  27. package/dist/backend/UserMenu.js +2 -2
  28. package/dist/backend/UserMenu.js.map +1 -1
  29. package/dist/backend/WebhookSetupGuide.js +11 -11
  30. package/dist/backend/WebhookSetupGuide.js.map +2 -2
  31. package/dist/backend/charts/KpiCard.js +3 -3
  32. package/dist/backend/charts/KpiCard.js.map +1 -1
  33. package/dist/backend/columns/ColumnChooserPanel.js +1 -1
  34. package/dist/backend/columns/ColumnChooserPanel.js.map +2 -2
  35. package/dist/backend/custom-fields/FieldDefinitionsEditor.js +3 -3
  36. package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +2 -2
  37. package/dist/backend/dashboard/DashboardScreen.js +1 -1
  38. package/dist/backend/dashboard/DashboardScreen.js.map +1 -1
  39. package/dist/backend/date-range/DateRangeSelect.js +1 -1
  40. package/dist/backend/date-range/DateRangeSelect.js.map +1 -1
  41. package/dist/backend/date-range/InlineDateRangeSelect.js +1 -1
  42. package/dist/backend/date-range/InlineDateRangeSelect.js.map +1 -1
  43. package/dist/backend/detail/AccessDeniedMessage.js +1 -1
  44. package/dist/backend/detail/AccessDeniedMessage.js.map +1 -1
  45. package/dist/backend/detail/ActivitiesSection.js +5 -5
  46. package/dist/backend/detail/ActivitiesSection.js.map +1 -1
  47. package/dist/backend/detail/AddressEditor.js +3 -3
  48. package/dist/backend/detail/AddressEditor.js.map +2 -2
  49. package/dist/backend/detail/AddressTiles.js +3 -3
  50. package/dist/backend/detail/AddressTiles.js.map +2 -2
  51. package/dist/backend/detail/AttachmentMetadataDialog.js +1 -1
  52. package/dist/backend/detail/AttachmentMetadataDialog.js.map +1 -1
  53. package/dist/backend/detail/CustomDataSection.js +1 -1
  54. package/dist/backend/detail/CustomDataSection.js.map +1 -1
  55. package/dist/backend/detail/InlineEditors.js +5 -5
  56. package/dist/backend/detail/InlineEditors.js.map +1 -1
  57. package/dist/backend/detail/NotesSection.js +6 -6
  58. package/dist/backend/detail/NotesSection.js.map +1 -1
  59. package/dist/backend/detail/TagsSection.js +1 -1
  60. package/dist/backend/detail/TagsSection.js.map +1 -1
  61. package/dist/backend/devtools/UmesDevToolsPanel.js +6 -6
  62. package/dist/backend/devtools/UmesDevToolsPanel.js.map +2 -2
  63. package/dist/backend/devtools/components/ConflictWarnings.js +3 -3
  64. package/dist/backend/devtools/components/ConflictWarnings.js.map +2 -2
  65. package/dist/backend/devtools/components/EnricherTiming.js +2 -2
  66. package/dist/backend/devtools/components/EnricherTiming.js.map +2 -2
  67. package/dist/backend/devtools/components/EventFlow.js +5 -5
  68. package/dist/backend/devtools/components/EventFlow.js.map +2 -2
  69. package/dist/backend/devtools/components/ExtensionPointList.js +3 -3
  70. package/dist/backend/devtools/components/ExtensionPointList.js.map +2 -2
  71. package/dist/backend/devtools/components/InterceptorActivity.js +6 -6
  72. package/dist/backend/devtools/components/InterceptorActivity.js.map +2 -2
  73. package/dist/backend/forms/ActionsDropdown.js +1 -1
  74. package/dist/backend/forms/ActionsDropdown.js.map +1 -1
  75. package/dist/backend/forms/FormActionButtons.js +2 -3
  76. package/dist/backend/forms/FormActionButtons.js.map +2 -2
  77. package/dist/backend/indexes/PartialIndexBanner.js +8 -8
  78. package/dist/backend/indexes/PartialIndexBanner.js.map +2 -2
  79. package/dist/backend/inputs/ComboboxInput.js +1 -1
  80. package/dist/backend/inputs/ComboboxInput.js.map +2 -2
  81. package/dist/backend/inputs/DatePicker.js +3 -3
  82. package/dist/backend/inputs/DatePicker.js.map +1 -1
  83. package/dist/backend/inputs/DateTimePicker.js +3 -3
  84. package/dist/backend/inputs/DateTimePicker.js.map +1 -1
  85. package/dist/backend/inputs/EventSelect.js +1 -1
  86. package/dist/backend/inputs/EventSelect.js.map +2 -2
  87. package/dist/backend/inputs/LookupSelect.js +1 -1
  88. package/dist/backend/inputs/LookupSelect.js.map +1 -1
  89. package/dist/backend/inputs/SwitchableMarkdownInput.js +1 -1
  90. package/dist/backend/inputs/SwitchableMarkdownInput.js.map +1 -1
  91. package/dist/backend/inputs/TagsInput.js +2 -2
  92. package/dist/backend/inputs/TagsInput.js.map +2 -2
  93. package/dist/backend/inputs/TimeInput.js +1 -1
  94. package/dist/backend/inputs/TimeInput.js.map +1 -1
  95. package/dist/backend/inputs/TimePicker.js +3 -3
  96. package/dist/backend/inputs/TimePicker.js.map +1 -1
  97. package/dist/backend/messages/MessageObjectDetail.js +1 -1
  98. package/dist/backend/messages/MessageObjectDetail.js.map +1 -1
  99. package/dist/backend/messages/MessageObjectPreview.js +1 -1
  100. package/dist/backend/messages/MessageObjectPreview.js.map +1 -1
  101. package/dist/backend/messages/message-compose-form-groups.js +3 -3
  102. package/dist/backend/messages/message-compose-form-groups.js.map +1 -1
  103. package/dist/backend/notifications/NotificationCountBadge.js +1 -1
  104. package/dist/backend/notifications/NotificationCountBadge.js.map +2 -2
  105. package/dist/backend/notifications/NotificationPanel.js +3 -3
  106. package/dist/backend/notifications/NotificationPanel.js.map +1 -1
  107. package/dist/backend/progress/ProgressTopBar.js +4 -4
  108. package/dist/backend/progress/ProgressTopBar.js.map +2 -2
  109. package/dist/backend/schedule/ScheduleAgenda.js +1 -1
  110. package/dist/backend/schedule/ScheduleAgenda.js.map +2 -2
  111. package/dist/backend/schedule/ScheduleCalendar.js +1 -1
  112. package/dist/backend/schedule/ScheduleCalendar.js.map +1 -1
  113. package/dist/backend/schedule/ScheduleGrid.js +1 -1
  114. package/dist/backend/schedule/ScheduleGrid.js.map +2 -2
  115. package/dist/backend/version-history/VersionHistoryPanel.js +4 -4
  116. package/dist/backend/version-history/VersionHistoryPanel.js.map +2 -2
  117. package/dist/frontend/AuthFooter.js +1 -1
  118. package/dist/frontend/AuthFooter.js.map +1 -1
  119. package/dist/frontend/LanguageSwitcher.js +1 -1
  120. package/dist/frontend/LanguageSwitcher.js.map +1 -1
  121. package/dist/frontend/Layout.js +2 -2
  122. package/dist/frontend/Layout.js.map +1 -1
  123. package/dist/index.js +5 -0
  124. package/dist/index.js.map +2 -2
  125. package/dist/portal/PortalShell.js +15 -15
  126. package/dist/portal/PortalShell.js.map +2 -2
  127. package/dist/portal/components/PortalCard.js +2 -2
  128. package/dist/portal/components/PortalCard.js.map +2 -2
  129. package/dist/portal/components/PortalNotificationPanel.js +18 -18
  130. package/dist/portal/components/PortalNotificationPanel.js.map +2 -2
  131. package/dist/portal/components/PortalPageHeader.js +1 -1
  132. package/dist/portal/components/PortalPageHeader.js.map +2 -2
  133. package/dist/primitives/avatar.js +11 -1
  134. package/dist/primitives/avatar.js.map +2 -2
  135. package/dist/primitives/badge.js +1 -1
  136. package/dist/primitives/badge.js.map +1 -1
  137. package/dist/primitives/button.js +9 -5
  138. package/dist/primitives/button.js.map +2 -2
  139. package/dist/primitives/calendar.js +1 -1
  140. package/dist/primitives/calendar.js.map +1 -1
  141. package/dist/primitives/checkbox-field.js +63 -0
  142. package/dist/primitives/checkbox-field.js.map +7 -0
  143. package/dist/primitives/checkbox.js +31 -17
  144. package/dist/primitives/checkbox.js.map +2 -2
  145. package/dist/primitives/dialog.js +4 -4
  146. package/dist/primitives/dialog.js.map +1 -1
  147. package/dist/primitives/fancy-button.js +72 -0
  148. package/dist/primitives/fancy-button.js.map +7 -0
  149. package/dist/primitives/icon-button.js +20 -4
  150. package/dist/primitives/icon-button.js.map +2 -2
  151. package/dist/primitives/kbd.js +27 -0
  152. package/dist/primitives/kbd.js.map +7 -0
  153. package/dist/primitives/link-button.js +56 -0
  154. package/dist/primitives/link-button.js.map +7 -0
  155. package/dist/primitives/popover.js +1 -1
  156. package/dist/primitives/popover.js.map +1 -1
  157. package/dist/primitives/social-button.js +61 -0
  158. package/dist/primitives/social-button.js.map +7 -0
  159. package/dist/primitives/tabs.js +1 -1
  160. package/dist/primitives/tabs.js.map +1 -1
  161. package/dist/primitives/tag.js +45 -0
  162. package/dist/primitives/tag.js.map +7 -0
  163. package/dist/primitives/tooltip.js +1 -1
  164. package/dist/primitives/tooltip.js.map +1 -1
  165. package/package.json +3 -3
  166. package/src/backend/AppShell.tsx +25 -28
  167. package/src/backend/ContextHelp.tsx +1 -1
  168. package/src/backend/CrudForm.tsx +12 -15
  169. package/src/backend/DataTable.tsx +9 -10
  170. package/src/backend/FilterBar.tsx +6 -5
  171. package/src/backend/FilterOverlay.tsx +10 -10
  172. package/src/backend/FlashMessages.tsx +1 -1
  173. package/src/backend/JsonBuilder.tsx +6 -6
  174. package/src/backend/NextStepCallout.tsx +1 -1
  175. package/src/backend/PerspectiveSidebar.tsx +2 -2
  176. package/src/backend/ProfileDropdown.tsx +1 -1
  177. package/src/backend/RowActions.tsx +1 -1
  178. package/src/backend/UserMenu.tsx +2 -2
  179. package/src/backend/WebhookSetupGuide.tsx +11 -11
  180. package/src/backend/charts/KpiCard.tsx +3 -3
  181. package/src/backend/columns/ColumnChooserPanel.tsx +1 -1
  182. package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +3 -3
  183. package/src/backend/dashboard/DashboardScreen.tsx +1 -1
  184. package/src/backend/date-range/DateRangeSelect.tsx +1 -1
  185. package/src/backend/date-range/InlineDateRangeSelect.tsx +1 -1
  186. package/src/backend/detail/AccessDeniedMessage.tsx +1 -1
  187. package/src/backend/detail/ActivitiesSection.tsx +5 -5
  188. package/src/backend/detail/AddressEditor.tsx +3 -3
  189. package/src/backend/detail/AddressTiles.tsx +3 -3
  190. package/src/backend/detail/AttachmentMetadataDialog.tsx +1 -1
  191. package/src/backend/detail/CustomDataSection.tsx +1 -1
  192. package/src/backend/detail/InlineEditors.tsx +5 -5
  193. package/src/backend/detail/NotesSection.tsx +6 -6
  194. package/src/backend/detail/TagsSection.tsx +1 -1
  195. package/src/backend/devtools/UmesDevToolsPanel.tsx +6 -6
  196. package/src/backend/devtools/components/ConflictWarnings.tsx +4 -4
  197. package/src/backend/devtools/components/EnricherTiming.tsx +2 -2
  198. package/src/backend/devtools/components/EventFlow.tsx +5 -5
  199. package/src/backend/devtools/components/ExtensionPointList.tsx +3 -3
  200. package/src/backend/devtools/components/InterceptorActivity.tsx +6 -6
  201. package/src/backend/forms/ActionsDropdown.tsx +1 -1
  202. package/src/backend/forms/FormActionButtons.tsx +4 -5
  203. package/src/backend/indexes/PartialIndexBanner.tsx +8 -8
  204. package/src/backend/inputs/ComboboxInput.tsx +1 -1
  205. package/src/backend/inputs/DatePicker.tsx +3 -3
  206. package/src/backend/inputs/DateTimePicker.tsx +3 -3
  207. package/src/backend/inputs/EventSelect.tsx +1 -1
  208. package/src/backend/inputs/LookupSelect.tsx +1 -1
  209. package/src/backend/inputs/SwitchableMarkdownInput.tsx +1 -1
  210. package/src/backend/inputs/TagsInput.tsx +2 -2
  211. package/src/backend/inputs/TimeInput.tsx +1 -1
  212. package/src/backend/inputs/TimePicker.tsx +3 -3
  213. package/src/backend/messages/MessageObjectDetail.tsx +1 -1
  214. package/src/backend/messages/MessageObjectPreview.tsx +1 -1
  215. package/src/backend/messages/message-compose-form-groups.tsx +3 -3
  216. package/src/backend/notifications/NotificationCountBadge.tsx +1 -1
  217. package/src/backend/notifications/NotificationPanel.tsx +3 -3
  218. package/src/backend/progress/ProgressTopBar.tsx +4 -4
  219. package/src/backend/schedule/ScheduleAgenda.tsx +1 -1
  220. package/src/backend/schedule/ScheduleCalendar.tsx +1 -1
  221. package/src/backend/schedule/ScheduleGrid.tsx +1 -1
  222. package/src/backend/version-history/VersionHistoryPanel.tsx +4 -4
  223. package/src/frontend/AuthFooter.tsx +1 -1
  224. package/src/frontend/LanguageSwitcher.tsx +1 -1
  225. package/src/frontend/Layout.tsx +2 -2
  226. package/src/index.ts +6 -1
  227. package/src/portal/PortalShell.tsx +15 -15
  228. package/src/portal/components/PortalCard.tsx +2 -2
  229. package/src/portal/components/PortalNotificationPanel.tsx +18 -18
  230. package/src/portal/components/PortalPageHeader.tsx +1 -1
  231. package/src/primitives/avatar.tsx +22 -0
  232. package/src/primitives/badge.tsx +1 -1
  233. package/src/primitives/button.tsx +12 -5
  234. package/src/primitives/calendar.tsx +1 -1
  235. package/src/primitives/checkbox-field.tsx +85 -0
  236. package/src/primitives/checkbox.tsx +44 -18
  237. package/src/primitives/dialog.tsx +4 -4
  238. package/src/primitives/fancy-button.tsx +89 -0
  239. package/src/primitives/icon-button.tsx +19 -2
  240. package/src/primitives/kbd.tsx +38 -0
  241. package/src/primitives/link-button.tsx +55 -0
  242. package/src/primitives/popover.tsx +1 -1
  243. package/src/primitives/social-button.tsx +80 -0
  244. package/src/primitives/tabs.tsx +1 -1
  245. package/src/primitives/tag.tsx +66 -0
  246. package/src/primitives/tooltip.tsx +1 -1
@@ -138,7 +138,7 @@ export function DateTimePicker({
138
138
  className={cn(
139
139
  'w-full h-9 flex items-center gap-2 rounded border px-3 text-sm text-left',
140
140
  'bg-background transition-colors',
141
- 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1',
141
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
142
142
  'disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed',
143
143
  readOnly && 'cursor-default opacity-70',
144
144
  !formattedValue && 'text-muted-foreground',
@@ -176,7 +176,7 @@ export function DateTimePicker({
176
176
  <button
177
177
  type="button"
178
178
  onClick={handleToday}
179
- className="text-sm text-primary hover:underline focus:outline-none"
179
+ className="text-sm text-primary hover:underline focus-visible:outline-none"
180
180
  >
181
181
  {todayText}
182
182
  </button>
@@ -185,7 +185,7 @@ export function DateTimePicker({
185
185
  <button
186
186
  type="button"
187
187
  onClick={handleClear}
188
- className="text-sm text-muted-foreground hover:text-foreground hover:underline focus:outline-none ml-auto"
188
+ className="text-sm text-muted-foreground hover:text-foreground hover:underline focus-visible:outline-none ml-auto"
189
189
  >
190
190
  {clearText}
191
191
  </button>
@@ -104,7 +104,7 @@ export function EventSelect({
104
104
  <select
105
105
  value={value}
106
106
  onChange={(e) => onChange(e.target.value)}
107
- className={`h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${className || ''}`}
107
+ className={`h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${className || ''}`}
108
108
  disabled={disabled || isLoading}
109
109
  >
110
110
  <option value="" disabled>
@@ -171,7 +171,7 @@ export function LookupSelect({
171
171
  <div
172
172
  key={item.id}
173
173
  className={cn(
174
- 'flex gap-3 rounded border bg-card p-3 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background',
174
+ 'flex gap-3 rounded border bg-card p-3 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background',
175
175
  isSelected ? 'border-primary/70 bg-primary/5' : 'hover:border-primary/50'
176
176
  )}
177
177
  role="button"
@@ -78,7 +78,7 @@ export function SwitchableMarkdownInput({
78
78
  const editorClasses = editorClassName ?? 'w-full'
79
79
  const textareaClasses =
80
80
  textareaClassName
81
- ?? 'w-full resize-none overflow-hidden rounded-lg border border-muted-foreground/20 bg-background px-3 py-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary'
81
+ ?? 'w-full resize-none overflow-hidden rounded-lg border border-muted-foreground/20 bg-background px-3 py-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'
82
82
 
83
83
  if (isMarkdownEnabled && !disableMarkdown) {
84
84
  return (
@@ -205,7 +205,7 @@ export function TagsInput({
205
205
  <span className="flex flex-col items-start leading-tight">
206
206
  <span className="whitespace-nowrap">{label}</span>
207
207
  {description ? (
208
- <span className="text-[10px] text-muted-foreground">{description}</span>
208
+ <span className="text-overline text-muted-foreground">{description}</span>
209
209
  ) : null}
210
210
  </span>
211
211
  <IconButton
@@ -285,7 +285,7 @@ export function TagsInput({
285
285
  >
286
286
  <span>{option.label}</span>
287
287
  {option.description ? (
288
- <span className="text-[10px] text-muted-foreground">{option.description}</span>
288
+ <span className="text-overline text-muted-foreground">{option.description}</span>
289
289
  ) : null}
290
290
  </Button>
291
291
  ))}
@@ -109,7 +109,7 @@ export function TimeInput({
109
109
 
110
110
  const inputClass = cn(
111
111
  'w-14 h-9 rounded border text-center text-sm tabular-nums',
112
- 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1',
112
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
113
113
  disabled && 'bg-muted text-muted-foreground cursor-not-allowed',
114
114
  'disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed'
115
115
  )
@@ -74,7 +74,7 @@ export function TimePicker({
74
74
  className={cn(
75
75
  'w-full h-9 flex items-center gap-2 rounded border px-3 text-sm text-left',
76
76
  'bg-background transition-colors',
77
- 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1',
77
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
78
78
  'disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed',
79
79
  readOnly && 'cursor-default opacity-70',
80
80
  !value && 'text-muted-foreground',
@@ -98,7 +98,7 @@ export function TimePicker({
98
98
  <button
99
99
  type="button"
100
100
  onClick={handleNow}
101
- className="text-sm text-primary hover:underline focus:outline-none"
101
+ className="text-sm text-primary hover:underline focus-visible:outline-none"
102
102
  >
103
103
  {nowText}
104
104
  </button>
@@ -107,7 +107,7 @@ export function TimePicker({
107
107
  <button
108
108
  type="button"
109
109
  onClick={handleClear}
110
- className="text-sm text-muted-foreground hover:text-foreground hover:underline focus:outline-none ml-auto"
110
+ className="text-sm text-muted-foreground hover:text-foreground hover:underline focus-visible:outline-none ml-auto"
111
111
  >
112
112
  {clearText}
113
113
  </button>
@@ -37,7 +37,7 @@ export function MessageObjectDetail(props: ObjectDetailProps) {
37
37
  {viewAction?.href ? (
38
38
  <Link
39
39
  href={resolveActionHref(viewAction.href, props.entityId)}
40
- className="block rounded-md transition-opacity hover:opacity-75"
40
+ className="block rounded-md transition-opacity hover:opacity-80"
41
41
  >
42
42
  {preview}
43
43
  </Link>
@@ -20,7 +20,7 @@ export function MessageObjectPreview({
20
20
  const Icon = resolveIcon(icon)
21
21
 
22
22
  return (
23
- <div className="flex items-start gap-3 rounded-md border bg-muted/20 p-3">
23
+ <div className="flex items-start gap-3 rounded-md border bg-muted/30 p-3">
24
24
  <Icon className="mt-0.5 h-4 w-4 text-muted-foreground" />
25
25
  <div className="min-w-0 flex-1 space-y-1">
26
26
  <div className="flex items-center gap-2">
@@ -228,7 +228,7 @@ function ComposeModeFields({ compose }: ComposeProps) {
228
228
  placeholder={compose.t('messages.placeholders.body', 'Write your message...')}
229
229
  inputId="messages-compose-body"
230
230
  rows={8}
231
- textareaClassName="min-h-[180px] w-full rounded-md border bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
231
+ textareaClassName="min-h-[180px] w-full rounded-md border bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
232
232
  />
233
233
 
234
234
  <div className="space-y-2">
@@ -256,7 +256,7 @@ function ReplyModeFields({ compose }: ComposeProps) {
256
256
  placeholder={compose.t('messages.placeholders.replyBody', 'Write your reply...')}
257
257
  inputId="messages-compose-body"
258
258
  rows={8}
259
- textareaClassName="min-h-[180px] w-full rounded-md border bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
259
+ textareaClassName="min-h-[180px] w-full rounded-md border bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
260
260
  />
261
261
 
262
262
  <div className="space-y-2">
@@ -289,7 +289,7 @@ function ForwardModeFields({ compose }: ComposeProps) {
289
289
  placeholder={compose.t('messages.placeholders.forwardContent', 'Review and edit forwarded content...')}
290
290
  inputId="messages-forward-note"
291
291
  rows={6}
292
- textareaClassName="min-h-[140px] w-full rounded-md border bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
292
+ textareaClassName="min-h-[140px] w-full rounded-md border bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
293
293
  />
294
294
  </>
295
295
  )
@@ -7,7 +7,7 @@ export type NotificationCountBadgeProps = {
7
7
  export function NotificationCountBadge({ count }: NotificationCountBadgeProps) {
8
8
  if (count <= 0) return null
9
9
  return (
10
- <span className="absolute -top-1 -right-1 flex h-5 w-5 items-center justify-center rounded-full bg-destructive text-[10px] font-medium text-destructive-foreground">
10
+ <span className="absolute -top-1 -right-1 flex h-5 w-5 items-center justify-center rounded-full bg-destructive text-overline font-medium text-destructive-foreground">
11
11
  {count > 99 ? '99+' : count}
12
12
  </span>
13
13
  )
@@ -120,13 +120,13 @@ export function NotificationPanel({
120
120
  return (
121
121
  <>
122
122
  <div
123
- className="fixed inset-0 z-40 bg-black/20"
123
+ className="fixed inset-0 z-overlay bg-black/20"
124
124
  onClick={() => onOpenChange(false)}
125
125
  aria-hidden="true"
126
126
  />
127
127
 
128
128
  <div
129
- className="fixed right-0 top-0 z-50 h-full w-full max-w-md border-l bg-background shadow-lg"
129
+ className="fixed right-0 top-0 z-modal h-full w-full max-w-md border-l bg-background shadow-lg"
130
130
  role="dialog"
131
131
  aria-modal="true"
132
132
  aria-label={t('notifications.title', 'Notifications')}
@@ -183,7 +183,7 @@ export function NotificationPanel({
183
183
  </Tabs>
184
184
 
185
185
  {dismissUndo && onUndoDismiss && (
186
- <div className="border-b bg-muted/40 px-4 py-2 text-sm">
186
+ <div className="border-b bg-muted/50 px-4 py-2 text-sm">
187
187
  <div className="flex items-center justify-between gap-3">
188
188
  <span>
189
189
  {t('notifications.toast.dismissed', 'Notification dismissed')}
@@ -58,7 +58,7 @@ export function ProgressTopBar({ className, t }: ProgressTopBarProps) {
58
58
  </>
59
59
  ) : (
60
60
  <>
61
- <CheckCircle className="h-4 w-4 text-green-500" />
61
+ <CheckCircle className="h-4 w-4 text-status-success-icon" />
62
62
  <span className="text-muted-foreground">
63
63
  {t('progress.recentlyCompleted', '{count} operations completed', { count: recentlyCompleted.length })}
64
64
  </span>
@@ -108,13 +108,13 @@ function ProgressJobCard({ job, t, onCancel }: { job: ProgressJobDto; t: Transla
108
108
  <div className={cn(
109
109
  'rounded-md border bg-card p-3',
110
110
  isFailed && 'border-destructive/50 bg-destructive/5',
111
- isCompleted && 'border-green-500/50 bg-green-50/50 dark:bg-green-950/20',
111
+ isCompleted && 'border-status-success-border bg-status-success-bg',
112
112
  )}>
113
113
  <div className="flex items-start justify-between gap-2">
114
114
  <div className="flex-1 min-w-0">
115
115
  <div className="flex items-center gap-2">
116
116
  {isActive && <Loader2 className="h-4 w-4 animate-spin text-primary flex-shrink-0" />}
117
- {isCompleted && <CheckCircle className="h-4 w-4 text-green-500 flex-shrink-0" />}
117
+ {isCompleted && <CheckCircle className="h-4 w-4 text-status-success-icon flex-shrink-0" />}
118
118
  {isFailed && <XCircle className="h-4 w-4 text-destructive flex-shrink-0" />}
119
119
  <span className="font-medium truncate">{job.name}</span>
120
120
  </div>
@@ -170,7 +170,7 @@ function IndeterminateProgressBar({ className }: { className?: string }) {
170
170
  return (
171
171
  <div className={cn('relative w-full overflow-hidden rounded-full bg-secondary', className)}>
172
172
  <div className="absolute inset-y-0 left-0 w-1/2 animate-pulse rounded-full bg-primary/80" />
173
- <div className="absolute inset-y-0 right-0 w-1/3 rounded-full bg-primary/40" />
173
+ <div className="absolute inset-y-0 right-0 w-1/3 rounded-full bg-primary/10" />
174
174
  </div>
175
175
  )
176
176
  }
@@ -119,7 +119,7 @@ export function ScheduleAgenda({ items, range, timezone, onItemClick, onSlotClic
119
119
  <span className="font-semibold">{item.title}</span>
120
120
  {statusLabel ? <Badge variant="secondary">{statusLabel}</Badge> : null}
121
121
  </div>
122
- <div className="flex items-center justify-between text-[11px] text-muted-foreground">
122
+ <div className="flex items-center justify-between text-overline text-muted-foreground">
123
123
  <span>{formatTimeRange(item, timezone)}</span>
124
124
  <span className="capitalize">{item.kind}</span>
125
125
  </div>
@@ -160,7 +160,7 @@ export default function ScheduleCalendar({
160
160
  type="button"
161
161
  variant="link"
162
162
  size="sm"
163
- className="h-auto p-0 text-[11px]"
163
+ className="h-auto p-0 text-overline"
164
164
  onClick={(clickEvent) => {
165
165
  clickEvent.stopPropagation()
166
166
  onItemClick?.(resource)
@@ -119,7 +119,7 @@ export function ScheduleGrid({ items, range, timezone, onItemClick, onSlotClick,
119
119
  <span className="font-semibold">{item.title}</span>
120
120
  {statusLabel ? <Badge variant="secondary">{statusLabel}</Badge> : null}
121
121
  </div>
122
- <div className="flex items-center justify-between text-[11px] text-muted-foreground">
122
+ <div className="flex items-center justify-between text-overline text-muted-foreground">
123
123
  <span>{formatTimeRange(item, timezone)}</span>
124
124
  <span className="capitalize">{item.kind}</span>
125
125
  </div>
@@ -142,12 +142,12 @@ export function VersionHistoryPanel({
142
142
  return (
143
143
  <>
144
144
  <div
145
- className="fixed inset-0 z-40 bg-black/20"
145
+ className="fixed inset-0 z-overlay bg-black/20"
146
146
  onClick={() => onOpenChange(false)}
147
147
  aria-hidden="true"
148
148
  />
149
149
  <div
150
- className="fixed right-0 top-0 z-50 h-full w-full max-w-md border-l bg-background shadow-lg"
150
+ className="fixed right-0 top-0 z-modal h-full w-full max-w-md border-l bg-background shadow-lg"
151
151
  role="dialog"
152
152
  aria-modal="true"
153
153
  aria-label={t('audit_logs.version_history.title')}
@@ -240,7 +240,7 @@ export function VersionHistoryPanel({
240
240
  return (
241
241
  <div
242
242
  key={entry.id}
243
- className={`flex items-start justify-between gap-3 py-3 transition-colors hover:bg-muted/40 ${isRelatedEntry ? 'pl-8 pr-4 border-l-2 border-l-muted-foreground/20' : 'px-4'}`}
243
+ className={`flex items-start justify-between gap-3 py-3 transition-colors hover:bg-muted/50 ${isRelatedEntry ? 'pl-8 pr-4 border-l-2 border-l-muted-foreground/20' : 'px-4'}`}
244
244
  >
245
245
  <Button
246
246
  type="button"
@@ -249,7 +249,7 @@ export function VersionHistoryPanel({
249
249
  onClick={() => setSelectedEntry(entry)}
250
250
  >
251
251
  {isRelatedEntry ? (
252
- <span className="text-[10px] uppercase tracking-wider text-muted-foreground/70 font-medium">
252
+ <span className="text-overline uppercase tracking-wider text-muted-foreground/70 font-medium">
253
253
  {humanizeResourceKind(entry.resourceKind, t)}
254
254
  </span>
255
255
  ) : null}
@@ -12,7 +12,7 @@ export function AuthFooter() {
12
12
  (typeof pathname === 'string' && pathname.startsWith('/onboarding'))
13
13
  if (!shouldShow) return null
14
14
  return (
15
- <footer className="w-full border-t bg-background/80 backdrop-blur supports-[backdrop-filter]:bg-background/50">
15
+ <footer className="w-full border-t bg-background/80 backdrop-blur supports-[backdrop-filter]:bg-background/80">
16
16
  <div className="max-w-screen-lg mx-auto px-4 py-3 flex flex-wrap items-center justify-end gap-4">
17
17
  <nav className="flex items-center gap-3 text-xs text-muted-foreground">
18
18
  <Link href="/terms" className="transition hover:text-foreground">
@@ -44,7 +44,7 @@ export function LanguageSwitcher() {
44
44
  <div className="relative">
45
45
  <select
46
46
  id={selectId}
47
- className="appearance-none rounded-md border bg-background px-3 py-1 pr-8 text-xs focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 disabled:opacity-60"
47
+ className="appearance-none rounded-md border bg-background px-3 py-1 pr-8 text-xs focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 disabled:opacity-50"
48
48
  value={current}
49
49
  onChange={(event) => setLocale(event.target.value as Locale)}
50
50
  disabled={pending}
@@ -5,9 +5,9 @@ export function FrontendLayout({ header, footer, children }: { header?: React.Re
5
5
  return (
6
6
  <div className="min-h-svh flex flex-col">
7
7
  <FlashMessages />
8
- {header ? <div className="border-b bg-background/60">{header}</div> : null}
8
+ {header ? <div className="border-b bg-background/80">{header}</div> : null}
9
9
  <div className="flex-1 min-h-0">{children}</div>
10
- {footer ? <div className="border-t bg-background/60">{footer}</div> : null}
10
+ {footer ? <div className="border-t bg-background/80">{footer}</div> : null}
11
11
  </div>
12
12
  )
13
13
  }
package/src/index.ts CHANGED
@@ -26,7 +26,12 @@ export * from './frontend/Layout'
26
26
  export * from './frontend/AuthFooter'
27
27
  export * from './frontend/LanguageSwitcher'
28
28
  export * from './primitives/button'
29
- export * from './primitives/icon-button'
29
+ export * from './primitives/icon-button'
30
+ export * from './primitives/link-button'
31
+ export * from './primitives/social-button'
32
+ export * from './primitives/fancy-button'
33
+ export * from './primitives/checkbox'
34
+ export * from './primitives/checkbox-field'
30
35
  export * from './primitives/label'
31
36
  export * from './primitives/separator'
32
37
  export * from './primitives/spinner'
@@ -94,7 +94,7 @@ function SidebarNavItem({
94
94
  if (!label) return null
95
95
 
96
96
  const cls = [
97
- 'flex items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium transition-colors',
97
+ 'flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium transition-colors',
98
98
  active
99
99
  ? 'bg-foreground text-background'
100
100
  : 'text-muted-foreground hover:bg-muted hover:text-foreground',
@@ -124,7 +124,7 @@ function UserAvatar({ name, className }: { name?: string; className?: string })
124
124
  ? name.split(' ').map((w) => w[0]).slice(0, 2).join('').toUpperCase()
125
125
  : '?'
126
126
  return (
127
- <div className={`flex items-center justify-center rounded-full bg-foreground text-[11px] font-semibold text-background ${className ?? 'size-8'}`}>
127
+ <div className={`flex items-center justify-center rounded-full bg-foreground text-overline font-semibold text-background ${className ?? 'size-8'}`}>
128
128
  {initials}
129
129
  </div>
130
130
  )
@@ -242,17 +242,17 @@ export function PortalShell({
242
242
  if (!authenticated) {
243
243
  return (
244
244
  <div className="flex min-h-svh flex-col bg-background" data-portal-handle={PORTAL_SHELL_HANDLE}>
245
- <header className="sticky top-0 z-40 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80" data-portal-handle={PORTAL_HEADER_HANDLE}>
245
+ <header className="sticky top-0 z-sticky border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80" data-portal-handle={PORTAL_HEADER_HANDLE}>
246
246
  <div className="mx-auto flex h-16 w-full max-w-screen-lg items-center justify-between px-6">
247
247
  <Link href={portalHome} className="flex items-center gap-2.5 text-foreground transition hover:opacity-80" aria-label={headerTitle}>
248
248
  <Image src={logo?.src ?? "/open-mercato.svg"} alt={logo?.alt ?? ""} width={28} height={28} className="" priority />
249
- <span className="text-[15px] font-semibold tracking-tight">{headerTitle}</span>
249
+ <span className="text-base font-semibold tracking-tight">{headerTitle}</span>
250
250
  </Link>
251
251
  <nav aria-label="Primary" className="flex items-center gap-1">
252
- <Button asChild variant="ghost" size="sm" className="text-[13px]">
252
+ <Button asChild variant="ghost" size="sm" className="text-sm">
253
253
  <Link href={loginHref}>{t('portal.nav.login', 'Log In')}</Link>
254
254
  </Button>
255
- <Button asChild size="sm" className="rounded-lg text-[13px]">
255
+ <Button asChild size="sm" className="rounded-lg text-sm">
256
256
  <Link href={signupHref}>{t('portal.nav.signup', 'Sign Up')}</Link>
257
257
  </Button>
258
258
  </nav>
@@ -287,12 +287,12 @@ export function PortalShell({
287
287
  <div className="flex h-16 items-center gap-2.5 border-b px-5">
288
288
  <Link href={portalHome} className="flex items-center gap-2.5 text-foreground transition hover:opacity-80" aria-label={headerTitle}>
289
289
  <Image src={logo?.src ?? "/open-mercato.svg"} alt={logo?.alt ?? ""} width={22} height={22} className="" />
290
- <span className="text-[14px] font-semibold tracking-tight truncate">{headerTitle}</span>
290
+ <span className="text-sm font-semibold tracking-tight truncate">{headerTitle}</span>
291
291
  </Link>
292
292
  </div>
293
293
 
294
294
  <nav aria-label="Portal navigation" className="flex-1 overflow-y-auto px-3 py-5">
295
- <p className="mb-2 px-3 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/50">
295
+ <p className="mb-2 px-3 text-overline font-semibold uppercase tracking-widest text-muted-foreground/50">
296
296
  {t('portal.nav.home', 'Portal')}
297
297
  </p>
298
298
  <div className="flex flex-col gap-0.5">
@@ -309,7 +309,7 @@ export function PortalShell({
309
309
 
310
310
  {mergedAccountItems.length > 0 ? (
311
311
  <div className="mt-8">
312
- <p className="mb-2 px-3 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/50">
312
+ <p className="mb-2 px-3 text-overline font-semibold uppercase tracking-widest text-muted-foreground/50">
313
313
  {t('portal.nav.account', 'Account')}
314
314
  </p>
315
315
  <div className="flex flex-col gap-0.5">
@@ -332,12 +332,12 @@ export function PortalShell({
332
332
  <UserAvatar name={userName} className="size-8" />
333
333
  <div className="min-w-0 flex-1">
334
334
  {userName ? (
335
- <p className="truncate text-[13px] font-medium leading-tight">{userName}</p>
335
+ <p className="truncate text-sm font-medium leading-tight">{userName}</p>
336
336
  ) : (
337
337
  <div className="h-4 w-24 animate-pulse rounded bg-muted" />
338
338
  )}
339
339
  {userEmail ? (
340
- <p className="truncate text-[11px] text-muted-foreground">{userEmail}</p>
340
+ <p className="truncate text-overline text-muted-foreground">{userEmail}</p>
341
341
  ) : (
342
342
  <div className="mt-1 h-3 w-32 animate-pulse rounded bg-muted" />
343
343
  )}
@@ -346,7 +346,7 @@ export function PortalShell({
346
346
  <button
347
347
  type="button"
348
348
  onClick={onLogout}
349
- className="mt-0.5 flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
349
+ className="mt-0.5 flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
350
350
  data-portal-handle={PORTAL_USER_MENU_HANDLE}
351
351
  data-menu-item-id="portal-logout"
352
352
  >
@@ -366,8 +366,8 @@ export function PortalShell({
366
366
  </aside>
367
367
 
368
368
  {mobileOpen ? (
369
- <div className="fixed inset-0 z-50 lg:hidden">
370
- <div className="absolute inset-0 bg-black/30 backdrop-blur-sm" onClick={closeMobile} />
369
+ <div className="fixed inset-0 z-modal lg:hidden">
370
+ <div className="absolute inset-0 bg-black/20 backdrop-blur-sm" onClick={closeMobile} />
371
371
  <aside className="relative z-10 h-full w-[280px] bg-background shadow-2xl">
372
372
  <div className="absolute right-3 top-4 z-20">
373
373
  <IconButton variant="ghost" size="sm" type="button" onClick={closeMobile} aria-label="Close menu">
@@ -398,7 +398,7 @@ export function PortalShell({
398
398
  </main>
399
399
 
400
400
  <footer className="border-t px-4 py-4 lg:px-8" data-portal-handle={PORTAL_FOOTER_HANDLE}>
401
- <p className="text-[11px] text-muted-foreground/50">
401
+ <p className="text-overline text-muted-foreground/50">
402
402
  {t('portal.footer.copyright', '\u00A9 {year} All rights reserved.', { year: new Date().getFullYear() })}
403
403
  </p>
404
404
  </footer>
@@ -35,7 +35,7 @@ export function PortalCardHeader({ title, description, label, action }: PortalCa
35
35
  <div className="mb-4 flex items-start justify-between gap-4">
36
36
  <div>
37
37
  {label ? (
38
- <p className="mb-1.5 text-[11px] font-medium uppercase tracking-widest text-muted-foreground/60">
38
+ <p className="mb-1.5 text-overline font-medium uppercase tracking-widest text-muted-foreground/60">
39
39
  {label}
40
40
  </p>
41
41
  ) : null}
@@ -61,7 +61,7 @@ type PortalStatRowProps = {
61
61
  export function PortalStatRow({ label, value }: PortalStatRowProps) {
62
62
  return (
63
63
  <div className="flex items-center justify-between gap-4 py-2.5">
64
- <span className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground/70">
64
+ <span className="text-overline font-medium uppercase tracking-wider text-muted-foreground/70">
65
65
  {label}
66
66
  </span>
67
67
  <span className="text-sm font-medium text-foreground">{value}</span>
@@ -22,10 +22,10 @@ function CheckIcon({ className }: { className?: string }) {
22
22
  }
23
23
 
24
24
  const SEVERITY_STYLES: Record<string, string> = {
25
- info: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
26
- success: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',
27
- warning: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',
28
- error: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400',
25
+ info: 'bg-status-info-bg text-status-info-text',
26
+ success: 'bg-status-success-bg text-status-success-text',
27
+ warning: 'bg-status-warning-bg text-status-warning-text',
28
+ error: 'bg-status-error-bg text-status-error-text',
29
29
  }
30
30
 
31
31
  type Tab = 'all' | 'unread'
@@ -84,19 +84,19 @@ export function PortalNotificationPanel({
84
84
  return (
85
85
  <>
86
86
  {/* Backdrop */}
87
- <div className="fixed inset-0 z-50 bg-black/20 backdrop-blur-sm" onClick={onClose} />
87
+ <div className="fixed inset-0 z-modal bg-black/20 backdrop-blur-sm" onClick={onClose} />
88
88
 
89
89
  {/* Panel */}
90
90
  <div
91
91
  ref={panelRef}
92
- className="fixed right-0 top-0 z-50 flex h-full w-full max-w-md flex-col border-l bg-background shadow-2xl"
92
+ className="fixed right-0 top-0 z-modal flex h-full w-full max-w-md flex-col border-l bg-background shadow-2xl"
93
93
  >
94
94
  {/* Header */}
95
95
  <div className="flex h-16 items-center justify-between border-b px-5">
96
96
  <div>
97
- <h2 className="text-[15px] font-semibold">{t('portal.notifications.title', 'Notifications')}</h2>
97
+ <h2 className="text-base font-semibold">{t('portal.notifications.title', 'Notifications')}</h2>
98
98
  {unreadCount > 0 ? (
99
- <p className="text-[11px] text-muted-foreground">
99
+ <p className="text-overline text-muted-foreground">
100
100
  {t('portal.notifications.unreadSummary', '{count} unread', { count: unreadCount })}
101
101
  </p>
102
102
  ) : null}
@@ -107,7 +107,7 @@ export function PortalNotificationPanel({
107
107
  type="button"
108
108
  variant="ghost"
109
109
  size="sm"
110
- className="text-[12px] text-muted-foreground"
110
+ className="text-xs text-muted-foreground"
111
111
  onClick={() => onMarkAllRead()}
112
112
  >
113
113
  <CheckIcon className="mr-1 size-3.5" />
@@ -127,7 +127,7 @@ export function PortalNotificationPanel({
127
127
  key={tabId}
128
128
  type="button"
129
129
  onClick={() => setTab(tabId)}
130
- className={`border-b-2 px-3 py-2.5 text-[13px] font-medium transition-colors ${
130
+ className={`border-b-2 px-3 py-2.5 text-sm font-medium transition-colors ${
131
131
  tab === tabId
132
132
  ? 'border-foreground text-foreground'
133
133
  : 'border-transparent text-muted-foreground hover:text-foreground'
@@ -137,7 +137,7 @@ export function PortalNotificationPanel({
137
137
  ? t('portal.notifications.tab.all', 'All')
138
138
  : t('portal.notifications.tab.unread', 'Unread')}
139
139
  {tabId === 'unread' && unreadCount > 0 ? (
140
- <span className="ml-1.5 inline-flex size-5 items-center justify-center rounded-full bg-foreground text-[10px] font-bold text-background">
140
+ <span className="ml-1.5 inline-flex size-5 items-center justify-center rounded-full bg-foreground text-overline font-bold text-background">
141
141
  {unreadCount}
142
142
  </span>
143
143
  ) : null}
@@ -164,22 +164,22 @@ export function PortalNotificationPanel({
164
164
  }`}
165
165
  >
166
166
  {/* Severity dot */}
167
- <div className={`mt-1 flex size-8 shrink-0 items-center justify-center rounded-lg text-[10px] font-bold ${SEVERITY_STYLES[notification.severity] ?? SEVERITY_STYLES.info}`}>
167
+ <div className={`mt-1 flex size-8 shrink-0 items-center justify-center rounded-lg text-overline font-bold ${SEVERITY_STYLES[notification.severity] ?? SEVERITY_STYLES.info}`}>
168
168
  {notification.severity.charAt(0).toUpperCase()}
169
169
  </div>
170
170
 
171
171
  {/* Content */}
172
172
  <div className="min-w-0 flex-1">
173
173
  <div className="flex items-start justify-between gap-2">
174
- <p className="text-[13px] font-medium leading-snug">
174
+ <p className="text-sm font-medium leading-snug">
175
175
  {notification.title}
176
176
  </p>
177
- <span className="shrink-0 text-[11px] text-muted-foreground/60">
177
+ <span className="shrink-0 text-overline text-muted-foreground/60">
178
178
  {formatTime(notification.createdAt)}
179
179
  </span>
180
180
  </div>
181
181
  {notification.body ? (
182
- <p className="mt-0.5 text-[12px] leading-relaxed text-muted-foreground">
182
+ <p className="mt-0.5 text-xs leading-relaxed text-muted-foreground">
183
183
  {notification.body}
184
184
  </p>
185
185
  ) : null}
@@ -191,7 +191,7 @@ export function PortalNotificationPanel({
191
191
  type="button"
192
192
  variant="ghost"
193
193
  size="sm"
194
- className="h-auto px-2 py-1 text-[11px] text-muted-foreground"
194
+ className="h-auto px-2 py-1 text-overline text-muted-foreground"
195
195
  onClick={() => onMarkAsRead(notification.id)}
196
196
  >
197
197
  {t('portal.notifications.markRead', 'Mark read')}
@@ -201,7 +201,7 @@ export function PortalNotificationPanel({
201
201
  type="button"
202
202
  variant="ghost"
203
203
  size="sm"
204
- className="h-auto px-2 py-1 text-[11px] text-muted-foreground"
204
+ className="h-auto px-2 py-1 text-overline text-muted-foreground"
205
205
  onClick={() => onDismiss(notification.id)}
206
206
  >
207
207
  {t('portal.notifications.dismiss', 'Dismiss')}
@@ -209,7 +209,7 @@ export function PortalNotificationPanel({
209
209
  {notification.linkHref ? (
210
210
  <a
211
211
  href={notification.linkHref}
212
- className="ml-auto text-[11px] font-medium text-foreground underline underline-offset-2 hover:opacity-80"
212
+ className="ml-auto text-overline font-medium text-foreground underline underline-offset-2 hover:opacity-80"
213
213
  onClick={() => {
214
214
  if (notification.status === 'unread') onMarkAsRead(notification.id)
215
215
  onClose()
@@ -18,7 +18,7 @@ export function PortalPageHeader({ title, description, label, action }: PortalPa
18
18
  <div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
19
19
  <div>
20
20
  {label ? (
21
- <p className="mb-1 text-[11px] font-medium uppercase tracking-widest text-muted-foreground/60">
21
+ <p className="mb-1 text-overline font-medium uppercase tracking-widest text-muted-foreground/60">
22
22
  {label}
23
23
  </p>
24
24
  ) : null}