@codeforamerica/marcomms-design-system 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/package.json +2 -1
  2. package/src/components/accordion.js +141 -0
  3. package/src/components/accordion.stories.js +56 -0
  4. package/src/components/avatar.js +62 -0
  5. package/src/components/avatar.stories.js +27 -0
  6. package/src/components/banner.js +152 -0
  7. package/src/components/banner.stories.js +115 -0
  8. package/src/components/bar.js +102 -0
  9. package/src/components/bar.stories.js +22 -0
  10. package/src/components/blob.js +119 -0
  11. package/src/components/blob.stories.js +64 -0
  12. package/src/components/box.js +55 -0
  13. package/src/components/box.stories.js +24 -0
  14. package/src/components/breadcrumbs.js +80 -0
  15. package/src/components/breadcrumbs.stories.js +27 -0
  16. package/src/components/button.js +167 -0
  17. package/src/components/button.scss +162 -0
  18. package/src/components/button.stories.js +49 -0
  19. package/src/components/callout.js +62 -0
  20. package/src/components/callout.stories.js +20 -0
  21. package/src/components/card.js +403 -0
  22. package/src/components/card.stories.js +170 -0
  23. package/src/components/carousel.js +182 -0
  24. package/src/components/carousel.stories.js +61 -0
  25. package/src/components/cta.js +99 -0
  26. package/src/components/cta.stories.js +22 -0
  27. package/src/components/details.scss +71 -0
  28. package/src/components/details.stories.js +27 -0
  29. package/src/components/flexible-layout.js +126 -0
  30. package/src/components/flexible-layout.stories.js +48 -0
  31. package/src/components/form-elements.scss +305 -0
  32. package/src/components/form-elements.stories.js +134 -0
  33. package/src/components/icon.js +41 -0
  34. package/src/components/icon.scss +31 -0
  35. package/src/components/icon.stories.js +16 -0
  36. package/src/components/label.js +63 -0
  37. package/src/components/label.stories.js +29 -0
  38. package/src/components/link-list.scss +80 -0
  39. package/src/components/link-list.stories.js +52 -0
  40. package/src/components/loader.scss +24 -0
  41. package/src/components/loader.stories.js +12 -0
  42. package/src/components/logo-card.js +93 -0
  43. package/src/components/logo-card.stories.js +48 -0
  44. package/src/components/nav.js +99 -0
  45. package/src/components/nav.stories.js +40 -0
  46. package/src/components/page-nav.js +171 -0
  47. package/src/components/page-nav.stories.js +112 -0
  48. package/src/components/pager.js +98 -0
  49. package/src/components/pager.stories.js +30 -0
  50. package/src/components/pagination.js +116 -0
  51. package/src/components/pagination.stories.js +30 -0
  52. package/src/components/person-card.js +240 -0
  53. package/src/components/person-card.stories.js +58 -0
  54. package/src/components/pill.js +33 -0
  55. package/src/components/pill.stories.js +23 -0
  56. package/src/components/promo.js +83 -0
  57. package/src/components/promo.stories.js +37 -0
  58. package/src/components/pullquote.js +42 -0
  59. package/src/components/pullquote.stories.js +16 -0
  60. package/src/components/quote.js +84 -0
  61. package/src/components/quote.stories.js +23 -0
  62. package/src/components/reveal.js +83 -0
  63. package/src/components/reveal.stories.js +40 -0
  64. package/src/components/slide.js +121 -0
  65. package/src/components/slide.stories.js +53 -0
  66. package/src/components/social-icon.js +233 -0
  67. package/src/components/social-icon.stories.js +36 -0
  68. package/src/components/stat.js +92 -0
  69. package/src/components/stat.stories.js +28 -0
  70. package/src/components/tab-list.js +114 -0
  71. package/src/components/tab-list.stories.js +18 -0
  72. package/src/components/tab.js +95 -0
  73. package/src/components/tab.stories.js +29 -0
  74. package/src/components/tile.js +150 -0
  75. package/src/components/tile.stories.js +41 -0
  76. package/src/components/transcript.js +44 -0
  77. package/src/components/transcript.stories.js +167 -0
  78. package/src/core/_base.scss +86 -0
  79. package/src/core/_grid.scss +295 -0
  80. package/src/core/_helpers.scss +111 -0
  81. package/src/core/_layout.scss +79 -0
  82. package/src/core/_reset.scss +53 -0
  83. package/src/core/_tokens.scss +251 -0
  84. package/src/core/_typography.scss +426 -0
  85. package/src/core/_wordpress.scss +27 -0
  86. package/src/core/colors.mdx +100 -0
  87. package/src/core/typography.mdx +66 -0
  88. package/src/shared/common.js +15 -0
  89. package/src/shared/layout.js +14 -0
  90. package/src/shared/typography.js +111 -0
  91. package/src/styles.scss +16 -0
