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.
<!-- eslint-disable vuejs-accessibility/anchor-has-content -->
<template>
<div class="flex flex-wrap gap-4 lg:gap-6 lg:flex-nowrap">
<div
v-for="({ image, title, description, button }, index) in cardDetails"
:key="`${title}-${index}`"
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="#"
/>
<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>
</template>
<script lang="ts" setup>
import { SfButton } from '@storefront-ui/vue';
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',
},
];
</script>
Category Card
The category card view with a circle shaped image, and category title, clickable as the one element.
<template>
<div class="flex flex-wrap gap-4 lg:gap-6 lg:flex-no-wrap">
<div
v-for="{ title, image } in categories"
:key="title"
class="relative flex-col min-w-[140px] max-w-[240px] justify-center group"
>
<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>
</template>
<script setup lang="ts">
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',
},
];
</script>
Card Feature
This type of card has only button to interact.
<template>
<div class="flex flex-wrap gap-4 lg:gap-6 lg:flex-nowrap">
<div
v-for="({ icon, title, description, buttonText, isDisabled }, index) in cardDetails"
:key="`${title}-${index}`"
class="flex flex-col w-full max-w-[325px] sm:w-[375px] lg:w-[496px] items-center"
>
<component :is="icon" size="2xl" :class="{ 'text-disabled-900': isDisabled }" />
<div class="p-4 flex flex-col items-center">
<p :class="['font-medium typography-text-base', { 'text-disabled-900': isDisabled }]">{{ title }}</p>
<p
:class="[
'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" class="mt-auto">{{ buttonText }}</SfButton>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { SfButton, SfIconPackage, SfIconWarehouse, SfIconPublishedWithChanges } from '@storefront-ui/vue';
const cardDetails = [
{
icon: SfIconPackage,
title: 'Free shipping',
description: 'Learn about our commitments to ethics, our team, our communities and more.',
buttonText: 'Read more',
isDisabled: false,
},
{
icon: SfIconWarehouse,
title: 'Click & Collect',
description: 'Learn about our commitments to ethics, our team, our communities and more.',
buttonText: 'Read more',
isDisabled: false,
},
{
icon: SfIconPublishedWithChanges,
title: 'Free 30-Day returns',
description: 'Learn about our commitments to ethics, our team, our communities and more.',
buttonText: 'Read more',
isDisabled: true,
},
];
</script>