From f466f55ff5313aa98c7a41c0db2456e7399c1437 Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Tue, 17 Oct 2023 23:20:11 -0400 Subject: [PATCH] Add kc-ui-focus-overlay --- src/kc-ui/focus-overlay.ts | 121 +++++++++++++++++++++++++++++++++++++ src/kc-ui/index.ts | 1 + src/kc-ui/kc-ui.css | 4 ++ 3 files changed, 126 insertions(+) create mode 100644 src/kc-ui/focus-overlay.ts diff --git a/src/kc-ui/focus-overlay.ts b/src/kc-ui/focus-overlay.ts new file mode 100644 index 00000000..82718437 --- /dev/null +++ b/src/kc-ui/focus-overlay.ts @@ -0,0 +1,121 @@ +/* + Copyright (c) 2023 Alethea Katherine Flowers. + Published under the standard MIT License. + Full text available at: https://opensource.org/licenses/MIT +*/ + +import { listen } from "../base/events"; +import { css, html } from "../base/web-components"; +import { KCUIElement } from "./element"; + +/** + * kc-ui-focus-overlay is an element that shows an overlay over its siblings + * until the user clicks within. + */ +export class KCUIFocusOverlay extends KCUIElement { + static override styles = [ + ...KCUIElement.styles, + css` + :host { + z-index: 10; + user-select: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + pointer-events: initial; + background: transparent; + contain: paint; + } + + :host(.has-focus) { + z-index: -10; + pointer-events: none; + } + + .bg { + background: var(--focus-overlay-bg); + opacity: 0; + transition: opacity var(--transition-time-short); + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + } + + :host(:hover) .bg { + opacity: var(--focus-overlay-opacity); + } + + :host(.has-focus) .bg { + opacity: 0; + } + + .fg { + position: absolute; + font-size: 1.5rem; + color: var(--focus-overlay-fg); + text-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px; + opacity: 0; + pointer-events: none; + } + + :host(:hover) .fg { + opacity: 1; + } + + :host(.has-focus) .fg { + opacity: 0; + } + `, + ]; + + #intersection_observer: IntersectionObserver; + + override initialContentCallback(): void | undefined { + this.addEventListener("click", () => { + this.classList.add("has-focus"); + }); + + this.addDisposable( + listen(document, "click", (e) => { + const outside = !e.composedPath().includes(this.parentElement!); + if (outside) { + this.classList.remove("has-focus"); + } + }), + ); + + this.#intersection_observer = new IntersectionObserver((entries) => { + for (const entry of entries) { + console.log(entry); + if (!entry.isIntersecting) { + this.classList.remove("has-focus"); + } + } + }); + + this.#intersection_observer.observe(this); + + this.addDisposable({ + dispose: () => { + this.#intersection_observer.disconnect(); + }, + }); + } + + override render() { + return html` +
+
Click or tap to interact
+ `; + } +} + +window.customElements.define("kc-ui-focus-overlay", KCUIFocusOverlay); diff --git a/src/kc-ui/index.ts b/src/kc-ui/index.ts index 22e64e0d..654ea504 100644 --- a/src/kc-ui/index.ts +++ b/src/kc-ui/index.ts @@ -12,6 +12,7 @@ export * from "./dropdown"; export * from "./element"; export * from "./filtered-list"; export * from "./floating-toolbar"; +export * from "./focus-overlay"; export * from "./icon"; export * from "./menu"; export * from "./panel"; diff --git a/src/kc-ui/kc-ui.css b/src/kc-ui/kc-ui.css index bb5cafde..69d9fb09 100644 --- a/src/kc-ui/kc-ui.css +++ b/src/kc-ui/kc-ui.css @@ -200,6 +200,10 @@ --list-item-hover-bg: var(--gradient-purple-green-highlight); --list-item-active-bg: var(--gradient-cyan-blue-light); + + --focus-overlay-bg: var(--gradient-purple-green-light); + --focus-overlay-opacity: 0.5; + --focus-overlay-fg: #f8f8f0; } /*