Skip to content

Commit

Permalink
Merge pull request #825 from MisRob/card-click-api
Browse files Browse the repository at this point in the history
More flexible KCard click event handling
  • Loading branch information
MisRob authored Nov 20, 2024
2 parents 43381e5 + a087d25 commit a43f175
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 169 deletions.
7 changes: 2 additions & 5 deletions docs/pages-components/DocsKCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
<slot name="aboveTitle"></slot>
</template>

<template v-if="$slots.title" #title>
<slot name="title"></slot>
<template v-if="$scopedSlots.title" #title="{ titleText }">
<slot name="title" :titleText="titleText"></slot>
</template>

<template v-if="$slots.belowTitle" #belowTitle>
Expand Down Expand Up @@ -152,9 +152,6 @@
if (this.title) {
return this.title;
}
if (this.$slots.title) {
return null;
}
return `${this.prependTitle} Learn everything about hummingbirds: their habitats, feeding patterns, and stunning flight abilities`;
},
Expand Down
169 changes: 124 additions & 45 deletions docs/pages/kcard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
:orientation="windowBreakpoint > 2 ? 'horizontal' : 'vertical'"
thumbnailDisplay="large"
thumbnailAlign="right"
prependTitle="(2)"
prependTitle="(1)"
showProgressInFooter
/>
</KCardGrid>
Expand All @@ -33,6 +33,7 @@
</li>
<li>Set a correct heading level (<DocsInternalLink text="Title" href="#title" />)</li>
<li>Ensure each card title is unique within a card grid (<DocsInternalLink text="Title" href="#title" />)</li>
<li>Do not use a heading element within the <code>title</code> slot</li>
<li>Ensure content provided via slots is accessible (<DocsInternalLink text="Accessibility" href="#a11y" />)</li>
<li>Even if a thumbnail image is available, provide a placeholder element (<DocsInternalLink text="Placeholder" href="#thumbnail-placeholder" />)</li>
<li>If using selection controls, use pre-defined labels (<DocsInternalLink text="Selection controls" href="#selection-controls" />)</li>
Expand All @@ -48,7 +49,7 @@
{ text: 'KCard and KCardGrid', href: '#k-card-and-grid' },
{ text: 'Title', href: '#title' },
{ text: 'Accessibility', href: '#a11y' },
{ text: 'Navigation', href: '#navigation' },
{ text: 'Click event and navigation', href: '#click-navigation' },
{ text: 'Layout', href: '#layout' },
{ text: 'Responsiveness', href: '#responsiveness' },
{ text: 'Content slots', href: '#content-slots' },
Expand Down Expand Up @@ -148,7 +149,7 @@
<DocsAnchorTarget anchor="#title" />
</h3>

<p><em>Use the <code>title</code> prop to assign an unique title to each card in a grid, and the <code>headingLevel</code> prop to set the heading level on it. The level needs to correspond to the surrounding context.</em> <DocsToggleButton contentId="more-heading-level" /></p>
<p><em>Always use the <code>title</code> prop to assign an unique title to each card in a grid, and the <code>headingLevel</code> prop to set the heading level on it. The level needs to correspond to the surrounding context.</em> <DocsToggleButton contentId="more-heading-level" /></p>

<DocsToggleContent id="more-heading-level">
<p>Examples:</p>
Expand All @@ -159,40 +160,79 @@
</ul>
</DocsToggleContent>

<p>The <code>titleMaxLines</code> prop can be used to truncate the title to a set number of lines.</p>
<p>The scoped <code>title</code> slot with its <code>titleText</code> attribute can be used to customize the title.</p>

<DocsShow block :style="{ maxWidth: '600px' }">
<KCardGrid
layout="1-1-1"
:skeletonsConfig="skeletonsConfig9"
:loading="loading"
>
<DocsKCard
:headingLevel="3"
orientation="horizontal"
thumbnailDisplay="small"
thumbnailAlign="right"
prependTitle="(1)"
hideFooter
>
<template #title="{ titleText }">
<KLabeledIcon icon="readSolid">
<KTextTruncator
:text="titleText"
:maxLines="1"
/>
</KLabeledIcon>
</template>
</DocsKCard>
</KCardGrid>
</DocsShow>

<!-- eslint-disable -->
<DocsShowCode language="html">
<template>
<KCardGrid>
<KCard
:headingLevel="3"
title="(1) Learn everything about hummingbirds: their habitats, feeding patterns, and stunning flight abilities"
...
>
<template #title="{ titleText }">
<KLabeledIcon icon="readSolid">
<KTextTruncator
:text="titleText"
:maxLines="1"
/>
</KLabeledIcon>
</template>
</KCard>
</KCardGrid>
</template>
</DocsShowCode>
<!-- eslint-enable -->

