diff --git a/.changeset/kind-beans-fry.md b/.changeset/kind-beans-fry.md
new file mode 100644
index 000000000..9f520b973
--- /dev/null
+++ b/.changeset/kind-beans-fry.md
@@ -0,0 +1,5 @@
+---
+'@cloudfour/patterns': minor
+---
+
+Add 'pencil' icon
diff --git a/.changeset/loud-ligers-remember.md b/.changeset/loud-ligers-remember.md
new file mode 100644
index 000000000..30296f0b7
--- /dev/null
+++ b/.changeset/loud-ligers-remember.md
@@ -0,0 +1,5 @@
+---
+'@cloudfour/patterns': minor
+---
+
+Add Badge component
diff --git a/src/assets/icons/pencil.svg b/src/assets/icons/pencil.svg
new file mode 100644
index 000000000..c15ff1cf3
--- /dev/null
+++ b/src/assets/icons/pencil.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/components/badge/badge.scss b/src/components/badge/badge.scss
new file mode 100644
index 000000000..f7781d5b6
--- /dev/null
+++ b/src/components/badge/badge.scss
@@ -0,0 +1,44 @@
+@use "../../compiled/tokens/scss/font-weight";
+@use "../../compiled/tokens/scss/line-height";
+@use "../../compiled/tokens/scss/size";
+@use '../../mixins/ms';
+@use 'sass:math';
+
+.c-badge {
+ align-items: center;
+ background: var(--theme-color-background-secondary);
+ border-radius: size.$border-radius-medium;
+ color: var(--theme-color-text-muted);
+ display: inline-flex;
+ font-size: ms.step(-1);
+ font-weight: font-weight.$medium;
+ // Because the text in a badge does not wrap, we can avoid icons accidentally
+ // increasing the height as often by setting this here instead of relying on
+ // vertical padding.
+ height: ms.step(2);
+ line-height: line-height.$tighter;
+ // We only apply half padding because the padding feels too tight around icons
+ // but not around the label content. We'll apply the other half of padding on
+ // the content element itself.
+ padding: 0 math.div(size.$padding-cell-horizontal, 2);
+ vertical-align: middle;
+ white-space: nowrap;
+}
+
+.c-badge__content {
+ &:first-child {
+ padding-left: math.div(size.$padding-cell-horizontal, 2);
+ }
+
+ &:last-child {
+ padding-right: math.div(size.$padding-cell-horizontal, 2);
+ }
+}
+
+.c-badge__extra {
+ align-items: center;
+ display: flex;
+ flex: none;
+ justify-content: center;
+ min-width: ms.step(2);
+}
diff --git a/src/components/badge/badge.stories.mdx b/src/components/badge/badge.stories.mdx
new file mode 100644
index 000000000..86ada3e5f
--- /dev/null
+++ b/src/components/badge/badge.stories.mdx
@@ -0,0 +1,46 @@
+import { Story, Canvas, Meta } from '@storybook/addon-docs/blocks';
+import template from './badge.twig';
+
+
+
+# Badge
+
+Badges help provide just a smidge more context to repetitive or serialized content. For example, a badge can help the reader identify when [a comment on an article is by the author of that article](/docs/components-comment--role-author#role-badges).
+
+
+
+## With icon
+
+
+
+## Template Properties
+
+- `class` (string)
+- `icon` (string): The name of one of [our icons](/docs/design-icons--page) to display.
+- `message` (string, default `'Label'`)
+
+## Template Blocks
+
+- `content`: The main label content, typically the value of `message`.
+- `extra`: A visual extra preceding the content, typically populated by an icon if `icon` is set.
diff --git a/src/components/badge/badge.twig b/src/components/badge/badge.twig
new file mode 100644
index 000000000..2ea053bf2
--- /dev/null
+++ b/src/components/badge/badge.twig
@@ -0,0 +1,23 @@
+{% set _extra_content %}
+ {% block extra %}
+ {% if icon %}
+ {% include '@cloudfour/components/icon/icon.twig' with {
+ name: icon,
+ aria_hidden: 'true',
+ } only %}
+ {% endif %}
+ {% endblock %}
+{% endset %}
+
+
+ {% if _extra_content|trim %}
+
+ {{_extra_content}}
+
+ {% endif %}
+
+ {% block content %}
+ {{label|default('Label')}}
+ {% endblock %}
+
+
diff --git a/src/components/comment/comment.stories.mdx b/src/components/comment/comment.stories.mdx
index ed148d160..6d9c599f4 100644
--- a/src/components/comment/comment.stories.mdx
+++ b/src/components/comment/comment.stories.mdx
@@ -12,9 +12,8 @@ Displays a single comment in a comment thread, optionally with replies. Multiple
This component is still a work in progress. The following features are still in development:
-- Indicating when a comment's author is a Cloud Four team member.
- Integrating the comment reply form.
-- Adding blocks to the template to allow for more customization.
+- Finalizing this pattern's blocks and properties for theme integration.
## Single
@@ -32,6 +31,22 @@ This information may be passed to the component as a `comment` object matching t
{template({ comment: makeComment() })}
+## Role badges
+
+It is helpful for context within a discussion to know when a commentor is the original post author or a Cloud Four team member. The mechanics of this feature are still in development, but these stories show how these roles should appear using [the Badge component](/docs/components-badge--basic).
+
+
+
+
+
## Unapproved
If `comment.approved` is not `true`, an [Alert](/docs/components-alert--basic) will indicate that the comment is not yet approved.
diff --git a/src/components/comment/comment.twig b/src/components/comment/comment.twig
index cde6507a3..16620f4c7 100644
--- a/src/components/comment/comment.twig
+++ b/src/components/comment/comment.twig
@@ -4,6 +4,33 @@
{{comment.author.name}}
+ {#
+ TODO: Replace `demo_post_author` and `demo_cloud_four_member` with
+ more meaningful blocks or properties once we have a better idea of how
+ we'll integrate role badging based on actual comment data.
+ #}
+ {% if demo_post_author %}
+ (Article
+ {% embed '@cloudfour/components/badge/badge.twig' with {
+ label: 'Author',
+ icon: 'pencil',
+ } only %}
+ {% endembed %}
+ )
+ {% elseif demo_cloud_four_member %}
+ (Cloud Four
+ {% embed '@cloudfour/components/badge/badge.twig' with {
+ label: 'Team'
+ } only %}
+ {% block extra %}
+ {% include '@cloudfour/assets/brand/logo.svg.twig' with {
+ class: 'c-icon',
+ aria_hidden: 'true',
+ } only %}
+ {% endblock %}
+ {% endembed %}
+ Member)
+ {% endif %}
{% if comment.is_child %}replied{% else %}said{% endif %}: