Skip to content

Commit 6bad210

Browse files
authored
Object: Deck (#1075)
1 parent 4511aaa commit 6bad210

File tree

9 files changed

+366
-10
lines changed

9 files changed

+366
-10
lines changed

.changeset/unlucky-colts-serve.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cloudfour/patterns': minor
3+
---
4+
5+
Add Deck layout object

src/components/card/card.scss

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ $_focus-overflow: (sizes.$edge-large * -1);
4545
* to this container.
4646
* 3. We define our column gap here instead of in the `c-card--horizontal`
4747
* modifiers so we don't have to define it within multiple media queries.
48-
*
49-
* @todo Coordinate column gap with eventual card grid object.
5048
*/
5149

5250
.c-card {
@@ -61,20 +59,20 @@ $_focus-overflow: (sizes.$edge-large * -1);
6159
@include fluid.grid-column-gap(
6260
breakpoint.$s,
6361
breakpoint.$xl,
64-
ms.step(1, 1rem),
65-
ms.step(3, 1rem)
62+
sizes.$gap-fluid-min,
63+
sizes.$gap-fluid-max
6664
); /* 3 */
6765
}
6866

6967
/**
7068
* Responsive horizontal modifiers
7169
*
72-
* 1. We define the layout as three columns instead of `2fr 1fr` so that the
70+
* 1. If this is in a multi-column grid layout, this insures it will fill the
71+
* available width.
72+
* 2. We define the layout as three columns instead of `2fr 1fr` so that the
7373
* gaps will line up with three-column elements below.
74-
* 2. The `fr` rows on the
74+
* 3. The `fr` rows on the
7575
* ends keep the content rows vertically centered.
76-
*
77-
* @todo Coordinate this with the eventual card grid object.
7876
*/
7977

8078
.c-card--horizontal {
@@ -83,14 +81,15 @@ $_focus-overflow: (sizes.$edge-large * -1);
8381
$to: xl,
8482
$include-default: false
8583
) {
84+
grid-column: 1 / -1; /* 1 */
8685
grid-template-areas:
8786
'cover cover .'
8887
'cover cover header'
8988
'cover cover content'
9089
'cover cover footer'
9190
'cover cover .';
92-
grid-template-columns: repeat(3, 1fr); /* 1 */
93-
grid-template-rows: 1fr repeat(3, minmax(0, auto)) 1fr; /* 2 */
91+
grid-template-columns: repeat(3, 1fr); /* 2 */
92+
grid-template-rows: 1fr repeat(3, minmax(0, auto)) 1fr; /* 3 */
9493
}
9594
}
9695

src/components/card/card.stories.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ If a card with a cover is meant to occupy its full container width, it may be pr
9090
</Story>
9191
</Canvas>
9292

