Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/five-turkeys-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudfour/patterns': major
---

Renamed the Heading property from `permalink_id` to `id` and allowed you to use `id` when `permalink` is false.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically a breaking change, though as far as I can tell we're not usingpermalink_id anywhere yet.

5 changes: 5 additions & 0 deletions .changeset/shaggy-pumpkins-hug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudfour/patterns': minor
---

Added Overview object for use in Article Listings
2 changes: 2 additions & 0 deletions src/components/heading/heading.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ The `c-heading` class may include a permalink using [a technique from Marcy Sutt
- `c-heading__content`: The actual semantic heading element (usually `<h1>` – `<h6>`), including the `id` referenced by `c-heading__permalink`.
- `c-heading__permalink`: The `<a>` element that exposes the permalink to the user. This element is kept separate from the actual heading so it won't disrupt a user's ability to navigate via headings.

You can specify an ID that will be used for the heading (and therefore the permalink hash) using the `id` property. (The `id` property can also be used without permalinking.)

Note that the layout of this pattern is optimized for [our prose containers](/docs/objects-container--prose#prose) with generous horizontal whitespace.

<!--
Expand Down
16 changes: 8 additions & 8 deletions src/components/heading/heading.twig
Original file line number Diff line number Diff line change
Expand Up @@ -47,37 +47,37 @@
{% endset %}

{#
If a `permalink` is desired but no `permalink_id` is specified, we try
creating a `permalink_id` from the value of `content`.
If a `permalink` is desired but no `id` is specified, we try
creating a `id` from the value of `content`.

Since Twig lacks a built-in slugify function, this is pretty fragile and
should be considered a fallback.
#}

{% if permalink and not permalink_id and content is not empty %}
{% set permalink_id = content|lower|escape('url')|replace({'%20': '-'}) %}
{% if permalink and not id and content is not empty %}
{% set id = content|lower|escape('url')|replace({'%20': '-'}) %}
{% endif %}

{#
Permalink heading markup based on this example from accessibility expert
Marcy Sutton: http://codepen.io/marcysutton/pen/rLKvgZ
#}

{% if permalink and permalink_id %}
{% if permalink and id %}
<div class="{{ _heading_class }}">
<a class="c-heading__permalink" href="#{{ permalink_id }}">
<a class="c-heading__permalink" href="#{{ id }}">
{% include '@cloudfour/components/icon/icon.twig' with {
name: 'link',
aria_hidden: 'true'
} only %}
<span class="u-hidden-visually">Permalink to {{ _content }}</span>
</a>
<{{ tag_name }} class="c-heading__content" id="{{ permalink_id }}">
<{{ tag_name }} class="c-heading__content" id="{{ id }}">
{{ _content }}
</{{ tag_name }}>
</div>
{% else %}
<{{ tag_name }} class="{{ _heading_class }}">
<{{ tag_name }} class="{{ _heading_class }}" {% if id %}id="{{id}}"{% endif %}>
{{ _content }}
</{{ tag_name }}>
{% endif %}
40 changes: 40 additions & 0 deletions src/objects/overview/demo/advanced.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{% embed '@cloudfour/objects/overview/overview.twig' with {
labelledby_id: 'more-topics'
} %}
{% block header %}
{% include '@cloudfour/components/heading/heading.twig' with {
level: -1,
weight: "light",
content: 'More Topics',
id: 'more-topics'
} only %}
{% endblock %}
{% block actions %}
{#
In the future we could swap this out for the Input Group component
that's currently in the works.
#}
<label>
<span class="u-hidden-visually">Search</span>
{% include '@cloudfour/components/input/input.twig' %}
</label>
{% endblock %}
{% block content %}
{% embed '@cloudfour/objects/list/list.twig' with {
"tag_name": "ul",
"class": "o-list--2-column@m o-list--3-column@l"
} %}
{% block content %}
{% for topic in topics %}
<li class="u-space-block-end-0">
{% include '@cloudfour/components/dot-leader/dot-leader.twig' with {
label: topic.title,
count: topic.count,
href: 'https://cloudfour.com/thinks/'
} only %}
</li>
{% endfor %}
{% endblock %}
{% endembed %}
{% endblock %}
{% endembed %}
11 changes: 11 additions & 0 deletions src/objects/overview/demo/basic.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% embed '@cloudfour/objects/overview/overview.twig' %}
{% block header %}
Header
{% endblock %}
{% block actions %}
Actions
{% endblock %}
{% block content %}
Content
{% endblock %}
{% endembed %}
56 changes: 56 additions & 0 deletions src/objects/overview/overview.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
@use "../../compiled/tokens/scss/breakpoint";
@use '../../mixins/ms';
@use "../../compiled/tokens/scss/size";
@use '../../mixins/fluid';

/**
* The Overview stacks content vertically on small screens.
* On large screens the header and actions are stacked horizontally above the content.
* The specific spacing values were inferred from the Article Listing prototype.
*/

.o-overview__header {
margin-bottom: ms.step(1);
}

.o-overview__actions {
margin-bottom: ms.step(3);
}

@supports (display: grid) {
Comment on lines +12 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this is necessary? We aren't optimizing for IE, and the content seems perfectly accessible without grid if the spacing's a little off in this section.

I'm open to it, I was just surprised to see these fallbacks and then the margin resets later on for a relatively simple layout object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have strong feelings here.

The only change for IE11 was the @supports statement itself. The margins and margin resets were to handle the layout changes between small screens and large screens. I attempted to simplify this an use display: grid with gaps on all screen sizes, but this didn't quite match the prototype design. (On small screens there are two different margin sizes, so it doesn't map to a consistent gap.)

All that said, I'm totally fine removing the supports statement if it's just extra cruft.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realize the margin resets were also a responsive concern. In that case this isn't much cruft at all.

@media (min-width: breakpoint.$l) {
.o-overview {
@include fluid.column-gap(
breakpoint.$s,
breakpoint.$xl,
size.$spacing-gap-fluid-min,
size.$spacing-gap-fluid-max
);
Comment on lines +23 to +28
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm torn on this. column-gap does seem to be well supported in Grid, though not quite as well supported as grid-column-gap. (We added this mixin for use with the columns property.)

I think it's probably fine, just typing out my initial pause.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had initially used grid-column-gap when building out this component but VS Code warned me it was deprecated and that I should use column-gap. The support for column-gap and grid-column-gap seems the same in Safari which is the main modern browser I'd worry about since updates are tied to OS updates.

That said, I don't have strong feelings about it and would be fine swapping over.


align-items: center;
display: grid;
grid-template-areas:
'header header actions'
'content content content';
grid-template-columns: repeat(3, 1fr);
row-gap: ms.step(3);
}

.o-overview__header,
.o-overview__actions {
margin: 0;
}

.o-overview__header {
grid-area: header;
}

.o-overview__actions {
grid-area: actions;
}

.o-overview__content {
grid-area: content;
}
}
}
79 changes: 79 additions & 0 deletions src/objects/overview/overview.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Story, Canvas, Meta } from '@storybook/addon-docs/blocks';
import basicDemo from './demo/basic.twig';
import advancedDemo from './demo/advanced.twig'; // The '!!raw-loader!' syntax is a non-standard, Webpack-specific, syntax.
// See: https://github.com/webpack-contrib/raw-loader#examples
// For now, it seems likely Storybook is pretty tied to Webpack, therefore, we are
// okay with the following Webpack-specific raw loader syntax. It's better to leave
// the ESLint rule enabled globally, and only thoughtfully disable as needed (e.g.
// within a Storybook docs page and not within an actual component).
// This can be revisited in the future if Storybook no longer relies on Webpack.
// eslint-disable-next-line @cloudfour/import/no-webpack-loader-syntax
import basicDemoSource from '!!raw-loader!./demo/basic.twig';
// eslint-disable-next-line @cloudfour/import/no-webpack-loader-syntax
import advancedDemoSource from '!!raw-loader!./demo/advanced.twig';
import topics from '../../components/dot-leader/demo/topics.json';

<!--
Inline stories disabled so media queries will behave as expected within
embedded examples.
-->

<Meta
title="Objects/Overview"
parameters={{ docs: { inlineStories: false } }}
/>

# Overview

The Overview object can be used to provide an overview of a site section. For example, it is used to provide an index of article categories, as well as a form to search for articles.

It handles the responsive layout of `header`, `actions`, and `content` blocks. On small screens they are stacked vertically. On large screens the `header` and `actions` blocks stack horizontally above the `content` block.

It should usually be placed in a [Container](/docs/objects-container--basic).

<Canvas>
<Story
name="Basic"
height="300px"
parameters={{
docs: {
source: {
code: basicDemoSource,
},
},
}}
>
{basicDemo()}
</Story>
</Canvas>

## Advanced Usage

Here's a more complex usage example, showing how the Overview object could be used on the article listing page.

<Canvas>
<Story
name="Advanced Usage"
height="300px"
parameters={{
docs: {
source: {
code: advancedDemoSource,
},
},
}}
>
{advancedDemo({ topics })}
</Story>
</Canvas>

## Template Properties

- `overview_tag` - defaults to `section` but can be switched out for any HTML tag.
- `labelledby_id` - an optional ID to use with the `aria-labelledby` attribute.

## Template blocks

- `header` - should generally contain a [Heading](/docs/components-heading--levels)
- `actions` - could contain a searchbar or other actions
- `content` the primary overview content. For example, a list of categories.
14 changes: 14 additions & 0 deletions src/objects/overview/overview.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<{{overview_tag|default('section')}}
class="o-overview"
{% if labelledby_id %}aria-labelledby="{{labelledby_id}}"{% endif %}
>
<header class="o-overview__header">
{% block header %}{% endblock %}
</header>
<div class="o-overview__actions">
{% block actions %}{% endblock %}
</div>
<div class="o-overview__content">
{% block content %}{% endblock %}
</div>
</{{overview_tag|default('section')}}>
43 changes: 0 additions & 43 deletions src/prototypes/article-listing/example/example.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,31 +74,8 @@
}
}

.topics-header {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prototype CSS was replaced by the new Object CSS.

padding-bottom: ms.step(3);

@media (min-width: breakpoint.$l) {
display: grid;
@include fluid.grid-gap(
breakpoint.$s,
breakpoint.$xl,
size.$spacing-gap-fluid-min,
size.$spacing-gap-fluid-max
);
grid-template-columns: repeat(3, minmax(max-content, 1fr));
padding-bottom: ms.step(3);
}
}

.search-content {
align-items: center;
display: flex;
grid-column: 3 / -1;
padding-top: ms.step(1);

@media (min-width: breakpoint.$l) {
padding-top: 0;
}
}

.search-input {
Expand All @@ -115,24 +92,4 @@
.search-btn .c-icon {
font-size: ms.step(1);
}

.topics-content {
@media (min-width: breakpoint.$m) {
columns: 2;
@include fluid.grid-gap(
breakpoint.$s,
breakpoint.$xl,
size.$spacing-gap-fluid-min,
size.$spacing-gap-fluid-max
);
}

@media (min-width: breakpoint.$l) {
columns: 3;
}
}

.topics-content li {
margin-bottom: ms.step(0);
}
}
Loading