-
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.
- Loading branch information
1 parent
bf51e66
commit 675b545
Showing
16 changed files
with
251 additions
and
28 deletions.
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 |
---|---|---|
|
@@ -9,6 +9,5 @@ | |
|
||
:root { | ||
--font-sans: "Inter", sans-serif; | ||
text-align: center; | ||
} | ||
</style> |
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
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
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 |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import type { Meta, StoryObj } from "@storybook/react" | ||
import { IconHeadset, IconSquareX } from "@tabler/icons-react" | ||
|
||
import { Paragraph } from "~/typography/Paragraph" | ||
|
||
import { FeatureCard } from "./FeatureCard" | ||
|
||
type Story = StoryObj<typeof FeatureCard> | ||
|
||
const Card = ( | ||
<div className="flex flex-wrap items-center gap-x-2.5 gap-y-3"> | ||
<IconHeadset /> | ||
<Paragraph className="font-medium">Need support?</Paragraph> | ||
|
||
<Paragraph size="sm" className="w-full opacity-60"> | ||
Contact with one of our experts to get support. | ||
</Paragraph> | ||
</div> | ||
) | ||
|
||
// Meta | ||
export default { | ||
title: "UI/FeatureCard", | ||
component: FeatureCard, | ||
args: { | ||
...FeatureCard.defaultProps, | ||
children: Card, | ||
style: { width: 240 }, | ||
closer: true, | ||
}, | ||
} satisfies Meta | ||
|
||
// Stories | ||
export const Default = { | ||
args: {}, | ||
} satisfies Story | ||
|
||
export const AsChild = { | ||
args: { | ||
asChild: true, | ||
closer: false, | ||
children: <a href="/">{Card}</a>, | ||
}, | ||
} satisfies Story | ||
|
||
export const WithCustomMarkup = { | ||
args: { | ||
closer: false, | ||
}, | ||
|
||
render: (props) => ( | ||
<FeatureCard.Root {...props}> | ||
{Card} | ||
|
||
<FeatureCard.Closer asChild className="text-base"> | ||
<button> | ||
<IconSquareX /> | ||
</button> | ||
</FeatureCard.Closer> | ||
</FeatureCard.Root> | ||
), | ||
} satisfies Story |
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,92 @@ | ||
import { Slot } from "@radix-ui/react-slot" | ||
import { IconX } from "@tabler/icons-react" | ||
import { forwardRef, isValidElement } from "react" | ||
import type { ButtonHTMLAttributes, HTMLAttributes } from "react" | ||
|
||
import { useTheme } from "~/providers" | ||
import { type VariantProps } from "~/shared/cva" | ||
import { Slottable } from "~/utils/Slottable" | ||
|
||
import { featureCardCloserVariants, featureCardVariants } from "./FeatureCard.variants" | ||
|
||
export type FeatureCardElement = HTMLDivElement | ||
|
||
export type FeatureCardProps = HTMLAttributes<FeatureCardElement> & | ||
VariantProps<typeof featureCardVariants> & { | ||
/** | ||
* If set to `true`, the button will be rendered as a child within the component. | ||
* This child component must be a valid React component. | ||
*/ | ||
asChild?: boolean | ||
|
||
/** | ||
* If set to `true`, it'll render a closer button. | ||
*/ | ||
closer?: boolean | ||
} | ||
|
||
type FeatureCardCloserProps = ButtonHTMLAttributes<HTMLButtonElement> & | ||
VariantProps<typeof featureCardCloserVariants> & { | ||
/** | ||
* If set to `true`, the button will be rendered as a child within the component. | ||
* This child component must be a valid React component. | ||
*/ | ||
asChild?: boolean | ||
} | ||
|
||
const FeatureCardRoot = forwardRef<FeatureCardElement, FeatureCardProps>((props, ref) => { | ||
const { className, asChild, theme: propTheme, variant, ...rest } = props | ||
|
||
const globalTheme = useTheme() | ||
const theme = propTheme || globalTheme | ||
|
||
const useAsChild = asChild && isValidElement(rest.children) | ||
const Component = useAsChild ? Slot : "div" | ||
|
||
return ( | ||
<Component className={featureCardVariants({ theme, variant, className })} ref={ref} {...rest} /> | ||
) | ||
}) | ||
|
||
const FeatureCardCloser = forwardRef<HTMLButtonElement, FeatureCardCloserProps>((props, ref) => { | ||
const { children, className, asChild, ...rest } = props | ||
|
||
const useAsChild = asChild && isValidElement(children) | ||
const Component = useAsChild ? Slot : "button" | ||
|
||
return ( | ||
<Component ref={ref} className={featureCardCloserVariants({ className })} {...rest}> | ||
{useAsChild ? children : <IconX />} | ||
</Component> | ||
) | ||
}) | ||
|
||
export const FeatureCardBase = forwardRef<FeatureCardElement, FeatureCardProps>((props, ref) => { | ||
const { children, asChild, closer, ...rest } = props | ||
|
||
return ( | ||
<FeatureCardRoot ref={ref} asChild={asChild} {...rest}> | ||
<Slottable child={children} asChild={asChild}> | ||
{(child) => ( | ||
<> | ||
{child} | ||
{closer && <FeatureCardCloser />} | ||
</> | ||
)} | ||
</Slottable> | ||
</FeatureCardRoot> | ||
) | ||
}) | ||
|
||
export const FeatureCard = Object.assign(FeatureCardBase, { | ||
Root: FeatureCardRoot, | ||
Closer: FeatureCardCloser, | ||
}) | ||
|
||
FeatureCard.defaultProps = { | ||
variant: "soft", | ||
asChild: false, | ||
closer: false, | ||
} | ||
|
||
FeatureCard.displayName = "FeatureCard" |
Oops, something went wrong.