Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
43c6504
WIP files
gerardo-rodriguez Nov 30, 2021
e5a476b
Fine-tuning
gerardo-rodriguez Dec 1, 2021
bd487aa
Remove unused code
gerardo-rodriguez Dec 1, 2021
a3e7671
Fix typo
gerardo-rodriguez Dec 1, 2021
9db9258
Story cleanup
gerardo-rodriguez Dec 1, 2021
a1d5b62
More adjustments
gerardo-rodriguez Dec 1, 2021
b8d84c9
More cleanup
gerardo-rodriguez Dec 1, 2021
cfd71bf
Small adjustments
gerardo-rodriguez Dec 1, 2021
5a6de08
Add a changeset
gerardo-rodriguez Dec 1, 2021
8145493
Start refactoring the Author pattern
gerardo-rodriguez Dec 1, 2021
c2f0d8e
More Author refactoring
gerardo-rodriguez Dec 1, 2021
21b5a9b
More refactoring of Author component
gerardo-rodriguez Dec 2, 2021
c5d5b74
Update changeset description
gerardo-rodriguez Dec 2, 2021
37542a8
Remove outdated comment
gerardo-rodriguez Dec 2, 2021
7fbcc66
Simplify some logic
gerardo-rodriguez Dec 2, 2021
4a7279b
More refactoring
gerardo-rodriguez Dec 2, 2021
02da4c8
Add some tests assertions for date/job title logic
gerardo-rodriguez Dec 2, 2021
f8174d1
Add more authors, update docs
gerardo-rodriguez Dec 2, 2021
984eb7c
Delete Speaker component
gerardo-rodriguez Dec 2, 2021
b111c34
Add comments
gerardo-rodriguez Dec 2, 2021
63349fd
PR feedback, add more comments
gerardo-rodriguez Dec 2, 2021
e6a8697
PR feedback
gerardo-rodriguez Dec 3, 2021
eeb1cf1
Fix typo
gerardo-rodriguez Dec 3, 2021
e0e22d6
PR feedback, fix typo
gerardo-rodriguez Dec 3, 2021
b6e2259
Add a date_prefix property
gerardo-rodriguez Dec 3, 2021
f4074b2
Add an author_prefix property
gerardo-rodriguez Dec 3, 2021
4a38794
Update test
gerardo-rodriguez Dec 3, 2021
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/real-olives-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudfour/patterns': minor
---

Refactor the Author component to work for article or presentation bylines
134 changes: 102 additions & 32 deletions src/components/author/author.stories.mdx
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
import { Story, Canvas, Meta } from '@storybook/addon-docs';
import template from './author.twig';
import ariannaImage from './demo/arianna.png';
import danielleImage from './demo/danielle.png';
import gerardoImage from './demo/gerardo.png';
import tylerImage from './demo/tyler.png';
import meganImage from './demo/megan.png';
const gerardo = {
name: 'Gerardo Rodriguez',
avatar: gerardoImage,
link: 'https://cloudfour.com/is/gerardo',
};
const tyler = {
name: 'Tyler Sticka',
avatar: tylerImage,
link: 'https://cloudfour.com/is/tyler',
};
const megan = {
name: 'Megan Notarte',
avatar: meganImage,
link: 'https://cloudfour.com/is/megnotarte',
};
const allAuthors = [
{
name: 'Arianna Chau',
avatar: ariannaImage,
link: 'https://cloudfour.com/is/arianna',
},
{
name: 'Danielle Romo',
avatar: danielleImage,
link: 'https://cloudfour.com/is/danielle',
},
{
name: 'Megan Notarte',
avatar: meganImage,
link: 'https://cloudfour.com/is/megnotarte',
},
{
name: 'Tyler Sticka',
avatar: tylerImage,
link: 'https://cloudfour.com/is/tyler',
},
{
name: 'Gerardo Rodriguez',
avatar: gerardoImage,
link: 'https://cloudfour.com/is/gerardo',
},
];
const authors = (count) => allAuthors.slice(0, count);

