Skip to content

Commit

Permalink
refactor(board-components): 使用悬念版API并重构信息组件
Browse files Browse the repository at this point in the history
- 将 `useSelf` 迁移到 `@liveblocks/react/suspense`。
- 重构 `Info` 组件,使用客户端导入,并添加 `boardId` 属性。
- 单独导出 `InfoSkeleton`、`ParticipantsSkeleton` 和 `ToolbarSkeleton` 组件。
- 更新 `Loading` 组件以使用单独导出的骨架组件。
- 修正语法错误和组件属性。
- 调整 `Button` 组件样式,增加 `board` 和 `boardActive` 变体。
- 重构 `Room` 组件中的注释以提高清晰度。

BREAKING CHANGE: `Info`, `Participants`, 和 `Toolbar` 组件现在有新的属性和导出。请确保在迁移时更新组件引用。
  • Loading branch information
YuniqueUnic committed Aug 21, 2024
1 parent 68a11ea commit a6fe86a
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 30 deletions.
4 changes: 2 additions & 2 deletions app/board/[boardId]/_components/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Info } from "./info";
import { Participants } from "./participants";
import { Toolbar } from "./toolbar";

import { useSelf } from "@liveblocks/react";
import { useSelf } from "@liveblocks/react/suspense";

interface CanvasProps {
boardId: string;
Expand All @@ -17,7 +17,7 @@ export const Canvas = ({ boardId }: CanvasProps) => {

return (
<main className="w-full h-full relative bg-neutral-100 touch-none">
<Info />
<Info boardId={boardId} />
<Participants />
<Toolbar />
</main>
Expand Down
70 changes: 66 additions & 4 deletions app/board/[boardId]/_components/info.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,76 @@
export const Info = () => {
"use client";

import Link from "next/link";
import Image from "next/image";
import { Poppins } from "next/font/google";

import { Id } from "@/convex/_generated/dataModel";
import { api } from "@/convex/_generated/api";
import { useQuery } from "convex/react";

import { cn } from "@/lib/utils";
import { Hint } from "@/components/hint";
import { Button } from "@/components/ui/button";
import { useRenameModal } from "@/store/use-rename-modal";

interface InfoProps {
boardId: string;
}

const font = Poppins({
subsets: ["latin"],
weight: ["600"],
});

export const TabSeparator = () => {
return (
<div className="text-neutral-300 px-1.5"></div>
);
};

export const Info = ({ boardId }: InfoProps) => {
const { onOpen } = useRenameModal();

const data = useQuery(api.board.get, {
id: boardId as Id<"boards">,
});

if (!data) return <InfoSkeleton />;

return (
<div
className="absolute top-2 left-2 bg-white rounded-md px-1.5 h-12
flex items-center shadow-md">
TODO: Information about the board
</div>
<Hint label="Go to boards" side="bottom" sideOffset={10}>
<Button asChild className="px-2" variant={"board"}>
<Link href={"/"}>
<Image
src={"/logo.svg"}
alt={"Logo"}
width={40}
height={40}
/>
<span className={cn(
"font-semibold text-xl ml-2 text-black",
font.className
)}>
Board
</span>
</Link>
</Button>
</Hint>
<TabSeparator />
<Button
onClick={() => { onOpen(data._id, data.title); }}
variant={"board"}
className="text-base font-normal px-2">
{data.title}
</Button>
</div >
);
};

Info.Skeleton = function InfoSkeleton() {
export const InfoSkeleton = () => {
return (
<div
className="absolute top-2 left-2 bg-white rounded-md px-1.5 h-12
Expand Down
15 changes: 8 additions & 7 deletions app/board/[boardId]/_components/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@


import { Loader } from "lucide-react";

import { Skeleton } from "@/components/ui/skeleton";
import { Info } from "./info";
import { Participants } from "./participants";
import { Toolbar } from "./toolbar";
import { InfoSkeleton } from "./info"; // Don't need the ''use client" through the export InfoSkeleton separately
import { ParticipantsSkeleton } from "./participants"; // So does ParticipantsSkeleton
import { ToolbarSkeleton } from "./toolbar"; // So does ToolbarSkeleton

export const Loading = () => {
return (
<main
className="w-full h-full relative bg-neutral-100 touch-none
flex items-center justify-center">
<Loader className="h-6 w-6 text-muted-foreground animate-spin" />
<Info.Skeleton />
<Participants.Skeleton />
<Toolbar.Skeleton />
<InfoSkeleton />
<ParticipantsSkeleton />
<ToolbarSkeleton />
</main>
);
};
2 changes: 1 addition & 1 deletion app/board/[boardId]/_components/participants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const Participants = () => {
);
};

Participants.Skeleton = function ParticipantsSkeleton() {
export const ParticipantsSkeleton = () => {
return (
<div
className="absolute h-12 top-2 right-2 bg-white
Expand Down
2 changes: 1 addition & 1 deletion app/board/[boardId]/_components/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const Toolbar = () => {
);
};

Toolbar.Skeleton = function ToolbarSkeleton() {
export const ToolbarSkeleton = () => {
return (
<div
className="absolute top-[50%] -translate-y-[50%] left-2 bg-white
Expand Down
2 changes: 1 addition & 1 deletion components/hint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const Hint = ({
}: HintProps) => {
return (
<TooltipProvider>
<Tooltip delayDuration={1000}>
<Tooltip delayDuration={512}>
<TooltipTrigger asChild>{children}</TooltipTrigger>
<TooltipContent
className="text-white bg-black border-black rounded-md px-2 py-1"
Expand Down
5 changes: 3 additions & 2 deletions components/room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ export const Room = ({ children, roomId, fallback }: RoomProps) => {
<LiveblocksProvider authEndpoint={"/api/liveblocks-auth"}>

<RoomProvider id={roomId} initialPresence={{}}>
{/* // there some problem that the board should not be access by a non-privledged user
{/* // there are some problem that the board should not be access by a non-privledged user
// the ui canvas should in the loading status when such users trying to join a board room which not belong to them */}
{/* // TODO: Keep the loading status when the user is not authorized to access the board */}
{/* // Fixed: Keep the loading status when the user is not authorized to access the board */}
{/* // Solution: import { useSelf } from "@liveblocks/react/suspense" instead of "@liveblocks/react" in canvas.tsx; */}
<ClientSideSuspense fallback={fallback}>
{() => children}
</ClientSideSuspense>
Expand Down
26 changes: 14 additions & 12 deletions components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
Expand All @@ -18,6 +18,8 @@ const buttonVariants = cva(
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
board: "hover:bg-blue-500/20 hover:text-blue-800",
boardAcive: "bg-blue-500/20 text-blue-800",
},
size: {
default: "h-10 px-4 py-2",
Expand All @@ -31,26 +33,26 @@ const buttonVariants = cva(
size: "default",
},
}
)
);

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
);
}
)
Button.displayName = "Button"
);
Button.displayName = "Button";

export { Button, buttonVariants }
export { Button, buttonVariants };

0 comments on commit a6fe86a

Please sign in to comment.