Detailed changes
@@ -74,7 +74,7 @@ export function CommentBox({ bugPrefix, bugStatus, ref_ }: CommentBoxProps) {
return (
<CommentCard.Root>
- <CommentCard.AuthorAvatar src={user.avatarUrl} name={user.displayName} />
+ <CommentCard.AuthorAvatar avatarUrl={user.avatarUrl} displayName={user.displayName} />
<CommentCard.Card>
<WritePreview.Root hasContent={hasMessage} preview={preview} onPreviewChange={setPreview}>
<WritePreview.Tabs className="border-border border-b px-4 py-2" />
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { formatDistanceToNow } from "date-fns";
+import type { BugSummaryFragment } from "@/__generated__/graphql";
import { Status } from "@/__generated__/graphql";
import { withRouter } from "@/../.storybook/decorators";
@@ -15,109 +16,91 @@ const meta = {
export default meta;
type Story = StoryObj<typeof meta>;
-const ago = formatDistanceToNow(new Date(Date.now() - 3600 * 1000), { addSuffix: true });
+// Mock data shaped like BugSummaryFragment from GraphQL
+const openBug: BugSummaryFragment = {
+ id: "abc123",
+ humanId: "a1b2c3",
+ status: Status.Open,
+ title: "Fix login page crash on empty email",
+ labels: [
+ { name: "bug", color: { R: 252, G: 41, B: 41 } },
+ { name: "priority", color: { R: 255, G: 152, B: 0 } },
+ ],
+ author: { id: "u1", humanId: "user1", displayName: "Jane Doe", avatarUrl: null },
+ createdAt: new Date(Date.now() - 3600 * 1000).toISOString(),
+ comments: { totalCount: 3 },
+};
-export const OpenIssue: Story = {
- args: { children: null },
- render: () => (
+const closedBug: BugSummaryFragment = {
+ id: "def456",
+ humanId: "d4e5f6",
+ status: Status.Closed,
+ title: "Add dark mode support",
+ labels: [{ name: "enhancement", color: { R: 163, G: 230, B: 53 } }],
+ author: { id: "u2", humanId: "user2", displayName: "Bob Smith", avatarUrl: null },
+ createdAt: new Date(Date.now() - 86400 * 1000).toISOString(),
+ comments: { totalCount: 12 },
+};
+
+const noLabelsBug: BugSummaryFragment = {
+ id: "ghi789",
+ humanId: "g7h8i9",
+ status: Status.Open,
+ title: "Simple issue with no labels",
+ labels: [],
+ author: { id: "u3", humanId: "user3", displayName: "Alice Wu", avatarUrl: null },
+ createdAt: new Date(Date.now() - 7200 * 1000).toISOString(),
+ comments: { totalCount: 0 },
+};
+
+function BugRow({ bug }: { bug: BugSummaryFragment }) {
+ const ago = formatDistanceToNow(new Date(bug.createdAt), { addSuffix: true });
+ return (
<IssueRow.Root className="hover:bg-muted/30">
- <IssueRow.StatusIcon status={Status.Open} />
+ <IssueRow.StatusIcon status={bug.status} />
<div className="min-w-0 flex-1">
<IssueRow.TitleArea>
<a href="#" className="text-foreground hover:text-primary font-medium hover:underline">
- Fix login page crash on empty email
+ {bug.title}
</a>
- <LabelBadge name="bug" color={{ R: 252, G: 41, B: 41 }} />
- <LabelBadge name="priority" color={{ R: 255, G: 152, B: 0 }} />
+ {bug.labels.map((l) => (
+ <LabelBadge key={l.name} {...l} />
+ ))}
</IssueRow.TitleArea>
<IssueRow.Meta>
- #a1b2c3 opened {ago} by <a href="#" className="hover:underline">Jane Doe</a>
+ #{bug.humanId} opened {ago} by{" "}
+ <a href="#" className="hover:underline">
+ {bug.author.displayName}
+ </a>
</IssueRow.Meta>
</div>
- <IssueRow.CommentCount count={3} />
+ <IssueRow.CommentCount count={bug.comments.totalCount} />
</IssueRow.Root>
- ),
+ );
+}
+
+export const OpenIssue: Story = {
+ args: { children: null },
+ render: () => <BugRow bug={openBug} />,
};
export const ClosedIssue: Story = {
args: { children: null },
- render: () => (
- <IssueRow.Root>
- <IssueRow.StatusIcon status={Status.Closed} />
- <div className="min-w-0 flex-1">
- <IssueRow.TitleArea>
- <a href="#" className="text-foreground hover:text-primary font-medium hover:underline">
- Add dark mode support
- </a>
- <LabelBadge name="enhancement" color={{ R: 163, G: 230, B: 53 }} />
- </IssueRow.TitleArea>
- <IssueRow.Meta>#d4e5f6 opened {ago}</IssueRow.Meta>
- </div>
- <IssueRow.CommentCount count={12} />
- </IssueRow.Root>
- ),
+ render: () => <BugRow bug={closedBug} />,
};
export const NoLabelsNoComments: Story = {
args: { children: null },
- render: () => (
- <IssueRow.Root>
- <IssueRow.StatusIcon status={Status.Open} />
- <div className="min-w-0 flex-1">
- <IssueRow.TitleArea>
- <a href="#" className="text-foreground hover:text-primary font-medium hover:underline">
- Simple issue with no labels
- </a>
- </IssueRow.TitleArea>
- <IssueRow.Meta>#abc123 opened {ago} by <a href="#" className="hover:underline">Bob</a></IssueRow.Meta>
- </div>
- <IssueRow.CommentCount count={0} />
- </IssueRow.Root>
- ),
+ render: () => <BugRow bug={noLabelsBug} />,
};
export const List: Story = {
args: { children: null },
render: () => (
<div className="border-border rounded-md border">
- <IssueRow.Root className="hover:bg-muted/30">
- <IssueRow.StatusIcon status={Status.Open} />
- <div className="min-w-0 flex-1">
- <IssueRow.TitleArea>
- <a href="#" className="text-foreground hover:text-primary font-medium hover:underline">
- Fix login page crash on empty email
- </a>
- <LabelBadge name="bug" color={{ R: 252, G: 41, B: 41 }} />
- </IssueRow.TitleArea>
- <IssueRow.Meta>#a1b2c3 opened {ago} by Jane Doe</IssueRow.Meta>
- </div>
- <IssueRow.CommentCount count={3} />
- </IssueRow.Root>
- <IssueRow.Root className="hover:bg-muted/30">
- <IssueRow.StatusIcon status={Status.Open} />
- <div className="min-w-0 flex-1">
- <IssueRow.TitleArea>
- <a href="#" className="text-foreground hover:text-primary font-medium hover:underline">
- Add dark mode support
- </a>
- <LabelBadge name="enhancement" color={{ R: 163, G: 230, B: 53 }} />
- </IssueRow.TitleArea>
- <IssueRow.Meta>#d4e5f6 opened {ago} by Bob</IssueRow.Meta>
- </div>
- <IssueRow.CommentCount count={0} />
- </IssueRow.Root>
- <IssueRow.Root className="hover:bg-muted/30">
- <IssueRow.StatusIcon status={Status.Closed} />
- <div className="min-w-0 flex-1">
- <IssueRow.TitleArea>
- <a href="#" className="text-foreground hover:text-primary font-medium hover:underline">
- Update dependencies
- </a>
- </IssueRow.TitleArea>
- <IssueRow.Meta>#g7h8i9 opened {ago} by Alice</IssueRow.Meta>
- </div>
- <IssueRow.CommentCount count={7} />
- </IssueRow.Root>
+ <BugRow bug={openBug} />
+ <BugRow bug={closedBug} />
+ <BugRow bug={noLabelsBug} />
</div>
),
};
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn } from "storybook/test";
+import type { LabelFieldsFragment } from "@/__generated__/graphql";
+
import { LabelBadge } from "./LabelBadge";
const meta = {
@@ -10,45 +12,39 @@ const meta = {
export default meta;
type Story = StoryObj<typeof meta>;
+// Mock data shaped like LabelFieldsFragment from GraphQL
+const bug: LabelFieldsFragment = { name: "bug", color: { R: 252, G: 41, B: 41 } };
+const enhancement: LabelFieldsFragment = { name: "enhancement", color: { R: 163, G: 230, B: 53 } };
+const documentation: LabelFieldsFragment = { name: "documentation", color: { R: 30, G: 80, B: 160 } };
+const helpWanted: LabelFieldsFragment = { name: "help wanted", color: { R: 0, G: 150, B: 136 } };
+const wontfix: LabelFieldsFragment = { name: "wontfix", color: { R: 200, G: 200, B: 200 } };
+const priority: LabelFieldsFragment = { name: "priority", color: { R: 255, G: 152, B: 0 } };
+
+const allLabels = [bug, enhancement, documentation, helpWanted, wontfix, priority];
+
export const Default: Story = {
- args: {
- name: "bug",
- color: { R: 252, G: 41, B: 41 },
- },
+ args: bug,
};
export const LightBackground: Story = {
- args: {
- name: "enhancement",
- color: { R: 163, G: 230, B: 53 },
- },
+ args: enhancement,
};
export const DarkBackground: Story = {
- args: {
- name: "documentation",
- color: { R: 30, G: 80, B: 160 },
- },
+ args: documentation,
};
export const Clickable: Story = {
- args: {
- name: "feature",
- color: { R: 100, G: 200, B: 150 },
- onClick: fn(),
- },
+ args: { ...helpWanted, onClick: fn() },
};
export const AllColors: Story = {
- args: { name: "", color: { R: 0, G: 0, B: 0 } },
+ args: bug,
render: () => (
<div className="flex flex-wrap gap-2">
- <LabelBadge name="bug" color={{ R: 252, G: 41, B: 41 }} />
- <LabelBadge name="enhancement" color={{ R: 163, G: 230, B: 53 }} />
- <LabelBadge name="documentation" color={{ R: 30, G: 80, B: 160 }} />
- <LabelBadge name="help wanted" color={{ R: 0, G: 150, B: 136 }} />
- <LabelBadge name="wontfix" color={{ R: 200, G: 200, B: 200 }} />
- <LabelBadge name="priority" color={{ R: 255, G: 152, B: 0 }} />
+ {allLabels.map((label) => (
+ <LabelBadge key={label.name} {...label} />
+ ))}
</div>
),
};
@@ -1,11 +1,11 @@
import { createLink, type LinkComponent } from "@tanstack/react-router";
import * as React from "react";
-interface LabelBadgeProps {
- name: string;
- color: { R: number; G: number; B: number };
+import type { LabelFieldsFragment } from "@/__generated__/graphql";
+
+type LabelBadgeProps = LabelFieldsFragment & {
className?: string;
-}
+};
function contrastColor(r: number, g: number, b: number): string {
// Perceived luminance — pick black or white text for readability
@@ -15,44 +15,46 @@ function contrastColor(r: number, g: number, b: number): string {
// Coloured label pill. Always renders as a <span>.
// Use LabelBadgeLink for a clickable variant that navigates.
-const LabelBadge = React.forwardRef<HTMLSpanElement, LabelBadgeProps & Omit<React.HTMLAttributes<HTMLSpanElement>, "color">>(
- ({ name, color, className, ...props }, ref) => {
+const LabelBadge = React.forwardRef<
+ HTMLSpanElement,
+ LabelBadgeProps & Omit<React.HTMLAttributes<HTMLSpanElement>, "color">
+>(({ name, color, className, ...props }, ref) => {
+ const bg = `rgb(${color.R},${color.G},${color.B})`;
+ const text = contrastColor(color.R, color.G, color.B);
+
+ return (
+ <span
+ ref={ref}
+ className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${className ?? ""}`}
+ style={{ backgroundColor: bg, color: text }}
+ {...props}
+ >
+ {name}
+ </span>
+ );
+});
+LabelBadge.displayName = "LabelBadge";
+
+// LabelBadge as a TanStack Router link — renders as <a> with label styling.
+const CreatedLabelBadgeLink = createLink(
+ React.forwardRef<
+ HTMLAnchorElement,
+ LabelBadgeProps & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "color">
+ >(({ name, color, className, ...props }, ref) => {
const bg = `rgb(${color.R},${color.G},${color.B})`;
const text = contrastColor(color.R, color.G, color.B);
return (
- <span
+ <a
ref={ref}
- className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${className ?? ""}`}
+ className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium hover:opacity-80 ${className ?? ""}`}
style={{ backgroundColor: bg, color: text }}
{...props}
>
{name}
- </span>
+ </a>
);
- },
-);
-LabelBadge.displayName = "LabelBadge";
-
-// LabelBadge as a TanStack Router link — renders as <a> with label styling.
-const CreatedLabelBadgeLink = createLink(
- React.forwardRef<HTMLAnchorElement, LabelBadgeProps & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "color">>(
- ({ name, color, className, ...props }, ref) => {
- const bg = `rgb(${color.R},${color.G},${color.B})`;
- const text = contrastColor(color.R, color.G, color.B);
-
- return (
- <a
- ref={ref}
- className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium hover:opacity-80 ${className ?? ""}`}
- style={{ backgroundColor: bg, color: text }}
- {...props}
- >
- {name}
- </a>
- );
- },
- ),
+ }),
);
const LabelBadgeLink: LinkComponent<typeof CreatedLabelBadgeLink> = (props) => {
@@ -60,3 +62,4 @@ const LabelBadgeLink: LinkComponent<typeof CreatedLabelBadgeLink> = (props) => {
};
export { LabelBadge, LabelBadgeLink };
+export type { LabelBadgeProps };
@@ -95,7 +95,7 @@ function CommentItem({
return (
<CommentCard.Root>
- <CommentCard.AuthorAvatar src={item.author.avatarUrl} name={item.author.displayName} />
+ <CommentCard.AuthorAvatar avatarUrl={item.author.avatarUrl} displayName={item.author.displayName} />
<CommentCard.Card>
<CommentCard.CardHeader>
<Link
@@ -3,7 +3,7 @@
exports[`IssueRow/ClosedIssue matches snapshot 1`] = `
<div>
<div
- class="border-border flex items-start gap-3 border-b px-4 py-3 last:border-0"
+ class="border-border flex items-start gap-3 border-b px-4 py-3 last:border-0 hover:bg-muted/30"
>
<svg
aria-hidden="true"
@@ -49,8 +49,18 @@ exports[`IssueRow/ClosedIssue matches snapshot 1`] = `
<p
class="text-muted-foreground mt-0.5 text-xs"
>
- #d4e5f6 opened
- about 1 hour ago
+ #
+ d4e5f6
+ opened
+ 1 day ago
+ by
+
+ <a
+ class="hover:underline"
+ href="#"
+ >
+ Bob Smith
+ </a>
</p>
</div>
<div
@@ -129,13 +139,28 @@ exports[`IssueRow/List matches snapshot 1`] = `
>
bug
</span>
+ <span
+ class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium "
+ style="background-color: rgb(255, 152, 0); color: rgba(0, 0, 0, 0.75);"
+ >
+ priority
+ </span>
</div>
<p
class="text-muted-foreground mt-0.5 text-xs"
>
- #a1b2c3 opened
+ #
+ a1b2c3
+ opened
about 1 hour ago
- by Jane Doe
+ by
+
+ <a
+ class="hover:underline"
+ href="#"
+ >
+ Jane Doe
+ </a>
</p>
</div>
<div
@@ -166,7 +191,7 @@ exports[`IssueRow/List matches snapshot 1`] = `
>
<svg
aria-hidden="true"
- class="lucide lucide-circle-dot mt-0.5 size-4 shrink-0 text-green-600 dark:text-green-400"
+ class="lucide lucide-circle-check mt-0.5 size-4 shrink-0 text-purple-600 dark:text-purple-400"
fill="none"
height="24"
stroke="currentColor"
@@ -182,10 +207,8 @@ exports[`IssueRow/List matches snapshot 1`] = `
cy="12"
r="10"
/>
- <circle
- cx="12"
- cy="12"
- r="1"
+ <path
+ d="m9 12 2 2 4-4"
/>
</svg>
<div
@@ -210,18 +233,49 @@ exports[`IssueRow/List matches snapshot 1`] = `
<p
class="text-muted-foreground mt-0.5 text-xs"
>
- #d4e5f6 opened
- about 1 hour ago
- by Bob
+ #
+ d4e5f6
+ opened
+ 1 day ago
+ by
+
+ <a
+ class="hover:underline"
+ href="#"
+ >
+ Bob Smith
+ </a>
</p>
</div>
+ <div
+ class="text-muted-foreground flex shrink-0 items-center gap-1 text-xs"
+ >
+ <svg
+ aria-hidden="true"
+ class="lucide lucide-message-square size-3.5"
+ fill="none"
+ height="24"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ viewBox="0 0 24 24"
+ width="24"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"
+ />
+ </svg>
+ 12
+ </div>
</div>
<div
class="border-border flex items-start gap-3 border-b px-4 py-3 last:border-0 hover:bg-muted/30"
>
<svg
aria-hidden="true"
- class="lucide lucide-circle-check mt-0.5 size-4 shrink-0 text-purple-600 dark:text-purple-400"
+ class="lucide lucide-circle-dot mt-0.5 size-4 shrink-0 text-green-600 dark:text-green-400"
fill="none"
height="24"
stroke="currentColor"
@@ -237,8 +291,10 @@ exports[`IssueRow/List matches snapshot 1`] = `
cy="12"
r="10"
/>
- <path
- d="m9 12 2 2 4-4"
+ <circle
+ cx="12"
+ cy="12"
+ r="1"
/>
</svg>
<div
@@ -251,39 +307,26 @@ exports[`IssueRow/List matches snapshot 1`] = `
class="text-foreground hover:text-primary font-medium hover:underline"
href="#"
>
- Update dependencies
+ Simple issue with no labels
</a>
</div>
<p
class="text-muted-foreground mt-0.5 text-xs"
>
- #g7h8i9 opened
- about 1 hour ago
- by Alice
+ #
+ g7h8i9
+ opened
+ about 2 hours ago
+ by
+
+ <a
+ class="hover:underline"
+ href="#"
+ >
+ Alice Wu
+ </a>
</p>
</div>
- <div
- class="text-muted-foreground flex shrink-0 items-center gap-1 text-xs"
- >
- <svg
- aria-hidden="true"
- class="lucide lucide-message-square size-3.5"
- fill="none"
- height="24"
- stroke="currentColor"
- stroke-linecap="round"
- stroke-linejoin="round"
- stroke-width="2"
- viewBox="0 0 24 24"
- width="24"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"
- />
- </svg>
- 7
- </div>
</div>
</div>
</div>
@@ -292,7 +335,7 @@ exports[`IssueRow/List matches snapshot 1`] = `
exports[`IssueRow/NoLabelsNoComments matches snapshot 1`] = `
<div>
<div
- class="border-border flex items-start gap-3 border-b px-4 py-3 last:border-0"
+ class="border-border flex items-start gap-3 border-b px-4 py-3 last:border-0 hover:bg-muted/30"
>
<svg
aria-hidden="true"
@@ -334,14 +377,17 @@ exports[`IssueRow/NoLabelsNoComments matches snapshot 1`] = `
<p
class="text-muted-foreground mt-0.5 text-xs"
>
- #abc123 opened
- about 1 hour ago
- by
+ #
+ g7h8i9
+ opened
+ about 2 hours ago
+ by
+
<a
class="hover:underline"
href="#"
>
- Bob
+ Alice Wu
</a>
</p>
</div>
@@ -406,9 +452,12 @@ exports[`IssueRow/OpenIssue matches snapshot 1`] = `
<p
class="text-muted-foreground mt-0.5 text-xs"
>
- #a1b2c3 opened
+ #
+ a1b2c3
+ opened
about 1 hour ago
- by
+ by
+
<a
class="hover:underline"
href="#"
@@ -49,9 +49,9 @@ exports[`LabelBadge/Clickable matches snapshot 1`] = `
<div>
<span
class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium "
- style="background-color: rgb(100, 200, 150); color: rgba(0, 0, 0, 0.75);"
+ style="background-color: rgb(0, 150, 136); color: rgba(255, 255, 255, 0.9);"
>
- feature
+ help wanted
</span>
</div>
`;
@@ -1,5 +1,7 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
+import type { IdentitySummaryFragment } from "@/__generated__/graphql";
+
import * as CommentCard from "./comment-card";
const meta = {
@@ -9,14 +11,36 @@ const meta = {
export default meta;
type Story = StoryObj<typeof meta>;
+// Mock data shaped like IdentitySummaryFragment
+const jane: IdentitySummaryFragment = {
+ id: "1",
+ humanId: "jane1",
+ displayName: "Jane Doe",
+ avatarUrl: null,
+};
+
+const bob: IdentitySummaryFragment = {
+ id: "2",
+ humanId: "bob1",
+ displayName: "Bob Smith",
+ avatarUrl: "https://github.com/shadcn.png",
+};
+
+const alice: IdentitySummaryFragment = {
+ id: "3",
+ humanId: "alice1",
+ displayName: "Alice Wu",
+ avatarUrl: null,
+};
+
export const Default: Story = {
args: { children: null },
render: () => (
<CommentCard.Root>
- <CommentCard.AuthorAvatar name="Jane Doe" />
+ <CommentCard.AuthorAvatar displayName={jane.displayName} avatarUrl={jane.avatarUrl} />
<CommentCard.Card>
<CommentCard.CardHeader>
- <span className="text-foreground font-medium">Jane Doe</span>
+ <span className="text-foreground font-medium">{jane.displayName}</span>
<span className="text-muted-foreground">2 hours ago</span>
</CommentCard.CardHeader>
<CommentCard.CardBody>
@@ -31,10 +55,10 @@ export const WithEditButton: Story = {
args: { children: null },
render: () => (
<CommentCard.Root>
- <CommentCard.AuthorAvatar name="Bob Smith" src="https://github.com/shadcn.png" />
+ <CommentCard.AuthorAvatar displayName={bob.displayName} avatarUrl={bob.avatarUrl} />
<CommentCard.Card>
<CommentCard.CardHeader>
- <span className="text-foreground font-medium">Bob Smith</span>
+ <span className="text-foreground font-medium">{bob.displayName}</span>
<span className="text-muted-foreground">1 day ago</span>
<span className="text-muted-foreground text-xs">edited</span>
<button className="text-muted-foreground hover:bg-muted ml-auto rounded-sm px-1.5 py-0.5 text-xs">
@@ -53,10 +77,10 @@ export const EmptyBody: Story = {
args: { children: null },
render: () => (
<CommentCard.Root>
- <CommentCard.AuthorAvatar name="Alice Wu" />
+ <CommentCard.AuthorAvatar displayName={alice.displayName} avatarUrl={alice.avatarUrl} />
<CommentCard.Card>
<CommentCard.CardHeader>
- <span className="text-foreground font-medium">Alice Wu</span>
+ <span className="text-foreground font-medium">{alice.displayName}</span>
<span className="text-muted-foreground">just now</span>
</CommentCard.CardHeader>
<CommentCard.CardBody>
@@ -1,3 +1,4 @@
+import type { IdentitySummaryFragment } from "@/__generated__/graphql";
import { cn } from "@/lib/utils";
import { Avatar, AvatarFallback, AvatarImage } from "./avatar";
@@ -11,18 +12,16 @@ export function Root({ children, className }: RootProps) {
return <div className={cn("flex gap-3", className)}>{children}</div>;
}
-interface AuthorAvatarProps {
- src?: string | null;
- name: string;
+type AuthorAvatarProps = Pick<IdentitySummaryFragment, "displayName" | "avatarUrl"> & {
className?: string;
-}
+};
-export function AuthorAvatar({ src, name, className }: AuthorAvatarProps) {
+export function AuthorAvatar({ avatarUrl, displayName, className }: AuthorAvatarProps) {
return (
<Avatar className={cn("mt-1 size-8 shrink-0", className)}>
- <AvatarImage src={src ?? undefined} alt={name} />
+ <AvatarImage src={avatarUrl ?? undefined} alt={displayName} />
<AvatarFallback className="text-xs">
- {name.slice(0, 2).toUpperCase()}
+ {displayName.slice(0, 2).toUpperCase()}
</AvatarFallback>
</Avatar>
);