Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions packages/lit-dev-content/.eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,24 +527,36 @@ ${content}
return `<style>${result.styles}</style>`;
});

/**
* Inline the Rollup-bundled version of a JavaScript module. Path is relative
* to ./rollupout.
*
* In dev mode, instead directly import the module, which has already been
* symlinked directly to the TypeScript output directory.
*/
eleventyConfig.addShortcode('inlinejs', (path) => {
const inlineJs = (path, type) => {
const typeAttribute = type ? ` type="${type}"` : '';
if (DEV) {
return `<script type="module" src="/js/${path}"></script>`;
return `<script${typeAttribute} src="/js/${path}"></script>`;
}
// Note we must trim before hashing, because our html-minifier will trim
// inline script trailing newlines, and otherwise our hash will be wrong.
const script = fsSync.readFileSync(`rollupout/${path}`, 'utf8').trim();
const hash =
'sha256-' + crypto.createHash('sha256').update(script).digest('base64');
cspInlineScriptHashes.add(hash);
return `<script type="module">${script}</script>`;
return `<script${typeAttribute}>${script}</script>`;
};

/**
* Inline the Rollup-bundled version of a JavaScript module. Path is relative
* to ./rollupout.
*
* In dev mode, instead directly import the module, which has already been
* symlinked directly to the TypeScript output directory.
*/
eleventyConfig.addShortcode('inlinejs', (path) => {
return inlineJs(path, 'module');
});

/**
* Inline a parser-blocking classic script.
*/
eleventyConfig.addShortcode('inlineclassicjs', (path) => {
return inlineJs(path);
});

eleventyConfig.addNunjucksAsyncShortcode('algoliaid', async () => {
Expand Down
4 changes: 3 additions & 1 deletion packages/lit-dev-content/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default [
// lit-hydrate-support MUST be loaded first to make sure lit hydration
// helpers are bundled before LitElement attempts to use hydration support
'lib/global/lit-hydrate-support.js',
'lib/global/theme-worker.js',
'lib/components/copy-button.js',
'lib/components/litdev-banner.js',
'lib/components/litdev-drawer.js',
Expand Down Expand Up @@ -151,7 +152,8 @@ export default [
// the asynchronously-loaded module bundles above.
{
input: [
'lib/global/apply-saved-theme.js',
'lib/global/apply-session-theme.js',
'lib/global/initialize-theme.js',
'lib/global/apply-mods.js',
'lib/global/initialize-typescript-mode.js',
'lib/global/mobile-drawer.js',
Expand Down
3 changes: 2 additions & 1 deletion packages/lit-dev-content/site/_includes/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<link rel="modulepreload" href="{{ site.baseurl }}/js/global/hydrate-common-components.js">

<meta name="theme-color" content="#fff">
{% inlinejs "global/apply-saved-theme.js" %}
{% inlinejs "global/initialize-theme.js" %}
{% inlinecss "colors.css" %}
{% inlinecss "global.css" %}

Expand Down Expand Up @@ -75,6 +75,7 @@
</mwc-drawer>

{% include 'header.html' %}
{% inlineclassicjs "global/apply-session-theme.js" %}

{% if selectedVersion !== latestVersion %}
<litdev-banner>
Expand Down
7 changes: 5 additions & 2 deletions packages/lit-dev-content/site/_includes/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@

<litdev-ripple-icon-button
id="mobileMenuButton"
label="Open menu"
label="Navigation menu"
button-title="Open navigation menu"
expanded="false"
controls="mobileDrawer"
>
<svg height="24" width="24" fill="currentcolor">
<svg height="24" width="24" fill="currentcolor" aria-hidden="true">
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
</svg>
</litdev-ripple-icon-button>
Expand Down
9 changes: 5 additions & 4 deletions packages/lit-dev-content/site/playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,22 @@ <h2 class="exampleSectionHeading">{{ section.name }}</h2>
</litdev-playground-share-button>

<litdev-ripple-icon-button
button-title="Toggle view mode"
label="Show preview only"
button-title="Show preview only"
id="view-mode-button">
<lazy-svg
class="preview"
label="Show Only Preview"
svg-aria-hidden
href="{{ site.baseurl }}/images/icons/preview.svg#icon"
loading="eager"></lazy-svg>
<lazy-svg
class="code"
label="Show Only Code"
svg-aria-hidden
href="{{ site.baseurl }}/images/icons/code.svg#icon"
loading="eager"></lazy-svg>
<lazy-svg
class="splitscreen"
label="Show Split View"
svg-aria-hidden
href="{{ site.baseurl }}/images/icons/splitscreen.svg#icon"
loading="eager"></lazy-svg>
</litdev-ripple-icon-button>
Expand Down
6 changes: 5 additions & 1 deletion packages/lit-dev-content/src/components/litdev-drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const closeIcon = html` <svg
height="24"
viewBox="0 0 24 24"
fill="currentcolor"
aria-hidden="true"
>
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
Expand All @@ -34,6 +35,7 @@ const bookIcon = html` <svg
height="24"
viewBox="0 0 24 24"
fill="currentcolor"
aria-hidden="true"
>
<path
d="M21,5c-1.11-0.35-2.33-0.5-3.5-0.5c-1.95,0-4.05,0.4-5.5,1.5c-1.45-1.1-3.55-1.5-5.5-1.5S2.45,4.9,1,6v14.65 c0,0.25,0.25,0.5,0.5,0.5c0.1,0,0.15-0.05,0.25-0.05C3.1,20.45,5.05,20,6.5,20c1.95,0,4.05,0.4,5.5,1.5c1.35-0.85,3.8-1.5,5.5-1.5 c1.65,0,3.35,0.3,4.75,1.05c0.1,0.05,0.15,0.05,0.25,0.05c0.25,0,0.5-0.25,0.5-0.5V6C22.4,5.55,21.75,5.25,21,5z M21,18.5 c-1.1-0.35-2.3-0.5-3.5-0.5c-1.7,0-4.15,0.65-5.5,1.5V8c1.35-0.85,3.8-1.5,5.5-1.5c1.2,0,2.4,0.15,3.5,0.5V18.5z"
Expand Down Expand Up @@ -152,7 +154,9 @@ export class LitDevDrawer extends LitElement {

<litdev-ripple-icon-button
id="openCloseButton"
aria-label="Open or close examples drawer"
label="Examples drawer"
.expanded=${this.open ? 'true' : 'false'}
controls="content"
@click=${this._onClickToggleButton}
>
${this.open ? closeIcon : bookIcon}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {LitDevPlaygroundShareButton} from './litdev-playground-share-button
import type {LitDevPlaygroundDownloadButton} from './litdev-playground-download-button.js';
import type {LitDevDrawer} from './litdev-drawer.js';
import type {LitDevExampleControls} from './litdev-example-controls.js';
import type {LitDevRippleIconButton} from './litdev-ripple-icon-button.js';
import type {PlaygroundProject} from 'playground-elements/playground-project.js';
import type {PlaygroundPreview} from 'playground-elements/playground-preview.js';
import type {PlaygroundFileEditor} from 'playground-elements/playground-file-editor.js';
Expand Down Expand Up @@ -115,7 +116,9 @@ export class LitDevPlaygroundPage extends LitElement {
firstUpdated(changed: PropertyValues<this>) {
super.firstUpdated(changed);
// toggle previewFullscreen when the fullscreen button is clicked
const iconButton = this.querySelector('#view-mode-button');
const iconButton = this.querySelector(
'#view-mode-button'
) as LitDevRippleIconButton | null;
iconButton?.addEventListener('click', () => {
const lastMode = this.viewMode;
if (lastMode === 'split') {
Expand All @@ -126,6 +129,7 @@ export class LitDevPlaygroundPage extends LitElement {
this.viewMode = 'split';
}
});
this._syncViewModeButton();
}

update(changed: PropertyValues<this>) {
Expand Down Expand Up @@ -161,6 +165,31 @@ export class LitDevPlaygroundPage extends LitElement {
super.update(changed);
}

updated(changed: PropertyValues<this>) {
if (changed.has('viewMode')) {
this._syncViewModeButton();
}
super.updated(changed);
}

private _syncViewModeButton() {
const button = this.querySelector(
'#view-mode-button'
) as LitDevRippleIconButton | null;
if (!button) {
return;
}

const label =
this.viewMode === 'split'
? 'Show preview only'
: this.viewMode === 'preview'
? 'Show code only'
: 'Show split view';
button.label = label;
button.buttonTitle = label;
}

/**
* When the code editor is changed, store that there are unsaved changes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,35 @@ import {customElement, property} from 'lit/decorators.js';
@customElement('litdev-ripple-icon-button')
export class LitDevRippleIconButton extends LitElement {
/**
* Aria label for the button.
* Accessible label for the button.
*/
@property()
label = '';

/**
* Sets aria-live for the button.
*/
@property({type: String})
live = '';

/**
* Aria label for the button.
* Tooltip text for the button.
*/
@property({attribute: 'button-title'})
buttonTitle = '';

/**
* Aria haspopup for the button.
* ARIA pressed state for toggle buttons.
*/
@property()
haspopup = '';
@property({attribute: false})
pressed?: boolean;

/**
* Aria expanded for the button.
* ARIA expanded state for disclosure buttons.
*/
@property()
expanded = '';
expanded: '' | 'true' | 'false' = '';

/**
* Aria controls for the button.
* ID of the element controlled by a disclosure button.
*/
@property()
controls = '';

/**
* Sets the role for the inner button.
*/
@property({attribute: 'button-role'})
buttonRole = '';

/**
* Href for the link button. If defined, this component switches to using an
* anchor element instead of a button.
Expand Down Expand Up @@ -105,7 +93,13 @@ export class LitDevRippleIconButton extends LitElement {
-webkit-tap-highlight-color: transparent;
}

.root:disabled {
.root:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}

.root:disabled,
.root[aria-disabled='true'] {
cursor: default;
pointer-events: none;
opacity: 0.38;
Expand Down Expand Up @@ -160,17 +154,33 @@ export class LitDevRippleIconButton extends LitElement {
return this.href ? this.renderAnchorRoot() : this.renderButtonRoot();
}

protected override firstUpdated() {
// Lit hydration adopts server attributes without patching client-only
// state, so reconcile ARIA state once after the initial hydration pass.
const button = this.renderRoot.querySelector('button');
if (this.pressed !== undefined) {
button?.setAttribute('aria-pressed', String(this.pressed));
}
if (this.expanded) {
button?.setAttribute('aria-expanded', this.expanded);
}
if (this.controls) {
button?.setAttribute('aria-controls', this.controls);
}
}

protected renderButtonRoot() {
return html`
<button
type="button"
class="root"
part="root button"
role=${this.buttonRole ? this.buttonRole : nothing}
aria-live=${this.live ? this.live : nothing}
aria-label=${this.label ? this.label : nothing}
aria-haspopup=${this.haspopup ? this.haspopup : nothing}
aria-expanded=${this.expanded ? this.expanded : nothing}
aria-controls=${this.controls ? this.controls : nothing}
aria-pressed=${this.pressed === undefined
? nothing
: String(this.pressed)}
aria-expanded=${this.expanded || nothing}
aria-controls=${this.controls || nothing}
?disabled=${this.disabled}
title=${this.buttonTitle ?? (nothing as unknown as string)}
>
Expand All @@ -184,9 +194,13 @@ export class LitDevRippleIconButton extends LitElement {
<a
class="root"
part="root anchor"
href=${this.href}
href=${this.disabled ? nothing : this.href}
role=${this.disabled ? 'link' : nothing}
aria-label=${this.label ? this.label : nothing}
?disabled=${this.disabled}
aria-disabled=${this.disabled ? 'true' : nothing}
tabindex=${this.disabled ? '-1' : nothing}
title=${this.buttonTitle || nothing}
@click=${this._handleAnchorClick}
>
${this.renderContent()}
</a>
Expand All @@ -197,4 +211,11 @@ export class LitDevRippleIconButton extends LitElement {
return html`<div id="ripple"></div>
<slot></slot>`;
}

private _handleAnchorClick(event: MouseEvent) {
if (this.disabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
}
}
8 changes: 3 additions & 5 deletions packages/lit-dev-content/src/components/litdev-tutorial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,9 @@ export class LitDevTutorial extends LitElement {
protected renderHeader() {
return html`<div id="tutorialHeader">
<div class="lhs">
<a href="/tutorials/" tabindex="-1">
<litdev-ripple-icon-button label="Tutorial Catalog">
${catalogIcon}
</litdev-ripple-icon-button>
</a>
<litdev-ripple-icon-button label="Tutorial Catalog" href="/tutorials/">
${catalogIcon}
</litdev-ripple-icon-button>
<span class="tutorial-metadata">
${this._manifestTask.render({
complete: (manifest) => html` <span class="tutorial-title"
Expand Down
Loading
Loading