@agent-native/core 0.180.0-nightly-20260915184036 → 0.180.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +10 -0
  3. package/corpus/templates/calendar/CHANGELOG.md +39 -0
  4. package/corpus/templates/calendar/INTERACTION-MATRIX.md +19 -17
  5. package/corpus/templates/calendar/actions/update-calendar-visual-preferences.ts +21 -0
  6. package/corpus/templates/calendar/actions/view-screen.ts +10 -2
  7. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +11 -0
  8. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +174 -145
  9. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +20 -16
  10. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +1 -0
  11. package/corpus/templates/calendar/app/hooks/use-events.ts +16 -0
  12. package/corpus/templates/calendar/app/hooks/use-view-preferences.ts +126 -14
  13. package/corpus/templates/calendar/app/i18n-data.ts +90 -0
  14. package/corpus/templates/calendar/app/lib/calendar-navigation.ts +29 -9
  15. package/corpus/templates/calendar/app/lib/calendar-timezone.ts +2 -0
  16. package/corpus/templates/calendar/app/lib/event-time-range.ts +34 -0
  17. package/corpus/templates/calendar/app/pages/CalendarView.tsx +245 -35
  18. package/corpus/templates/calendar/changelog/2026-09-13-calendar-sidebar-overflow-is-easier-to-discover.md +6 -0
  19. package/corpus/templates/calendar/changelog/2026-09-15-calendar-mirrors-notion-calendar-s-customizable-day-ranges-a.md +6 -0
  20. package/corpus/templates/calendar/shared/calendar-view-preferences.ts +36 -0
  21. package/corpus/templates/calendar/shared/timezone.ts +9 -2
  22. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +2 -0
  23. package/corpus/templates/clips/CHANGELOG.md +19 -0
  24. package/corpus/templates/clips/actions/save-browser-diagnostics.ts +43 -4
  25. package/corpus/templates/clips/app/components/player/browser-diagnostics-panel.tsx +114 -1
  26. package/corpus/templates/clips/app/i18n/en-US.ts +7 -0
  27. package/corpus/templates/clips/app/lib/browser-diagnostics-capture.ts +108 -0
  28. package/corpus/templates/clips/app/routes/record.tsx +1 -0
  29. package/corpus/templates/clips/changelog/2026-09-15-recordings-include-a-structured-timeline-of-browser-interact.md +6 -0
  30. package/corpus/templates/clips/chrome-extension/public/manifest.json +7 -0
  31. package/corpus/templates/clips/chrome-extension/src/background.ts +235 -9
  32. package/corpus/templates/clips/chrome-extension/src/content-history-bridge.ts +80 -0
  33. package/corpus/templates/clips/chrome-extension/src/content-script.ts +166 -5
  34. package/corpus/templates/clips/chrome-extension/vite.config.ts +4 -0
  35. package/corpus/templates/clips/server/db/schema.ts +3 -0
  36. package/corpus/templates/clips/server/lib/public-agent-context.ts +40 -2
  37. package/corpus/templates/clips/server/plugins/db.ts +5 -0
  38. package/corpus/templates/clips/shared/browser-diagnostics.ts +171 -0
  39. package/corpus/templates/content/.agents/skills/content/SKILL.md +4 -2
  40. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +8 -1
  41. package/corpus/templates/content/AGENTS.md +5 -6
  42. package/corpus/templates/content/CHANGELOG.md +24 -0
  43. package/corpus/templates/content/actions/_content-database-row-migration.ts +67 -36
  44. package/corpus/templates/content/actions/_document-edit-mutation.ts +74 -23
  45. package/corpus/templates/content/actions/edit-document.ts +48 -8
  46. package/corpus/templates/content/actions/migrate-content-database-rows.ts +69 -28
  47. package/corpus/templates/content/server/plugins/agent-chat.ts +1 -1
  48. package/corpus/templates/design/CHANGELOG.md +22 -0
  49. package/corpus/templates/factory/CHANGELOG.md +11 -0
  50. package/corpus/templates/forms/CHANGELOG.md +6 -0
  51. package/corpus/templates/mail/.agents/skills/mail-interaction-parity/references/interaction-matrix.md +24 -4
  52. package/corpus/templates/mail/CHANGELOG.md +68 -0
  53. package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +8 -0
  54. package/corpus/templates/mail/app/components/email/ComposeModal.tsx +33 -13
  55. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +23 -4
  56. package/corpus/templates/mail/app/components/email/EmailThread.tsx +56 -13
  57. package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +23 -4
  58. package/corpus/templates/mail/app/components/email/RecipientInput.tsx +9 -0
  59. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +8 -1
  60. package/corpus/templates/mail/app/i18n/en-US.ts +31 -0
  61. package/corpus/templates/mail/changelog/2026-09-15-mail-labels-recipient-and-account-controls-for-keyboard-and-.md +6 -0
  62. package/corpus/templates/slides/CHANGELOG.md +32 -0
  63. package/dist/client/CommandMenu.js +14 -2
  64. package/dist/client/settings/AccountSettingsCard.js +3 -2
  65. package/dist/client/settings/SettingsTabsPage.js +9 -1
  66. package/dist/client/settings/agent-settings-search.js +5 -1
  67. package/dist/client/sign-out.d.ts +1 -0
  68. package/dist/client/sign-out.js +8 -0
  69. package/dist/collab/routes.d.ts +1 -1
  70. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  71. package/dist/observability/routes.d.ts +3 -3
  72. package/dist/org/handlers.d.ts +1 -1
  73. package/dist/resources/handlers.d.ts +1 -1
  74. package/dist/secrets/routes.d.ts +3 -3
  75. package/dist/server/agent-engine-api-key-route.d.ts +2 -2
  76. package/dist/server/transcribe-voice.d.ts +1 -1
  77. package/package.json +4 -4
