Card Deck
Up to three suggested cards cascaded in a corner: the front card whole, the two behind it showing only their titles. The whole deck is one link to the full set.
When to Use
Use when:
A few suggested cards should be in reach without taking the screen: the Intervention Card peek in the live cockpit, where the top three cards for the running block wait in the corner, one tap from the full set.
Don't use when:
The reader compares the cards or acts on each one. Lay them out with ws_grid_start and a Card each; one route into a task is a Choice Card.
Variants
One, two or three cards
Pass the cards front first. The front card shows its title, its icon and its caption; each card behind it shows a title strip. Only the first three are drawn, and a deck with no card renders nothing.
<?= ws_card_deck([
['title' => 'The Naysayer', 'caption' => 'Difficult Participants · 1 of 3', 'icon' => 'support'],
['title' => 'The Silent One'],
['title' => 'Running Over'],
], ['href' => '/intervention/']) ?>Floating
position => 'float' pins the deck to the bottom right of its positioned container, over the content, as in the cockpit. A page with a dock lifts it clear by setting --ws-card-deck-bottom on the container.
Sailboat Retrospective
Running OverThe Silent OneThe NaysayerDifficult Participants · 1 of 3<?= ws_card_deck($cards, ['href' => $cardsUrl, 'position' => 'float']) ?>
States
| State | Behavior |
|---|---|
| Default | Every card on --shadow-md; the cards behind are scaled to 95% and 90% from their top edge, a strip apart. |
| Hover and focus | The shadows deepen to --shadow-lg and the strips fan open: each card behind lifts a little further than the one in front of it. Under prefers-reduced-motion only the shadow changes. |
| Focus | The platform's focus ring around the whole deck. |
| No cards | Nothing is rendered: an empty deck is not a link to nowhere. |
| Long titles | Each title stays on one line and ends in an ellipsis; the full titles are in the deck's accessible name. |
Real-World Usage
The live cockpit ranks the Intervention Cards for the running block and how late the room is, then peeks the top three from the corner of the panel. The deck opens the cards screen.
Exercise
Running OverThe Silent OneThe NaysayerDifficult Participants · 1 of 3 Sailboat Retrospective
07:20
left of 20 min
<?= ws_card_deck(array_map(fn($c, $i) => [
'title' => $c['title'],
'caption' => $i === 0 ? $c['category'] . ' · 1 of ' . count($top) : null,
'icon' => 'support',
], $top, array_keys($top)), ['href' => $cardsUrl, 'position' => 'float']) ?>Options
| Option | Type | Default | Purpose |
|---|---|---|---|
$cards | array | required | Positional. Front first; each card has title (required), caption and icon (a Material Symbols name). Only the front card shows its caption and icon. |
href | string | '' | Where the deck leads. Without it the deck is a named group rather than a link. |
name | string | 'Intervention Cards' | What the deck holds; it opens the accessible name |
label | string | derived | Replaces the derived accessible name |
position | string | 'inline' | inline or float (bottom right of the positioned container) |
id | string | '' | Element ID |
class | string | '' | Additional CSS classes |
attrs | array | [] | Extra HTML attributes, such as data-sk-go |
Accessibility
| Concern | Behavior |
|---|---|
| Semantics | One link, so one Tab stop, however many cards it shows. Without href it is a group. |
| Name | Says what it holds and every card in it, front first: "Intervention Cards, 3 suggested: The Naysayer, The Silent One, Running Over". label replaces it. |
| Icon | aria-hidden: the name already says what the deck is. |
| Focus | The sky-blue focus ring (--focus-ring) around the whole deck. |
| Motion | The hover lift is a transform and is left out under prefers-reduced-motion. |
| Target | 220 by about 140 pixels, far above the 44px minimum. |
Tokens
| Token | Used for |
|---|---|
--shadow-md / --shadow-lg | Each card at rest, and on hover and focus |
--space-8 | The strip each card behind shows |
--space-10, --space-5, --space-16, --space-2 | The deck's width and a back card's height |
--space-4 | The floating deck's inset from the right and, by default, the bottom |
--ws-card-deck-bottom | Set on the container to lift a floating deck clear of a dock |
--brand-ink | The front card's icon |
--card-radius | The deck's corners, which the focus ring follows |
--focus-ring / --focus-ring-offset | Keyboard focus |
info
Each card is a
ws-card ws-card--compact, so its fill, border, radius and padding are the Card's own tokens.
CSS Classes
| Class | Purpose |
|---|---|
.ws-card-deck | The deck: a link (or a group) holding the cards |
.ws-card-deck--float | Pinned to the bottom right of the positioned container |
.ws-card-deck__card | Each card, on .ws-card.ws-card--compact |
.ws-card-deck__card--1 / --2 / --3 | Front, second and third. The back cards come first in the markup, so the front paints over them. |
.ws-card-deck__head | The front card's title and icon row |
.ws-card-deck__icon | The front card's icon |
Files
| File | Purpose |
|---|---|
includes/components/helpers.php | ws_card_deck() helper function |
includes/components/card-deck.php | Template: the cards, back first, and the accessible name |
includes/components/components.css | Styles (.ws-card-deck rules) |