Skip to content

Commit

Permalink
wip: rename popover
Browse files Browse the repository at this point in the history
  • Loading branch information
steeeee0223 committed Dec 15, 2024
1 parent 9a496ec commit a2674f8
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 20 deletions.
43 changes: 43 additions & 0 deletions apps/storybook/src/stories/notion/tmp.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useState } from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";

import { RenamePopover } from "@swy/notion";
import { Button } from "@swy/ui/shadcn";

const meta = {
title: "notion/Rename Form",
component: RenamePopover,
args: {
onChange: fn(),
},
} satisfies Meta<typeof RenamePopover>;
export default meta;

type Story = StoryObj<typeof meta>;

const Template: Story["render"] = ({ children, ...props }) => {
const [icon, setIcon] = useState(props.icon);
const [title, setTitle] = useState(props.title);
return (
<RenamePopover
title={title}
icon={icon}
onChange={({ title, icon }) => {
setTitle(title);
setIcon(icon);
}}
>
{children}
</RenamePopover>
);
};

export const Default: Story = {
args: {
title: "My workspace",
icon: { type: "lucide", name: "currency" },
children: <Button size="sm">Rename</Button>,
},
render: Template,
};
1 change: 1 addition & 0 deletions packages/notion/src/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./base-modal";
export * as Icon from "./icons";
export * from "./rename-popover";
export * from "./utils";
66 changes: 66 additions & 0 deletions packages/notion/src/common/rename-popover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use client";

import React, { useRef, useState } from "react";

import { Input, Popover, PopoverContent, PopoverTrigger } from "@swy/ui/shadcn";
import { IconBlock, IconInfo, IconMenu } from "@swy/ui/shared";

interface RenamePopoverProps extends React.PropsWithChildren {
title: string;
icon: IconInfo;
onChange: (value: { title: string; icon: IconInfo }) => void;
}

export const RenamePopover: React.FC<RenamePopoverProps> = ({
children,
title,
icon,
onChange,
}) => {
const inputRef = useRef<HTMLInputElement>(null);

const [open, setOpen] = useState(false);
const onOpenChange = (isOpen: boolean) => {
setOpen(isOpen);
if (isOpen)
setTimeout(() => {
inputRef.current?.focus();
inputRef.current?.select();
}, 0);
};
const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
e.stopPropagation();
if (e.key === "Enter") {
const value = inputRef.current?.value;
if (value && value !== title) onChange({ title: value, icon });
setOpen(false);
}
};

return (
<Popover open={open} onOpenChange={onOpenChange}>
<PopoverTrigger asChild>{children}</PopoverTrigger>
<PopoverContent
className="flex w-[380px] items-center gap-1.5 px-2 py-1"
onClick={(e) => e.stopPropagation()}
>
<IconMenu
className="size-7 shrink-0 border border-border-button hover:bg-primary/5"
onSelect={(icon) => onChange({ title, icon })}
onRemove={() =>
onChange({ title, icon: { type: "lucide", name: "file" } })
}
>
<IconBlock icon={icon} className="p-0 text-lg/[22px]" />
</IconMenu>
<Input
ref={inputRef}
className="whitespace-pre-wrap break-words"
value={title}
onChange={(e) => onChange({ title: e.target.value, icon })}
onKeyDown={onKeyDown}
/>
</PopoverContent>
</Popover>
);
};
22 changes: 15 additions & 7 deletions packages/notion/src/sidebar-2/_components/action-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@swy/ui/shadcn";
import { Hint } from "@swy/ui/shared";
import { Hint, IconInfo } from "@swy/ui/shared";

import { Icon, toDateString } from "../../common";
import { Icon, RenamePopover, toDateString } from "../../common";
import type { UpdatePageParams } from "../../types";
import { MenuType } from "./types";

