Skip to content

Commit dd7a89a

Browse files
authored
Merge branch 'main' into github-pages
2 parents da2d069 + b6bb965 commit dd7a89a

File tree

8 files changed

+496
-170
lines changed

8 files changed

+496
-170
lines changed

demo/story-template.ts

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,33 @@
1-
import { css, html, LitElement, type CSSResultGroup } from 'lit';
2-
import { property, state } from 'lit/decorators.js';
1+
import {
2+
css,
3+
html,
4+
LitElement,
5+
nothing,
6+
TemplateResult,
7+
type CSSResultGroup,
8+
} from 'lit';
9+
import { property, queryAll, state } from 'lit/decorators.js';
310
import { customElement } from 'lit/decorators/custom-element.js';
411
import { when } from 'lit/directives/when.js';
12+
import { ifDefined } from 'lit/directives/if-defined.js';
513

614
import './syntax-highlighter';
715
import themeStyles from '@src/themes/theme-styles';
816

917
import arrow from './arrow.svg';
1018
import testTube from './test-tube.svg';
1119

20+
export type StyleInputSettings = {
21+
label: string;
22+
cssVariable: string;
23+
defaultValue?: string;
24+
inputType?: 'color' | 'text';
25+
};
26+
27+
export type StyleInputData = {
28+
settings: StyleInputSettings[];
29+
};
30+
1231
/**
1332
* A template for demoing the use of a custom element.
1433
*/
@@ -18,10 +37,21 @@ export class StoryTemplate extends LitElement {
1837

1938
@property({ type: String }) exampleUsage = '';
2039

40+
@property({ type: Object }) styleInputData?: StyleInputData;
41+
2142
@property({ type: Boolean }) labs = false;
2243

2344
@state() private visible = false;
2445

46+
/* Stringified styles applied for the demo component */
47+
@state() private appliedStyles?: string;
48+
49+
/* Whether settings inputs have been slotted in and should be displayed */
50+
@state() private shouldShowPropertySettings: boolean = false;
51+
52+
@queryAll('.style-input')
53+
private styleInputs?: NodeListOf<HTMLInputElement>;
54+
2555
render() {
2656
return html`
2757
<h2>
@@ -49,28 +79,78 @@ export class StoryTemplate extends LitElement {
4979
return html`
5080
<div id="container">
5181
<h3>Demo</h3>
52-
<div class="slot-container">
82+
<div class="slot-container" style=${ifDefined(this.appliedStyles)}>
5383
<slot name="demo"></slot>
5484
</div>
5585
<h3>Import</h3>
5686
<syntax-highlighter .code=${this.importCode}></syntax-highlighter>
5787
<h3>Usage</h3>
58-
<syntax-highlighter .code=${this.exampleUsage}></syntax-highlighter>
59-
<h3>Settings</h3>
60-
<div class="slot-container">
88+
<syntax-highlighter
89+
.code=${this.exampleUsage + this.cssCode}
90+
></syntax-highlighter>
91+
${this.styleSettingsTemplate}
92+
${this.shouldShowPropertySettings ? html` <h3>Settings</h3>` : nothing}
93+
<div
94+
class="slot-container"
95+
style="${!this.shouldShowPropertySettings ? 'display: none' : ''}"
96+
@slotchange=${this.handleSettingsSlotChange}
97+
>
6198
<slot name="settings"></slot>
6299
</div>
63100
</div>
64101
`;
65102
}
66103

104+
private get styleSettingsTemplate(): TemplateResult | typeof nothing {
105+
if (!this.styleInputData) return nothing;
106+
107+
return html`
108+
<h3>Styles</h3>
109+
<div class="style-options">
110+
<table>
111+
${this.styleInputData.settings.map(
112+
(input) => html`
113+
<tr>
114+
<td>
115+
<label for=${this.labelToId(input.label)}
116+
>${input.label}</label
117+
>
118+
</td>
119+
<td>
120+
<input
121+
id=${this.labelToId(input.label)}
122+
class="style-input"
123+
type=${input.inputType ?? 'text'}
124+
value=${input.defaultValue ?? ''}
125+
data-variable=${input.cssVariable}
126+
/>
127+
</td>
128+
</tr>
129+
`,
130+
)}
131+
</table>
132+
<button @click=${this.applyStyles}>Apply</button>
133+
</div>
134+
`;
135+
}
136+
67137
private get importCode(): string {
68138
return `
69139
import '${this.modulePath}';
70140
import { ${this.elementClassName} } from '${this.modulePath}';
71141
`;
72142
}
73143

144+
private get cssCode(): string {
145+
if (!this.appliedStyles) return '';
146+
return `
147+
148+
${this.elementTag} {
149+
${this.appliedStyles}
150+
}
151+
`;
152+
}
153+
74154
private get elementClassName(): string | undefined {
75155
return customElements.get(this.elementTag)?.name;
76156
}
@@ -81,6 +161,29 @@ import { ${this.elementClassName} } from '${this.modulePath}';
81161
: `@internetarchive/elements/${this.elementTag}/${this.elementTag}`;
82162
}
83163

164+
/* Toggles visibility of section depending on whether inputs have been slotted into it */
165+
private handleSettingsSlotChange(e: Event): void {
166+
const slottedChildren = (e.target as HTMLSlotElement).assignedElements();
167+
this.shouldShowPropertySettings = slottedChildren.length > 0;
168+
}
169+
170+
/* Applies styles to demo component. */
171+
private applyStyles(): void {
172+
const appliedStyles: string[] = [];
173+
174+
this.styleInputs?.forEach((input) => {
175+
if (!input.dataset.variable || !input.value) return;
176+
appliedStyles.push(`${input.dataset.variable}: ${input.value};`);
177+
});
178+
179+
this.appliedStyles = appliedStyles.join('\n ');
180+
}
181+
182+
/* Converts a label to a usable input id, i.e. My setting -> my-setting */
183+
private labelToId(label: string): string {
184+
return label.toLowerCase().split(' ').join('-');
185+
}
186+
84187
static get styles(): CSSResultGroup {
85188
return [
86189
themeStyles,
@@ -100,7 +203,8 @@ import { ${this.elementClassName} } from '${this.modulePath}';
100203
margin-bottom: 8px;
101204
}
102205
103-
.slot-container {
206+
.slot-container,
207+
.style-options {
104208
background-color: var(--primary-background-color);
105209
padding: 1em;
106210
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@internetarchive/elements",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "A web component library from the Internet Archive.",
55
"license": "AGPL-3.0-only",
66
"types": "./dist/src/elements/index.d.ts",
Lines changed: 24 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,45 @@
11
import { html, LitElement } from 'lit';
2-
import { customElement, query, state } from 'lit/decorators.js';
2+
import { customElement } from 'lit/decorators.js';
3+
4+
import type { StyleInputSettings } from '@demo/story-template';
35

46
import './ia-button';
57
import '@demo/story-template';
68

9+
const styleInputSettings: StyleInputSettings[] = [
10+
{
11+
label: 'Text Color (Primary)',
12+
cssVariable: '--ia-theme-primary-cta-text-color',
13+
defaultValue: '#ffffff',
14+
inputType: 'color',
15+
},
16+
{
17+
label: 'Background Color (Primary)',
18+
cssVariable: '--ia-theme-primary-cta-fill',
19+
defaultValue: '#194880',
20+
inputType: 'color',
21+
},
22+
];
23+
724
@customElement('ia-button-story')
825
export class IAButtonStory extends LitElement {
9-
@query('#backgroundColor')
10-
private backgroundColorInput!: HTMLInputElement;
11-
12-
@query('#textColor')
13-
private textColorInput!: HTMLInputElement;
14-
15-
@state()
16-
private backgroundColor: string = '#194880';
17-
18-
@state()
19-
private textColor: string = '#ffffff';
20-
21-
@query('ia-button')
22-
private button!: HTMLElement;
23-
24-
@state()
25-
private includeStyle = false;
26-
2726
render() {
2827
return html`
29-
<story-template elementTag="ia-button" .exampleUsage=${this.exampleUsage}>
28+
<story-template
29+
elementTag="ia-button"
30+
.exampleUsage=${this.exampleUsage}
31+
.styleInputData=${{ settings: styleInputSettings }}
32+
>
3033
<div slot="demo">
3134
<ia-button @click=${() => alert('Button clicked!')}
3235
>Click Me</ia-button
3336
>
3437
</div>
35-
36-
<div slot="settings">
37-
<table>
38-
<tr>
39-
<td>Text Color</td>
40-
<td><input type="color" value="#ffffff" id="textColor" /></td>
41-
</tr>
42-
<tr>
43-
<td>Background Color</td>
44-
<td>
45-
<input type="color" value="#194880" id="backgroundColor" />
46-
</td>
47-
</tr>
48-
</table>
49-
<button @click=${this.apply}>Apply</button>
50-
</div>
5138
</story-template>
5239
`;
5340
}
5441

5542
private get exampleUsage(): string {
56-
return this.includeStyle
57-
? `<ia-button
58-
@click=\${() => alert('Button clicked!')}
59-
style="--ia-theme-primary-cta-fill: ${this.backgroundColor}; --ia-theme-primary-cta-text-color: ${this.textColor}">Click Me</ia-button>`
60-
: `<ia-button @click=\${() => alert('Button clicked!')}>Click Me</ia-button>`;
61-
}
62-
63-
private apply() {
64-
this.includeStyle = true;
65-
this.backgroundColor = this.backgroundColorInput.value;
66-
this.textColor = this.textColorInput.value;
67-
this.button.style.setProperty(
68-
'--ia-theme-primary-cta-fill',
69-
this.backgroundColor,
70-
);
71-
this.button.style.setProperty(
72-
'--ia-theme-primary-cta-text-color',
73-
this.textColor,
74-
);
43+
return `<ia-button @click=\${() => alert('Button clicked!')}>Click Me</ia-button>`;
7544
}
7645
}

0 commit comments

Comments
 (0)