@@ -22,6 +22,18 @@ interaction is safe and repeatable. Report `n`, p50, and empirical p95 only at
22
22
  `n >= 30`; below that, report `n`, median, and range, and mark p95 unsupported.
23
23
  Do not treat live provider-send time as a client-latency benchmark.
24
24
 
25
+ Captured evidence for the post-fix head `7d080b8` is available in the
26
+ [dark visual recap image](https://plan.agent-native.com/_agent-native/recap-image/e56aa10a91f59d04e12cb7e2e816fc8f0700614d7ef240fe1fba40a2f6162edb.png?v=34988715504-1)
27
+ and [light visual recap image](https://plan.agent-native.com/_agent-native/recap-image/af44730d61a368149a97eb899203d847433e574878dd979ff1610cc2b2b1205f.png?v=34988715504-1).
28
+ Captions: the inbox/list panel shows localized row-action labels and the
29
+ account-filter popover; the compact compose panel shows localized recipient and
30
+ compose controls; the thread panel shows the localized conversation controls.
31
+ The before/after layout comparison is recorded in COMPOSE-001: the previous
32
+ Mail card was 540px by 520px at bottom-right, while the post-fix desktop card
33
+ is 490px by 300px near the top of the workspace. Inline CUA captures in the
34
+ task also show the post-fix no-results Search and Command palette states, but
35
+ no stable local screenshot artifact was returned for those captures.
36
+
25
37
  Unverified local performance lead (reported 2026-09-14 by the coordinating
26
38
  task, not a controlled profile): the normal Mail server logged about 408
27
39
  requests over 23 minutes. Repeated `GET /api/emails` and
@@ -458,10 +470,18 @@ app/hooks/use-undo.test.tsx app/components/email/EmailList.keyboard-navigation.t
458
470
  pane; Mail's prior card was fixed bottom-right, 540px wide, and 520px tall.
459
471
  The follow-up source change now uses a 490px-wide, 300px-tall desktop card
460
472
  positioned near the top while preserving the full-height mobile layout and
461
- explicit fullscreen branch. A local visual replay after this change is
462
- pending because the Mail browser tab is currently at its sign-in gate; no
463
- login or live provider action was performed, so no global parity claim is
464
- made.
473
+ explicit fullscreen branch. A follow-up local CUA replay on 2026-09-15 at
474
+ 1280x720 confirmed the compact inbox, thread, and compose states after the
475
+ change, including the named account filter, recipient removal control, and
476
+ To combobox. The same replay opened and dismissed no-results Search and the
477
+ Command palette, found no unlabeled buttons, and reported no browser console
478
+ errors. Search open measured n=30, p50=273.9ms, empirical p95=281.2ms;
479
+ Command palette open measured n=30, p50=63.3ms, empirical p95=102.1ms.
480
+ These are local UI/harness observations, not provider or global performance
481
+ proof. Captures were shown inline in the task; CUA returned no stable image
482
+ artifact path. The only connected account was steve@builder.io, so the
483
+ separate sewell.steve@gmail.com provider round trip and all send/reply
484
+ mutation cases remain unverified; no email was sent.
465
485
  - COMPOSE-002 — Minimize, restore, fullscreen, pop out, close, close all, switch
466
486
  draft tabs, create a second draft, and reopen a closed draft. Test mouse,
467
487
  keyboard, outside click, Escape, and browser navigation. On 2026-09-14,
@@ -3,6 +3,74 @@
3
3
  All notable user-facing changes to Agent-Native Mail are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-09-15
7
+
8
+ ### Improved
9
+
10
+ - Mail labels recipient and account controls for keyboard and assistive-technology parity.
11
+ - Match Superhuman's compact compose card geometry on desktop
12
+
13
+ ### Fixed
14
+
15
+ - New drafts focus the To field immediately for keyboard-first composing
16
+
17
+ ## 2026-09-14
18
+
19
+ ### Added
20
+
21
+ - Find implemented keyboard shortcuts by context from the Command menu.
22
+
23
+ ### Improved
24
+
25
+ - Choose a send time by typing a date or time in natural language.
26
+ - Keyboard navigation keeps recipient suggestions visible
27
+ - Mail Trash shortcuts now also support #
28
+ - Make Mail search clear buttons keyboard-activatable while preserving input focus
29
+ - New and reopened drafts open in a compact compose card, with fullscreen opt-in.
30
+ - Replies can be sent and marked Done with a shortcut or preference
31
+ - Screen readers can identify Mail's Search and clear controls.
32
+ - Send Later and Send + Mark Done are available in the compose command palette
33
+
34
+ ### Fixed
35
+
36
+ - Canceled inbox swipes no longer suppress the next tap on a message.
37
+ - Expired multi-key shortcuts no longer fire after a layout refresh.
38
+ - Mail move actions stay on the selected mailbox account
39
+ - Mail now prompts you to finish or clear recipient text before sending or scheduling.
40
+ - Mail triage actions stay on the selected mailbox account
41
+ - Recipient autocomplete resets its highlighted suggestion when the search query changes.
42
+ - Search works on keyboard layouts that require Shift to type the slash key.
43
+ - Starting another draft brings it into view even when an existing draft is minimized.
44
+ - The message-list A shortcut now opens a Reply All draft
45
+ - Forward drafts now retain the original message attachments
46
+ - Undo for archive and trash actions now targets only the latest operation and expires after 10 seconds.
47
+
48
+ ## 2026-09-13
49
+
50
+ ### Added
51
+
52
+ - Compose can suggest common phrases on desktop when autocomplete is enabled
53
+
54
+ ### Improved
55
+
56
+ - Escape clears the command search before closing the palette and returns focus to the control that opened it.
57
+ - Tab stays in compose fields, and a shortcut opens Bcc directly.
58
+
59
+ ### Fixed
60
+
61
+ - All Mail and Archive now show their correct keyboard shortcuts in the command palette.
62
+ - Drafts and sent messages now use the selected Gmail account.
63
+ - Fixed Mail to keep scheduled sends bound to the selected account, validate recipients, and report incomplete account and move operations.
64
+ - G+A now opens All Mail instead of Archive.
65
+ - Gmail drafts report account refresh failures clearly, and multi-account inbox sync avoids repeated lookups.
66
+ - Harden scheduled sends and mixed-account moves; localize move confirmations.
67
+ - Mail chooses a usable connected account when the default mailbox cannot refresh
68
+ - Mail fetches labels from a managed Gmail account when its cache is empty alongside OAuth accounts
69
+ - Mail no longer shows a failed OAuth account as connected through a same-address workspace grant.
70
+ - Mail reports Gmail account read failures instead of showing incomplete results as empty.
71
+ - Search and recipient autocomplete keep keyboard selection aligned with current suggestions
72
+ - Search opens and focuses from the command menu
73
+
6
74
  ## 2026-09-12
7
75
 
8
76
  ### Improved
@@ -296,6 +296,7 @@ export function ComposeBubbleToolbar({
296
296
  <input
297
297
  autoFocus
298
298
  type="url"
299
+ aria-label={t("mail.compose.enterLinkUrl")}
299
300
  placeholder={t("mail.compose.pasteLink")}
300
301
  value={linkUrl}
301
302
  onChange={(e) => setLinkUrl(e.target.value)}
@@ -309,6 +310,7 @@ export function ComposeBubbleToolbar({
309
310
  className="bg-transparent border-none outline-none text-popover-foreground text-sm w-48 px-1 py-0.5 placeholder:text-muted-foreground"
310
311
  />
311
312
  <button
313
+ type="button"
312
314
  onClick={handleSetLink}
313
315
  className="text-xs text-primary hover:text-primary/80 px-1.5 py-0.5 font-medium"
314
316
  >
@@ -331,6 +333,7 @@ export function ComposeBubbleToolbar({
331
333
  <>
332
334
  <textarea
333
335
  autoFocus
336
+ aria-label={t("mail.compose.aiAssist")}
334
337
  placeholder={t("mail.compose.aiAssistPlaceholder")}
335
338
  value={aiPrompt}
336
339
  rows={2}
@@ -352,6 +355,7 @@ export function ComposeBubbleToolbar({
352
355
  <Tooltip>
353
356
  <TooltipTrigger asChild>
354
357
  <button
358
+ type="button"
355
359
  onClick={() => void handleAiAssist()}
356
360
  className="text-xs text-primary hover:text-primary/80 px-1.5 py-0.5 font-medium shrink-0 self-end pb-1"
357
361
  >
@@ -390,6 +394,8 @@ export function ComposeBubbleToolbar({
390
394
  <Tooltip key={title}>
391
395
  <TooltipTrigger asChild>
392
396
  <button
397
+ type="button"
398
+ aria-label={title}
393
399
  onClick={action}
394
400
  className={cn(
395
401
  "p-1.5 rounded transition-colors",
@@ -409,6 +415,8 @@ export function ComposeBubbleToolbar({
409
415
  <Tooltip>
410
416
  <TooltipTrigger asChild>
411
417
  <button
418
+ type="button"
419
+ aria-label={t("mail.compose.aiAssist")}
412
420
  onMouseDown={(e) => {
413
421
  e.preventDefault();
414
422
  e.stopPropagation();
@@ -128,10 +128,12 @@ function FromAccountSelector({
128
128
  accounts,
129
129
  value,
130
130
  onChange,
131
+ label,
131
132
  }: {
132
133
  accounts: ComposeAccount[];
133
134
  value: string | undefined;
134
135
  onChange: (email: string) => void;
136
+ label: string;
135
137
  }) {
136
138
  // On mount, if no account is set, apply the sticky default
137
139
  const resolvedValue =
@@ -154,7 +156,7 @@ function FromAccountSelector({
154
156
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
155
157
 
156
158
  return (
157
- <ComposeFieldRow label="From">
159
+ <ComposeFieldRow label={label}>
158
160
  <Select
159
161
  value={resolvedValue}
160
162
  onValueChange={(email) => {
@@ -819,13 +821,13 @@ export function ComposeModal({
819
821
 
820
822
  const title = activeDraft
821
823
  ? activeDraft.queuedDraftId
822
- ? "Queued draft"
824
+ ? t("mail.compose.queuedDraft")
823
825
  : activeDraft.mode === "reply"
824
- ? "Reply"
826
+ ? t("mail.compose.reply")
825
827
  : activeDraft.mode === "forward"
826
- ? "Forward"
827
- : "New message"
828
- : "New message";
828
+ ? t("mail.compose.forward")
829
+ : t("mail.compose.newMessage")
830
+ : t("mail.compose.newMessage");
829
831
 
830
832
  const composeStyle = {
831
833
  right: isMobile ? 0 : sidebarRight,
@@ -865,12 +867,12 @@ export function ComposeModal({
865
867
  const label =
866
868
  draft.subject?.trim() ||
867
869
  (draft.queuedDraftId
868
- ? "Queued draft"
870
+ ? t("mail.compose.queuedDraft")
869
871
  : draft.mode === "reply"
870
- ? "Reply"
872
+ ? t("mail.compose.reply")
871
873
  : draft.mode === "forward"
872
- ? "Forward"
873
- : "New message");
874
+ ? t("mail.compose.forward")
875
+ : t("mail.compose.newMessage"));
874
876
  return (
875
877
  <button
876
878
  key={draft.id}
@@ -905,6 +907,8 @@ export function ComposeModal({
905
907
  <Tooltip>
906
908
  <TooltipTrigger asChild>
907
909
  <button
910
+ type="button"
911
+ aria-label={t("mail.compose.newDraft")}
908
912
  onClick={onNewDraft}
909
913
  className="flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground/50 hover:text-foreground hover:bg-accent/30 transition-colors"
910
914
  >
@@ -982,8 +986,10 @@ export function ComposeModal({
982
986
  <Button
983
987
  variant="ghost"
984
988
  size="icon"
989
+ type="button"
985
990
  className="h-7 w-7"
986
991
  onClick={onCloseAll}
992
+ aria-label={t("mail.compose.closeAllDrafts")}
987
993
  >
988
994
  <IconX className="h-3.5 w-3.5" />
989
995
  </Button>
@@ -998,13 +1004,14 @@ export function ComposeModal({
998
1004
  <FromAccountSelector
999
1005
  accounts={allAccounts}
1000
1006
  value={activeDraft.accountEmail}
1007
+ label={t("mail.compose.from")}
1001
1008
  onChange={(email) =>
1002
1009
  onUpdate(activeId!, { accountEmail: email })
1003
1010
  }
1004
1011
  />
1005
1012
  )}
1006
1013
  <ComposeFieldRow
1007
- label="To"
1014
+ label={t("mail.compose.to")}
1008
1015
  trailing={
1009
1016
  <button
1010
1017
  type="button"
@@ -1033,6 +1040,7 @@ export function ComposeModal({
1033
1040
  value={activeDraft.to}
1034
1041
  onChange={(val) => onUpdate(activeId!, { to: val })}
1035
1042
  autoFocus={activeDraft.mode === "compose"}
1043
+ ariaLabel={t("mail.compose.toRecipients")}
1036
1044
  field="to"
1037
1045
  onMoveRecipient={moveRecipient}
1038
1046
  />
@@ -1040,18 +1048,20 @@ export function ComposeModal({
1040
1048
 
1041
1049
  {showCcBcc && (
1042
1050
  <>
1043
- <ComposeFieldRow label="Cc">
1051
+ <ComposeFieldRow label={t("mail.compose.cc")}>
1044
1052
  <RecipientInput
1045
1053
  value={activeDraft.cc ?? ""}
1046
1054
  onChange={(val) => onUpdate(activeId!, { cc: val })}
1055
+ ariaLabel={t("mail.compose.ccRecipients")}
1047
1056
  field="cc"
1048
1057
  onMoveRecipient={moveRecipient}
1049
1058
  />
1050
1059
  </ComposeFieldRow>
1051
- <ComposeFieldRow label="Bcc">
1060
+ <ComposeFieldRow label={t("mail.compose.bcc")}>
1052
1061
  <RecipientInput
1053
1062
  value={activeDraft.bcc ?? ""}
1054
1063
  onChange={(val) => onUpdate(activeId!, { bcc: val })}
1064
+ ariaLabel={t("mail.compose.bccRecipients")}
1055
1065
  field="bcc"
1056
1066
  onMoveRecipient={moveRecipient}
1057
1067
  />
@@ -1107,6 +1117,8 @@ export function ComposeModal({
1107
1117
  <Button
1108
1118
  variant="ghost"
1109
1119
  size="icon"
1120
+ type="button"
1121
+ aria-label={t("mail.compose.bold")}
1110
1122
  className="h-7 w-7"
1111
1123
  onClick={() => editorRef.current?.toggleBold()}
1112
1124
  >
@@ -1120,6 +1132,8 @@ export function ComposeModal({
1120
1132
  <Button
1121
1133
  variant="ghost"
1122
1134
  size="icon"
1135
+ type="button"
1136
+ aria-label={t("mail.compose.italic")}
1123
1137
  className="h-7 w-7"
1124
1138
  onClick={() => editorRef.current?.toggleItalic()}
1125
1139
  >
@@ -1133,6 +1147,8 @@ export function ComposeModal({
1133
1147
  <Button
1134
1148
  variant="ghost"
1135
1149
  size="icon"
1150
+ type="button"
1151
+ aria-label={t("mail.compose.insertLink")}
1136
1152
  className="h-7 w-7"
1137
1153
  onClick={() => editorRef.current?.setLink()}
1138
1154
  >
@@ -1146,6 +1162,8 @@ export function ComposeModal({
1146
1162
  <Button
1147
1163
  variant="ghost"
1148
1164
  size="icon"
1165
+ type="button"
1166
+ aria-label={t("mail.compose.attachFile")}
1149
1167
  className="h-7 w-7"
1150
1168
  onClick={() => void handleAttach()}
1151
1169
  >
@@ -1220,6 +1238,8 @@ export function ComposeModal({
1220
1238
  <Tooltip>
1221
1239
  <TooltipTrigger asChild>
1222
1240
  <button
1241
+ type="button"
1242
+ aria-label={t("mail.compose.deleteDraft")}
1223
1243
  onClick={() => activeId && onDiscard(activeId)}
1224
1244
  className="flex h-8 w-8 items-center justify-center rounded text-muted-foreground/40 hover:text-red-400 hover:bg-red-400/10 transition-colors"
1225
1245
  >
@@ -539,7 +539,11 @@ export const EmailListItem = memo(function EmailListItem({
539
539
  <div className="relative me-2 flex h-full w-5 shrink-0 items-center justify-center">
540
540
  <button
541
541
  type="button"
542
- aria-label={isMultiSelected ? "Deselect email" : "Select email"}
542
+ aria-label={t(
543
+ isMultiSelected
544
+ ? "mail.selection.deselectEmail"
545
+ : "mail.selection.selectEmail",
546
+ )}
543
547
  onClick={handleToggleMultiSelectClick}
544
548
  className={cn(
545
549
  "absolute inset-y-0 left-1/2 flex w-6 -translate-x-1/2 items-center justify-center rounded text-muted-foreground transition-opacity hover:text-foreground",
@@ -644,6 +648,11 @@ export const EmailListItem = memo(function EmailListItem({
644
648
  <button
645
649
  type="button"
646
650
  onClick={handleToggleReadClick}
651
+ aria-label={t(
652
+ isUnread
653
+ ? "mail.actions.markRead"
654
+ : "mail.actions.markUnread",
655
+ )}
647
656
  className="flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
648
657
  >
649
658
  {isUnread ? (
@@ -666,12 +675,13 @@ export const EmailListItem = memo(function EmailListItem({
666
675
  <button
667
676
  type="button"
668
677
  onClick={handleArchiveClick}
678
+ aria-label={t("mail.actions.archive")}
669
679
  className="flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-emerald-500/10 hover:text-emerald-600 dark:hover:text-emerald-400"
670
680
  >
671
681
  <IconArchive className="h-3.5 w-3.5" />
672
682
  </button>
673
683
  </TooltipTrigger>
674
- <TooltipContent>Archive</TooltipContent>
684
+ <TooltipContent>{t("mail.actions.archive")}</TooltipContent>
675
685
  </Tooltip>
676
686
  )}
677
687
  {showSnooze && (
@@ -680,12 +690,13 @@ export const EmailListItem = memo(function EmailListItem({
680
690
  <button
681
691
  type="button"
682
692
  onClick={handleSnoozeClick}
693
+ aria-label={t("mail.snooze.snooze")}
683
694
  className="flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-amber-500/10 hover:text-amber-600 dark:hover:text-amber-400"
684
695
  >
685
696
  <IconClock className="h-3.5 w-3.5" />
686
697
  </button>
687
698
  </TooltipTrigger>
688
- <TooltipContent>Snooze</TooltipContent>
699
+ <TooltipContent>{t("mail.snooze.snooze")}</TooltipContent>
689
700
  </Tooltip>
690
701
  )}
691
702
  {showSendNow && (
@@ -694,6 +705,7 @@ export const EmailListItem = memo(function EmailListItem({
694
705
  <button
695
706
  type="button"
696
707
  onClick={handleSendNowClick}
708
+ aria-label={t("mail.sendLater.sendNow")}
697
709
  className="flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
698
710
  >
699
711
  <IconSend className="h-3.5 w-3.5 rtl:-scale-x-100" />
@@ -708,6 +720,7 @@ export const EmailListItem = memo(function EmailListItem({
708
720
  <button
709
721
  type="button"
710
722
  onClick={handleCancelScheduleClick}
723
+ aria-label={t("mail.sendLater.cancelScheduledSend")}
711
724
  className="flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
712
725
  >
713
726
  <IconX className="h-3.5 w-3.5" />
@@ -724,6 +737,7 @@ export const EmailListItem = memo(function EmailListItem({
724
737
  <button
725
738
  type="button"
726
739
  onClick={handleTrashClick}
740
+ aria-label={t("mail.actions.moveToTrash")}
727
741
  className="flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
728
742
  >
729
743
  <IconTrash className="h-3.5 w-3.5" />
@@ -737,6 +751,9 @@ export const EmailListItem = memo(function EmailListItem({
737
751
  <button
738
752
  type="button"
739
753
  onClick={handleStarClick}
754
+ aria-label={t(
755
+ isStarred ? "mail.actions.unstar" : "mail.actions.star",
756
+ )}
740
757
  className={cn(
741
758
  "flex h-6 w-6 items-center justify-center rounded transition-colors",
742
759
  isStarred
@@ -747,7 +764,9 @@ export const EmailListItem = memo(function EmailListItem({
747
764
  <IconStarFilled className="h-3.5 w-3.5" />
748
765
  </button>
749
766
  </TooltipTrigger>
750
- <TooltipContent>{isStarred ? "Unpin" : "Pin"}</TooltipContent>
767
+ <TooltipContent>
768
+ {t(isStarred ? "mail.actions.unstar" : "mail.actions.star")}
769
+ </TooltipContent>
751
770
  </Tooltip>
752
771
  </div>
753
772
  </div>