<p>For more customization, the <code>title</code> slot can be used. Provide only a title text to the slot without wrapping it in a heading element to avoid duplicate headings in the markup output. <DocsToggleButton contentId="more-title-slot" /></p>
<p><em>Do not use a heading element within the <code>title</code> slot to avoid duplicate headings in the markup output.</em><code>KCard</code> already handles a heading element internally.<DocsToggleButton contentId="more-title-slot" /></p>

<DocsToggleContent id="more-title-slot">
<DocsDoNot>
<template #do>
<!-- eslint-disable -->
<DocsShowCode language="html">
<template>
<KCardGrid>
<KCard
:headingLevel="3"
...
>
<template #title>
Card title
</template>
</KCard>
</KCardGrid>
</template>
</DocsShowCode>
<!-- eslint-enable -->
</template>
<template #not>
<DocsShowCode language="html">
<template>
<KCardGrid>
<KCard
:headingLevel="3"
title="(1) Learn everything about hummingbirds"
...
>
<template #title>
<h3>Card title</h3>
<template #title="{ titleText }">
<h3>
<KLabeledIcon icon="readSolid">
<KTextTruncator
:text="titleText"
:maxLines="2"
/>
</KLabeledIcon>
</h3>
</template>
</KCard>
</KCardGrid>
Expand All @@ -202,6 +242,8 @@
</DocsDoNot>
</DocsToggleContent>

<p>The <code>titleMaxLines</code> prop can be used to truncate the title to a set number of lines.</p>

<h3>
Accessibility
<DocsAnchorTarget anchor="#a11y" />
Expand All @@ -214,28 +256,56 @@
<p><em>Always test semantics, accessibility, and right-to-left of the final cards.</em></p>

<h3>
Navigation
<DocsAnchorTarget anchor="#navigation" />
Click event and navigation
<DocsAnchorTarget anchor="#click-navigation" />
</h3>

<p><code>KCard</code>'s entire area is clickable, navigating to a target provided via the <code>to</code> prop as a regular Vue route object. <DocsToggleButton contentId="more-navigation" /></p>
<p><code>KCard</code>'s entire area is clickable.</p>

<DocsToggleContent id="more-navigation">
<!-- eslint-disable -->
<DocsShowCode language="html">
<KCardGrid ...>
<KCard
:to="{ name: 'NamedRoute' }"
...
/>
<KCard
:to="{ path: '/kcard' }"
...
/>
</KCardGrid>
</DocsShowCode>
<!-- eslint-enable -->
</DocsToggleContent>
<p>You can use the <code>to</code> prop to navigate to a URL when the card is clicked.</p>

<DocsShowCode language="html">
<KCardGrid ...>
<KCard
...
:to="{ name: 'NamedRoute' }"
/>
<KCard
...
:to="{ path: '/kcard' }"
/>
</KCardGrid>
</DocsShowCode>

<p>Listen to the <code>click</code> event to perform a custom action (whether or not the <code>to</code> prop is used).</p>

<DocsShowCode language="html">
<KCardGrid ...>
<KCard
...
@click="onClick"
/>
<KCard
...
:to="{ path: '/kcard' }"
@click="onClick"
/>
</KCardGrid>
</DocsShowCode>

<!-- eslint-disable -->
<DocsShowCode language="javascript">
export default {
methods() {
onClick() {
console.log('Card clicked');
}
},
};
</DocsShowCode>
<!-- eslint-enable -->

<p>Note that long clicks are ignored to allow for text selection.</p>

<p>See <DocsInternalLink text="Interactive elements" href="#interactive-elements" /> to learn how to disable card navigation in favor of a custom handler when elements like buttons are rendered within a card.</p>

Expand Down Expand Up @@ -563,7 +633,7 @@
<DocsAnchorTarget anchor="#interactive-elements" />
</h3>

<p>When adding interactive elements like buttons to a card via slots, apply the <code>.stop</code> event modifier to their <code>@click</code> event to prevent the card from navigating away when clicked.</p>
<p>When adding interactive elements like buttons to a card via slots, apply the <code>.stop</code> event modifier to their <code>@click</code> event to prevent the card <DocsInternalLink text="click event and navigation" href="#click-navigation" />.</p>

<p><em>This applies to all slot content, but considering accessibility is especially important with interactive elements.</em> For instance, <code>ariaLabel</code> is applied to the bookmark icon button in the following example so that screenreaders can communicate its purpose. In production, more work would be needed to indicate the bookmark's toggled state. Always assess on a case-by-case basis.</p>

Expand Down Expand Up @@ -861,6 +931,15 @@
height: '180px',
},
],
skeletonsConfig9: [
{
breakpoints: [0, 1, 2, 3, 4, 5, 6, 7],
orientation: 'horizontal',
thumbnailDisplay: 'small',
thumbnailAlign: 'right',
height: '130px',
},
],
};
},
mounted() {
Expand Down
Loading

0 comments on commit a43f175

Please sign in to comment.