mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 02:44:50 +01:00
test(ui): cover privacy menu and create toggle in Storybook
Add visual stories for the privacy action menu and the private-task toggle using existing components and design tokens. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
75ac8b4dbb
commit
fa8d58c4ee
1 file changed
+109
@@ -0,0 +1,109 @@
|
||||
import { useMemo } from "react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import type { Issue } from "@paperclipai/shared";
|
||||
import { IssuePrivacyActions } from "@/components/IssuePrivacyActions";
|
||||
import { ToggleSwitch } from "@/components/ui/toggle-switch";
|
||||
import { queryKeys } from "@/lib/queryKeys";
|
||||
|
||||
const COMPANY_ID = "company-storybook";
|
||||
|
||||
function makeClient() {
|
||||
const client = new QueryClient({
|
||||
defaultOptions: { queries: { staleTime: Infinity, retry: false, gcTime: Infinity } },
|
||||
});
|
||||
// Seed empty grants so opening Share… from the menu lands on the empty state
|
||||
// rather than a spinner.
|
||||
client.setQueryData(queryKeys.issues.accessGrants("issue-menu-1"), []);
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the privacy `⋯`-menu items inside a faux DropdownMenu surface so the
|
||||
* spacing/hover/destructive treatment reads the way it will in the real popover.
|
||||
*/
|
||||
function MenuHost({
|
||||
visibility,
|
||||
canManage,
|
||||
}: {
|
||||
visibility: Issue["visibility"];
|
||||
canManage: boolean;
|
||||
}) {
|
||||
const client = useMemo(() => makeClient(), []);
|
||||
const issue = {
|
||||
id: "issue-menu-1",
|
||||
identifier: "PAP-4242",
|
||||
visibility,
|
||||
} as Pick<Issue, "id" | "identifier" | "visibility">;
|
||||
return (
|
||||
<QueryClientProvider client={client}>
|
||||
<div className="p-6">
|
||||
<div className="min-w-[13rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md">
|
||||
<div className="px-2 py-1 text-(length:--text-nano) font-medium uppercase tracking-wide text-muted-foreground">
|
||||
Privacy
|
||||
</div>
|
||||
<IssuePrivacyActions
|
||||
issue={issue}
|
||||
companyId={COMPANY_ID}
|
||||
canManage={canManage}
|
||||
closeMenu={() => {}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const meta: Meta<typeof MenuHost> = {
|
||||
title: "Privacy/IssuePrivacyActions",
|
||||
component: MenuHost,
|
||||
parameters: { layout: "fullscreen" },
|
||||
};
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof MenuHost>;
|
||||
|
||||
/** Private task, setter: Share… + destructive Make public. */
|
||||
export const PrivateTaskSetter: Story = {
|
||||
args: { visibility: "private", canManage: true },
|
||||
};
|
||||
|
||||
/** Public task, setter: single Make private (no confirm). */
|
||||
export const PublicTaskSetter: Story = {
|
||||
args: { visibility: "open", canManage: true },
|
||||
};
|
||||
|
||||
/** Non-setter: items disabled; tooltip explains why (hover to reveal). */
|
||||
export const NonSetter: Story = {
|
||||
args: { visibility: "private", canManage: false },
|
||||
};
|
||||
|
||||
/**
|
||||
* The create-dialog "Private task" toggle row, lifted verbatim from
|
||||
* NewIssueDialog so its resting on/off states are screenshot-documented.
|
||||
*/
|
||||
function PrivateToggleRow({ checked }: { checked: boolean }) {
|
||||
return (
|
||||
<div className="max-w-md p-6">
|
||||
<div className="rounded-md border border-border/60">
|
||||
<div className="flex items-start justify-between gap-3 border-t border-border/60 px-4 py-2.5 first:border-t-0">
|
||||
<div className="min-w-0">
|
||||
<div className="text-xs font-medium">Private task</div>
|
||||
<div className="text-(length:--text-micro) text-muted-foreground">
|
||||
Only you and people you share with can read it. Subtasks stay private too.
|
||||
</div>
|
||||
</div>
|
||||
<ToggleSwitch checked={checked} onCheckedChange={() => {}} aria-label="Private task" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const CreateDialogToggleOff: StoryObj = {
|
||||
render: () => <PrivateToggleRow checked={false} />,
|
||||
};
|
||||
|
||||
export const CreateDialogToggleOn: StoryObj = {
|
||||
render: () => <PrivateToggleRow checked={true} />,
|
||||
};
|
||||
Reference in new issue
Block a user