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 { component$ } from '@builder.io/qwik';
import { SfButton } from 'qwik-storefront-ui';
const cardDetails = [
{
image: '/images/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: '/images/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: '/images/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 component$(() => {
return (
<div class="flex flex-wrap gap-4 lg:gap-6 lg:flex-nowrap">
{cardDetails.map(({ image, title, description, button }) => (
<div
key={title}
class="flex flex-col min-w-[325px] max-w-[375px] lg:w-[496px] relative border border-neutral-200 rounded-md hover:shadow-xl"
>
<a
class="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}
class="object-cover h-auto rounded-t-md aspect-video"
/>
<div class="flex flex-col items-start p-4 grow">
<p class="font-medium typography-text-base">{title}</p>
<p class="mt-1 mb-4 font-normal typography-text-sm text-neutral-700">
{description}
</p>
<SfButton size="sm" variant="tertiary" class="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.
import { component$ } from '@builder.io/qwik';
const categories = [
{
title: `Women`,
image: '/images/women_category.png',
},
{
title: `Men`,
image: '/images/men_category.png',
},
{
title: `Kid`,
image: '/images/kid_category.png',
},
];
export default component$(() => {
return (
<div class="flex flex-wrap gap-4 lg:gap-6 lg:flex-no-wrap">
{categories.map(({ title, image }) => (
<div
class="relative min-w-[180px] flex-col max-w-[240px] group"
key={title}
>
<a
class="absolute w-full h-full z-1 focus-visible:outline focus-visible:outline-offset focus-visible:rounded-md"
href="/"
aria-label={title}
/>
<img
class="rounded-full bg-neutral-100 group-hover:shadow-xl group-active:shadow-none"
src={image}
alt={title}
width={240}
height={240}
/>
<div class="flex justify-center">
<a class="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 { component$ } from '@builder.io/qwik';
import {
SfButton,
SfIconPackage,
SfIconPublishedWithChanges,
SfIconWarehouse,
} from 'qwik-storefront-ui';
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 component$(() => {
return (
<div class="flex flex-wrap gap-4 lg:gap-6 lg:flex-nowrap">
{cardDetails.map(
({ icon, title, description, buttonText, isDisabled }) => (
<div
key={title}
class="flex flex-col min-w-[325px] w-[375px] lg:w-[496px] items-center"
>
<span class={{ 'text-disabled-900': isDisabled }}>{icon}</span>
<div class="p-4 flex flex-col items-center">
<p
class={{
'font-medium typography-text-base': true,
'text-disabled-900': isDisabled,
}}
>
{title}
</p>
<p
class={{
'mt-1 mb-4 font-normal typography-text-sm text-neutral-700 text-center':
true,
'text-disabled-700': isDisabled,
}}
>
{description}
</p>
<SfButton
size="sm"
variant="secondary"
disabled={isDisabled}
class="mt-auto"
>
{buttonText}
</SfButton>
</div>
</div>
)
)}
</div>
);
});