@brad-frost-web/eddie-recipes 0.19.0 → 0.19.2
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 -2
- package/recipes/bradfrost-com/timeline/timeline.scss +24 -0
- package/recipes/bradfrost-com/timeline/timeline.ts +35 -0
- package/recipes/bradfrost-com/timeline-node/timeline-node.scss +92 -0
- package/recipes/bradfrost-com/timeline-node/timeline-node.ts +84 -0
- package/recipes/we-are-here/chunky-checkbox/chunky-checkbox.scss +68 -0
- package/recipes/we-are-here/chunky-checkbox/chunky-checkbox.stories.ts +55 -0
- package/recipes/we-are-here/chunky-checkbox/chunky-checkbox.ts +88 -0
- package/recipes/we-are-here/chunky-checkbox/test/chunky-checkbox.test.ts +5 -0
- package/recipes/we-are-here/wah-link-list/test/wah-link-list.test.ts +5 -0
- package/recipes/we-are-here/wah-link-list/wah-link-list.scss +56 -0
- package/recipes/we-are-here/wah-link-list/wah-link-list.stories.ts +50 -0
- package/recipes/we-are-here/wah-link-list/wah-link-list.ts +89 -0
- package/recipes/we-are-here/wah-logo/test/wah-logo.test.ts +5 -0
- package/recipes/we-are-here/wah-logo/wah-logo.scss +36 -0
- package/recipes/we-are-here/wah-logo/wah-logo.stories.ts +14 -0
- package/recipes/we-are-here/wah-logo/wah-logo.ts +62 -0
- package/recipes/we-are-here/wah-site-footer/test/wah-site-footer.test.ts +5 -0
- package/recipes/we-are-here/wah-site-footer/wah-site-footer.scss +33 -0
- package/recipes/we-are-here/wah-site-footer/wah-site-footer.stories.ts +10 -0
- package/recipes/we-are-here/wah-site-footer/wah-site-footer.ts +68 -0
- package/recipes/we-are-here/wah-site-header/test/wah-site-header.test.ts +5 -0
- package/recipes/we-are-here/wah-site-header/wah-site-header.scss +137 -0
- package/recipes/we-are-here/wah-site-header/wah-site-header.stories.ts +13 -0
- package/recipes/we-are-here/wah-site-header/wah-site-header.ts +132 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brad-frost-web/eddie-recipes",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@brad-frost-web/eddie-web-components": "^0.19.0",
|
|
22
|
-
"@brad-frost-web/eddie-design-tokens": "^0.
|
|
22
|
+
"@brad-frost-web/eddie-design-tokens": "^0.19.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"del-cli": "^7.0.0",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#TIMELINE
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Timeline
|
|
8
|
+
* 1) A vertical timeline that displays a series of nodes along a vertical line
|
|
9
|
+
* 2) The line runs down the left side with nodes branching to the right
|
|
10
|
+
*/
|
|
11
|
+
.ed-r-c-timeline {
|
|
12
|
+
position: relative;
|
|
13
|
+
padding-inline-start: size(6);
|
|
14
|
+
|
|
15
|
+
&::before {
|
|
16
|
+
content: '';
|
|
17
|
+
position: absolute;
|
|
18
|
+
top: 0;
|
|
19
|
+
bottom: 0;
|
|
20
|
+
left: size(2);
|
|
21
|
+
width: 2px;
|
|
22
|
+
background: var(--ed-theme-color-border-default);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import { html, unsafeCSS } from 'lit';
|
|
3
|
+
import styles from './timeline.scss?inline';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A vertical timeline component that displays a series of timeline nodes
|
|
7
|
+
* along a vertical line. Used as a wrapper around `ed-r-timeline-node` elements.
|
|
8
|
+
*
|
|
9
|
+
* @slot - Timeline node elements (`ed-r-timeline-node`)
|
|
10
|
+
*/
|
|
11
|
+
export class EdRTimeline extends EdElement {
|
|
12
|
+
static get styles() {
|
|
13
|
+
return unsafeCSS(styles);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
const componentClassName = this.componentClassNames('ed-r-c-timeline', {});
|
|
18
|
+
|
|
19
|
+
return html`
|
|
20
|
+
<div class="${componentClassName}">
|
|
21
|
+
<slot></slot>
|
|
22
|
+
</div>
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (customElements.get('ed-r-timeline') === undefined) {
|
|
28
|
+
customElements.define('ed-r-timeline', EdRTimeline);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare global {
|
|
32
|
+
interface HTMLElementTagNameMap {
|
|
33
|
+
'ed-r-timeline': EdRTimeline;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#TIMELINE-NODE
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Timeline node
|
|
8
|
+
* 1) A single entry on the vertical timeline
|
|
9
|
+
* 2) Positioned relative so the marker can align with the timeline line
|
|
10
|
+
*/
|
|
11
|
+
.ed-r-c-timeline-node {
|
|
12
|
+
position: relative;
|
|
13
|
+
padding-block-end: size(4);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Timeline node marker
|
|
18
|
+
* 1) The circular dot that sits on the timeline line
|
|
19
|
+
* 2) Absolutely positioned to align with the vertical line from the parent timeline
|
|
20
|
+
*/
|
|
21
|
+
.ed-r-c-timeline-node__marker {
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: size(0.5);
|
|
24
|
+
left: calc(size(-4) - 5px);
|
|
25
|
+
width: 12px;
|
|
26
|
+
height: 12px;
|
|
27
|
+
border-radius: 50%;
|
|
28
|
+
background: var(--ed-theme-color-background-brand);
|
|
29
|
+
border: 2px solid var(--ed-theme-color-background-default);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Timeline node marker highlight variant
|
|
34
|
+
* 1) Larger marker for important timeline events
|
|
35
|
+
*/
|
|
36
|
+
.ed-r-c-timeline-node--highlight .ed-r-c-timeline-node__marker {
|
|
37
|
+
width: 16px;
|
|
38
|
+
height: 16px;
|
|
39
|
+
left: calc(size(-4) - 7px);
|
|
40
|
+
box-shadow: 0 0 0 3px var(--ed-theme-color-background-brand);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Timeline node body
|
|
45
|
+
* 1) The content area to the right of the marker
|
|
46
|
+
*/
|
|
47
|
+
.ed-r-c-timeline-node__body {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
gap: size(0.5);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Timeline node date
|
|
55
|
+
* 1) The date label styled with meta typography
|
|
56
|
+
*/
|
|
57
|
+
.ed-r-c-timeline-node__date {
|
|
58
|
+
@include ed-theme-typography-meta-default();
|
|
59
|
+
color: var(--ed-theme-color-content-subtle);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Timeline node heading
|
|
64
|
+
*/
|
|
65
|
+
.ed-r-c-timeline-node__heading {
|
|
66
|
+
display: block;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Timeline node link
|
|
71
|
+
* 1) Inherits heading color, underlines on hover
|
|
72
|
+
*/
|
|
73
|
+
.ed-r-c-timeline-node__link {
|
|
74
|
+
color: inherit;
|
|
75
|
+
text-decoration: none;
|
|
76
|
+
|
|
77
|
+
&:hover,
|
|
78
|
+
&:focus {
|
|
79
|
+
text-decoration: underline;
|
|
80
|
+
color: var(--ed-theme-link-color-content-hover);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Timeline node content
|
|
86
|
+
* 1) Slotted content area below the heading
|
|
87
|
+
*/
|
|
88
|
+
.ed-r-c-timeline-node__content {
|
|
89
|
+
&:empty {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import '@brad-frost-web/eddie-web-components/components/heading/heading';
|
|
3
|
+
import { html, nothing, unsafeCSS } from 'lit';
|
|
4
|
+
import { property } from 'lit/decorators.js';
|
|
5
|
+
import styles from './timeline-node.scss?inline';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A single node on a vertical timeline. Displays a dot marker on the timeline
|
|
9
|
+
* line with a heading, optional date, and slotted content to the right.
|
|
10
|
+
*
|
|
11
|
+
* @slot - Additional content for this timeline entry
|
|
12
|
+
*/
|
|
13
|
+
export class EdRTimelineNode extends EdElement {
|
|
14
|
+
static get styles() {
|
|
15
|
+
return unsafeCSS(styles);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The heading text for this timeline node
|
|
20
|
+
*/
|
|
21
|
+
@property()
|
|
22
|
+
text = '';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Optional date or time label displayed above/beside the heading
|
|
26
|
+
*/
|
|
27
|
+
@property()
|
|
28
|
+
date?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* URL the heading links to
|
|
32
|
+
*/
|
|
33
|
+
@property()
|
|
34
|
+
href?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Heading tag name for semantic heading level
|
|
38
|
+
*/
|
|
39
|
+
@property()
|
|
40
|
+
headingTagName: 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h3';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Visual variant of the node marker
|
|
44
|
+
*/
|
|
45
|
+
@property()
|
|
46
|
+
variant?: 'default' | 'highlight';
|
|
47
|
+
|
|
48
|
+
render() {
|
|
49
|
+
const componentClassName = this.componentClassNames('ed-r-c-timeline-node', {
|
|
50
|
+
'ed-r-c-timeline-node--highlight': this.variant === 'highlight'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return html`
|
|
54
|
+
<div class="${componentClassName}">
|
|
55
|
+
<div class="ed-r-c-timeline-node__marker"></div>
|
|
56
|
+
<div class="ed-r-c-timeline-node__body">
|
|
57
|
+
${this.date
|
|
58
|
+
? html`<span class="ed-r-c-timeline-node__date">${this.date}</span>`
|
|
59
|
+
: nothing}
|
|
60
|
+
${this.text
|
|
61
|
+
? html`<ed-heading class="ed-r-c-timeline-node__heading" tagName="${this.headingTagName}" variant="headline-sm">
|
|
62
|
+
${this.href
|
|
63
|
+
? html`<a class="ed-r-c-timeline-node__link" href="${this.href}">${this.text}</a>`
|
|
64
|
+
: this.text}
|
|
65
|
+
</ed-heading>`
|
|
66
|
+
: nothing}
|
|
67
|
+
<div class="ed-r-c-timeline-node__content">
|
|
68
|
+
<slot></slot>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (customElements.get('ed-r-timeline-node') === undefined) {
|
|
77
|
+
customElements.define('ed-r-timeline-node', EdRTimelineNode);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
declare global {
|
|
81
|
+
interface HTMLElementTagNameMap {
|
|
82
|
+
'ed-r-timeline-node': EdRTimelineNode;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#CHUNKY-CHECKBOX
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Chunky checkbox card
|
|
12
|
+
* 1) Cursor pointer to indicate interactivity
|
|
13
|
+
* 2) Transition border color for checked state feedback
|
|
14
|
+
*/
|
|
15
|
+
.ed-r-c-chunky-checkbox {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: flex-start;
|
|
18
|
+
gap: size(2);
|
|
19
|
+
padding: size(2.5);
|
|
20
|
+
border: var(--ed-border-width-md) solid var(--ed-theme-color-border-subtle);
|
|
21
|
+
border-radius: var(--ed-border-radius-md);
|
|
22
|
+
cursor: pointer; /* 1 */
|
|
23
|
+
transition: border-color 0.15s ease, background-color 0.15s ease; /* 2 */
|
|
24
|
+
background-color: var(--ed-theme-color-background-default);
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
border-color: var(--ed-theme-color-border-default);
|
|
28
|
+
background-color: var(--ed-theme-color-background-subtle);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Checked state
|
|
34
|
+
*/
|
|
35
|
+
.ed-r-c-chunky-checkbox--checked {
|
|
36
|
+
border-color: var(--ed-theme-color-border-brand);
|
|
37
|
+
background-color: var(--ed-theme-color-background-subtle);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Native checkbox input
|
|
42
|
+
* 1) Visually present but styled minimally; browser default checkbox appearance
|
|
43
|
+
* 2) Flex-shrink to prevent squishing
|
|
44
|
+
*/
|
|
45
|
+
.ed-r-c-chunky-checkbox__input {
|
|
46
|
+
flex-shrink: 0; /* 2 */
|
|
47
|
+
margin-block-start: size(0.5);
|
|
48
|
+
width: size(2.5);
|
|
49
|
+
height: size(2.5);
|
|
50
|
+
accent-color: var(--ed-theme-color-content-brand);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ed-r-c-chunky-checkbox__body {
|
|
54
|
+
flex: 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ed-r-c-chunky-checkbox__heading {
|
|
58
|
+
margin: 0;
|
|
59
|
+
font-size: var(--ed-font-size-lg);
|
|
60
|
+
font-weight: var(--ed-font-weight-bold);
|
|
61
|
+
color: var(--ed-theme-color-content-default);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.ed-r-c-chunky-checkbox__description {
|
|
65
|
+
margin-block-start: size(0.5);
|
|
66
|
+
font-size: var(--ed-font-size-sm);
|
|
67
|
+
color: var(--ed-theme-color-content-subtle);
|
|
68
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './chunky-checkbox';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Recipes/we are here./Chunky Checkbox',
|
|
6
|
+
component: 'ed-r-chunky-checkbox',
|
|
7
|
+
parameters: { status: { type: 'beta' } },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = () =>
|
|
11
|
+
html`<ed-r-chunky-checkbox
|
|
12
|
+
text="Connect"
|
|
13
|
+
description="Connect and hang out with cool people with shared interests."
|
|
14
|
+
name="purpose"
|
|
15
|
+
value="connect"
|
|
16
|
+
></ed-r-chunky-checkbox>`;
|
|
17
|
+
|
|
18
|
+
export const Checked = () =>
|
|
19
|
+
html`<ed-r-chunky-checkbox
|
|
20
|
+
text="Be"
|
|
21
|
+
description="Find calm, slow down, and cultivate presence."
|
|
22
|
+
name="purpose"
|
|
23
|
+
value="be"
|
|
24
|
+
?checked=${true}
|
|
25
|
+
></ed-r-chunky-checkbox>`;
|
|
26
|
+
|
|
27
|
+
export const Group = () =>
|
|
28
|
+
html`
|
|
29
|
+
<ed-grid>
|
|
30
|
+
<ed-grid-item>
|
|
31
|
+
<ed-r-chunky-checkbox text="Be" description="Find calm, slow down, and cultivate presence." name="purpose" value="be"></ed-r-chunky-checkbox>
|
|
32
|
+
</ed-grid-item>
|
|
33
|
+
<ed-grid-item>
|
|
34
|
+
<ed-r-chunky-checkbox text="Connect" description="Connect and hang out with cool people with shared interests." name="purpose" value="connect"></ed-r-chunky-checkbox>
|
|
35
|
+
</ed-grid-item>
|
|
36
|
+
<ed-grid-item>
|
|
37
|
+
<ed-r-chunky-checkbox text="Explore" description="Explore your location, hobbies, expand your horizons." name="purpose" value="explore"></ed-r-chunky-checkbox>
|
|
38
|
+
</ed-grid-item>
|
|
39
|
+
<ed-grid-item>
|
|
40
|
+
<ed-r-chunky-checkbox text="Grow" description="Improve areas of your life with support and guidance." name="purpose" value="grow"></ed-r-chunky-checkbox>
|
|
41
|
+
</ed-grid-item>
|
|
42
|
+
<ed-grid-item>
|
|
43
|
+
<ed-r-chunky-checkbox text="Help" description="Help the people in your life, your community, and the world." name="purpose" value="help"></ed-r-chunky-checkbox>
|
|
44
|
+
</ed-grid-item>
|
|
45
|
+
<ed-grid-item>
|
|
46
|
+
<ed-r-chunky-checkbox text="Create" description="Unlock your creative potential and express yourself." name="purpose" value="create"></ed-r-chunky-checkbox>
|
|
47
|
+
</ed-grid-item>
|
|
48
|
+
<ed-grid-item>
|
|
49
|
+
<ed-r-chunky-checkbox text="Learn" description="Expand your horizons and learn new things." name="purpose" value="learn"></ed-r-chunky-checkbox>
|
|
50
|
+
</ed-grid-item>
|
|
51
|
+
<ed-grid-item>
|
|
52
|
+
<ed-r-chunky-checkbox text="I'm not sure!" description="Just checking things out for now, and will decide later." name="purpose" value="unsure"></ed-r-chunky-checkbox>
|
|
53
|
+
</ed-grid-item>
|
|
54
|
+
</ed-grid>
|
|
55
|
+
`;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import { html, unsafeCSS } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators.js';
|
|
4
|
+
import styles from './chunky-checkbox.scss?inline';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A large, card-style checkbox for multi-select interfaces (e.g. onboarding flows).
|
|
8
|
+
* Renders a native checkbox input inside a styled card with a heading and description.
|
|
9
|
+
*/
|
|
10
|
+
export class EdRChunkyCheckbox extends EdElement {
|
|
11
|
+
static get styles() {
|
|
12
|
+
return unsafeCSS(styles);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The checkbox label / heading text.
|
|
17
|
+
*/
|
|
18
|
+
@property()
|
|
19
|
+
text!: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Description text shown below the heading.
|
|
23
|
+
*/
|
|
24
|
+
@property()
|
|
25
|
+
description?: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The checkbox input value attribute.
|
|
29
|
+
*/
|
|
30
|
+
@property()
|
|
31
|
+
value?: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The name attribute for the checkbox input.
|
|
35
|
+
*/
|
|
36
|
+
@property()
|
|
37
|
+
name?: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether the checkbox is checked.
|
|
41
|
+
*/
|
|
42
|
+
@property({ type: Boolean })
|
|
43
|
+
checked = false;
|
|
44
|
+
|
|
45
|
+
private handleChange(e: Event) {
|
|
46
|
+
const input = e.target as HTMLInputElement;
|
|
47
|
+
this.checked = input.checked;
|
|
48
|
+
this.dispatch({
|
|
49
|
+
eventName: 'change',
|
|
50
|
+
detailObj: { checked: this.checked, value: this.value },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
render() {
|
|
55
|
+
const componentClassName = this.componentClassNames('ed-r-c-chunky-checkbox', {
|
|
56
|
+
'ed-r-c-chunky-checkbox--checked': this.checked,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return html`
|
|
60
|
+
<label class="${componentClassName}">
|
|
61
|
+
<input
|
|
62
|
+
type="checkbox"
|
|
63
|
+
class="ed-r-c-chunky-checkbox__input"
|
|
64
|
+
.checked="${this.checked}"
|
|
65
|
+
name="${this.name || ''}"
|
|
66
|
+
value="${this.value || ''}"
|
|
67
|
+
@change="${this.handleChange}"
|
|
68
|
+
/>
|
|
69
|
+
<div class="ed-r-c-chunky-checkbox__body">
|
|
70
|
+
<h3 class="ed-r-c-chunky-checkbox__heading">${this.text}</h3>
|
|
71
|
+
${this.description
|
|
72
|
+
? html`<div class="ed-r-c-chunky-checkbox__description">${this.description}</div>`
|
|
73
|
+
: ''}
|
|
74
|
+
</div>
|
|
75
|
+
</label>
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (customElements.get('ed-r-chunky-checkbox') === undefined) {
|
|
81
|
+
customElements.define('ed-r-chunky-checkbox', EdRChunkyCheckbox);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
declare global {
|
|
85
|
+
interface HTMLElementTagNameMap {
|
|
86
|
+
'ed-r-chunky-checkbox': EdRChunkyCheckbox;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#WAH-LINK-LIST
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.ed-r-c-wah-link-list__header {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: baseline;
|
|
13
|
+
gap: size(2);
|
|
14
|
+
margin-block-end: size(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ed-r-c-wah-link-list__heading {
|
|
18
|
+
margin: 0;
|
|
19
|
+
font-size: var(--ed-font-size-lg);
|
|
20
|
+
font-weight: var(--ed-font-weight-bold);
|
|
21
|
+
color: var(--ed-theme-color-content-default);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ed-r-c-wah-link-list__heading-link {
|
|
25
|
+
font-size: var(--ed-font-size-sm);
|
|
26
|
+
color: var(--ed-theme-color-content-subtle);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.ed-r-c-wah-link-list__list {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
gap: size(0.5) size(1.5);
|
|
33
|
+
list-style: none;
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ed-r-c-wah-link-list__link {
|
|
39
|
+
color: var(--ed-theme-color-content-subtle);
|
|
40
|
+
text-decoration: none;
|
|
41
|
+
font-size: var(--ed-font-size-sm);
|
|
42
|
+
|
|
43
|
+
&:hover {
|
|
44
|
+
color: var(--ed-theme-color-content-default);
|
|
45
|
+
text-decoration: underline;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Featured items
|
|
51
|
+
* 1) Bolder color and weight to stand out from normal items
|
|
52
|
+
*/
|
|
53
|
+
.ed-r-c-wah-link-list__item--featured .ed-r-c-wah-link-list__link {
|
|
54
|
+
color: var(--ed-theme-color-content-default); /* 1 */
|
|
55
|
+
font-weight: var(--ed-font-weight-bold); /* 1 */
|
|
56
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './wah-link-list';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Recipes/we are here./Wah Link List',
|
|
6
|
+
component: 'ed-r-wah-link-list',
|
|
7
|
+
parameters: { status: { type: 'beta' } },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = () =>
|
|
11
|
+
html`<ed-r-wah-link-list
|
|
12
|
+
heading="Music"
|
|
13
|
+
headingLinkText="Links to Last.fm, BandCamp, Music Services"
|
|
14
|
+
headingLinkHref="#"
|
|
15
|
+
.items=${[
|
|
16
|
+
{ text: 'Rubblebucket', href: '#', featured: true },
|
|
17
|
+
{ text: 'Led Zeppelin', href: '#', featured: true },
|
|
18
|
+
{ text: 'CAKE', href: '#', featured: true },
|
|
19
|
+
{ text: 'Outkast', href: '#', featured: true },
|
|
20
|
+
{ text: 'Fela Kuti', href: '#' },
|
|
21
|
+
{ text: 'Tune Yards', href: '#' },
|
|
22
|
+
{ text: 'Dr. Dog', href: '#' },
|
|
23
|
+
{ text: 'Beasie Boys', href: '#' },
|
|
24
|
+
{ text: 'View All', href: '#' },
|
|
25
|
+
]}
|
|
26
|
+
></ed-r-wah-link-list>`;
|
|
27
|
+
|
|
28
|
+
export const Communities = () =>
|
|
29
|
+
html`<ed-r-wah-link-list
|
|
30
|
+
heading="My Communities"
|
|
31
|
+
.items=${[
|
|
32
|
+
{ text: 'Brad Frost Web', href: '/communities', featured: true },
|
|
33
|
+
{ text: 'Smashing Membership', href: '/communities' },
|
|
34
|
+
{ text: 'Friends of beyond tellerrand', href: '/communities' },
|
|
35
|
+
{ text: 'Design Better', href: '/communities' },
|
|
36
|
+
{ text: 'OpenUI', href: '/communities' },
|
|
37
|
+
]}
|
|
38
|
+
></ed-r-wah-link-list>`;
|
|
39
|
+
|
|
40
|
+
export const NoFeatured = () =>
|
|
41
|
+
html`<ed-r-wah-link-list
|
|
42
|
+
heading="Hobbies"
|
|
43
|
+
.items=${[
|
|
44
|
+
{ text: 'Playing Drums', href: '#' },
|
|
45
|
+
{ text: 'Playing Bass', href: '#' },
|
|
46
|
+
{ text: 'Making Art', href: '#' },
|
|
47
|
+
{ text: 'Painting', href: '#' },
|
|
48
|
+
{ text: 'Woodworking', href: '#' },
|
|
49
|
+
]}
|
|
50
|
+
></ed-r-wah-link-list>`;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import { html, unsafeCSS, nothing } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators.js';
|
|
4
|
+
import styles from './wah-link-list.scss?inline';
|
|
5
|
+
|
|
6
|
+
interface WahLinkItem {
|
|
7
|
+
text: string;
|
|
8
|
+
href: string;
|
|
9
|
+
featured?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A link list with optional "featured" items rendered with visual emphasis.
|
|
14
|
+
* Used extensively in topic profiles for lists of interests, media, communities, etc.
|
|
15
|
+
*
|
|
16
|
+
* @slot - Optional slotted content rendered after the generated list
|
|
17
|
+
*/
|
|
18
|
+
export class EdRWahLinkList extends EdElement {
|
|
19
|
+
static get styles() {
|
|
20
|
+
return unsafeCSS(styles);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Array of link items. Each item can optionally be marked as `featured`.
|
|
25
|
+
*/
|
|
26
|
+
@property({ type: Array })
|
|
27
|
+
items: WahLinkItem[] = [];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Optional heading text rendered above the list.
|
|
31
|
+
*/
|
|
32
|
+
@property()
|
|
33
|
+
heading?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Optional heading-level link (e.g. "Link to Last.fm").
|
|
37
|
+
*/
|
|
38
|
+
@property()
|
|
39
|
+
headingLinkText?: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* URL for the heading-level link.
|
|
43
|
+
*/
|
|
44
|
+
@property()
|
|
45
|
+
headingLinkHref?: string;
|
|
46
|
+
|
|
47
|
+
render() {
|
|
48
|
+
const componentClassName = this.componentClassNames('ed-r-c-wah-link-list', {});
|
|
49
|
+
|
|
50
|
+
return html`
|
|
51
|
+
<div class="${componentClassName}">
|
|
52
|
+
${this.heading
|
|
53
|
+
? html`
|
|
54
|
+
<div class="ed-r-c-wah-link-list__header">
|
|
55
|
+
<h3 class="ed-r-c-wah-link-list__heading">${this.heading}</h3>
|
|
56
|
+
${this.headingLinkText && this.headingLinkHref
|
|
57
|
+
? html`<a href="${this.headingLinkHref}" class="ed-r-c-wah-link-list__heading-link">${this.headingLinkText}</a>`
|
|
58
|
+
: nothing}
|
|
59
|
+
</div>
|
|
60
|
+
`
|
|
61
|
+
: nothing}
|
|
62
|
+
${this.items.length > 0
|
|
63
|
+
? html`
|
|
64
|
+
<ul class="ed-r-c-wah-link-list__list">
|
|
65
|
+
${this.items.map(
|
|
66
|
+
(item) => html`
|
|
67
|
+
<li class="ed-r-c-wah-link-list__item ${item.featured ? 'ed-r-c-wah-link-list__item--featured' : ''}">
|
|
68
|
+
<a href="${item.href}" class="ed-r-c-wah-link-list__link">${item.text}</a>
|
|
69
|
+
</li>
|
|
70
|
+
`
|
|
71
|
+
)}
|
|
72
|
+
</ul>
|
|
73
|
+
`
|
|
74
|
+
: nothing}
|
|
75
|
+
<slot></slot>
|
|
76
|
+
</div>
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (customElements.get('ed-r-wah-link-list') === undefined) {
|
|
82
|
+
customElements.define('ed-r-wah-link-list', EdRWahLinkList);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare global {
|
|
86
|
+
interface HTMLElementTagNameMap {
|
|
87
|
+
'ed-r-wah-link-list': EdRWahLinkList;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#WAH-LOGO
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* we are here. concentric-circle logo
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
:host {
|
|
11
|
+
display: inline-block;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ed-r-c-wah-logo {
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Logo link
|
|
21
|
+
* 1) Remove default link underline
|
|
22
|
+
* 2) Inherit dimensions from parent
|
|
23
|
+
*/
|
|
24
|
+
.ed-r-c-wah-logo__link {
|
|
25
|
+
display: inline-flex;
|
|
26
|
+
text-decoration: none; /* 1 */
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Logo SVG image
|
|
31
|
+
* 1) Size the logo mark; consumers can override via CSS custom property
|
|
32
|
+
*/
|
|
33
|
+
.ed-r-c-wah-logo__image {
|
|
34
|
+
width: var(--ed-r-c-wah-logo-size, size(8)); /* 1 */
|
|
35
|
+
height: auto;
|
|
36
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './wah-logo';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Recipes/we are here./Wah Logo',
|
|
6
|
+
component: 'ed-r-wah-logo',
|
|
7
|
+
parameters: { status: { type: 'beta' } },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = () => html`<ed-r-wah-logo></ed-r-wah-logo>`;
|
|
11
|
+
|
|
12
|
+
export const WithLink = () => html`<ed-r-wah-logo href="/dashboard"></ed-r-wah-logo>`;
|
|
13
|
+
|
|
14
|
+
export const CustomSize = () => html`<ed-r-wah-logo style="--ed-r-c-wah-logo-size: 12rem;"></ed-r-wah-logo>`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import { html, unsafeCSS } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators.js';
|
|
4
|
+
import styles from './wah-logo.scss?inline';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* we are here. logo — concentric circle SVG mark.
|
|
8
|
+
*
|
|
9
|
+
* @slot - Optional slotted content (e.g. wordmark text)
|
|
10
|
+
*/
|
|
11
|
+
export class EdRWahLogo extends EdElement {
|
|
12
|
+
static get styles() {
|
|
13
|
+
return unsafeCSS(styles);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Optional link URL. When provided, the logo renders as an anchor.
|
|
18
|
+
*/
|
|
19
|
+
@property()
|
|
20
|
+
href?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Accessible title for the SVG.
|
|
24
|
+
*/
|
|
25
|
+
@property()
|
|
26
|
+
logoTitle?: string = 'we are here.';
|
|
27
|
+
|
|
28
|
+
render() {
|
|
29
|
+
const componentClassName = this.componentClassNames('ed-r-c-wah-logo', {});
|
|
30
|
+
|
|
31
|
+
const svg = html`
|
|
32
|
+
<svg class="ed-r-c-wah-logo__image" fill="none" height="502" viewBox="0 0 502 502" width="502" xmlns="http://www.w3.org/2000/svg">
|
|
33
|
+
<title>${this.logoTitle}</title>
|
|
34
|
+
<circle cx="251.176" cy="250.62" fill="#be6700" r="250.62"></circle>
|
|
35
|
+
<circle cx="251.176" cy="250.62" fill="#fa8700" r="210.521"></circle>
|
|
36
|
+
<circle cx="251.176" cy="250.62" fill="#ffa438" r="170.422"></circle>
|
|
37
|
+
<circle cx="251.176" cy="250.62" fill="#ffc075" r="130.322"></circle>
|
|
38
|
+
<circle cx="251.176" cy="250.62" fill="#ffdcb3" r="90.2232"></circle>
|
|
39
|
+
<circle cx="251.176" cy="250.62" fill="#fff8f0" r="50.2232"></circle>
|
|
40
|
+
</svg>
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
return html`
|
|
44
|
+
<div class="${componentClassName}">
|
|
45
|
+
${this.href
|
|
46
|
+
? html`<a href="${this.href}" class="ed-r-c-wah-logo__link">${svg}</a>`
|
|
47
|
+
: svg}
|
|
48
|
+
<slot></slot>
|
|
49
|
+
</div>
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (customElements.get('ed-r-wah-logo') === undefined) {
|
|
55
|
+
customElements.define('ed-r-wah-logo', EdRWahLogo);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare global {
|
|
59
|
+
interface HTMLElementTagNameMap {
|
|
60
|
+
'ed-r-wah-logo': EdRWahLogo;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#WAH-SITE-FOOTER
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.ed-r-c-wah-site-footer {
|
|
11
|
+
padding-block: size(4);
|
|
12
|
+
border-block-start: var(--ed-border-width-sm) solid var(--ed-theme-color-border-subtle);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.ed-r-c-wah-site-footer__nav-list {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-wrap: wrap;
|
|
18
|
+
gap: size(1) size(3);
|
|
19
|
+
list-style: none;
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ed-r-c-wah-site-footer__nav-link {
|
|
25
|
+
color: var(--ed-theme-color-content-subtle);
|
|
26
|
+
text-decoration: none;
|
|
27
|
+
font-size: var(--ed-font-size-sm);
|
|
28
|
+
|
|
29
|
+
&:hover {
|
|
30
|
+
color: var(--ed-theme-color-content-default);
|
|
31
|
+
text-decoration: underline;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './wah-site-footer';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Recipes/we are here./Wah Site Footer',
|
|
6
|
+
component: 'ed-r-wah-site-footer',
|
|
7
|
+
parameters: { status: { type: 'beta' } },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = () => html`<ed-r-wah-site-footer></ed-r-wah-site-footer>`;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import '@brad-frost-web/eddie-web-components/components/layout-container/layout-container';
|
|
3
|
+
import { html, unsafeCSS } from 'lit';
|
|
4
|
+
import { property } from 'lit/decorators.js';
|
|
5
|
+
import styles from './wah-site-footer.scss?inline';
|
|
6
|
+
|
|
7
|
+
interface WahFooterNavItem {
|
|
8
|
+
text: string;
|
|
9
|
+
href: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* we are here. site footer with navigation links.
|
|
14
|
+
*/
|
|
15
|
+
export class EdRWahSiteFooter extends EdElement {
|
|
16
|
+
static get styles() {
|
|
17
|
+
return unsafeCSS(styles);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Footer navigation items.
|
|
22
|
+
*/
|
|
23
|
+
@property({ type: Array })
|
|
24
|
+
navItems: WahFooterNavItem[] = [
|
|
25
|
+
{ text: 'Report an issue', href: '/contact' },
|
|
26
|
+
{ text: 'Code of Conduct', href: '/code-of-conduct' },
|
|
27
|
+
{ text: 'Privacy Policy', href: '/privacy-policy' },
|
|
28
|
+
{ text: 'Terms of Service', href: '/terms-of-service' },
|
|
29
|
+
{ text: 'About we are here.', href: '/team' },
|
|
30
|
+
{ text: 'Mission & Values', href: '/mission-values' },
|
|
31
|
+
{ text: 'Idea Jar', href: '/idea-jar' },
|
|
32
|
+
{ text: 'Contact', href: '/contact' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
render() {
|
|
36
|
+
const componentClassName = this.componentClassNames('ed-r-c-wah-site-footer', {});
|
|
37
|
+
|
|
38
|
+
return html`
|
|
39
|
+
<footer class="${componentClassName}" role="contentinfo">
|
|
40
|
+
<ed-layout-container>
|
|
41
|
+
<div class="ed-r-c-wah-site-footer__inner">
|
|
42
|
+
<nav class="ed-r-c-wah-site-footer__nav" aria-label="Footer">
|
|
43
|
+
<ul class="ed-r-c-wah-site-footer__nav-list">
|
|
44
|
+
${this.navItems.map(
|
|
45
|
+
(item) => html`
|
|
46
|
+
<li class="ed-r-c-wah-site-footer__nav-item">
|
|
47
|
+
<a href="${item.href}" class="ed-r-c-wah-site-footer__nav-link">${item.text}</a>
|
|
48
|
+
</li>
|
|
49
|
+
`
|
|
50
|
+
)}
|
|
51
|
+
</ul>
|
|
52
|
+
</nav>
|
|
53
|
+
</div>
|
|
54
|
+
</ed-layout-container>
|
|
55
|
+
</footer>
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (customElements.get('ed-r-wah-site-footer') === undefined) {
|
|
61
|
+
customElements.define('ed-r-wah-site-footer', EdRWahSiteFooter);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
declare global {
|
|
65
|
+
interface HTMLElementTagNameMap {
|
|
66
|
+
'ed-r-wah-site-footer': EdRWahSiteFooter;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
@use '@brad-frost-web/eddie-design-tokens/core/scss/component.scss' as *;
|
|
2
|
+
/*------------------------------------*\
|
|
3
|
+
#WAH-SITE-HEADER
|
|
4
|
+
\*------------------------------------*/
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Header root
|
|
12
|
+
* 1) Sticky to top of viewport
|
|
13
|
+
*/
|
|
14
|
+
.ed-r-c-wah-site-header {
|
|
15
|
+
position: sticky; /* 1 */
|
|
16
|
+
top: 0;
|
|
17
|
+
z-index: 10;
|
|
18
|
+
background-color: var(--ed-theme-color-background-default);
|
|
19
|
+
border-block-end: var(--ed-border-width-sm) solid var(--ed-theme-color-border-subtle);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ed-r-c-wah-site-header__inner {
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-wrap: wrap;
|
|
25
|
+
align-items: center;
|
|
26
|
+
padding-block: size(1.5);
|
|
27
|
+
gap: size(2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ed-r-c-wah-site-header__logo {
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Menu button
|
|
36
|
+
* 1) Only visible on small screens
|
|
37
|
+
*/
|
|
38
|
+
.ed-r-c-wah-site-header__menu-button {
|
|
39
|
+
margin-inline-start: auto;
|
|
40
|
+
|
|
41
|
+
@media all and (min-width: $ed-bp-md) {
|
|
42
|
+
display: none; /* 1 */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Primary nav
|
|
48
|
+
* 1) Hidden on mobile until menu is toggled open
|
|
49
|
+
* 2) Full width on small screens
|
|
50
|
+
*/
|
|
51
|
+
.ed-r-c-wah-site-header__primary-nav {
|
|
52
|
+
display: none; /* 1 */
|
|
53
|
+
width: 100%; /* 2 */
|
|
54
|
+
|
|
55
|
+
.ed-r-c-wah-site-header.ed-is-active & {
|
|
56
|
+
display: block;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media all and (min-width: $ed-bp-md) {
|
|
60
|
+
display: block;
|
|
61
|
+
width: auto;
|
|
62
|
+
margin-inline-start: auto;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.ed-r-c-wah-site-header__primary-nav-list {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: size(0.5);
|
|
70
|
+
list-style: none;
|
|
71
|
+
margin: 0;
|
|
72
|
+
padding: 0;
|
|
73
|
+
|
|
74
|
+
@media all and (min-width: $ed-bp-md) {
|
|
75
|
+
flex-direction: row;
|
|
76
|
+
gap: size(2);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.ed-r-c-wah-site-header__primary-nav-link {
|
|
81
|
+
display: block;
|
|
82
|
+
padding: size(1) 0;
|
|
83
|
+
color: var(--ed-theme-color-content-default);
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
font-weight: var(--ed-font-weight-normal);
|
|
86
|
+
|
|
87
|
+
&:hover {
|
|
88
|
+
color: var(--ed-theme-color-content-brand);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Active nav item modifier
|
|
94
|
+
*/
|
|
95
|
+
.ed-r-c-wah-site-header__primary-nav-item--active .ed-r-c-wah-site-header__primary-nav-link {
|
|
96
|
+
font-weight: var(--ed-font-weight-bold);
|
|
97
|
+
color: var(--ed-theme-color-content-brand);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Utility nav
|
|
102
|
+
* 1) Hidden on mobile until menu is toggled open
|
|
103
|
+
*/
|
|
104
|
+
.ed-r-c-wah-site-header__utility-nav {
|
|
105
|
+
display: none; /* 1 */
|
|
106
|
+
width: 100%;
|
|
107
|
+
|
|
108
|
+
.ed-r-c-wah-site-header.ed-is-active & {
|
|
109
|
+
display: block;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@media all and (min-width: $ed-bp-md) {
|
|
113
|
+
display: none;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.ed-r-c-wah-site-header__utility-nav-list {
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
gap: size(0.5);
|
|
121
|
+
list-style: none;
|
|
122
|
+
margin: 0;
|
|
123
|
+
padding: size(2) 0 0;
|
|
124
|
+
border-block-start: var(--ed-border-width-sm) solid var(--ed-theme-color-border-subtle);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.ed-r-c-wah-site-header__utility-nav-link {
|
|
128
|
+
display: block;
|
|
129
|
+
padding: size(0.5) 0;
|
|
130
|
+
color: var(--ed-theme-color-content-subtle);
|
|
131
|
+
text-decoration: none;
|
|
132
|
+
font-size: var(--ed-font-size-sm);
|
|
133
|
+
|
|
134
|
+
&:hover {
|
|
135
|
+
color: var(--ed-theme-color-content-default);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './wah-site-header';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Recipes/we are here./Wah Site Header',
|
|
6
|
+
component: 'ed-r-wah-site-header',
|
|
7
|
+
parameters: { status: { type: 'beta' } },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = () => html`<ed-r-wah-site-header></ed-r-wah-site-header>`;
|
|
11
|
+
|
|
12
|
+
export const WithActiveItem = () =>
|
|
13
|
+
html`<ed-r-wah-site-header activeNavItem="Your Profile"></ed-r-wah-site-header>`;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdElement';
|
|
2
|
+
import '@brad-frost-web/eddie-web-components/components/button/button';
|
|
3
|
+
import '@brad-frost-web/eddie-web-components/components/layout-container/layout-container';
|
|
4
|
+
import '../wah-logo/wah-logo';
|
|
5
|
+
import { html, unsafeCSS } from 'lit';
|
|
6
|
+
import { property, state } from 'lit/decorators.js';
|
|
7
|
+
import styles from './wah-site-header.scss?inline';
|
|
8
|
+
|
|
9
|
+
interface WahNavItem {
|
|
10
|
+
text: string;
|
|
11
|
+
href: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* we are here. site header recipe composing the logo, primary navigation,
|
|
16
|
+
* utility navigation, and a mobile menu toggle.
|
|
17
|
+
*/
|
|
18
|
+
export class EdRWahSiteHeader extends EdElement {
|
|
19
|
+
static get styles() {
|
|
20
|
+
return unsafeCSS(styles);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Primary nav items displayed in the main navigation.
|
|
25
|
+
*/
|
|
26
|
+
@property({ type: Array })
|
|
27
|
+
primaryNavItems: WahNavItem[] = [
|
|
28
|
+
{ text: 'Your Profile', href: '/profile' },
|
|
29
|
+
{ text: 'Be', href: '/be' },
|
|
30
|
+
{ text: 'Connect', href: '/connect' },
|
|
31
|
+
{ text: 'Grow', href: '/grow' },
|
|
32
|
+
{ text: 'Help', href: '/help' },
|
|
33
|
+
{ text: 'Create', href: '/create' },
|
|
34
|
+
{ text: 'Learn', href: '/learn' },
|
|
35
|
+
{ text: 'Explore', href: '/explore' },
|
|
36
|
+
{ text: 'Random', href: '#' },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Utility nav items displayed below primary nav.
|
|
41
|
+
*/
|
|
42
|
+
@property({ type: Array })
|
|
43
|
+
utilityNavItems: WahNavItem[] = [
|
|
44
|
+
{ text: 'Report an issue', href: '/contact' },
|
|
45
|
+
{ text: 'Code of Conduct', href: '/code-of-conduct' },
|
|
46
|
+
{ text: 'Privacy Policy', href: '/privacy-policy' },
|
|
47
|
+
{ text: 'Terms of Service', href: '/terms-of-service' },
|
|
48
|
+
{ text: 'Our Mission & Values', href: '/mission-values' },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* URL for the logo link.
|
|
53
|
+
*/
|
|
54
|
+
@property()
|
|
55
|
+
logoHref?: string = '/dashboard';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Highlighted primary nav item text (e.g. "Your Profile" gets a special style).
|
|
59
|
+
*/
|
|
60
|
+
@property()
|
|
61
|
+
activeNavItem?: string;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Internal mobile menu state.
|
|
65
|
+
*/
|
|
66
|
+
@state()
|
|
67
|
+
private isMenuOpen = false;
|
|
68
|
+
|
|
69
|
+
private toggleMenu() {
|
|
70
|
+
this.isMenuOpen = !this.isMenuOpen;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
render() {
|
|
74
|
+
const componentClassName = this.componentClassNames('ed-r-c-wah-site-header', {
|
|
75
|
+
'ed-is-active': this.isMenuOpen,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return html`
|
|
79
|
+
<header class="${componentClassName}" role="banner">
|
|
80
|
+
<ed-layout-container class="ed-r-c-wah-site-header__container">
|
|
81
|
+
<div class="ed-r-c-wah-site-header__inner">
|
|
82
|
+
<ed-r-wah-logo class="ed-r-c-wah-site-header__logo" href="${this.logoHref}"></ed-r-wah-logo>
|
|
83
|
+
|
|
84
|
+
<ed-button
|
|
85
|
+
class="ed-r-c-wah-site-header__menu-button"
|
|
86
|
+
variant="bare"
|
|
87
|
+
text="Menu"
|
|
88
|
+
iconName="menu"
|
|
89
|
+
iconPosition="before"
|
|
90
|
+
aria-expanded="${this.isMenuOpen}"
|
|
91
|
+
@click="${this.toggleMenu}"
|
|
92
|
+
></ed-button>
|
|
93
|
+
|
|
94
|
+
<nav class="ed-r-c-wah-site-header__primary-nav" aria-label="Primary">
|
|
95
|
+
<ul class="ed-r-c-wah-site-header__primary-nav-list">
|
|
96
|
+
${this.primaryNavItems.map(
|
|
97
|
+
(item) => html`
|
|
98
|
+
<li class="ed-r-c-wah-site-header__primary-nav-item ${item.text === this.activeNavItem ? 'ed-r-c-wah-site-header__primary-nav-item--active' : ''}">
|
|
99
|
+
<a href="${item.href}" class="ed-r-c-wah-site-header__primary-nav-link">${item.text}</a>
|
|
100
|
+
</li>
|
|
101
|
+
`
|
|
102
|
+
)}
|
|
103
|
+
</ul>
|
|
104
|
+
</nav>
|
|
105
|
+
|
|
106
|
+
<nav class="ed-r-c-wah-site-header__utility-nav" aria-label="Utility">
|
|
107
|
+
<ul class="ed-r-c-wah-site-header__utility-nav-list">
|
|
108
|
+
${this.utilityNavItems.map(
|
|
109
|
+
(item) => html`
|
|
110
|
+
<li class="ed-r-c-wah-site-header__utility-nav-item">
|
|
111
|
+
<a href="${item.href}" class="ed-r-c-wah-site-header__utility-nav-link">${item.text}</a>
|
|
112
|
+
</li>
|
|
113
|
+
`
|
|
114
|
+
)}
|
|
115
|
+
</ul>
|
|
116
|
+
</nav>
|
|
117
|
+
</div>
|
|
118
|
+
</ed-layout-container>
|
|
119
|
+
</header>
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (customElements.get('ed-r-wah-site-header') === undefined) {
|
|
125
|
+
customElements.define('ed-r-wah-site-header', EdRWahSiteHeader);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
declare global {
|
|
129
|
+
interface HTMLElementTagNameMap {
|
|
130
|
+
'ed-r-wah-site-header': EdRWahSiteHeader;
|
|
131
|
+
}
|
|
132
|
+
}
|