interface ActionGroupProps {
type: MenuType;
title: string;
icon: IconInfo;
pageLink: string;
isFavorite: boolean;
lastEditedBy: string;
Expand All @@ -37,6 +39,8 @@ interface ActionGroupProps {

export const ActionGroup: React.FC<ActionGroupProps> = ({
type,
title,
icon,
pageLink,
isFavorite,
lastEditedBy,
Expand All @@ -55,10 +59,11 @@ export const ActionGroup: React.FC<ActionGroupProps> = ({
side="bottom"
description="Delete, duplicate, and more..."
>
<DropdownMenuTrigger onClick={(e) => e.stopPropagation()} asChild>
<DropdownMenuTrigger asChild>
<Button
variant="hint"
className="ml-auto size-auto p-0.5 opacity-0 group-hover:opacity-100"
onClick={(e) => e.stopPropagation()}
>
<MoreHorizontal className="size-4" />
</Button>
Expand Down Expand Up @@ -93,10 +98,13 @@ export const ActionGroup: React.FC<ActionGroupProps> = ({
Duplicate
</DropdownMenuItem>
)}
<DropdownMenuItem>
<SquarePen className="mr-2 size-4" />
Rename
</DropdownMenuItem>

<RenamePopover title={title} icon={icon} onChange={onUpdate}>
<DropdownMenuItem onClick={(e) => e.stopPropagation()}>
<SquarePen className="mr-2 size-4" />
Rename
</DropdownMenuItem>
</RenamePopover>
{type === MenuType.Normal && (
<DropdownMenuItem
onClick={onDelete}
Expand Down
14 changes: 5 additions & 9 deletions packages/notion/src/sidebar-2/_components/doc-list.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import React from "react";

import { useOrigin } from "@swy/ui/hooks";
import {
buildTree,
TreeGroup,
TreeItem,
TreeList,
type IconInfo,
} from "@swy/ui/shared";
import { buildTree, TreeGroup, TreeItem, TreeList } from "@swy/ui/shared";

import { generateDefaultIcon } from "../../common";
import { usePlatformStore } from "../../slices";
import type { UpdatePageParams } from "../../types";
import { ActionGroup } from "./action-group";
Expand All @@ -17,7 +12,6 @@ import { MenuType } from "./types";
interface DocListProps {
group: string;
title: string;
defaultIcon?: IconInfo;
isLoading?: boolean;
redirect: (url: string) => void;
onCreate: (parentId?: string) => void;
Expand All @@ -28,14 +22,14 @@ interface DocListProps {
export const DocList: React.FC<DocListProps> = ({
group,
title,
defaultIcon,
isLoading,
redirect,
onCreate,
onArchive,
onUpdate,
}) => {
const origin = useOrigin();
const defaultIcon = generateDefaultIcon(group);

const pages = usePlatformStore((state) =>
Object.values(state.pages).filter(
Expand Down Expand Up @@ -74,6 +68,8 @@ export const DocList: React.FC<DocListProps> = ({
>
<ActionGroup
type={MenuType.Normal}
title={node.title}
icon={node.icon ?? defaultIcon}
pageLink={node.url ? `${origin}/${node.url}` : "#"}
isFavorite={node.isFavorite}
lastEditedBy={node.lastEditedBy}
Expand Down
3 changes: 3 additions & 0 deletions packages/notion/src/sidebar-2/_components/favorite-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
TreeNode,
} from "@swy/ui/shared";

import { generateDefaultIcon } from "../../common";
import { usePlatformStore } from "../../slices";
import type { Page, UpdatePageParams } from "../../types";
import { ActionGroup } from "./action-group";
Expand Down Expand Up @@ -59,6 +60,8 @@ export const FavoriteList: React.FC<FavoriteListProps> = ({
>
<ActionGroup
type={node.isFavorite ? MenuType.Favorites : MenuType.Normal}
title={node.title}
icon={node.icon ?? generateDefaultIcon(node.type)}
pageLink={node.url ? `${origin}/${node.url}` : "#"}
isFavorite={node.isFavorite}
lastEditedBy={node.lastEditedBy}
Expand Down
3 changes: 0 additions & 3 deletions packages/notion/src/sidebar-2/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ export const Sidebar2 = forwardRef<HTMLElement, SidebarProps>(function Sidebar(
isLoading={pages.isLoading}
group="document"
title="Document"
defaultIcon={{ type: "lucide", name: "file-text" }}
redirect={(url) => redirect?.(url)}
onCreate={(parentId) => pages.onCreate?.("document", parentId)}
onArchive={(id) => pages.onArchive?.(id)}
Expand All @@ -151,7 +150,6 @@ export const Sidebar2 = forwardRef<HTMLElement, SidebarProps>(function Sidebar(
isLoading={pages.isLoading}
group="kanban"
title="Kanban"
defaultIcon={{ type: "lucide", name: "columns-3" }}
redirect={(url) => redirect?.(url)}
onCreate={(parentId) => pages.onCreate?.("kanban", parentId)}
onArchive={(id) => pages.onArchive?.(id)}
Expand All @@ -161,7 +159,6 @@ export const Sidebar2 = forwardRef<HTMLElement, SidebarProps>(function Sidebar(
isLoading={pages.isLoading}
group="whiteboard"
title="Whiteboard"
defaultIcon={{ type: "lucide", name: "presentation" }}
redirect={(url) => redirect?.(url)}
onCreate={(parentId) => pages.onCreate?.("whiteboard", parentId)}
onArchive={(id) => pages.onArchive?.(id)}
Expand Down
4 changes: 3 additions & 1 deletion packages/notion/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@ export interface Page {
lastEditedBy: string;
}

export type UpdatePageParams = Partial<Pick<Page, "isFavorite">>;
export type UpdatePageParams = Partial<
Pick<Page, "title" | "icon" | "isFavorite">
>;

0 comments on commit a2674f8

Please sign in to comment.