93+
Horizontal cards will attempt to span all available columns of a CSS Grid Layout. This comes in handy when displaying them [in a Deck](/?path=/docs/objects-deck--horizontal-card#with-horizontal-cards).
94+
9395
## Coming soon
9496

9597
- Progressive enhancement based on CSS Grid support

src/design-tokens/sizes.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ props:
2727
trouble of recalculating the stupidly large value.
2828
type: pixel
2929
category: radius
30+
- name: card_column_min
31+
value: 15em
32+
comment: |
33+
The minimum space to display a default card in a grid.
34+
type: relative
35+
category: sizing
3036
- name: control_height
3137
value: 4
3238
type: modular/em
@@ -76,6 +82,18 @@ props:
7682
value: 1
7783
type: modular/em
7884
category: sizing
85+
- name: gap_fluid_min
86+
comment: |
87+
Minimum size of a large content gap, for example gutters between cards.
88+
value: 3
89+
type: modular/rem
90+
category: sizing
91+
- name: gap_fluid_max
92+
comment: |
93+
Maximum size of a large content gap, for example gutters between cards.
94+
value: 6
95+
type: modular/rem
96+
category: sizing
7997
- name: cell_pad_horizontal
8098
comment: |
8199
Used for table cells or other repeating content rows.

src/objects/deck/deck.scss

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
@use '../../design-tokens/breakpoint.yml';
2+
@use '../../design-tokens/sizes.yml';
3+
@use '../../mixins/fluid';
4+
@use '../../mixins/media-query';
5+
6+
/**
7+
* 1. If horizontal items are shown at the wrong column count, they will appear
8+
* to break the grid. This rule keeps items densely packed so it will always
9+
* appear visually correct.
10+
*
11+
* @todo Use progressive enhancement so older browsers get a minimal fallback.
12+
*/
13+
14+
.o-deck {
15+
display: grid;
16+
grid-auto-flow: dense; /* 1 */
17+
@include fluid.grid-gap(
18+
breakpoint.$s,
19+
breakpoint.$xl,
20+
sizes.$gap-fluid-min,
21+
sizes.$gap-fluid-max
22+
);
23+
24+
/**
25+
* We define a media query for our initial grid so child elements will flex
26+
* for viewports smaller than our minimum column size.
27+
*
28+
* Our use of `auto-fit` means columns will be automatically created as space
29+
* allows.
30+
*/
31+
32+
@media (width >= breakpoint.$xs) {
33+
grid-template-columns: repeat(
34+
auto-fit,
35+
minmax(#{sizes.$card-column-min}, 1fr)
36+
);
37+
}
38+
}
39+
40+
/**
41+
* Responsive column count modifiers
42+
*
43+
* These modifier classes specify a hard-set column count at a particular
44+
* breakpoint. This may be used to limit the column count to a particular
45+
* maximum or to coordinate with adjacent elements.
46+
*/
47+
48+
@for $i from 2 through 3 {
49+
.o-deck--#{$i}-column {
50+
@include media-query.breakpoint-classes($from: s, $to: xl) {
51+
grid-template-columns: repeat(#{$i}, 1fr);
52+
}
53+
}
54+
}

src/objects/deck/deck.stories.mdx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { Story, Canvas, Meta } from '@storybook/addon-docs/blocks';
2+
import articles from './demo/articles.json';
3+
import articlesDemo from './demo/articles.twig';
4+
const articlesStory = (args) => articlesDemo({ items: articles, ...args });
5+
6+
<Meta
7+
title="Objects/Deck"
8+
parameters={{ docs: { inlineStories: false } }}
9+
argTypes={{
10+
columns: {
11+
control: {
12+
type: 'range',
13+
min: 2,
14+
max: 3,
15+
step: 1,
16+
},
17+
defaultValue: 3,
18+
},
19+
columnsBreakpoint: {
20+
type: { name: 'string' },
21+
control: {
22+
type: 'inline-radio',
23+
options: ['none', '@s', '@m', '@l', '@xl'],
24+
},
25+
defaultValue: 'none',
26+
},
27+
horizontalItem: {
28+
control: {
29+
type: 'range',
30+
min: 1,
31+
max: articles.length,
32+
step: 1,
33+
},
34+
defaultValue: 1,
35+
},
36+
horizontalBreakpoint: {
37+
type: { name: 'string' },
38+
control: { type: 'inline-radio', options: ['none', '@m', '@l', '@xl'] },
39+
defaultValue: 'none',
40+
},
41+
}}
42+
/>
43+
44+
# Deck
45+
46+
What do you call a group of multiple [Cards](/?path=/docs/components-card--content-blocks)?
47+
48+
A “stack” of cards? Sure, but that may imply verticality…
49+
50+
How about a “deck” of cards?
51+
52+
By default, the `o-deck` class will use CSS Grid Layout to arrange child elements in a grid with generous whitespace. Additional columns will appear automatically as space allows.
53+
54+
<Canvas>
55+
<Story name="Basic" height="400px">
56+
{articlesStory.bind({})}
57+
</Story>
58+
</Canvas>
59+
60+
## Specifying Columns
61+
62+
While automatic columns are convenient, there are times when a specific column count is desired. For example, you may want to limit a design to three columns at larger breakpoints to align with adjacent elements.
63+
64+
To do this, add a modifier class in the format of `o-deck--X-column@Y`, where `X` is the desired column count (from 2 to 3) and `Y` is the desired [breakpoint](/?path=/docs/design-tokens-breakpoint--page) (from `s` to `xl`). In this example, we force the grid to display three columns starting from the `m` breakpoint.
65+
66+
<Canvas>
67+
<Story
68+
name="Columns"
69+
height="400px"
70+
args={{
71+
columns: 3,
72+
columnsBreakpoint: '@m',
73+
}}
74+
>
75+
{articlesStory.bind({})}
76+
</Story>
77+
</Canvas>
78+
79+
## With Horizontal Cards
80+
81+
[Horizontal cards](/?path=/docs/components-card--content-blocks#horizontal) will automatically span all available columns.
82+
83+
<Canvas>
84+
<Story
85+
name="Horizontal Card"
86+
height="500px"
87+
args={{
88+
columns: 3,
89+
columnsBreakpoint: '@l',
90+
horizontalBreakpoint: '@m',
91+
}}
92+
>
93+
{articlesStory.bind({})}
94+
</Story>
95+
</Canvas>

src/objects/deck/deck.twig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="o-deck{% if class %} {{class}}{% endif %}">
2+
{% block content %}{% endblock %}
3+
</div>

src/objects/deck/demo/articles.json

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
[
2+
{
3+
"title": "Building Flexible Components With Transparency",
4+
"pubDate": "2020-11-19 17:28:54",
5+
"link": "https://cloudfour.com/thinks/building-flexible-components-with-transparency/",
6+
"guid": "https://cloudfour.com/?p=6017",
7+
"author": "Paul Hebert",
8+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/11/transparent-flexible.png",
9+
"description": "By adding a touch of transparency, we can design components that automatically adapt to their backgrounds."
10+
},
11+
{
12+
"title": "A GitHub Action for automated deployment to WP Engine",
13+
"pubDate": "2020-11-17 08:30:14",
14+
"link": "https://cloudfour.com/thinks/a-github-action-for-automated-deployment-to-wp-engine/",
15+
"guid": "https://cloudfour.com/?p=5945",
16+
"author": "Emerson Loustau",
17+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/06/SpongeBob-SquarePants-Nervous-Sweating.gif",
18+
"description": "We recently set up a GitHub Action to automatically upload our site updates to WP Engine whenever we push to a specific branch. we suspect other teams might find it useful, too."
19+
},
20+
{
21+
"title": "Perfectly Broken Code",
22+
"pubDate": "2020-10-30 08:00:21",
23+
"link": "https://cloudfour.com/thinks/perfectly-broken-code/",
24+
"guid": "https://cloudfour.com/?p=5898",
25+
"author": "Gerardo Rodriguez",
26+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/10/perfectly-broken-code-preview-2.png",
27+
"description": "Join me in exploring a recent experience where I started with flawed logic (without realizing it) and the steps I took to fix my bug. Let’s experience some broken code together. 🎉"
28+
},
29+
{
30+
"title": "Designers, Design Systems and Finding Our Focus",
31+
"pubDate": "2020-10-19 15:44:36",
32+
"link": "https://cloudfour.com/thinks/designers-design-systems-and-finding-our-focus/",
33+
"guid": "https://cloudfour.com/?p=5944",
34+
"author": "Tyler Sticka",
35+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/10/focus-areas-r2.png",
36+
"description": "For many designers, the process of finding one's place within a design system can be surprisingly tough."
37+
},
38+
{
39+
"title": "Styling Complex Labels",
40+
"pubDate": "2020-09-02 09:00:06",
41+
"link": "https://cloudfour.com/thinks/styling-complex-labels/",
42+
"guid": "https://cloudfour.com/?p=5959",
43+
"author": "Danielle Romo",
44+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/07/custom-label.png",
45+
"description": "Consider the common pattern of selecting a pricing plan for a hypothetical service. To make a selection, users need to know the name of the plan, the price, and its features. But if we include all of those details, it gets hard to read: Each option’s plan information is included in a label. To improve […]"
46+
},
47+
{
48+
"title": "Performance is an issue of equity",
49+
"pubDate": "2020-08-11 18:28:00",
50+
"link": "https://cloudfour.com/thinks/performance-is-an-issue-of-equity/",
51+
"guid": "https://cloudfour.com/?p=5981",
52+
"author": "Megan Notarte",
53+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/08/perf-equity-r3-alt.png",
54+
"description": "Website speed and performance are a question of equity. Fast and lightweight sites mean that everyone can access your content equally. It’s not only an economic imperative; it’s a moral imperative."
55+
},
56+
{
57+
"title": "Generating complementary gradients with CSS filters",
58+
"pubDate": "2020-05-27 15:51:07",
59+
"link": "https://cloudfour.com/thinks/generating-complementary-gradients-with-css-filters/",
60+
"guid": "https://cloudfour.com/?p=5918",
61+
"author": "Paul Hebert",
62+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/05/socks-hero3.png",
63+
"description": "CSS filters unlock powerful new opportunities for playing with color. By applying some color theory we can dynamically generate harmonious color combos and gradients. Let's sell some socks!"
64+
},
65+
{
66+
"title": "CSS Animation Timelines: Building a Rube Goldberg Machine",
67+
"pubDate": "2020-04-13 15:41:25",
68+
"link": "https://cloudfour.com/thinks/css-animation-timelines-building-a-rube-goldberg-machine/",
69+
"guid": "https://cloudfour.com/?p=5784",
70+
"author": "Paul Hebert",
71+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/04/rgm.gif",
72+
"description": "Lately I’ve been using variables to plan out pure CSS timelines for complex animations. I built an SVG and CSS Rube Goldberg machine to put this technique to the test!"
73+
},
74+
{
75+
"title": "Getting Unstuck",
76+
"pubDate": "2020-04-03 08:00:06",
77+
"link": "https://cloudfour.com/thinks/getting-unstuck/",
78+
"guid": "https://cloudfour.com/?p=5752",
79+
"author": "Emerson Loustau",
80+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/04/HD.4G.038_10537689444-scaled-e1585787011260.jpg",
81+
"description": "Problem-solving is an essential part of software development. Sometimes we get stuck on a particularly baffling problem, and this can feel frustrating and discouraging. The following are some strategies for getting yourself “unstuck.”"
82+
},
83+
{
84+
"title": "Responsive Images the Simple Way",
85+
"pubDate": "2020-04-02 17:18:08",
86+
"link": "https://cloudfour.com/thinks/responsive-images-the-simple-way/",
87+
"guid": "https://cloudfour.com/?p=5773",
88+
"author": "Scott Vandehey",
89+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/03/summary.png",
90+
"description": "The responsive images spec is fantastic and covers a lot of use cases, but most of the time you’ll only need one: resolution switching using the `srcset` and `sizes` attributes."
91+
},
92+
{
93+
"title": "Navigation for Design Systems and Style Guides",
94+
"pubDate": "2020-02-21 16:35:31",
95+
"link": "https://cloudfour.com/thinks/navigation-for-design-systems-and-style-guides/",
96+
"guid": "https://cloudfour.com/?p=5740",
97+
"author": "Danielle Romo",
98+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/02/design-system-navigation.png",
99+
"description": "A key part of my job for the past year has been contributing to design systems. To benefit from those contributions though, users need to be able to find them. That’s why it’s not only the content of a design system that’s important but also its usability. Design systems should be easy to navigate, especially..."
100+
},
101+
{
102+
"title": "What Flushing Toilets Taught Me About Web Design",
103+
"pubDate": "2020-02-06 16:22:05",
104+
"link": "https://cloudfour.com/thinks/what-flushing-toilets-taught-me-about-web-design/",
105+
"guid": "https://cloudfour.com/?p=5718",
106+
"author": "Paul Hebert",
107+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/02/Sharing-Image.png",
108+
"description": " I re-learned an old design lesson from the humble toilet flusher. As new features are added to existing technologies, careful design is required to make their usage clear."
109+
},
110+
{
111+
"title": "Tiny Web Stacks",
112+
"pubDate": "2020-02-05 16:47:06",
113+
"link": "https://cloudfour.com/thinks/tiny-web-stacks/",
114+
"guid": "https://cloudfour.com/?p=5712",
115+
"author": "Tyler Sticka",
116+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/02/tiny-web-stacks-r2.png",
117+
"description": "When it comes to side projects, micro-sites and one-off experiments, you don't need much to get started."
118+
},
119+
{
120+
"title": "22 Panels That Always Work: Wally Wood’s Legendary Productivity Hack",
121+
"pubDate": "2020-01-14 16:49:28",
122+
"link": "https://cloudfour.com/thinks/22-panels-that-always-work-wally-woods-legendary-productivity-hack/",
123+
"guid": "https://cloudfour.com/?p=5678",
124+
"author": "Scott Vandehey",
125+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2020/01/wallywood22panel1600.jpg",
126+
"description": "Comic book artist Wally Wood’s “22 Panels That Always Work” is a legendary bit of productivity hacking. How can you reduce “noodling” in your work?"
127+
},
128+
{
129+
"title": "An HTML attribute potentially worth $4.4M to Chipotle",
130+
"pubDate": "2019-09-19 16:57:12",
131+
"link": "https://cloudfour.com/thinks/an-html-attribute-potentially-worth-4-4m-to-chipotle/",
132+
"guid": "https://cloudfour.com/?p=5555",
133+
"author": "Jason Grigsby",
134+
"thumbnail": "https://cloudfour.com/wp-content/uploads/2019/09/Screen-Shot-2019-09-19-at-9.52.57-AM.png",
135+
"description": "My parents are retired. They continue to try to pay for meals. I don't want them to. So we often end up in a competition to see who can pay first. In this case, I knew I had an advantage. My card details were already stored in the browser. I just needed to use autofill..."
136+
}
137+
]

0 commit comments

Comments
 (0)