@@ -0,0 +1,83 @@
1
+ import { LitElement, html, css, nothing } from "lit";
2
+ import { commonStyles } from "../shared/common";
3
+ import { typographyStyles } from "../shared/typography";
4
+ import "./icon";
5
+
6
+ class Promo extends LitElement {
7
+ static properties = {
8
+ heading: {},
9
+ text: {},
10
+ actionLabel: {},
11
+ linkUrl: {},
12
+ linkTarget: {},
13
+ };
14
+ static styles = [
15
+ commonStyles,
16
+ typographyStyles,
17
+ css`
18
+ :host {
19
+ --bg-color: var(--blue-20);
20
+ --padding: var(--spacing-component-4);
21
+ --text-color: var(--black);
22
+ --action-label-color: var(--purple-60);
23
+ --action-label-hover-color: var(--red-60);
24
+
25
+ display: block;
26
+ }
27
+
28
+ .promo,
29
+ a.promo {
30
+ background-color: var(--bg-color);
31
+ box-shadow: var(--shadow-small);
32
+ color: var(--text-color, #000);
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: var(--spacing-layout-half);
36
+ padding: var(--padding);
37
+ text-align: center;
38
+ text-decoration: none;
39
+ transition: box-shadow 0.2s ease-in-out;
40
+ width: 100%;
41
+ }
42
+
43
+ a.promo:hover {
44
+ box-shadow: var(--shadow-medium);
45
+ }
46
+
47
+ .action-label {
48
+ color: var(--action-label-color);
49
+ }
50
+
51
+ a.promo:hover .action-label {
52
+ color: var(--action-label-hover-color);
53
+ }
54
+ `,
55
+ ];
56
+
57
+ render() {
58
+ return html`
59
+ <a
60
+ href="${this.linkUrl || "javascript:void(0)"}"
61
+ target="${this.linkTarget || nothing}"
62
+ class="promo
63
+ "
64
+ >
65
+ ${this.heading
66
+ ? html` <div class="h4 sans-serif">${this.heading}</div> `
67
+ : nothing}
68
+ ${this.text ? html` <div class="small">${this.text}</div> ` : nothing}
69
+ ${this.actionLabel
70
+ ? html`
71
+ <div class="action-label small strong">
72
+ ${this.actionLabel} <cfa-icon>arrow_forward</cfa-icon>
73
+ </div>
74
+ `
75
+ : nothing}
76
+ </a>
77
+ `;
78
+ }
79
+ }
80
+
81
+ if (!customElements.get("cfa-promo")) {
82
+ customElements.define("cfa-promo", Promo);
83
+ }
@@ -0,0 +1,37 @@
1
+ import { html } from "lit-html";
2
+ import "./promo";
3
+
4
+ export default {
5
+ title: "Molecules/Promo",
6
+ argTypes: {
7
+ heading: { type: "string" },
8
+ text: { type: "string" },
9
+ linkUrl: { type: "string" },
10
+ linkTarget: { type: "string" },
11
+ actionLabel: { type: "string" },
12
+ },
13
+ };
14
+
15
+ const Template = ({ heading, text, linkUrl, linkTarget, actionLabel }) => html`
16
+ <div class="row center-xs">
17
+ <div class="col-xs-12 col-md-6">
18
+ <cfa-promo
19
+ heading="${heading}"
20
+ text="${text}"
21
+ linkUrl="${linkUrl}"
22
+ linkTarget="${linkTarget}"
23
+ actionLabel="${actionLabel}"
24
+ >
25
+ </cfa-promo>
26
+ </div>
27
+ </div>
28
+ `;
29
+
30
+ export const Default = Template.bind({});
31
+ Default.args = {
32
+ heading: "Summit 2023",
33
+ text: "Join us in D.C. next month",
34
+ linkUrl: "https://summit.codeforamerica.org",
35
+ linkTarget: "_blank",
36
+ actionLabel: "Register now",
37
+ };
@@ -0,0 +1,42 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { commonStyles } from "../shared/common";
3
+
4
+ class PullQuote extends LitElement {
5
+ static properties = {};
6
+ static styles = [
7
+ commonStyles,
8
+ css`
9
+ :host {
10
+ --color: var(--purple-60);
11
+
12
+ display: block;
13
+ }
14
+ blockquote {
15
+ border-inline-start: var(--thick) solid var(--color);
16
+ color: var(--color);
17
+ font-size: var(--font-size-h3);
18
+ font-weight: 600;
19
+ line-height: var(--line-height-h3);
20
+ margin: 0;
21
+ padding: var(--spacing-layout-half) var(--spacing-layout-1);
22
+ }
23
+ p {
24
+ margin: 0;
25
+ }
26
+ p + p {
27
+ margin-block-start: var(--spacing-layout-half);
28
+ }
29
+ `,
30
+ ];
31
+ render() {
32
+ return html`
33
+ <blockquote>
34
+ <slot />
35
+ </blockquote>
36
+ `;
37
+ }
38
+ }
39
+
40
+ if (!customElements.get("cfa-pullquote")) {
41
+ customElements.define("cfa-pullquote", PullQuote);
42
+ }
@@ -0,0 +1,16 @@
1
+ import { html } from "lit-html";
2
+ import "./pullquote";
3
+
4
+ export default {
5
+ title: "Atoms/PullQuote",
6
+ argTypes: {},
7
+ };
8
+
9
+ const Template = ({ text }) => html`
10
+ <cfa-pullquote .innerHTML="${text}"></cfa-pullquote>
11
+ `;
12
+
13
+ export const Default = Template.bind({});
14
+ Default.args = {
15
+ text: "What truly ignites my interest in civic tech is the opportunity to <strong>leverage technology</strong> to close the gap between government and the people it serves.",
16
+ };
@@ -0,0 +1,84 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { commonStyles } from "../shared/common";
3
+
4
+ class Quote extends LitElement {
5
+ static properties = {
6
+ text: {},
7
+ attribution: {},
8
+ };
9
+ static styles = [
10
+ commonStyles,
11
+ css`
12
+ :host {
13
+ --attribution-color: var(--purple-60);
14
+ }
15
+
16
+ figure {
17
+ margin-inline: auto;
18
+ max-width: var(--column-span-8);
19
+ position: relative;
20
+ }
21
+
22
+ blockquote {
23
+ font-family: var(--font-family-serif);
24
+ font-size: var(--font-size-h3);
25
+ line-height: var(--line-height-h3);
26
+ padding: 0;
27
+ margin: 0;
28
+ position: relative;
29
+ }
30
+
31
+ blockquote::before {
32
+ color: var(--attribution-color);
33
+ content: "“";
34
+ display: block;
35
+ font-size: var(--font-size-display-1);
36
+ left: -0.5em;
37
+ line-height: 1;
38
+ position: absolute;
39
+ top: 0;
40
+ width: 0.25em;
41
+ }
42
+
43
+ ::slotted(*) {
44
+ display: inline;
45
+ }
46
+
47
+ figcaption {
48
+ color: var(--attribution-color);
49
+ font-size: var(--font-size-small);
50
+ line-height: var(--line-height-small);
51
+ font-weight: 600;
52
+ margin-block-start: var(--spacing-layout-half);
53
+ margin-inline: 0;
54
+ position: relative;
55
+ }
56
+
57
+ figcaption::before {
58
+ background-color: currentColor;
59
+ content: "";
60
+ display: inline-block;
61
+ vertical-align: middle;
62
+ height: var(--hairline);
63
+ width: var(--spacing-component-4);
64
+ margin-inline-end: var(--spacing-component-2);
65
+ }
66
+ `,
67
+ ];
68
+ render() {
69
+ return html`
70
+ <figure>
71
+ <blockquote>
72
+ <slot name="text"></slot>
73
+ </blockquote>
74
+ <figcaption>
75
+ <slot name="attribution"></slot>
76
+ </figcaption>
77
+ </figure>
78
+ `;
79
+ }
80
+ }
81
+
82
+ if (!customElements.get("cfa-quote")) {
83
+ customElements.define("cfa-quote", Quote);
84
+ }
@@ -0,0 +1,23 @@
1
+ import { html } from "lit-html";
2
+ import "./quote";
3
+
4
+ export default {
5
+ title: "Atoms/Quote",
6
+ argTypes: {
7
+ text: { type: "string" },
8
+ attribution: { type: "string" },
9
+ },
10
+ };
11
+
12
+ const Template = ({ text, attribution }) => html`
13
+ <cfa-quote>
14
+ <blockquote slot="text" .innerHTML="${text}"></blockquote>
15
+ <figcaption slot="attribution" .innerHTML="${attribution}"></figcaption>
16
+ </cfa-quote>
17
+ `;
18
+
19
+ export const Default = Template.bind({});
20
+ Default.args = {
21
+ text: "What truly ignites my interest in civic tech is the opportunity to <strong>leverage technology</strong> to close the gap between government and the people it serves.",
22
+ attribution: "Amanda Renteria, CEO of Code for America",
23
+ };
@@ -0,0 +1,83 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { commonStyles } from "../shared/common";
3
+ import "./icon";
4
+
5
+ class Reveal extends LitElement {
6
+ static properties = {
7
+ showLabel: { type: String },
8
+ hideLabel: { type: String },
9
+ showIcon: { type: String },
10
+ hideIcon: { type: String },
11
+ expanded: { type: Boolean, reflect: true },
12
+ };
13
+ static styles = [
14
+ commonStyles,
15
+ css`
16
+ :host {
17
+ --color: var(--purple-60);
18
+ --hover-color: var(--red-60);
19
+ --margin-top: var(--spacing-layout-half) !important;
20
+
21
+ display: flex;
22
+ flex-direction: column;
23
+ row-gap: var(--spacing-between, 1rem);
24
+ }
25
+
26
+ :host([expanded]) {
27
+ --margin-top: var(--spacing) !important;
28
+ }
29
+
30
+ button {
31
+ background: transparent;
32
+ border: none;
33
+ color: var(--color);
34
+ cursor: pointer;
35
+ font: inherit;
36
+ font-size: var(--font-size-small, 0.8rem);
37
+ font-weight: bold;
38
+ color: var(--)
39
+ line-height: normal;
40
+ margin: 0;
41
+ overflow: visible;
42
+ padding: 0;
43
+ width: auto;
44
+ }
45
+
46
+ button:hover {
47
+ color: var(--hover-color);
48
+ }
49
+ `,
50
+ ];
51
+ constructor() {
52
+ super();
53
+ this.showLabel = "Show more";
54
+ this.hideLabel = "Show less";
55
+ this.showIcon = "expand_more";
56
+ this.hideIcon = "expand_less";
57
+ this.expanded = false;
58
+ }
59
+ render() {
60
+ return html`
61
+ <slot
62
+ id="content"
63
+ class="content ${this.expanded ? "is-expanded" : "is-collapsed"}"
64
+ aria-labelledby="button"
65
+ ?hidden="${!this.expanded}"
66
+ ></slot>
67
+ <div class="controls">
68
+ <button
69
+ @click="${() => (this.expanded = !this.expanded)}"
70
+ aria-expanded="${this.expanded}"
71
+ aria-controls="content"
72
+ >
73
+ ${this.expanded ? this.hideLabel : this.showLabel}
74
+ <cfa-icon>${this.expanded ? this.hideIcon : this.showIcon}</cfa-icon>
75
+ </button>
76
+ </div>
77
+ `;
78
+ }
79
+ }
80
+
81
+ if (!customElements.get("cfa-reveal")) {
82
+ customElements.define("cfa-reveal", Reveal);
83
+ }
@@ -0,0 +1,40 @@
1
+ import { html } from "lit-html";
2
+ import "./reveal";
3
+
4
+ export default {
5
+ title: "Molecules/Reveal",
6
+ argTypes: {
7
+ content: { type: "string" },
8
+ showLabel: { type: "string" },
9
+ hideLabel: { type: "string" },
10
+ showIcon: { type: "string" },
11
+ hideIcon: { type: "string" },
12
+ },
13
+ };
14
+
15
+ const Template = ({
16
+ content,
17
+ showLabel,
18
+ hideLabel,
19
+ showIcon,
20
+ hideIcon,
21
+ }) => html`
22
+ <cfa-reveal
23
+ showLabel="${showLabel}"
24
+ hideLabel="${hideLabel}"
25
+ showIcon="${showIcon}"
26
+ hideIcon="${hideIcon}"
27
+ .innerHTML="${content}"
28
+ >
29
+ </cfa-reveal>
30
+ `;
31
+
32
+ export const Default = Template.bind({});
33
+ Default.args = {
34
+ content:
35
+ "<div>Government can work for the people, by the people, in the digital age. We believe government at all levels can and should work well for all people.</div><div>We use insights and ideas from real people to guide us to real solutions that break down barriers to meet community needs and improve government in meaningful ways.</div><div>Let’s make it work for everyone.</div>",
36
+ showLabel: "Show more",
37
+ hideLabel: "Show less",
38
+ showIcon: "expand_more",
39
+ hideIcon: "expand_less",
40
+ };
@@ -0,0 +1,121 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { commonStyles } from "../shared/common";
3
+
4
+ class Slide extends LitElement {
5
+ static properties = {
6
+ imageUrl: {},
7
+ imageAltText: {},
8
+ linkUrl: {},
9
+ linkTarget: {},
10
+ };
11
+ static styles = [
12
+ commonStyles,
13
+ css`
14
+ :host {
15
+ --background: var(--white, #fff);
16
+ --width: var(--column-span-12);
17
+ }
18
+
19
+ .slide {
20
+ background: var(--background);
21
+ box-shadow: var(--shadow-small);
22
+ color: inherit;
23
+ display: flex;
24
+ flex-direction: column;
25
+ height: 100%;
26
+ justify-content: stretch;
27
+ margin-inline: auto;
28
+ max-width: var(--width);
29
+ text-decoration: none;
30
+ transition: box-shadow 0.2s ease-in-out;
31
+ width: 100%;
32
+ }
33
+
34
+ .slide:hover,
35
+ .slide:focus {
36
+ box-shadow: var(--shadow-medium);
37
+ }
38
+
39
+ .image {
40
+ background-image: url("https://codeforamerica.org/wp-content/themes/cfa-core/static/images/bg-placeholder-03.svg");
41
+ background-position: center center;
42
+ background-size: cover;
43
+ height: var(--spacing-layout-9);
44
+ position: relative;
45
+ }
46
+
47
+ .image::after {
48
+ bottom: 0;
49
+ box-shadow: inset 0 -50px 50px -50px var(--black-40);
50
+ content: "";
51
+ left: 0;
52
+ position: absolute;
53
+ right: 0;
54
+ top: 0;
55
+ z-index: 2;
56
+ }
57
+
58
+ .image img {
59
+ height: 100%;
60
+ object-fit: cover;
61
+ width: 100%;
62
+ }
63
+
64
+ .content {
65
+ align-items: center;
66
+ box-sizing: border-box;
67
+ display: flex;
68
+ padding: var(--spacing-component-4);
69
+ }
70
+
71
+ @media (min-width: 1024px) {
72
+ .slide {
73
+ flex-direction: row;
74
+ min-height: calc(12 * var(--spacing-layout-1));
75
+ }
76
+
77
+ .slide > * {
78
+ flex-basis: 50%;
79
+ }
80
+
81
+ .image {
82
+ height: auto;
83
+ }
84
+
85
+ .image::after {
86
+ box-shadow: inset -50px -50px 50px -50px var(--black-20);
87
+ }
88
+ }
89
+ `,
90
+ ];
91
+ constructor() {
92
+ super();
93
+ this.linkUrl = "javascript:void(0);";
94
+ this.linkTarget = "_self";
95
+ }
96
+ render() {
97
+ return html`
98
+ <a href="${this.linkUrl}" target="${this.linkTarget}" class="slide">
99
+ <div class="image">
100
+ ${this.imageUrl
101
+ ? html`
102
+ <img
103
+ src="${this.imageUrl}"
104
+ alt="${this.imageAltText}"
105
+ loading="lazy"
106
+ onerror="this.style.display='none'"
107
+ />
108
+ `
109
+ : ""}
110
+ </div>
111
+ <div class="content">
112
+ <slot></slot>
113
+ </div>
114
+ </a>
115
+ `;
116
+ }
117
+ }
118
+
119
+ if (!customElements.get("cfa-slide")) {
120
+ customElements.define("cfa-slide", Slide);
121
+ }
@@ -0,0 +1,53 @@
1
+ import { html } from "lit-html";
2
+ import "./slide";
3
+
4
+ export default {
5
+ title: "Molecules/Slide",
6
+ argTypes: {
7
+ imageUrl: { type: "string" },
8
+ imageAltText: { type: "string" },
9
+ linkUrl: { type: "string" },
10
+ },
11
+ };
12
+
13
+ const Template = ({ imageUrl, imageAltText, linkUrl }) => html`
14
+ <cfa-slide
15
+ imageUrl="${imageUrl}"
16
+ imageAltText="${imageAltText}"
17
+ linkUrl="${linkUrl}"
18
+ >
19
+ <div class="stack">
20
+ <div>
21
+ <div class="eyebrow" style="color: var(--purple-60)">
22
+ Featured story
23
+ </div>
24
+ <div class="h2">
25
+ Making Automatic Record Clearance a People Centered, End-to-End
26
+ Service
27
+ </div>
28
+ </div>
29
+ <p class="small">
30
+ The state of automatic record clearance in the US shows hope for a
31
+ future where more people get the help they need to achieve a fresh start
32
+ </p>
33
+ <ul class="ul ul--inline-with-separators small strong">
34
+ <li>Alia Toran-Burrell</li>
35
+ <li>David Crawford</li>
36
+ </ul>
37
+ <div class="small subtle">March 9, 2023</div>
38
+ </div>
39
+ </cfa-slide>
40
+ `;
41
+
42
+ export const Default = Template.bind({});
43
+ Default.args = {
44
+ imageUrl:
45
+ "https://files.codeforamerica.org/2023/03/08131615/record-clearance-blog-1024x571.png",
46
+ imageAltText: "Illustration of man and child at table",
47
+ linkUrl: "#",
48
+ };
49
+
50
+ export const SlideWithoutImage = Template.bind({});
51
+ SlideWithoutImage.args = {
52
+ linkUrl: "#",
53
+ };