-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🧩
ui
Add notion component: settings panel
- Loading branch information
1 parent
c625716
commit c1f1b60
Showing
30 changed files
with
983 additions
and
5 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
apps/storybook/src/stories/notion/settings-panel/index.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import { SettingsPanel } from "@acme/ui/components"; | ||
|
||
import { Settings } from "./settings"; | ||
|
||
const meta = { | ||
title: "notion/Settings Panel", | ||
component: SettingsPanel, | ||
parameters: { layout: "centered" }, | ||
tags: ["autodocs"], | ||
} satisfies Meta<typeof SettingsPanel>; | ||
export default meta; | ||
|
||
type Story = StoryObj<typeof meta>; | ||
|
||
export const Default: Story = { | ||
render: () => <Settings />, | ||
}; |
24 changes: 24 additions & 0 deletions
24
apps/storybook/src/stories/notion/settings-panel/settings.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
"use client"; | ||
|
||
import { useEffect, useState } from "react"; | ||
import { SettingsIcon } from "lucide-react"; | ||
|
||
import { Button, SettingsPanel, useSettings } from "@acme/ui/components"; | ||
|
||
export const Settings = () => { | ||
const settings = useSettings(); | ||
const [isMounted, setIsMounted] = useState(false); | ||
|
||
useEffect(() => { | ||
setIsMounted(true); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<Button variant="outline" size="icon" onClick={settings.onOpen}> | ||
<SettingsIcon /> | ||
</Button> | ||
{isMounted && <SettingsPanel />} | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
"use client"; | ||
|
||
import { useEffect, useState } from "react"; | ||
import { BlockNoteEditor } from "@blocknote/core"; | ||
import { BlockNoteView, useBlockNote } from "@blocknote/react"; | ||
import LiveblocksProvider from "@liveblocks/yjs"; | ||
import { useTheme } from "next-themes"; | ||
import * as Y from "yjs"; | ||
|
||
import "@blocknote/core/style.css"; | ||
|
||
import { useRoom, useSelf } from "~/liveblocks.config"; | ||
|
||
// Collaborative text editor with simple rich text, live cursors, and live avatars | ||
export default function CollaborativeEditor() { | ||
const room = useRoom(); | ||
const [doc, setDoc] = useState<Y.Doc>(); | ||
const [provider, setProvider] = | ||
useState<LiveblocksProvider<never, never, never, never>>(); | ||
|
||
// Set up Liveblocks Yjs provider | ||
useEffect(() => { | ||
const yDoc = new Y.Doc(); | ||
const yProvider = new LiveblocksProvider(room, yDoc); | ||
setDoc(yDoc); | ||
setProvider(yProvider); | ||
|
||
return () => { | ||
yDoc?.destroy(); | ||
yProvider?.destroy(); | ||
}; | ||
}, [room]); | ||
|
||
if (!doc || !provider) { | ||
return null; | ||
} | ||
|
||
return <BlockNote doc={doc} provider={provider} />; | ||
} | ||
|
||
interface EditorProps { | ||
doc: Y.Doc; | ||
provider: LiveblocksProvider<never, never, never, never>; | ||
} | ||
|
||
function BlockNote({ doc, provider }: EditorProps) { | ||
// Get user info from Liveblocks authentication endpoint | ||
const userInfo = useSelf((me) => me.info); | ||
|
||
const editor: BlockNoteEditor = useBlockNote({ | ||
collaboration: { | ||
provider, | ||
|
||
// Where to store BlockNote data in the Y.Doc: | ||
fragment: doc.getXmlFragment("document-store"), | ||
|
||
// Information for this user: | ||
user: { | ||
name: userInfo?.name ?? "User", | ||
color: userInfo?.picture ?? "", | ||
}, | ||
}, | ||
}); | ||
|
||
const { resolvedTheme } = useTheme(); | ||
|
||
return ( | ||
<div> | ||
<BlockNoteView | ||
editor={editor} | ||
theme={resolvedTheme === "dark" ? "dark" : "light"} | ||
/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { | ||
// defaultBlockSchema, | ||
// defaultBlockSpecs, | ||
defaultProps, | ||
} from "@blocknote/core"; | ||
import { createReactBlockSpec } from "@blocknote/react"; | ||
|
||
export const TodoBlock = createReactBlockSpec( | ||
{ | ||
type: "todo", | ||
propSchema: { | ||
...defaultProps, | ||
checked: { | ||
default: false, | ||
}, | ||
}, | ||
content: "none", | ||
}, | ||
{ | ||
render: ({ block, contentRef }) => { | ||
console.log(block); | ||
|
||
return ( | ||
<div> | ||
<input type="checkbox" /> | ||
<p ref={contentRef}>{block.content}</p> | ||
</div> | ||
); | ||
}, | ||
parse: (_element) => { | ||
return { | ||
checked: false, | ||
}; | ||
}, | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from "./settings-panel"; | ||
export * from "./workspace-switcher"; |
10 changes: 10 additions & 0 deletions
10
packages/ui/src/components/notion/settings-panel/index.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { render } from "@testing-library/react"; | ||
|
||
import { SettingsPanel } from "."; | ||
|
||
describe("<SettingsPanel />", () => { | ||
it("should render the default text", () => { | ||
const { getByText } = render(<SettingsPanel />); | ||
expect(getByText("Settings Panel")).toBeDefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./settings-panel"; | ||
export * from "./use-settings"; |
39 changes: 39 additions & 0 deletions
39
packages/ui/src/components/notion/settings-panel/panels/account.data.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import type { PanelData } from "./utils"; | ||
|
||
const $account = [ | ||
"email", | ||
"password", | ||
"verification", | ||
"support", | ||
"logout", | ||
"del", | ||
] as const; | ||
|
||
export const myAccount: PanelData<typeof $account> = { | ||
email: { title: "Email", description: "email" }, | ||
password: { | ||
title: "Password", | ||
description: | ||
"If you lose access to your school email address, you'll be able to log in using your password.", | ||
}, | ||
verification: { | ||
title: "2-step verification", | ||
description: | ||
"Add an additional layer of security to your account during login.", | ||
}, | ||
support: { | ||
title: "Support access", | ||
description: | ||
"Grant Notion support temporary access to your account so we can troubleshoot problems or recover content on your behalf. You can revoke access at any time.", | ||
}, | ||
logout: { | ||
title: "Log out of all devices", | ||
description: | ||
"Log out of all other active sessions on other devices besides this one.", | ||
}, | ||
del: { | ||
title: "Delete my account", | ||
description: | ||
"Permanently delete the account and remove access from all workspaces.", | ||
}, | ||
}; |
89 changes: 89 additions & 0 deletions
89
packages/ui/src/components/notion/settings-panel/panels/account.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { ChangeEvent } from "react"; | ||
import { ChevronRight } from "lucide-react"; | ||
|
||
import { | ||
Avatar, | ||
AvatarFallback, | ||
AvatarImage, | ||
Button, | ||
Input, | ||
Label, | ||
Switch, | ||
} from "@/components/ui"; | ||
import { mockUser } from "../../workspace-switcher/mock"; | ||
import { Section, SectionItem, SectionSeparator } from "../section"; | ||
import { myAccount } from "./account.data"; | ||
|
||
export const Account = () => { | ||
const user = mockUser; | ||
const handleUpdateName = (e: ChangeEvent<HTMLInputElement>) => | ||
console.log(`Changed preffered name to ${e.currentTarget.value}`); | ||
|
||
return ( | ||
<> | ||
<Section title="My profile"> | ||
<div className="flex flex-col"> | ||
<div className="flex items-center"> | ||
<Avatar className="size-[60px]"> | ||
<AvatarImage src="https://github.com/shadcn.png" /> | ||
<AvatarFallback>CN</AvatarFallback> | ||
</Avatar> | ||
<div className="ml-5 w-[250px]"> | ||
<Label | ||
className="mb-1 block text-xs text-primary/65" | ||
htmlFor="username" | ||
> | ||
Preferred name | ||
</Label> | ||
<Input | ||
type="username" | ||
id="username" | ||
value={user.name} | ||
onChange={handleUpdateName} | ||
className="bg-primary/6 h-7 select-none rounded-sm text-sm" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</Section> | ||
<SectionSeparator /> | ||
<Section title="Account security"> | ||
<SectionItem title={myAccount.email.title} description={user.email}> | ||
<Button | ||
variant="outline" | ||
size="sm" | ||
className="select-none hover:bg-primary/10" | ||
> | ||
Change email | ||
</Button> | ||
</SectionItem> | ||
<SectionSeparator size="sm" /> | ||
<SectionItem {...myAccount.password}> | ||
<Switch /> | ||
</SectionItem> | ||
<SectionSeparator size="sm" /> | ||
<SectionItem {...myAccount.verification}> | ||
<Switch disabled /> | ||
</SectionItem> | ||
</Section> | ||
<SectionSeparator /> | ||
<Section title="Support"> | ||
<SectionItem {...myAccount.support}> | ||
<Switch /> | ||
</SectionItem> | ||
<SectionSeparator size="sm" /> | ||
<SectionItem {...myAccount.logout}> | ||
<Button variant="ghost" size="icon-sm" className="text-primary/35"> | ||
<ChevronRight className="h-4 w-4" /> | ||
</Button> | ||
</SectionItem> | ||
<SectionSeparator size="sm" /> | ||
<SectionItem {...myAccount.del} titleProps="text-[#eb5757]"> | ||
<Button variant="ghost" size="icon-sm" className="text-primary/35"> | ||
<ChevronRight className="h-4 w-4" /> | ||
</Button> | ||
</SectionItem> | ||
</Section> | ||
</> | ||
); | ||
}; |
2 changes: 2 additions & 0 deletions
2
packages/ui/src/components/notion/settings-panel/panels/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./account"; | ||
export * from "./settings"; |
59 changes: 59 additions & 0 deletions
59
packages/ui/src/components/notion/settings-panel/panels/settings.data.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import type { Option } from "../section"; | ||
import { PanelData } from "./utils"; | ||
|
||
const $settings = [ | ||
"appearance", | ||
"openStart", | ||
"openLinks", | ||
"setTimezone", | ||
"timezone", | ||
"cookie", | ||
"viewHistory", | ||
"profile", | ||
] as const; | ||
|
||
export const mySettings: PanelData<typeof $settings> = { | ||
appearance: { | ||
title: "Appearance", | ||
description: "Customize how Notion looks on your device.", | ||
}, | ||
openStart: { | ||
title: "Open on start", | ||
description: | ||
"Choose what to show when Notion starts or when you switch workspaces.", | ||
}, | ||
openLinks: { | ||
title: "Open links in desktop app", | ||
description: "You must have the Mac or Windows app installed", | ||
}, | ||
setTimezone: { | ||
title: "Set timezone automatically using your location", | ||
description: | ||
"Reminders, notifications and emails are delivered based on your time zone.", | ||
}, | ||
timezone: { title: "Time Zone", description: "Current time zone setting." }, | ||
cookie: { | ||
title: "Cookie settings", | ||
description: "Customize cookies. See Cookie Notice for details.", | ||
}, | ||
viewHistory: { | ||
title: "Show my view history", | ||
description: | ||
"People with edit or full access will be able to see when you’ve viewed a page. Leran more.", | ||
}, | ||
profile: { | ||
title: "Profile discoverability", | ||
description: | ||
"Users with your email can see your name and profile picture when inviting you to a new workspace. Learn more.", | ||
}, | ||
}; | ||
|
||
export const appearanceOptions: Option[] = [ | ||
{ label: "Use system setting", value: "system" }, | ||
{ label: "Light", value: "light" }, | ||
{ label: "Dark", value: "dark" }, | ||
]; | ||
export const openStartOptions: Option[] = [ | ||
{ label: "Last visited page", value: "last" }, | ||
{ label: "Top page in sidebar", value: "top" }, | ||
]; |
Oops, something went wrong.