@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.
- package/package.json +2 -1
- package/src/components/accordion.js +141 -0
- package/src/components/accordion.stories.js +56 -0
- package/src/components/avatar.js +62 -0
- package/src/components/avatar.stories.js +27 -0
- package/src/components/banner.js +152 -0
- package/src/components/banner.stories.js +115 -0
- package/src/components/bar.js +102 -0
- package/src/components/bar.stories.js +22 -0
- package/src/components/blob.js +119 -0
- package/src/components/blob.stories.js +64 -0
- package/src/components/box.js +55 -0
- package/src/components/box.stories.js +24 -0
- package/src/components/breadcrumbs.js +80 -0
- package/src/components/breadcrumbs.stories.js +27 -0
- package/src/components/button.js +167 -0
- package/src/components/button.scss +162 -0
- package/src/components/button.stories.js +49 -0
- package/src/components/callout.js +62 -0
- package/src/components/callout.stories.js +20 -0
- package/src/components/card.js +403 -0
- package/src/components/card.stories.js +170 -0
- package/src/components/carousel.js +182 -0
- package/src/components/carousel.stories.js +61 -0
- package/src/components/cta.js +99 -0
- package/src/components/cta.stories.js +22 -0
- package/src/components/details.scss +71 -0
- package/src/components/details.stories.js +27 -0
- package/src/components/flexible-layout.js +126 -0
- package/src/components/flexible-layout.stories.js +48 -0
- package/src/components/form-elements.scss +305 -0
- package/src/components/form-elements.stories.js +134 -0
- package/src/components/icon.js +41 -0
- package/src/components/icon.scss +31 -0
- package/src/components/icon.stories.js +16 -0
- package/src/components/label.js +63 -0
- package/src/components/label.stories.js +29 -0
- package/src/components/link-list.scss +80 -0
- package/src/components/link-list.stories.js +52 -0
- package/src/components/loader.scss +24 -0
- package/src/components/loader.stories.js +12 -0
- package/src/components/logo-card.js +93 -0
- package/src/components/logo-card.stories.js +48 -0
- package/src/components/nav.js +99 -0
- package/src/components/nav.stories.js +40 -0
- package/src/components/page-nav.js +171 -0
- package/src/components/page-nav.stories.js +112 -0
- package/src/components/pager.js +98 -0
- package/src/components/pager.stories.js +30 -0
- package/src/components/pagination.js +116 -0
- package/src/components/pagination.stories.js +30 -0
- package/src/components/person-card.js +240 -0
- package/src/components/person-card.stories.js +58 -0
- package/src/components/pill.js +33 -0
- package/src/components/pill.stories.js +23 -0
- package/src/components/promo.js +83 -0
- package/src/components/promo.stories.js +37 -0
- package/src/components/pullquote.js +42 -0
- package/src/components/pullquote.stories.js +16 -0
- package/src/components/quote.js +84 -0
- package/src/components/quote.stories.js +23 -0
- package/src/components/reveal.js +83 -0
- package/src/components/reveal.stories.js +40 -0
- package/src/components/slide.js +121 -0
- package/src/components/slide.stories.js +53 -0
- package/src/components/social-icon.js +233 -0
- package/src/components/social-icon.stories.js +36 -0
- package/src/components/stat.js +92 -0
- package/src/components/stat.stories.js +28 -0
- package/src/components/tab-list.js +114 -0
- package/src/components/tab-list.stories.js +18 -0
- package/src/components/tab.js +95 -0
- package/src/components/tab.stories.js +29 -0
- package/src/components/tile.js +150 -0
- package/src/components/tile.stories.js +41 -0
- package/src/components/transcript.js +44 -0
- package/src/components/transcript.stories.js +167 -0
- package/src/core/_base.scss +86 -0
- package/src/core/_grid.scss +295 -0
- package/src/core/_helpers.scss +111 -0
- package/src/core/_layout.scss +79 -0
- package/src/core/_reset.scss +53 -0
- package/src/core/_tokens.scss +251 -0
- package/src/core/_typography.scss +426 -0
- package/src/core/_wordpress.scss +27 -0
- package/src/core/colors.mdx +100 -0
- package/src/core/typography.mdx +66 -0
- package/src/shared/common.js +15 -0
- package/src/shared/layout.js +14 -0
- package/src/shared/typography.js +111 -0
- package/src/styles.scss +16 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { html } from "lit-html";
|
|
2
|
+
import "./link-list.scss";
|
|
3
|
+
import "./icon";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: "Molecules/LinkList",
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const Template = () => html`
|
|
10
|
+
<div class="container-fluid wrapper">
|
|
11
|
+
<div class="row center-md">
|
|
12
|
+
<div class="col-xs-12 col-md-6">
|
|
13
|
+
<ul class="link-list">
|
|
14
|
+
<li>
|
|
15
|
+
<a href="#">Best Practices for Data Aggregation in Summer EBT</a>
|
|
16
|
+
</li>
|
|
17
|
+
<li>
|
|
18
|
+
<a href="#">Tips for Working with Vendors</a>
|
|
19
|
+
</li>
|
|
20
|
+
<li>
|
|
21
|
+
<a href="#">
|
|
22
|
+
Tips for Creating a Human-Centered Summer EBT Application
|
|
23
|
+
</a>
|
|
24
|
+
</li>
|
|
25
|
+
</ul>
|
|
26
|
+
<br />
|
|
27
|
+
<ul class="link-list">
|
|
28
|
+
<li>
|
|
29
|
+
<a href="#">
|
|
30
|
+
<cfa-icon>favorite</cfa-icon> Best Practices for Data Aggregation
|
|
31
|
+
in Summer EBT
|
|
32
|
+
</a>
|
|
33
|
+
</li>
|
|
34
|
+
<li>
|
|
35
|
+
<a href="#">Tips for Working with Vendors </a>
|
|
36
|
+
</li>
|
|
37
|
+
<li>
|
|
38
|
+
<a href="#">
|
|
39
|
+
<cfa-icon>download</cfa-icon> Playbook: Tips for Creating a
|
|
40
|
+
Human-Centered Summer EBT Application
|
|
41
|
+
</a>
|
|
42
|
+
</li>
|
|
43
|
+
</ul>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
export const Default = Template.bind({});
|
|
50
|
+
Default.args = {
|
|
51
|
+
theme: "default",
|
|
52
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.cfa-loader {
|
|
2
|
+
--size: var(--spacing-component-3);
|
|
3
|
+
|
|
4
|
+
animation: pulse 2s infinite;
|
|
5
|
+
border-radius: 50%;
|
|
6
|
+
display: block;
|
|
7
|
+
height: var(--size);
|
|
8
|
+
margin-left: auto;
|
|
9
|
+
margin-right: auto;
|
|
10
|
+
text-indent: -9999px;
|
|
11
|
+
width: var(--size);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@keyframes pulse {
|
|
15
|
+
0% {
|
|
16
|
+
background-color: rgba(0,0,0,0);
|
|
17
|
+
}
|
|
18
|
+
50% {
|
|
19
|
+
background-color: rgba(0,0,0,0.3);
|
|
20
|
+
}
|
|
21
|
+
100% {
|
|
22
|
+
background-color: rgba(0,0,0,0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { html } from "lit-html";
|
|
2
|
+
import "./loader.scss";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: "Atoms/Loader",
|
|
6
|
+
argTypes: {},
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const Template = () => html`<div class="cfa-loader">Loading</div>`;
|
|
10
|
+
|
|
11
|
+
export const Default = Template.bind({});
|
|
12
|
+
Default.args = {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { LitElement, html, css, nothing } from "lit";
|
|
2
|
+
import { commonStyles } from "../shared/common";
|
|
3
|
+
import { typographyStyles } from "../shared/typography";
|
|
4
|
+
|
|
5
|
+
class LogoCard extends LitElement {
|
|
6
|
+
static properties = {
|
|
7
|
+
name: {},
|
|
8
|
+
imageUrl: {},
|
|
9
|
+
linkUrl: {},
|
|
10
|
+
linkTarget: {},
|
|
11
|
+
};
|
|
12
|
+
static styles = [
|
|
13
|
+
commonStyles,
|
|
14
|
+
typographyStyles,
|
|
15
|
+
css`
|
|
16
|
+
:host {
|
|
17
|
+
--bg-color: var(--blue-20);
|
|
18
|
+
--text-color: var(--black);
|
|
19
|
+
|
|
20
|
+
align-items: stretch;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: row;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.card {
|
|
26
|
+
align-items: center;
|
|
27
|
+
background-color: var(--white);
|
|
28
|
+
border: var(--hairline) solid var(--black-10);
|
|
29
|
+
color: var(--text-color);
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
font-size: var(--font-size-h3);
|
|
33
|
+
font-weight: bold;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
line-height: var(--line-height-h4);
|
|
36
|
+
margin-inline: auto;
|
|
37
|
+
max-width: 100%;
|
|
38
|
+
min-height: var(--spacing-layout-8);
|
|
39
|
+
padding: var(--spacing-component-5);
|
|
40
|
+
text-align: center;
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
transition: box-shadow 1s;
|
|
43
|
+
width: var(--column-span-4);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
a.card {
|
|
47
|
+
box-shadow: var(--shadow-small);
|
|
48
|
+
color: var(--text-color);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
a.card:hover {
|
|
52
|
+
box-shadow: var(--shadow-medium);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
img {
|
|
56
|
+
aspect-ratio: 2 / 1;
|
|
57
|
+
object-fit: contain;
|
|
58
|
+
width: 100%;
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
];
|
|
62
|
+
cardContentTemplate() {
|
|
63
|
+
let template;
|
|
64
|
+
if (this.imageUrl) {
|
|
65
|
+
template = html` <img src="${this.imageUrl}" alt="${this.name}" /> `;
|
|
66
|
+
} else {
|
|
67
|
+
template = html` ${this.name} `;
|
|
68
|
+
}
|
|
69
|
+
return template;
|
|
70
|
+
}
|
|
71
|
+
render() {
|
|
72
|
+
return html`
|
|
73
|
+
${this.linkUrl
|
|
74
|
+
? html`
|
|
75
|
+
<a
|
|
76
|
+
href="${this.linkUrl}"
|
|
77
|
+
target="${this.linkTarget || "_self"}"
|
|
78
|
+
rel="${this.linkTarget == "_blank"
|
|
79
|
+
? "noopener noreferrer"
|
|
80
|
+
: nothing}"
|
|
81
|
+
class="card"
|
|
82
|
+
>
|
|
83
|
+
${this.cardContentTemplate()}
|
|
84
|
+
</a>
|
|
85
|
+
`
|
|
86
|
+
: html` <div class="card">${this.cardContentTemplate()}</div> `}
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!customElements.get("cfa-logo-card")) {
|
|
92
|
+
customElements.define("cfa-logo-card", LogoCard);
|
|
93
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { html } from "lit-html";
|
|
2
|
+
import "./logo-card";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: "Molecules/LogoCard",
|
|
6
|
+
argTypes: {
|
|
7
|
+
name: { type: "string" },
|
|
8
|
+
imageUrl: { type: "string" },
|
|
9
|
+
linkUrl: { type: "string" },
|
|
10
|
+
linkTarget: { type: "string" },
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const Template = ({ name, imageUrl, linkUrl, linkTarget }) => html`
|
|
15
|
+
<cfa-logo-card
|
|
16
|
+
name="${name}"
|
|
17
|
+
imageUrl="${imageUrl}"
|
|
18
|
+
linkUrl="${linkUrl}"
|
|
19
|
+
linkTarget="${linkTarget}"
|
|
20
|
+
></cfa-logo-card>
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
export const Default = Template.bind({});
|
|
24
|
+
Default.args = {
|
|
25
|
+
name: "Code for America",
|
|
26
|
+
imageUrl:
|
|
27
|
+
"https://files.codeforamerica.org/2021/05/28124702/code-for-america-logo-black.svg",
|
|
28
|
+
linkUrl: "https://codeforamerica.org",
|
|
29
|
+
linkTarget: "_blank",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const LogoCardWithoutLink = Template.bind({});
|
|
33
|
+
LogoCardWithoutLink.args = {
|
|
34
|
+
name: "Code for America",
|
|
35
|
+
imageUrl:
|
|
36
|
+
"https://files.codeforamerica.org/2021/05/28124702/code-for-america-logo-black.svg",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const LogoCardWithoutImage = Template.bind({});
|
|
40
|
+
LogoCardWithoutImage.args = {
|
|
41
|
+
name: "Code for America",
|
|
42
|
+
linkUrl: "https://codeforamerica.org",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const LogoCardWithTextOnly = Template.bind({});
|
|
46
|
+
LogoCardWithTextOnly.args = {
|
|
47
|
+
name: "Code for America",
|
|
48
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import { commonStyles } from "../shared/common";
|
|
3
|
+
|
|
4
|
+
class Nav extends LitElement {
|
|
5
|
+
static properties = {
|
|
6
|
+
fontSize: {},
|
|
7
|
+
};
|
|
8
|
+
static styles = [
|
|
9
|
+
commonStyles,
|
|
10
|
+
css`
|
|
11
|
+
:host {
|
|
12
|
+
--link-color: var(--purple-80);
|
|
13
|
+
--link-hover-color: var(--purple-80);
|
|
14
|
+
|
|
15
|
+
display: block;
|
|
16
|
+
font-family: var(--font-family-sans-serif);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
slot {
|
|
20
|
+
display: none;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
nav {
|
|
24
|
+
font-size: var(--font-size-base);
|
|
25
|
+
line-height: var(--line-height-base);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
nav[data-font-size="small"] {
|
|
29
|
+
font-size: var(--font-size-small);
|
|
30
|
+
line-height: var(--line-height-small);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
nav[data-font-size="large"] {
|
|
34
|
+
font-size: var(--font-size-h3);
|
|
35
|
+
line-height: var(--line-height-h3);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
ul {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: row;
|
|
41
|
+
gap: var(--spacing-component-1);
|
|
42
|
+
list-style: none;
|
|
43
|
+
margin: 0;
|
|
44
|
+
padding: 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
li {
|
|
48
|
+
flex-shrink: 0;
|
|
49
|
+
margin: 0;
|
|
50
|
+
padding: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
li.is-active a {
|
|
54
|
+
box-shadow: inset 0 calc(-1 * var(--medium)) var(--link-hover-color);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
a {
|
|
58
|
+
box-shadow: 0;
|
|
59
|
+
color: var(--link-color);
|
|
60
|
+
display: block;
|
|
61
|
+
font-weight: bold;
|
|
62
|
+
height: 100%;
|
|
63
|
+
padding: var(--spacing-component-2) var(--spacing-component-3);
|
|
64
|
+
text-decoration: none;
|
|
65
|
+
transition: box-shadow 0.25s ease-in-out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
a:hover {
|
|
69
|
+
box-shadow: inset 0 calc(-1 * var(--medium)) var(--link-hover-color);
|
|
70
|
+
}
|
|
71
|
+
`,
|
|
72
|
+
];
|
|
73
|
+
handleSlotchange(event) {
|
|
74
|
+
const slot = event.target;
|
|
75
|
+
const assignedNodes = slot.assignedNodes({ flatten: true });
|
|
76
|
+
const breadcrumbContainer = this.shadowRoot.querySelector("ul");
|
|
77
|
+
breadcrumbContainer.innerHTML = ""; // Clear the existing content
|
|
78
|
+
assignedNodes.forEach((node) => {
|
|
79
|
+
if (node.tagName === "UL") {
|
|
80
|
+
const liElements = node.querySelectorAll("li");
|
|
81
|
+
liElements.forEach((li) => {
|
|
82
|
+
breadcrumbContainer.appendChild(li.cloneNode(true));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
render() {
|
|
88
|
+
return html`
|
|
89
|
+
<slot @slotchange=${this.handleSlotchange}></slot>
|
|
90
|
+
<nav data-font-size="${this.fontSize}">
|
|
91
|
+
<ul></ul>
|
|
92
|
+
</nav>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!customElements.get("cfa-nav")) {
|
|
98
|
+
customElements.define("cfa-nav", Nav);
|
|
99
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// TODO: Turn into web component, consider renaming (maybe 'navbar' or 'menu-bar'?)
|
|
2
|
+
|
|
3
|
+
import { html } from "lit-html";
|
|
4
|
+
import "./nav.js";
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: "Molecules/Nav",
|
|
8
|
+
argTypes: {
|
|
9
|
+
fontSize: {
|
|
10
|
+
type: String,
|
|
11
|
+
control: "inline-radio",
|
|
12
|
+
options: ["small", "base", "large"],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const Template = ({ fontSize }) => html`
|
|
18
|
+
<cfa-nav fontSize="${fontSize}">
|
|
19
|
+
<ul>
|
|
20
|
+
<li>
|
|
21
|
+
<a href="#"> Actions </a>
|
|
22
|
+
</li>
|
|
23
|
+
<li>
|
|
24
|
+
<a href="#"> Schedule </a>
|
|
25
|
+
</li>
|
|
26
|
+
<li>
|
|
27
|
+
<a href="#"> How to participate </a>
|
|
28
|
+
</li>
|
|
29
|
+
<li>
|
|
30
|
+
<a href="#"> FAQs </a>
|
|
31
|
+
</li>
|
|
32
|
+
</ul>
|
|
33
|
+
</cfa-nav>
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
export const Default = Template.bind({});
|
|
37
|
+
Default.args = {
|
|
38
|
+
// font size
|
|
39
|
+
fontSize: "base",
|
|
40
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import { commonStyles } from "../shared/common";
|
|
3
|
+
|
|
4
|
+
class PageNav extends LitElement {
|
|
5
|
+
static properties = {
|
|
6
|
+
fontSize: {},
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
static styles = [
|
|
10
|
+
commonStyles,
|
|
11
|
+
css`
|
|
12
|
+
:host {
|
|
13
|
+
--bg-color: var(--white);
|
|
14
|
+
--link-color: var(--purple-80);
|
|
15
|
+
--link-hover-color: var(--purple-80);
|
|
16
|
+
|
|
17
|
+
background-color: var(--bg-color);
|
|
18
|
+
display: block;
|
|
19
|
+
padding-block: var(--spacing-layout-1);
|
|
20
|
+
display: block;
|
|
21
|
+
font-family: var(--font-family-sans-serif);
|
|
22
|
+
font-size: var(--font-size-small);
|
|
23
|
+
line-height: var(--font-size-small);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
slot {
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
nav {
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ul {
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
gap: var(--spacing-layout-half);
|
|
37
|
+
margin: 0;
|
|
38
|
+
padding: 0 var(--outer-margin);
|
|
39
|
+
min-height: var(--spacing-layout-2);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
li {
|
|
43
|
+
display: block;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
a {
|
|
47
|
+
background-color: var(--purple-10);
|
|
48
|
+
border-radius: var(--rounded-corners);
|
|
49
|
+
color: var(--link-color);
|
|
50
|
+
display: block;
|
|
51
|
+
position: relative;
|
|
52
|
+
padding: var(--spacing-layout-half);
|
|
53
|
+
text-decoration: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
a:hover {
|
|
57
|
+
background-color: var(--blue-20);
|
|
58
|
+
color: var(--link-hover-color);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
a:active {
|
|
62
|
+
background-color: var(--blue-40);
|
|
63
|
+
color: var(--link-color);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@media (min-width: 768px) {
|
|
67
|
+
:host {
|
|
68
|
+
box-shadow: var(--shadow-small);
|
|
69
|
+
padding-block: var(--spacing-component-2);
|
|
70
|
+
position: sticky;
|
|
71
|
+
top: 0;
|
|
72
|
+
z-index: 3;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
nav {
|
|
76
|
+
align-items: center;
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: row;
|
|
79
|
+
margin-inline: auto;
|
|
80
|
+
max-width: var(--grid-max-width);
|
|
81
|
+
overflow-x: auto;
|
|
82
|
+
overflow-y: hidden;
|
|
83
|
+
scrollbar-width: none;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ul {
|
|
87
|
+
align-items: center;
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: row;
|
|
90
|
+
gap: var(--spacing-component-2);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
a,
|
|
94
|
+
li {
|
|
95
|
+
max-width: none;
|
|
96
|
+
white-space: nowrap;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
a.is-active {
|
|
100
|
+
background-color: var(--blue-40);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
`,
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
handleSlotchange(event) {
|
|
107
|
+
const slot = event.target;
|
|
108
|
+
const assignedNodes = slot.assignedNodes({ flatten: true });
|
|
109
|
+
const breadcrumbContainer = this.shadowRoot.querySelector("ul");
|
|
110
|
+
|
|
111
|
+
// Create an array to hold the IDs of all the anchor links in the nav
|
|
112
|
+
const navItemIds = [];
|
|
113
|
+
|
|
114
|
+
assignedNodes.forEach((node) => {
|
|
115
|
+
if (node.tagName === "UL") {
|
|
116
|
+
const liElements = node.querySelectorAll("li");
|
|
117
|
+
liElements.forEach((li) => {
|
|
118
|
+
breadcrumbContainer.appendChild(li.cloneNode(true));
|
|
119
|
+
// If it's an anchor link (starting with '#') add the anchor ID to the navItemIds array
|
|
120
|
+
const linkUrl = li.querySelector("a")?.getAttribute("href");
|
|
121
|
+
if (linkUrl && linkUrl.startsWith("#")) {
|
|
122
|
+
navItemIds.push(linkUrl.substring(1));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Add a scroll event listener to highlight the active nav
|
|
129
|
+
window.addEventListener("scroll", () => this.updateActiveNav(navItemIds));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
updateActiveNav(navItemIds) {
|
|
133
|
+
const scrollPosition = window.scrollY;
|
|
134
|
+
let activeSectionId = null;
|
|
135
|
+
|
|
136
|
+
navItemIds.forEach((id) => {
|
|
137
|
+
const section = document.getElementById(id);
|
|
138
|
+
if (section && section.offsetTop <= scrollPosition + 256) {
|
|
139
|
+
activeSectionId = id;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
this.shadowRoot.querySelectorAll("li a").forEach((item) => {
|
|
144
|
+
item.classList.remove("is-active");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (activeSectionId) {
|
|
148
|
+
const activeNavItem = this.shadowRoot.querySelector(
|
|
149
|
+
`li a[href*="#${activeSectionId}"]`,
|
|
150
|
+
);
|
|
151
|
+
if (activeNavItem) {
|
|
152
|
+
activeNavItem.classList.add("is-active");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
render() {
|
|
158
|
+
return html`
|
|
159
|
+
<slot @slotchange=${this.handleSlotchange}></slot>
|
|
160
|
+
<nav>
|
|
161
|
+
<ul>
|
|
162
|
+
<li><strong>On this page:  </strong></li>
|
|
163
|
+
</ul>
|
|
164
|
+
</nav>
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!customElements.get("cfa-page-nav")) {
|
|
170
|
+
customElements.define("cfa-page-nav", PageNav);
|
|
171
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { html } from "lit-html";
|
|
2
|
+
import "./page-nav.js";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: "Molecules/PageNav",
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: "fullscreen",
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const Template = () => html`
|
|
12
|
+
<cfa-page-nav>
|
|
13
|
+
<ul>
|
|
14
|
+
<li>
|
|
15
|
+
<a href="#actions" target="_self"> Actions </a>
|
|
16
|
+
</li>
|
|
17
|
+
<li>
|
|
18
|
+
<a href="#participate" target="_self"> How to participate </a>
|
|
19
|
+
</li>
|
|
20
|
+
<li>
|
|
21
|
+
<a href="#faq" target="_self"> FAQs </a>
|
|
22
|
+
</li>
|
|
23
|
+
</ul>
|
|
24
|
+
</cfa-page-nav>
|
|
25
|
+
|
|
26
|
+
<section id="actions" class="section">
|
|
27
|
+
<div class="container-fluid wrapper">
|
|
28
|
+
<h2>Take action</h2>
|
|
29
|
+
<p>
|
|
30
|
+
We’re organizing a few types of actions and activities that volunteers
|
|
31
|
+
can participate in.
|
|
32
|
+
</p>
|
|
33
|
+
<p>
|
|
34
|
+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet
|
|
35
|
+
deserunt hic, perspiciatis eligendi doloremque vero ipsa, voluptatum
|
|
36
|
+
nihil aut dolorem praesentium dolor temporibus nemo? Neque et voluptate
|
|
37
|
+
asperiores dignissimos maiores. Lorem ipsum dolor, sit amet consectetur
|
|
38
|
+
adipisicing elit. Quidem, dicta adipisci aut ad delectus, iure sint
|
|
39
|
+
exercitationem tenetur illum voluptates officia at incidunt numquam
|
|
40
|
+
corporis, non pariatur quod magnam quasi. Lorem, ipsum dolor sit amet
|
|
41
|
+
consectetur adipisicing elit. Eveniet vitae, aliquam accusantium maiores
|
|
42
|
+
animi nobis tenetur, et pariatur amet provident libero exercitationem
|
|
43
|
+
commodi tempore est ex. Excepturi modi ea ipsam.
|
|
44
|
+
</p>
|
|
45
|
+
<p>
|
|
46
|
+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloribus, eum
|
|
47
|
+
at ipsa cumque, fugiat suscipit veritatis vero ab minus quaerat ipsam
|
|
48
|
+
enim mollitia dolor! Aperiam, optio ipsum. Est, explicabo quod?
|
|
49
|
+
</p>
|
|
50
|
+
</div>
|
|
51
|
+
</section>
|
|
52
|
+
<section id="participate" class="section">
|
|
53
|
+
<div class="container-fluid wrapper">
|
|
54
|
+
<h2>Participate</h2>
|
|
55
|
+
<p>
|
|
56
|
+
In the spirit of collective action (and to reduce weekend Zoom fatigue!)
|
|
57
|
+
we will be hosting this year’s National Day of Civic Hacking on Gather,
|
|
58
|
+
where participants will have the opportunity to virtually mingle and
|
|
59
|
+
make connections. Prepare yourself for the day by reading our Gather
|
|
60
|
+
Guidelines document or view the Gather Guidelines video. For more
|
|
61
|
+
information about the platform, please see our FAQs.
|
|
62
|
+
</p>
|
|
63
|
+
<p>
|
|
64
|
+
On the day of the event, we will provide step-by-step guidance for
|
|
65
|
+
participating in your chosen action(s). You will need a laptop,
|
|
66
|
+
Wi-Fi/internet access, and should be prepared to use Gather, Zoom,
|
|
67
|
+
Slack, and Google Docs/Google Sheets; we suggest downloading these
|
|
68
|
+
applications and becoming familiar with them ahead of time.
|
|
69
|
+
</p>
|
|
70
|
+
<p>
|
|
71
|
+
Interested in organizing an event with your local Brigade or a team of
|
|
72
|
+
people locally for National Day of Civic Hacking? View this year’s
|
|
73
|
+
toolkit to learn how you can start preparing for your event.
|
|
74
|
+
</p>
|
|
75
|
+
</div>
|
|
76
|
+
</section>
|
|
77
|
+
<section id="faq" class="section">
|
|
78
|
+
<div class="container-fluid wrapper">
|
|
79
|
+
<h2>Frequently Asked Questions</h2>
|
|
80
|
+
<h3>Why do we take collective action?</h3>
|
|
81
|
+
<p>
|
|
82
|
+
Over the years, common themes have emerged from our Brigade Network on
|
|
83
|
+
challenges they face locally and opportunities for addressing those
|
|
84
|
+
challenges. Brigade leaders identified various pain points in addressing
|
|
85
|
+
these challenges. One Brigade leader commented, “We’re not as powerful
|
|
86
|
+
as our numbers should make us. We have talented people; we need to give
|
|
87
|
+
them ways to channel that but we don’t know how to do it.”
|
|
88
|
+
</p>
|
|
89
|
+
<p>
|
|
90
|
+
The National Advisory Council (NAC), an elected group of 10 Brigade
|
|
91
|
+
members, the Network team, and Brigade leaders from across the country
|
|
92
|
+
came together—in person and online—to strategize around these challenges
|
|
93
|
+
and opportunities to support our diverse and growing network across the
|
|
94
|
+
county. National Day of Civic Hacking emerged as a clear opportunity to
|
|
95
|
+
come together as a network, focus our efforts, provide dedicated
|
|
96
|
+
resources to volunteers, amplify actions across the country, and
|
|
97
|
+
leverage the collective power of all of Code for America’s resources.
|
|
98
|
+
</p>
|
|
99
|
+
<h3>Who can participate in National Day of Civic Hacking?</h3>
|
|
100
|
+
<p>
|
|
101
|
+
Anyone who wants to volunteer is welcome to participate. While “hacking”
|
|
102
|
+
is in the name, you don’t need to know how to code to contribute. We
|
|
103
|
+
welcome people with all kinds of backgrounds—like marketing, community
|
|
104
|
+
organizing, logistics, engineering, and project management skills, just
|
|
105
|
+
to name a few!
|
|
106
|
+
</p>
|
|
107
|
+
</div>
|
|
108
|
+
</section>
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
export const Default = Template.bind({});
|
|
112
|
+
Default.args = {};
|