@remit/ui 0.0.147 → 0.0.149
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/package.json
CHANGED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Decorator, Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { MailActionToolbar } from "./mail-action-toolbar.js";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof MailActionToolbar> = {
|
|
5
|
+
title: "Kit/MailActionToolbar",
|
|
6
|
+
component: MailActionToolbar,
|
|
7
|
+
parameters: { layout: "centered" },
|
|
8
|
+
decorators: [
|
|
9
|
+
((Story) => (
|
|
10
|
+
<div
|
|
11
|
+
className="overflow-hidden rounded-lg border border-line"
|
|
12
|
+
style={{ width: 720 }}
|
|
13
|
+
>
|
|
14
|
+
<Story />
|
|
15
|
+
</div>
|
|
16
|
+
)) satisfies Decorator,
|
|
17
|
+
],
|
|
18
|
+
args: {
|
|
19
|
+
hasThread: true,
|
|
20
|
+
onReply: () => undefined,
|
|
21
|
+
onReplyAll: () => undefined,
|
|
22
|
+
onForward: () => undefined,
|
|
23
|
+
onDelete: () => undefined,
|
|
24
|
+
onMove: () => undefined,
|
|
25
|
+
onToggleStar: () => undefined,
|
|
26
|
+
onUnavailable: () => undefined,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
export default meta;
|
|
30
|
+
|
|
31
|
+
type Story = StoryObj<typeof MailActionToolbar>;
|
|
32
|
+
|
|
33
|
+
/** The conversation has answered and the open message is not starred. */
|
|
34
|
+
export const Default: Story = { args: { isStarred: false } };
|
|
35
|
+
|
|
36
|
+
/** The open message is starred: the star is lit and reads as pressed. It
|
|
37
|
+
* follows the conversation, not the list row that opened it (#602). */
|
|
38
|
+
export const Starred: Story = { args: { isStarred: true } };
|
|
39
|
+
|
|
40
|
+
/** The conversation has not answered yet, so the star state is unknown. The
|
|
41
|
+
* button omits `aria-pressed` rather than announcing "not pressed" for a
|
|
42
|
+
* message that may well be starred. */
|
|
43
|
+
export const StarUnknown: Story = { args: { isStarred: undefined } };
|
|
44
|
+
|
|
45
|
+
/** The mobile pane's management bar already owns triage, so the toolbar drops
|
|
46
|
+
* the cluster instead of offering a second set of the same accessible names. */
|
|
47
|
+
export const WithoutTriage: Story = { args: { showTriage: false } };
|
|
48
|
+
|
|
49
|
+
/** No message open: the verbs no-op and the bar surfaces a one-line reason
|
|
50
|
+
* instead of disabling. */
|
|
51
|
+
export const NoMessageOpen: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
hasThread: false,
|
|
54
|
+
unavailableHint: "Open a message first",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -32,6 +32,11 @@ export interface MailActionToolbarProps {
|
|
|
32
32
|
onUnavailable?: (action: MailAction) => void;
|
|
33
33
|
/** A one-line inline notice rendered under the toolbar (e.g. "Open a message first"). */
|
|
34
34
|
unavailableHint?: ReactNode;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the open message is starred. Undefined until the conversation
|
|
37
|
+
* says — the button then omits `aria-pressed` rather than announcing an
|
|
38
|
+
* unstarred state it does not know yet.
|
|
39
|
+
*/
|
|
35
40
|
isStarred?: boolean;
|
|
36
41
|
/**
|
|
37
42
|
* Whether to render the triage cluster (move-to-trash / move / flag).
|
|
@@ -166,6 +171,7 @@ export function MailActionToolbar({
|
|
|
166
171
|
}
|
|
167
172
|
title={flagTitle}
|
|
168
173
|
aria-label="Star"
|
|
174
|
+
aria-pressed={isStarred}
|
|
169
175
|
onClick={act("flag", onToggleStar)}
|
|
170
176
|
/>
|
|
171
177
|
</>
|
|
@@ -100,23 +100,12 @@ function Harness({
|
|
|
100
100
|
const [displayNames, setDisplayNames] = useState<Record<string, string>>({});
|
|
101
101
|
|
|
102
102
|
const handleAppoint = (role: FolderRole, mailboxId: string | null) => {
|
|
103
|
-
setAppointments((prev) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
// Exclusivity: appointing a folder to one role clears it from any other.
|
|
111
|
-
if (mailboxId) {
|
|
112
|
-
for (const other of Object.keys(next)) {
|
|
113
|
-
if (other === role) continue;
|
|
114
|
-
if (next[other]?.mailboxId !== mailboxId) continue;
|
|
115
|
-
next[other] = { mailboxId: null, source: "None" };
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return next;
|
|
119
|
-
});
|
|
103
|
+
setAppointments((prev) => ({
|
|
104
|
+
...prev,
|
|
105
|
+
[role]: mailboxId
|
|
106
|
+
? { mailboxId, source: "Appointed" }
|
|
107
|
+
: { mailboxId: null, source: "None" },
|
|
108
|
+
}));
|
|
120
109
|
};
|
|
121
110
|
|
|
122
111
|
const handleRename = (mailboxId: string, name: string) =>
|
|
@@ -300,10 +300,9 @@ export function RoleAppointmentList({
|
|
|
300
300
|
</h2>
|
|
301
301
|
<p className="text-xs text-fg-muted">
|
|
302
302
|
Each role points to one folder. Pick the folder that holds the mail —
|
|
303
|
-
the counts help you tell real folders from empty look-alikes.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
or a name reader matched.
|
|
303
|
+
the counts help you tell real folders from empty look-alikes. Each row
|
|
304
|
+
says where its answer came from — your choice, the mail server's own
|
|
305
|
+
flag, or a name reader matched.
|
|
307
306
|
</p>
|
|
308
307
|
</header>
|
|
309
308
|
<div className="rounded-sm border border-line bg-surface">
|