<Meta
title="Components/Author"
args={{
count: 2,
}}
argTypes={{
count: {
type: 'number',
defaultValue: 1,
description: 'Number of authors to show',
control: {
type: 'range',
min: 1,
max: 3,
max: allAuthors.length,
step: 1,
},
},
Expand All @@ -40,13 +53,61 @@ const megan = {

# Author

Displays an author, or set of authors, for article bylines.
Displays an author, or set of authors, with optional meta content.

<Canvas>
<Story name="Basic usage" args={{ count: 1 }}>
{(args) =>
template({
authors: authors(args.count),
})
}
</Story>
</Canvas>

## With `meta` content

You can use the `meta` property to add meta content, for example, the author title.

<Canvas>
<Story name="Default">
<Story name="With meta content" args={{ count: 1 }}>
{(args) =>
template({
authors: [gerardo, tyler, megan].slice(0, args.count),
authors: authors(args.count),
meta: 'Front-end Designer',
})
}
</Story>
</Canvas>

## With `date` content

If a date is desired for the meta content, use the `date` property with a
date object value. The Author template has extra logic to create a more
accessible user experience.

**Note:** The `meta` property will override the `date` if both are set.

<Canvas>
<Story name="With date content" args={{ count: 1 }}>
{(args) =>
template({
authors: authors(args.count),
date: new Date('March 31, 2021'),
})
}
</Story>
</Canvas>

## Multiple authors

Multiple authors are also supported.

<Canvas>
<Story name="Multiple authors" args={{ count: 3 }}>
{(args) =>
template({
authors: authors(args.count),
date: new Date('March 31, 2021'),
})
}
Expand All @@ -55,15 +116,24 @@ Displays an author, or set of authors, for article bylines.

## Template Properties

- `class`: Append a class to the root element.
- `authors`: Array of [author objects](https://timber.github.io/docs/reference/timber-user/#properties) of the type:
`class` (string): CSS class(es) to append to the root element

```ts
{
name: string | () => string;
avatar: string | () => string;
link: string | () => string;
}
```
`authors` (array): Array of [author objects](https://timber.github.io/docs/reference/timber-user/#properties) of the type:

```ts
{
name: string | () => string;
avatar: string | () => string;
link: string | () => string;
}
```

`author_prefix` (optional, string, default "By"): Used to create a more
accessible user experience by adding visually hidden text, prefixes the author name (e.g. "By Arianna Chau")

`meta` (optional, string): Extra information to be rendered below the author name(s)

`date` (optional, date object): Represents a publication date

- `date`: A date object representing the publication date
`date_prefix` (optional, string, default "Published on"): Used to create a more
accessible user experience by adding visually hidden text, prefixes the date value (e.g. "Published on March 31st, 2021")
62 changes: 62 additions & 0 deletions src/components/author/author.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import path from 'path';
import { withBrowser } from 'pleasantest';
import { loadTwigTemplate } from '../../../test-utils';

/** Helper to load the Twig template file */
const template = loadTwigTemplate(path.join(__dirname, './author.twig'));

describe('Author', () => {
test(
'more accessible experience for publish date',
withBrowser(async ({ utils, screen }) => {
await utils.injectHTML(
await template({
// The avatar is not included because I couldn't figure out how
// to include it. For the purposes of this test, though, it is
// not important so I left it out.
authors: [
{
name: 'Shakira Isabel Mebarak Ripoll',
link: 'https://www.shakira.com/',
},
],
date: new Date('March 31, 2021'),
date_prefix: 'Presented on',
})
);

// Confirm a more accessible user experience
await screen.getByText('Presented on March 31st, 2021');
})
);

test(
'meta is prioritized over date',
withBrowser(async ({ utils, screen }) => {
await utils.injectHTML(
await template({
// The avatar is not included because I couldn't figure out how
// to include it. For the purposes of this test, though, it is
// not important so I left it out.
authors: [
{
name: 'Shakira Isabel Mebarak Ripoll',
link: 'https://www.shakira.com/',
},
],
date: new Date('March 31, 2021'),
meta: 'Singer and songwriter',
})
);

// Confirm the meta value is rendered
await screen.getByText('Singer and songwriter');

// Confirm the date is not rendered
const publishDate = await screen.queryByText(
'Published on March 31st, 2021'
);
expect(publishDate).toBeNull();
})
);
});
65 changes: 57 additions & 8 deletions src/components/author/author.twig
Original file line number Diff line number Diff line change
@@ -1,23 +1,72 @@
{#
If both the `meta` and `date` properties contain values, the `meta` value has
a higher priority and will override the `date` value.

If rendering a date as meta data, it is recommended to use the `date` property.
There is extra template logic to create a more accessible user experience.
#}
{% set _meta_content %}
{% block meta_content %}
{% if meta %}
<p>{{ meta }}</p>
{% elseif date %}
<p>
{# This creates a more accessible, and less confusing, user experience #}
<span class="u-hidden-visually">
{{ date_prefix|default('Published on') }} {{ date|date('F jS, Y') }}
</span>
{#
The <time> element is not well supported by screen readers, therefore,
it is aria-hidden. On macOS VoiceOver, for example, the date would be
read twice, which was a confusing experience.

@see: https://twitter.com/LeonieWatson/status/1333078194925264898

The `<time>` element was not removed because per MDN Web Docs,
it allows for better search engine results:

> The `<time>` HTML element represents a specific period in time.
It may include the `datetime` attribute to translate dates into
machine-readable format, allowing for better search engine results or
custom features such as reminders.

@see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
#}
<time aria-hidden="true" datetime="{{ date|date('Y-m-d') }}">
{{ date|date('F jS, Y') }}
</time>
</p>
{% endif %}
{% endblock %}
{% endset %}

<div class="c-author o-media{% if class %} {{ class }}{% endif %}">
{# Avatar(s) #}
{% embed '@cloudfour/objects/bunch/bunch.twig' with { class: 'o-media__object' } %}
{% block content %}
{% for author in authors %}
{% include '@cloudfour/components/avatar/avatar.twig' with { src: author.avatar } only %}
{% endfor %}
{% endblock %}
{% endembed %}
<div class="o-media__content">
<div>
<span class="u-hidden-visually">Authored by</span>

{# Author content #}
<div class="c-author__content-container o-media__content">
{# Author links #}
<p class="c-author__author">
<span class="u-hidden-visually">{{ author_prefix|default("By") }}</span>
{% for author in authors %}
{% if loop.last and loop.length > 1 %}and {% endif %}
<a href="{{ author.link }}">{{ author.name }}</a>
{%- if not loop.last and loop.length > 2 %},{% endif %}
{% endfor %}
</div>
<div>
<span class="u-hidden-visually">Published on</span>
<time datetime="{{ date|date('Y-m-d') }}">{{ date|date('F jS, Y') }}</time>
</div>
</p>

{# Author meta content #}
{% if _meta_content|trim %}
<div class="c-author__meta">
{{ _meta_content }}
</div>
{% endif %}
</div>
</div>
Binary file added src/components/author/demo/arianna.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/author/demo/danielle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.