Card
The Card component contains content and actions that inform about a single subject.
Default Card
The default card view with a rectangle shaped image, a title, a description and a button for some additional actions.
This block contain empty anchor
element, this specific manipulation adds possibility to navigate with tab
through whole card. With this structure we can click buttons inside or whole card itself. If root card element would be anchor
element, we would not have possibility to click button
inside.
import { SfButton } from '@storefront-ui/react';
const cardDetails = [
{
image: 'https://storage.googleapis.com/sfui_docs_artifacts_bucket_public/production/card-3.png',
title: 'Sip Sustainably: The Rise of Boxed Water',
description:
'Boxed water is a sustainable alternative to traditional plastic bottles, made from renewable resources.',
button: 'Read more',
},
{
image: 'https://storage.googleapis.com/sfui_docs_artifacts_bucket_public/production/card-2.png',
title: 'Ride the Future: Exploring the Benefits of e-Bikes',
description:
'Eco-friendly, efficient, and fun modes of transportation that provide a range of benefits for riders and the environment.',
button: 'Read more',
},
{
image: 'https://storage.googleapis.com/sfui_docs_artifacts_bucket_public/production/card-1.png',
title: 'Unleash the Ultimate Listening Experience',
description:
'Audiophile headphones offer unmatched sound quality and clarity, making them the go-to choice for music enthusiasts.',
button: 'Read more',
},
];
export default function CardDefault() {
return (
<div className="flex flex-wrap gap-4 lg:gap-6 lg:flex-nowrap">
{cardDetails.map(({ image, title, description, button }) => (
<div
key={title}
className="flex flex-col min-w-[325px] max-w-[375px] lg:w-[496px] relative border border-neutral-200 rounded-md hover:shadow-xl"
>
<a
className="absolute inset-0 z-1 focus-visible:outline focus-visible:outline-offset focus-visible:rounded-md"
href="#"
aria-label={title}
/>
<img src={image} alt={title} className="object-cover h-auto rounded-t-md aspect-video" />
<div className="flex flex-col items-start p-4 grow">
<p className="font-medium typography-text-base">{title}</p>
<p className="mt-1 mb-4 font-normal typography-text-sm text-neutral-700">{description}</p>
<SfButton size="sm" variant="tertiary" className="relative mt-auto">
{button}
</SfButton>
</div>
</div>
))}
</div>
);
}
Category Card
The category card view with a circle shaped image, and category title, clickable as the one element.
const categories = [
{
title: `Women`,
image: 'https://storage.googleapis.com/sfui_docs_artifacts_bucket_public/production/women_category.png',
},
{
title: `Men`,
image: 'https://storage.googleapis.com/sfui_docs_artifacts_bucket_public/production/men_category.png',
},
{
title: `Kid`,
image: 'https://storage.googleapis.com/sfui_docs_artifacts_bucket_public/production/kid_category.png',
},
];
export default function CategoryCard() {
return (
<div className="flex flex-wrap gap-4 lg:gap-6 lg:flex-no-wrap">
{categories.map(({ title, image }) => (
<div className="relative min-w-[180px] flex-col max-w-[240px] group" key={title}>
<a
className="absolute w-full h-full z-[1] focus-visible:outline focus-visible:outline-offset focus-visible:rounded-md"
href="#"
aria-label={title}
/>
<img
className="rounded-full bg-neutral-100 group-hover:shadow-xl group-active:shadow-none"
src={image}
alt={title}
width="240"
height="240"
/>
<div className="flex justify-center">
<a className="mt-4 font-semibold no-underline text-normal-900 typography-text-base group-hover:underline group-hover:text-primary-800 group-hover:font-normal group-active:text-primary-800 group-active:font-normal">
{title}
</a>
</div>
</div>
))}
</div>
);
}
Card Feature
This type of card has only button to interact.
import { SfButton, SfIconPackage, SfIconWarehouse, SfIconPublishedWithChanges } from '@storefront-ui/react';
import classNames from 'classnames';
const cardDetails = [
{
icon: <SfIconPackage size="2xl" />,
title: 'Free shipping',
description: 'Learn about our commitments to ethics, our team, our communities and more.',
buttonText: 'Read more',
isDisabled: false,
},
{
icon: <SfIconWarehouse size="2xl" />,
title: 'Click & Collect',
description: 'Learn about our commitments to ethics, our team, our communities and more.',
buttonText: 'Read more',
isDisabled: false,
},
{
icon: <SfIconPublishedWithChanges size="2xl" />,
title: 'Free 30-Day returns',
description: 'Learn about our commitments to ethics, our team, our communities and more.',
buttonText: 'Read more',
isDisabled: true,
},
];
export default function CardFeature() {
return (
<div className="flex flex-wrap gap-4 lg:gap-6 lg:flex-nowrap">
{cardDetails.map(({ icon, title, description, buttonText, isDisabled }) => (
<div key={title} className="flex flex-col w-full max-w-[325px] sm:w-[375px] lg:w-[496px] items-center">
<span className={classNames(isDisabled && 'text-disabled-900')}>{icon}</span>
<div className="p-4 flex flex-col items-center">
<p className={classNames('font-medium typography-text-base', { 'text-disabled-900': isDisabled })}>
{title}
</p>
<p
className={classNames('mt-1 mb-4 font-normal typography-text-sm text-neutral-700 text-center', {
'text-disabled-700': isDisabled,
})}
>
{description}
</p>
<SfButton size="sm" variant="secondary" disabled={isDisabled} className="mt-auto">
{buttonText}
</SfButton>
</div>
</div>
))}
</div>
);
}