-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(sparkle): add metric card component * patch version * refactor(sparkle): reorganize metric card component structure * update dependencies * fix issue * card:improvement * resolving conflict * fixing package * fix package lock * [sparkle] - refactor: clean up formatting in Card component - Standardize object and component formatting for consistency - Remove extraneous newlines and ensure proper newline at EOF in Card component files - Simplify export statements in components index file * [sparkle] - feature: bump version to 0.2.328 - Updated package version in package-lock.json and package.json for new release - Changes include synchronization of the version across both files --------- Co-authored-by: JulesBelveze <[email protected]>
- Loading branch information
1 parent
c210dff
commit 66e190e
Showing
4 changed files
with
264 additions
and
1 deletion.
There are no files selected for viewing
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,140 @@ | ||
import { cva, type VariantProps } from "class-variance-authority"; | ||
import * as React from "react"; | ||
|
||
import { Spinner } from "@sparkle/components"; | ||
import { cn } from "@sparkle/lib/utils"; | ||
|
||
const CARD_SIZES = ["xs", "sm", "md", "lg"] as const; | ||
export type CardSizeType = (typeof CARD_SIZES)[number]; | ||
|
||
const cardVariants = cva( | ||
"s-flex s-flex-col s-gap-2 s-rounded-2xl s-bg-structure-50 s-p-4 s-min-h-[128px]", | ||
{ | ||
variants: { | ||
size: { | ||
xs: "s-w-[180px]", | ||
sm: "s-w-[240px]", | ||
md: "s-w-[300px]", | ||
lg: "s-w-[360px]", | ||
}, | ||
}, | ||
defaultVariants: { | ||
size: "sm", | ||
}, | ||
} | ||
); | ||
|
||
interface CardRootProps extends VariantProps<typeof cardVariants> { | ||
children: React.ReactNode; | ||
className?: string; | ||
} | ||
const Root = ({ size, className, children }: CardRootProps) => ( | ||
<div className={cn(cardVariants({ size }), className)}>{children}</div> | ||
); | ||
|
||
interface CardHeaderProps { | ||
children: React.ReactNode; | ||
className?: string; | ||
} | ||
|
||
const Header = ({ className, children }: CardHeaderProps) => ( | ||
<div className={cn("s-space-y-0.5", className)}>{children}</div> | ||
); | ||
|
||
interface CardTitleProps { | ||
children: React.ReactNode; | ||
className?: string; | ||
} | ||
|
||
const Title = ({ className, children }: CardTitleProps) => ( | ||
<div | ||
className={cn("s-text-sm s-font-semibold s-text-element-800", className)} | ||
> | ||
{children} | ||
</div> | ||
); | ||
|
||
interface CardSubtitleProps { | ||
children: React.ReactNode; | ||
className?: string; | ||
} | ||
|
||
const Subtitle = ({ className, children }: CardSubtitleProps) => ( | ||
<div className={cn("s-text-sm s-text-element-700", className)}> | ||
{children} | ||
</div> | ||
); | ||
|
||
interface CardContentProps { | ||
children?: React.ReactNode; | ||
className?: string; | ||
isLoading?: boolean; | ||
} | ||
|
||
const Content = ({ | ||
className, | ||
children, | ||
isLoading = false, | ||
}: CardContentProps) => { | ||
if (isLoading) { | ||
return ( | ||
<div className="s-flex s-items-center s-justify-start"> | ||
<Spinner size="sm" /> | ||
</div> | ||
); | ||
} | ||
return ( | ||
<div className={cn("s-flex s-flex-col s-gap-3", className)}>{children}</div> | ||
); | ||
}; | ||
|
||
interface CardFooterProps { | ||
children: React.ReactNode; | ||
className?: string; | ||
} | ||
|
||
const Footer = ({ className, children }: CardFooterProps) => ( | ||
<div className={cn("s-flex s-items-center s-gap-2", className)}> | ||
{children} | ||
</div> | ||
); | ||
|
||
interface CardProps { | ||
title: string; | ||
subtitle?: string; | ||
content: React.ReactNode; | ||
footer?: React.ReactNode; | ||
isLoading?: boolean; | ||
size?: CardSizeType; | ||
className?: string; | ||
} | ||
|
||
export const Card = ({ | ||
title, | ||
subtitle, | ||
content, | ||
footer, | ||
isLoading = false, | ||
size = "sm", | ||
className, | ||
}: CardProps) => { | ||
return ( | ||
<Root size={size} className={className}> | ||
<Header> | ||
<Title>{title}</Title> | ||
{subtitle && <Subtitle>{subtitle}</Subtitle>} | ||
</Header> | ||
<Content isLoading={isLoading}>{content}</Content> | ||
{footer && <Footer>{footer}</Footer>} | ||
</Root> | ||
); | ||
}; | ||
|
||
export const ComposableCard = { | ||
Root, | ||
Header, | ||
Title, | ||
Subtitle, | ||
Content, | ||
Footer, | ||
}; |
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,2 +1,2 @@ | ||
import "./styles/global_with_tw_base.css"; | ||
export * from "./index"; | ||
export * from "./index"; |
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,122 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import * as React from "react"; | ||
|
||
import { | ||
Avatar, | ||
} from "@sparkle/components"; | ||
import { HandThumbUpIcon } from "@sparkle/icons/solid"; | ||
|
||
import { Card,ComposableCard } from "../components/Card"; | ||
|
||
const meta: Meta<typeof Card> = { | ||
title: "Components/Card", | ||
component: Card, | ||
parameters: { | ||
layout: "padded", | ||
}, | ||
argTypes: { | ||
size: { | ||
control: 'select', | ||
options: ['xs', 'sm', 'md', 'lg'], | ||
}, | ||
className: { | ||
control: 'text' | ||
}, | ||
}, | ||
args: { | ||
size: 'sm', | ||
}, | ||
tags: ["autodocs"], | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof Card>; | ||
|
||
export const Basic: Story = { | ||
args: { | ||
title: "Messages", | ||
subtitle: "Monthly activity", | ||
content: ( | ||
<div className="s-flex s-items-center s-gap-2"> | ||
<div className="s-text-lg s-font-semibold s-text-element-900"> | ||
847 | ||
</div> | ||
</div> | ||
), | ||
}, | ||
}; | ||
|
||
export const Loading: Story = { | ||
args: { | ||
...Basic.args, | ||
isLoading: true, | ||
}, | ||
}; | ||
|
||
export const WithIcons: Story = { | ||
args: { | ||
title: "Reactions", | ||
content: ( | ||
<div className="s-flex s-items-center s-gap-2"> | ||
<HandThumbUpIcon className="s-h-4 s-w-4 s-text-element-600" /> | ||
<div className="s-text-lg s-font-semibold s-text-element-900">12</div> | ||
</div> | ||
), | ||
}, | ||
}; | ||
|
||
export const Sizes: Story = { | ||
render: (args) => ( | ||
<div className="s-flex s-flex-wrap s-gap-4"> | ||
{(["xs", "sm", "md"] as const).map((size) => ( | ||
<Card | ||
key={size} | ||
{...args} | ||
size={size} | ||
title={`Size: ${size}`} | ||
content={ | ||
<div className="s-text-lg s-font-semibold s-text-element-900"> | ||
847 | ||
</div> | ||
} | ||
/> | ||
))} | ||
</div> | ||
), | ||
}; | ||
|
||
export const Composable: Story = { | ||
render: () => ( | ||
<ComposableCard.Root size="sm"> | ||
<ComposableCard.Header> | ||
<ComposableCard.Title>Messages</ComposableCard.Title> | ||
<ComposableCard.Subtitle>Monthly activity</ComposableCard.Subtitle> | ||
</ComposableCard.Header> | ||
<ComposableCard.Content> | ||
<div className="s-flex s-items-center s-gap-2"> | ||
<HandThumbUpIcon className="s-h-4 s-w-4 s-text-element-600" /> | ||
<div className="s-text-lg s-font-semibold">847</div> | ||
</div> | ||
</ComposableCard.Content> | ||
<ComposableCard.Footer> | ||
<div className="s-flex -s-space-x-2"> | ||
<Avatar | ||
size="sm" | ||
name="John Doe" | ||
visual="https://dust.tt/static/droidavatar/Droid_Lime_3.jpg" | ||
/> | ||
<Avatar | ||
size="sm" | ||
name="Jane Smith" | ||
visual="https://dust.tt/static/droidavatar/Droid_Yellow_3.jpg" | ||
/> | ||
<Avatar | ||
size="sm" | ||
name="Bob Johnson" | ||
visual="https://dust.tt/static/droidavatar/Droid_Red_3.jpg" | ||
/> | ||
</div> | ||
</ComposableCard.Footer> | ||
</ComposableCard.Root> | ||
), | ||
}; |