@open-mercato/ui 0.5.1-develop.2856.35de414092 → 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.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +204 -121
- package/dist/backend/AppShell.js +25 -28
- package/dist/backend/AppShell.js.map +2 -2
- package/dist/backend/ContextHelp.js +1 -1
- package/dist/backend/ContextHelp.js.map +1 -1
- package/dist/backend/CrudForm.js +12 -15
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +9 -10
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/FilterBar.js +6 -8
- package/dist/backend/FilterBar.js.map +2 -2
- package/dist/backend/FilterOverlay.js +10 -10
- package/dist/backend/FilterOverlay.js.map +2 -2
- package/dist/backend/FlashMessages.js +1 -1
- package/dist/backend/FlashMessages.js.map +2 -2
- package/dist/backend/JsonBuilder.js +6 -6
- package/dist/backend/JsonBuilder.js.map +1 -1
- package/dist/backend/NextStepCallout.js +1 -1
- package/dist/backend/NextStepCallout.js.map +1 -1
- package/dist/backend/PerspectiveSidebar.js +2 -2
- package/dist/backend/PerspectiveSidebar.js.map +2 -2
- package/dist/backend/ProfileDropdown.js +1 -1
- package/dist/backend/ProfileDropdown.js.map +1 -1
- package/dist/backend/RowActions.js +1 -1
- package/dist/backend/RowActions.js.map +1 -1
- package/dist/backend/UserMenu.js +2 -2
- package/dist/backend/UserMenu.js.map +1 -1
- package/dist/backend/WebhookSetupGuide.js +11 -11
- package/dist/backend/WebhookSetupGuide.js.map +2 -2
- package/dist/backend/charts/KpiCard.js +3 -3
- package/dist/backend/charts/KpiCard.js.map +1 -1
- package/dist/backend/columns/ColumnChooserPanel.js +1 -1
- package/dist/backend/columns/ColumnChooserPanel.js.map +2 -2
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js +3 -3
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +2 -2
- package/dist/backend/dashboard/DashboardScreen.js +1 -1
- package/dist/backend/dashboard/DashboardScreen.js.map +1 -1
- package/dist/backend/date-range/DateRangeSelect.js +1 -1
- package/dist/backend/date-range/DateRangeSelect.js.map +1 -1
- package/dist/backend/date-range/InlineDateRangeSelect.js +1 -1
- package/dist/backend/date-range/InlineDateRangeSelect.js.map +1 -1
- package/dist/backend/detail/AccessDeniedMessage.js +1 -1
- package/dist/backend/detail/AccessDeniedMessage.js.map +1 -1
- package/dist/backend/detail/ActivitiesSection.js +5 -5
- package/dist/backend/detail/ActivitiesSection.js.map +1 -1
- package/dist/backend/detail/AddressEditor.js +3 -3
- package/dist/backend/detail/AddressEditor.js.map +2 -2
- package/dist/backend/detail/AddressTiles.js +3 -3
- package/dist/backend/detail/AddressTiles.js.map +2 -2
- package/dist/backend/detail/AttachmentMetadataDialog.js +1 -1
- package/dist/backend/detail/AttachmentMetadataDialog.js.map +1 -1
- package/dist/backend/detail/CustomDataSection.js +1 -1
- package/dist/backend/detail/CustomDataSection.js.map +1 -1
- package/dist/backend/detail/InlineEditors.js +5 -5
- package/dist/backend/detail/InlineEditors.js.map +1 -1
- package/dist/backend/detail/NotesSection.js +6 -6
- package/dist/backend/detail/NotesSection.js.map +1 -1
- package/dist/backend/detail/TagsSection.js +1 -1
- package/dist/backend/detail/TagsSection.js.map +1 -1
- package/dist/backend/devtools/UmesDevToolsPanel.js +6 -6
- package/dist/backend/devtools/UmesDevToolsPanel.js.map +2 -2
- package/dist/backend/devtools/components/ConflictWarnings.js +3 -3
- package/dist/backend/devtools/components/ConflictWarnings.js.map +2 -2
- package/dist/backend/devtools/components/EnricherTiming.js +2 -2
- package/dist/backend/devtools/components/EnricherTiming.js.map +2 -2
- package/dist/backend/devtools/components/EventFlow.js +5 -5
- package/dist/backend/devtools/components/EventFlow.js.map +2 -2
- package/dist/backend/devtools/components/ExtensionPointList.js +3 -3
- package/dist/backend/devtools/components/ExtensionPointList.js.map +2 -2
- package/dist/backend/devtools/components/InterceptorActivity.js +6 -6
- package/dist/backend/devtools/components/InterceptorActivity.js.map +2 -2
- package/dist/backend/forms/ActionsDropdown.js +1 -1
- package/dist/backend/forms/ActionsDropdown.js.map +1 -1
- package/dist/backend/forms/FormActionButtons.js +2 -3
- package/dist/backend/forms/FormActionButtons.js.map +2 -2
- package/dist/backend/indexes/PartialIndexBanner.js +8 -8
- package/dist/backend/indexes/PartialIndexBanner.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js +1 -1
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/dist/backend/inputs/DatePicker.js +3 -3
- package/dist/backend/inputs/DatePicker.js.map +1 -1
- package/dist/backend/inputs/DateTimePicker.js +3 -3
- package/dist/backend/inputs/DateTimePicker.js.map +1 -1
- package/dist/backend/inputs/EventSelect.js +1 -1
- package/dist/backend/inputs/EventSelect.js.map +2 -2
- package/dist/backend/inputs/LookupSelect.js +1 -1
- package/dist/backend/inputs/LookupSelect.js.map +1 -1
- package/dist/backend/inputs/SwitchableMarkdownInput.js +1 -1
- package/dist/backend/inputs/SwitchableMarkdownInput.js.map +1 -1
- package/dist/backend/inputs/TagsInput.js +2 -2
- package/dist/backend/inputs/TagsInput.js.map +2 -2
- package/dist/backend/inputs/TimeInput.js +1 -1
- package/dist/backend/inputs/TimeInput.js.map +1 -1
- package/dist/backend/inputs/TimePicker.js +3 -3
- package/dist/backend/inputs/TimePicker.js.map +1 -1
- package/dist/backend/messages/MessageObjectDetail.js +1 -1
- package/dist/backend/messages/MessageObjectDetail.js.map +1 -1
- package/dist/backend/messages/MessageObjectPreview.js +1 -1
- package/dist/backend/messages/MessageObjectPreview.js.map +1 -1
- package/dist/backend/messages/message-compose-form-groups.js +3 -3
- package/dist/backend/messages/message-compose-form-groups.js.map +1 -1
- package/dist/backend/notifications/NotificationCountBadge.js +1 -1
- package/dist/backend/notifications/NotificationCountBadge.js.map +2 -2
- package/dist/backend/notifications/NotificationPanel.js +3 -3
- package/dist/backend/notifications/NotificationPanel.js.map +1 -1
- package/dist/backend/progress/ProgressTopBar.js +4 -4
- package/dist/backend/progress/ProgressTopBar.js.map +2 -2
- package/dist/backend/schedule/ScheduleAgenda.js +1 -1
- package/dist/backend/schedule/ScheduleAgenda.js.map +2 -2
- package/dist/backend/schedule/ScheduleCalendar.js +1 -1
- package/dist/backend/schedule/ScheduleCalendar.js.map +1 -1
- package/dist/backend/schedule/ScheduleGrid.js +1 -1
- package/dist/backend/schedule/ScheduleGrid.js.map +2 -2
- package/dist/backend/version-history/VersionHistoryPanel.js +4 -4
- package/dist/backend/version-history/VersionHistoryPanel.js.map +2 -2
- package/dist/frontend/AuthFooter.js +1 -1
- package/dist/frontend/AuthFooter.js.map +1 -1
- package/dist/frontend/LanguageSwitcher.js +1 -1
- package/dist/frontend/LanguageSwitcher.js.map +1 -1
- package/dist/frontend/Layout.js +2 -2
- package/dist/frontend/Layout.js.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +2 -2
- package/dist/portal/PortalShell.js +15 -15
- package/dist/portal/PortalShell.js.map +2 -2
- package/dist/portal/components/PortalCard.js +2 -2
- package/dist/portal/components/PortalCard.js.map +2 -2
- package/dist/portal/components/PortalNotificationPanel.js +18 -18
- package/dist/portal/components/PortalNotificationPanel.js.map +2 -2
- package/dist/portal/components/PortalPageHeader.js +1 -1
- package/dist/portal/components/PortalPageHeader.js.map +2 -2
- package/dist/primitives/avatar.js +11 -1
- package/dist/primitives/avatar.js.map +2 -2
- package/dist/primitives/badge.js +1 -1
- package/dist/primitives/badge.js.map +1 -1
- package/dist/primitives/button.js +9 -5
- package/dist/primitives/button.js.map +2 -2
- package/dist/primitives/calendar.js +1 -1
- package/dist/primitives/calendar.js.map +1 -1
- package/dist/primitives/checkbox-field.js +63 -0
- package/dist/primitives/checkbox-field.js.map +7 -0
- package/dist/primitives/checkbox.js +31 -17
- package/dist/primitives/checkbox.js.map +2 -2
- package/dist/primitives/dialog.js +4 -4
- package/dist/primitives/dialog.js.map +1 -1
- package/dist/primitives/fancy-button.js +72 -0
- package/dist/primitives/fancy-button.js.map +7 -0
- package/dist/primitives/icon-button.js +20 -4
- package/dist/primitives/icon-button.js.map +2 -2
- package/dist/primitives/kbd.js +27 -0
- package/dist/primitives/kbd.js.map +7 -0
- package/dist/primitives/link-button.js +56 -0
- package/dist/primitives/link-button.js.map +7 -0
- package/dist/primitives/popover.js +1 -1
- package/dist/primitives/popover.js.map +1 -1
- package/dist/primitives/social-button.js +61 -0
- package/dist/primitives/social-button.js.map +7 -0
- package/dist/primitives/tabs.js +1 -1
- package/dist/primitives/tabs.js.map +1 -1
- package/dist/primitives/tag.js +45 -0
- package/dist/primitives/tag.js.map +7 -0
- package/dist/primitives/tooltip.js +1 -1
- package/dist/primitives/tooltip.js.map +1 -1
- package/package.json +3 -3
- package/src/backend/AppShell.tsx +25 -28
- package/src/backend/ContextHelp.tsx +1 -1
- package/src/backend/CrudForm.tsx +12 -15
- package/src/backend/DataTable.tsx +9 -10
- package/src/backend/FilterBar.tsx +6 -5
- package/src/backend/FilterOverlay.tsx +10 -10
- package/src/backend/FlashMessages.tsx +1 -1
- package/src/backend/JsonBuilder.tsx +6 -6
- package/src/backend/NextStepCallout.tsx +1 -1
- package/src/backend/PerspectiveSidebar.tsx +2 -2
- package/src/backend/ProfileDropdown.tsx +1 -1
- package/src/backend/RowActions.tsx +1 -1
- package/src/backend/UserMenu.tsx +2 -2
- package/src/backend/WebhookSetupGuide.tsx +11 -11
- package/src/backend/charts/KpiCard.tsx +3 -3
- package/src/backend/columns/ColumnChooserPanel.tsx +1 -1
- package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +3 -3
- package/src/backend/dashboard/DashboardScreen.tsx +1 -1
- package/src/backend/date-range/DateRangeSelect.tsx +1 -1
- package/src/backend/date-range/InlineDateRangeSelect.tsx +1 -1
- package/src/backend/detail/AccessDeniedMessage.tsx +1 -1
- package/src/backend/detail/ActivitiesSection.tsx +5 -5
- package/src/backend/detail/AddressEditor.tsx +3 -3
- package/src/backend/detail/AddressTiles.tsx +3 -3
- package/src/backend/detail/AttachmentMetadataDialog.tsx +1 -1
- package/src/backend/detail/CustomDataSection.tsx +1 -1
- package/src/backend/detail/InlineEditors.tsx +5 -5
- package/src/backend/detail/NotesSection.tsx +6 -6
- package/src/backend/detail/TagsSection.tsx +1 -1
- package/src/backend/devtools/UmesDevToolsPanel.tsx +6 -6
- package/src/backend/devtools/components/ConflictWarnings.tsx +4 -4
- package/src/backend/devtools/components/EnricherTiming.tsx +2 -2
- package/src/backend/devtools/components/EventFlow.tsx +5 -5
- package/src/backend/devtools/components/ExtensionPointList.tsx +3 -3
- package/src/backend/devtools/components/InterceptorActivity.tsx +6 -6
- package/src/backend/forms/ActionsDropdown.tsx +1 -1
- package/src/backend/forms/FormActionButtons.tsx +4 -5
- package/src/backend/indexes/PartialIndexBanner.tsx +8 -8
- package/src/backend/inputs/ComboboxInput.tsx +1 -1
- package/src/backend/inputs/DatePicker.tsx +3 -3
- package/src/backend/inputs/DateTimePicker.tsx +3 -3
- package/src/backend/inputs/EventSelect.tsx +1 -1
- package/src/backend/inputs/LookupSelect.tsx +1 -1
- package/src/backend/inputs/SwitchableMarkdownInput.tsx +1 -1
- package/src/backend/inputs/TagsInput.tsx +2 -2
- package/src/backend/inputs/TimeInput.tsx +1 -1
- package/src/backend/inputs/TimePicker.tsx +3 -3
- package/src/backend/messages/MessageObjectDetail.tsx +1 -1
- package/src/backend/messages/MessageObjectPreview.tsx +1 -1
- package/src/backend/messages/message-compose-form-groups.tsx +3 -3
- package/src/backend/notifications/NotificationCountBadge.tsx +1 -1
- package/src/backend/notifications/NotificationPanel.tsx +3 -3
- package/src/backend/progress/ProgressTopBar.tsx +4 -4
- package/src/backend/schedule/ScheduleAgenda.tsx +1 -1
- package/src/backend/schedule/ScheduleCalendar.tsx +1 -1
- package/src/backend/schedule/ScheduleGrid.tsx +1 -1
- package/src/backend/version-history/VersionHistoryPanel.tsx +4 -4
- package/src/frontend/AuthFooter.tsx +1 -1
- package/src/frontend/LanguageSwitcher.tsx +1 -1
- package/src/frontend/Layout.tsx +2 -2
- package/src/index.ts +6 -1
- package/src/portal/PortalShell.tsx +15 -15
- package/src/portal/components/PortalCard.tsx +2 -2
- package/src/portal/components/PortalNotificationPanel.tsx +18 -18
- package/src/portal/components/PortalPageHeader.tsx +1 -1
- package/src/primitives/avatar.tsx +22 -0
- package/src/primitives/badge.tsx +1 -1
- package/src/primitives/button.tsx +12 -5
- package/src/primitives/calendar.tsx +1 -1
- package/src/primitives/checkbox-field.tsx +85 -0
- package/src/primitives/checkbox.tsx +44 -18
- package/src/primitives/dialog.tsx +4 -4
- package/src/primitives/fancy-button.tsx +89 -0
- package/src/primitives/icon-button.tsx +19 -2
- package/src/primitives/kbd.tsx +38 -0
- package/src/primitives/link-button.tsx +55 -0
- package/src/primitives/popover.tsx +1 -1
- package/src/primitives/social-button.tsx +80 -0
- package/src/primitives/tabs.tsx +1 -1
- package/src/primitives/tag.tsx +66 -0
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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/
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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/
|
|
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-
|
|
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-
|
|
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-
|
|
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/
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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/
|
|
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-
|
|
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/
|
|
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-
|
|
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}
|
package/src/frontend/Layout.tsx
CHANGED
|
@@ -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/
|
|
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/
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
370
|
-
<div className="absolute inset-0 bg-black/
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
26
|
-
success: 'bg-
|
|
27
|
-
warning: 'bg-
|
|
28
|
-
error: 'bg-
|
|
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-
|
|
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-
|
|
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-
|
|
97
|
+
<h2 className="text-base font-semibold">{t('portal.notifications.title', 'Notifications')}</h2>
|
|
98
98
|
{unreadCount > 0 ? (
|
|
99
|
-
<p className="text-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
174
|
+
<p className="text-sm font-medium leading-snug">
|
|
175
175
|
{notification.title}
|
|
176
176
|
</p>
|
|
177
|
-
<span className="shrink-0 text-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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}
|