Skip to content

Commit

Permalink
Merge pull request #5275 from material-components:stories-page
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 590302109
  • Loading branch information
copybara-github committed Dec 12, 2023
2 parents 27d3541 + 4f4792a commit 8e75343
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 28 deletions.
3 changes: 2 additions & 1 deletion catalog/eleventy-helpers/shortcodes/playground-example.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function playgroundExample(eleventyConfig) {
<md-icon aria-hidden="true">expand_more</md-icon>
<md-icon aria-hidden="true" slot="selected">expand_less</md-icon>
</md-outlined-icon-button>
Expand interactive demo.
View interactive demo inline.
</summary>
<lit-island on:visible import="/js/hydration-entrypoints/playground-elements.js" class="example" aria-hidden="true">
<playground-project
Expand All @@ -68,6 +68,7 @@ function playgroundExample(eleventyConfig) {
><md-circular-progress indeterminate></md-circular-progress></playground-file-editor>
</lit-island>
</details>
<p><a href="./stories/" target="_blank">Open interactive demo in new tab.</a></p>
`;
});
}
Expand Down
34 changes: 34 additions & 0 deletions catalog/site/css/stories.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

#dragbar {
max-width: 100%;
max-height: 100%;
}

#editor {
margin-block: 0;
height: 100%;
box-sizing: border-box;
}

#editor-wrapper {
height: 100%;
overflow: hidden;
}

body {
height: 100dvh;
}

#preview {
position: relative;
}

#preview md-circular-progress {
inset: 50%;
transform: translate(-50%, -50%);
}
1 change: 1 addition & 0 deletions catalog/site/css/syntax-highlight.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

/* Formats the code boxes themselves */
.example playground-file-editor,
playground-file-editor,
pre[class*='language-'] {
padding: var(--__code-block-font-size);
/* Remove the extra hard coded 3px from line number padding. */
Expand Down
97 changes: 97 additions & 0 deletions catalog/site/stories/stories.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---js
{
pagination: {
data: "collections.component",
size: 1,
alias: "component",
before: components => {
// remove any components that don't have a dirname
return components.filter(component => component.data.dirname)
}
},
permalink: "components/{{component.data.page.fileSlug}}/stories/index.html",
fullHeightContent: "true",
collections: ["stories"],
eleventyComputed: {
dirname: ({component}) => component.data.dirname,
}
}
---

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"
/>
<title>Material Web - Stories {{component.data.name}}</title>
<!-- Set the color of the url bar on mobile to match theme -->
<meta name="theme-color" content="#251f16" />
<link
href="/images/favicon.svg"
rel="icon"
sizes="any"
type="image/svg+xml"
/>
<!-- Inlines the global css in site/css/global.css -->
{% inlinecss "global.css" %}
<!-- MUST be loaded before any lit bundle. allows hydration of SSRd components -->
<script type="module" src="/js/ssr-utils/lit-hydrate-support.js"></script>
<!-- Inlines the material theming logic since we want to prevent FOUC -->
{% inlinejs "inline/apply-saved-theme.js" %}
<!-- Needed for intializing theme if this is the first page they ever visit -->
<script type="module" src="/js/pages/global.js"></script>
<noscript>
<link rel="stylesheet" href="/css/no-js.css" />
</noscript>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap"
/>
<!-- If JS is disabled just show the contents without the polyfill -->
<noscript
><style>
body[dsd-pending] {
display: block !important;
}
</style>
</noscript>
<!-- Syncs theme with playground -->
<script type="module" src="/js/pages/components.js"></script>
<script type="module" src="/js/pages/stories.js"></script>
<script
type="module"
src="/js/hydration-entrypoints/playground-elements.js"
></script>
<link rel="stylesheet" href="/css/syntax-highlight.css" />
<link rel="stylesheet" href="/css/stories.css" />
</head>
<!-- dsd-pending hides body until the polyfill has run on browsers that do not support DSD -->
<body dsd-pending>
<!-- Inlines the declarative shadow dom polyfill for FF since it's performance sensitive -->
{% inlinejs "ssr-utils/dsd-polyfill.js" %}
<playground-project
id="project"
project-src="/assets/stories/{{dirname}}/project.json"
>
</playground-project>
<drag-playground id="dragbar">
<playground-preview id="preview" project="project" slot="preview">
<md-circular-progress indeterminate></md-circular-progress>
</playground-preview>
<div slot="editor" id="editor-wrapper">
<playground-file-editor
id="editor"
project="project"
filename="stories.ts"
line-numbers
aria-hidden="true"
>
<md-circular-progress indeterminate></md-circular-progress>
</playground-file-editor>
</div>
</drag-playground>
</body>
</html>
216 changes: 216 additions & 0 deletions catalog/src/components/drag-playground.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/


import { LitElement, css, html } from 'lit';
import { customElement, state, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { styleMap } from 'lit/directives/style-map.js';
import '@material/web/icon/icon.js';

/**
* A playground preview + editor with a draggable handle.
*/
@customElement('drag-playground')
export class DragPlayground extends LitElement {
static styles = css`
:host {
display: block;
--_drag-bar-height: 24px;
--_drag-bar-border-width: 1px;
--_half-drag-bar-height: calc(
(var(--_drag-bar-height) / 2) + var(--_drag-bar-border-width)
);
}
#wrapper {
display: flex;
flex-direction: column;
}
:host,
#wrapper,
::slotted(*) {
height: 100%;
}
slot {
display: block;
overflow: hidden;
}
[name='preview'] {
height: max(
calc(
100% - var(--editor-percentage, 0%) - var(--_half-drag-bar-height)
),
0px
);
}
[name='editor'] {
height: max(
calc(var(--editor-percentage, 0px) - var(--_half-drag-bar-height)),
0px
);
}
#drag-bar {
touch-action: none;
background-color: var(--md-sys-color-surface-container);
color: var(--md-sys-color-on-surface);
border: var(--_drag-bar-border-width) solid var(--md-sys-color-outline);
border-radius: 12px;
height: var(--_drag-bar-height);
display: flex;
justify-content: center;
align-items: center;
-webkit-user-select: none;
user-select: none;
}
#drag-bar:hover {
background-color: var(--md-sys-color-surface-container-high);
cursor: grab;
}
#drag-bar.isDragging {
background-color: var(--md-sys-color-inverse-surface);
color: var(--md-sys-color-inverse-on-surface);
cursor: grabbing;
}
`;

/**
* Whether or not we are in the "dragging" state.
*/
@state() private isDragging = false;

/**
* The percentage of the editor height.
*/
@state() private editorHeightPercent = 0;

@query('#wrapper') private wrapperEl!: HTMLElement;

/**
* A set of pointer IDs in the case that the user is dragging with multiple
* pointers.
*/
private pointerIds = new Set<number>();

render() {
return html`<div
id="wrapper"
style=${styleMap({
'--editor-percentage': `${this.editorHeightPercent}%`,
})}
>
<slot name="preview"></slot>
<div
id="drag-bar"
tabindex="0"
role="slider"
aria-orientation="vertical"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="${this.editorHeightPercent}"
aria-valuetext="${this.editorHeightPercent} percent"
aria-label="Editor height"
@focus=${this.onFocus}
@blur=${this.onBlur}
@keydown=${this.onKeydown}
@pointerdown=${this.onPointerdown}
@pointerup=${this.onPointerup}
@pointermove=${this.onPointermove}
class=${classMap({
isDragging: this.isDragging,
})}
>
<md-icon>drag_handle</md-icon>
</div>
<slot name="editor"></slot>
</div>`;
}

private onFocus() {
this.isDragging = true;
}

private onBlur() {
this.isDragging = false;
}

private onKeydown(event: KeyboardEvent) {
const { key } = event;
switch (key) {
case 'ArrowRight':
case 'ArrowUp':
this.editorHeightPercent = Math.min(this.editorHeightPercent + 1, 100);
break;
case 'ArrowLeft':
case 'ArrowDown':
this.editorHeightPercent = Math.max(this.editorHeightPercent - 1, 0);
break;
case 'PageUp':
this.editorHeightPercent = Math.min(this.editorHeightPercent + 10, 100);
break;
case 'PageDown':
this.editorHeightPercent = Math.max(this.editorHeightPercent - 10, 0);
break;
case 'Home':
this.editorHeightPercent = 0;
break;
case 'End':
this.editorHeightPercent = 100;
break;
default:
break;
}
}

private onPointerdown(event: PointerEvent) {
this.isDragging = true;

if (this.pointerIds.has(event.pointerId)) return;

this.pointerIds.add(event.pointerId);
(event.target as HTMLElement).setPointerCapture(event.pointerId);
}

private onPointerup(event: PointerEvent) {
this.pointerIds.delete(event.pointerId);
(event.target as HTMLElement).releasePointerCapture(event.pointerId);

if (this.pointerIds.size === 0) {
this.isDragging = false;
}
}

private onPointermove(event: PointerEvent) {
if (!this.isDragging) return;

const { clientY: mouseY } = event;
const { top: wrapperTop, bottom: wrapperBottom } =
this.wrapperEl.getBoundingClientRect();

// The height of the wrapper
const height = wrapperBottom - wrapperTop;

// Calculate the percentage of the editor height in which the pointer is
// located
const editorHeightPercent = 100 - ((mouseY - wrapperTop) / height) * 100;

// Clamp the percentage between 0 and 100
this.editorHeightPercent = Math.min(Math.max(editorHeightPercent, 0), 100);
}
}

declare global {
interface HTMLElementTagNameMap {
'drag-playground': DragPlayground;
}
}
7 changes: 7 additions & 0 deletions catalog/src/pages/stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import '../components/drag-playground.js';
1 change: 1 addition & 0 deletions catalog/src/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ import './components/catalog-component-header-title.js';
import './components/nav-drawer.js';
import './components/theme-changer.js';
import './components/top-app-bar.js';
import './components/drag-playground.js';
// 🤫
import '@material/web/labs/item/item.js';
Loading

0 comments on commit 8e75343

Please sign in to comment.