UI styling, main workspace layout (#119)

This commit is contained in:
Danny McGee
2024-04-05 20:15:09 -04:00
committed by GitHub
parent c5a0250d9f
commit bfc638b644
57 changed files with 2004 additions and 694 deletions
+36 -9
View File
@@ -1,13 +1,15 @@
@use "sass:math";
:host {
display: inline-flex;
align-items: center;
align-items: baseline;
gap: 0.75rem;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
font: {
family: "Fira Sans", sans-serif;
size: 15px;
size: math.div(15, 16) * 1rem;
weight: 500;
}
line-height: 1.5;
@@ -16,9 +18,8 @@
cursor: pointer;
user-select: none;
background: var(--background-color, #0006);
color: #FFFC;
backdrop-filter: blur(16px);
background: var(--neutral-200);
color: #FFF;
transition: {
property: background, color;
duration: 0.1s;
@@ -26,11 +27,20 @@
}
}
:host(:hover) {
background: #0008;
color: #FFFF;
:host(.icon-only) {
padding-inline: 0.5rem;
}
:host(:hover) {
background: var(--neutral-250);
}
:host(.primary) { background: var(--color-accent) }
:host(.primary:hover) { background: var(--color-accent-hover) }
:host(.secondary) { background: var(--neutral-400) }
:host(.secondary:hover) { background: var(--neutral-450) }
:host(.disabled),
:host(.disabled:hover) {
background: #0003;
@@ -38,6 +48,23 @@
cursor: default;
}
.icon {
.icon, .dropdown-icon {
align-self: center;
fill: currentColor;
}
.dropdown-icon {
font-size: 0.75rem;
}
.keybind {
// margin-inline-start: auto;
flex: 1 0 0;
margin-inline-start: 2.25rem;
color: rgba(#FFF, 0.75);
font: {
size: 0.875rem;
weight: 400;
}
text-align: end;
}
+51 -11
View File
@@ -1,6 +1,7 @@
import { on } from "@storyteller/framework";
import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import { customElement, property, state } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import styles from "./button.element.scss?inline";
@@ -16,11 +17,33 @@ export class ButtonElement extends LitElement {
@property() icon?: string;
@property({ type: Boolean }) disabled = false;
@property({ type: Boolean })
primary?: boolean;
@property({ type: Boolean }) primary?: boolean;
@property({ type: Boolean }) secondary?: boolean;
@property({ type: Boolean }) dropdown?: boolean;
@property() keybind?: string;
@property({ reflect: true, type: Number })
override tabIndex = 0;
@state() _hasSlottedContent = false;
#defaultSlotRef = createRef<HTMLSlotElement>();
_checkForSlotContent(): void {
const nodes = this.#defaultSlotRef.value?.assignedNodes() ?? [];
this._hasSlottedContent = (
nodes.length > 0
&& nodes.some(node => Boolean(node.textContent?.trim()))
);
}
override connectedCallback(): void {
super.connectedCallback();
this._checkForSlotContent();
}
protected override update(changes: PropertyValues<this>): void {
if (changes.has("disabled")) {
this.ariaDisabled = this.disabled ? "true" : null;
@@ -28,13 +51,14 @@ export class ButtonElement extends LitElement {
this.classList.toggle("disabled", this.disabled);
}
if (changes.has("primary")) {
if (this.primary) {
this.style.setProperty("--background-color", "var(--color-accent)");
} else {
this.style.removeProperty("--background-color");
}
}
if (changes.has("primary"))
this.classList.toggle("primary", Boolean(this.primary));
if (changes.has("secondary"))
this.classList.toggle("secondary", Boolean(this.secondary))
if (changes.has("_hasSlottedContent"))
this.classList.toggle("icon-only", !this._hasSlottedContent);
super.update(changes);
}
@@ -50,11 +74,27 @@ export class ButtonElement extends LitElement {
protected override render = () => html`
${this.icon ? html`
<sts-icon
class="icon"
part="icon"
icon=${this.icon}
aria-hidden="true"
></sts-icon>
` : nothing}
<slot></slot>
<slot
${ref(this.#defaultSlotRef)}
@slotchange=${this._checkForSlotContent}
></slot>
${this.keybind ? html`
<span class="keybind">${this.keybind}</span>
` : nothing}
${this.dropdown ? html`
<sts-icon
class="dropdown-icon"
part="dropdown-icon"
icon="chevron-down"
></sts-icon>
` : nothing}
`
}
+7 -1
View File
@@ -1,6 +1,6 @@
import { deref, inject } from "@storyteller/framework";
import { type ArrayOrSingle, asArray, exists } from "@storyteller/utility";
import { LitElement, TemplateResult, type PropertyValues } from "lit";
import { LitElement, TemplateResult, type PropertyValues, css } from "lit";
import { html, unsafeStatic } from "lit/static-html.js";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
@@ -86,6 +86,12 @@ import { type DialogBaseElement } from "./dialog-base.element";
*/
@customElement("sts-dialog")
export class DialogElement extends LitElement {
static override styles = css`
:host {
display: none;
}
`;
/**
* Tag-name of a custom element inheriting from {@linkcode DialogBaseElement}`
*/
+2 -1
View File
@@ -1,3 +1,4 @@
export * from "./form-field-base.element";
export * from "./text-field.element";
export * from "./scalar-field.element";
export * from "./select";
export * from "./text-field.element";
+5
View File
@@ -0,0 +1,5 @@
import "./radio-group.element";
import "./radio.element";
export * from "./radio-group.element";
export * from "./radio.element";
@@ -0,0 +1,4 @@
:host {
display: flex;
gap: 0.25rem;
}
@@ -0,0 +1,61 @@
import { on } from "@storyteller/framework";
import { PropertyValues, html, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import { FormFieldBaseElement } from "../form-field-base.element";
import { RadioElement } from "./radio.element";
import styles from "./radio-group.element.scss?inline";
@customElement("sts-radio-group")
export class RadioGroupElement extends FormFieldBaseElement {
static override styles = unsafeCSS(styles);
@property({ reflect: true })
override role = "radiogroup";
@property({ attribute: false })
value?: any;
#slotRef = createRef<HTMLSlotElement>();
override connectedCallback(): void {
super.connectedCallback();
this.#checkValue();
}
protected override update(changes: PropertyValues<this>): void {
if (changes.has("value"))
this.#checkValue();
super.update(changes);
}
@on("click", { capture: true })
onClick(event: PointerEvent): void {
if (event.target instanceof RadioElement) {
this.dispatchEvent(new CustomEvent("value-change", {
detail: event.target.value,
}));
}
}
#checkValue(): void {
for (let node of this.#slotRef.value?.assignedElements() ?? []) {
if (node instanceof RadioElement) {
node.checked = node.value != null && node.value === this.value;
if (node.checked)
this.internals.ariaValueText = node.textContent;
}
}
}
protected override render = () => html`
<slot
${ref(this.#slotRef)}
@slotchange=${this.#checkValue}
></slot>
`;
}
@@ -0,0 +1,30 @@
:host {
position: relative;
padding: 0.5rem;
border-radius: 0.5rem;
color: #FFF;
outline: transparent 2px solid;
transition: {
property: background, outline-color;
duration: 100ms;
timing-function: linear;
}
cursor: pointer;
}
::slotted(*) {
pointer-events: none;
}
:host(:hover) {
background: var(--neutral-250);
}
:host(.checked) {
outline-color: var(--color-accent);
}
:host(.checked:hover) {
background: var(--color-accent-fade);
}
@@ -0,0 +1,29 @@
import { LitElement, PropertyValues, html, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import styles from "./radio.element.scss?inline";
@customElement("sts-radio")
export class RadioElement extends LitElement {
static override styles = unsafeCSS(styles);
@property({ reflect: true })
override role = "radio";
@property({ attribute: false })
value?: any;
@property({ type: Boolean })
checked = false;
protected override update(changes: PropertyValues<this>): void {
if (changes.has("checked"))
this.classList.toggle("checked", this.checked);
super.update(changes);
}
protected override render = () => html`
<slot></slot>
`;
}
@@ -4,28 +4,33 @@
box-sizing: border-box;
display: block;
padding: 0.5rem 0.75rem;
border-radius: 0.25rem;
border-radius: 0.5rem;
background: var(--neutral-200);
border: 1px solid transparent;
color: #FFF;
outline: transparent 2px solid {
offset: -2px;
}
background: #0004;
border: 1px solid #FFF2;
color: #FFFC;
outline: none !important;
transition: {
property: background-color, border-color, color;
duration: 33.333ms;
property: background-color, outline-color;
duration: 100ms;
timing-function: linear;
}
font: {
family: "Fira Sans", sans-serif;
size: math.div(15, 16) * 1rem;
size: math.div(14, 16) * 1rem;
weight: 500;
}
line-height: 1;
white-space: nowrap;
}
:host(:focus-within) {
border-color: #FFF4;
background: #0006;
color: #FFFF;
outline-color: var(--color-accent);
background: var(--neutral-100)
}
:host(:not(.editing)) {
@@ -45,4 +50,8 @@
&:first-line {
display: inline-block;
}
&::selection {
background: var(--neutral-300);
}
}
+5
View File
@@ -0,0 +1,5 @@
import "./select.element";
import "./option.element";
export * from "./select.element";
export * from "./option.element";
@@ -0,0 +1,7 @@
:host {
padding: 0.375rem 0;
border-radius: 0.5rem;
background: var(--neutral-350);
transition: background 100ms linear;
overflow: hidden;
}
@@ -0,0 +1,16 @@
import { LitElement, html, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import styles from "./listbox.element.scss?inline";
@customElement("sts-listbox")
export class ListboxElement extends LitElement {
static override styles = unsafeCSS(styles);
@property({ reflect: true })
override role = "listbox";
protected override render = () => html`
<slot></slot>
`;
}
@@ -0,0 +1,28 @@
@use "sass:math";
:host {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
color: #FFF;
transition: background 100ms linear;
cursor: pointer;
user-select: none;
font-size: math.div(15, 16) * 1rem;
line-height: 1;
}
:host(:hover) {
background: rgba(#FFF, 0.1);
}
:host(.selected) {
background: var(--neutral-200);
}
::slotted(*) {
pointer-events: none;
}
@@ -0,0 +1,35 @@
import { LitElement, PropertyValues, html, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import styles from "./option.element.scss?inline";
@customElement("sts-option")
export class OptionElement extends LitElement {
static override styles = unsafeCSS(styles);
@property({ reflect: true })
override role = "option";
@property({ attribute: false })
value?: any;
@property({ type: Boolean })
selected?: boolean;
protected override update(changes: PropertyValues<this>): void {
if (changes.has("selected")) {
this.classList.toggle("selected", this.selected);
if (this.selected)
this.setAttribute("aria-selected", "true")
else
this.removeAttribute("aria-selected");
}
super.update(changes);
}
protected override render = () => html`
<slot></slot>
`;
}
@@ -0,0 +1,40 @@
@use "sass:math";
:host {
padding: 0.5rem;
background: var(--neutral-350);
color: #FFF;
transition: {
property: background;
duration: 100ms;
timing-function: linear;
}
user-select: none;
cursor: pointer;
font-size: math.div(15, 16) * 1rem;
line-height: 1;
}
:host(:hover) {
background: var(--neutral-400);
}
.selected {
display: flex;
align-items: center;
gap: 0.75rem;
sts-option {
padding: 0;
}
}
.dropdown-icon {
font-size: 0.75rem;
}
.hidden {
display: none;
}
@@ -0,0 +1,148 @@
import { inject, on } from "@storyteller/framework";
import { PropertyValues, html, nothing, unsafeCSS } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import { styleMap } from "lit/directives/style-map.js";
import {
OVERLAY_PROVIDER,
OverlayHandle,
type OverlayProvider,
} from "../../overlay-provider.element";
import { FormFieldBaseElement } from "../form-field-base.element";
import { OptionElement } from "./option.element";
import "./listbox.element";
import styles from "./select.element.scss?inline";
@customElement("sts-select")
export class SelectElement extends FormFieldBaseElement {
static override styles = unsafeCSS(styles);
@property({ reflect: true })
override role = "combobox";
@property({ attribute: false })
value?: any;
@property()
placeholder?: string;
@property({ type: Number, reflect: true })
override tabIndex = 0;
@inject(OVERLAY_PROVIDER)
_overlay!: OverlayProvider
@state() _selected?: OptionElement;
#slotRef = createRef<HTMLSlotElement>();
#overlayHandle?: WeakRef<OverlayHandle>;
get #selectedOption() {
return this.#slotRef.value
?.assignedNodes()
.find((node: Node): node is OptionElement => (
node.nodeType === Node.ELEMENT_NODE
&& node instanceof OptionElement
&& node.value === this.value
));
}
override connectedCallback(): void {
super.connectedCallback();
this.#checkValue();
}
protected override update(changes: PropertyValues<this>): void {
if (changes.has("value"))
this.#checkValue();
super.update(changes);
}
@on("click")
onClick(): void {
const nodes = this.#slotRef.value
?.assignedNodes()
.map(node => {
const cloned = node.cloneNode(true);
if (
cloned.nodeType === Node.ELEMENT_NODE
&& cloned instanceof OptionElement
) {
cloned.value = (node as OptionElement).value;
cloned.selected = cloned.value === this.value;
}
return cloned;
});
const rect = this.getBoundingClientRect();
this.#overlayHandle = this._overlay.attach(this, html`
<sts-listbox
style=${styleMap({
position: "absolute",
top: `${rect.bottom + 4}px`,
left: `${rect.left}px`,
minWidth: `${rect.width}px`,
})}
@click=${this.onListboxClick}
>
${nodes ?? nothing}
</sts-listbox>
`, {
onBackdropClick: () => this.#close(),
});
}
onListboxClick(event: PointerEvent): void {
if (event.target instanceof OptionElement) {
this.dispatchEvent(new CustomEvent("value-change", {
detail: event.target.value,
}));
this.#close();
}
}
#checkValue(): void {
const cloned = this.#selectedOption?.cloneNode(true) as OptionElement | undefined;
if (cloned) {
this.internals.ariaValueText = cloned.textContent;
cloned.removeAttribute("role");
cloned.style.setProperty("pointer-events", "none");
this._selected = cloned;
}
}
#close(): void {
if (!this.#overlayHandle) return;
this._overlay.detach(this.#overlayHandle);
this.#overlayHandle = undefined;
}
protected override render = () => html`
<div class="selected">
${this._selected ?? html`
<div class="placeholder">
${this.placeholder ?? nothing}
</div>
`}
<sts-icon
class="dropdown-icon"
icon="chevron-down"
></sts-icon>
</div>
<div class="hidden">
<slot
${ref(this.#slotRef)}
@slotchange=${this.#checkValue}
></slot>
</div>
`;
}
+45 -35
View File
@@ -4,13 +4,12 @@ import { LitElement, TemplateResult, html, nothing, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import { unsafeSVG } from "lit/directives/unsafe-svg.js";
import farCrosshairs from "@fortawesome/fontawesome-pro/svgs/regular/crosshairs.svg?raw";
import farVideo from "@fortawesome/fontawesome-pro/svgs/regular/video.svg?raw";
import fasCrosshairs from "@fortawesome/fontawesome-pro/svgs/solid/crosshairs.svg?raw";
import fasVideo from "@fortawesome/fontawesome-pro/svgs/solid/video.svg?raw";
import fasCircleQuestion from "@fortawesome/fontawesome-pro/svgs/solid/circle-question.svg?raw";
import fasKey from "@fortawesome/fontawesome-pro/svgs/solid/key.svg?raw";
import farCube from "@fortawesome/fontawesome-pro/svgs/regular/cube.svg?raw";
import farGlobe from "@fortawesome/fontawesome-pro/svgs/regular/globe.svg?raw";
import farUpDownLeftRight from "@fortawesome/fontawesome-pro/svgs/regular/arrows-up-down-left-right.svg?raw";
import fasGlobe from "@fortawesome/fontawesome-pro/svgs/solid/globe.svg?raw";
import fasUpDownLeftRight from "@fortawesome/fontawesome-pro/svgs/solid/arrows-up-down-left-right.svg?raw";
import fasPlay from "@fortawesome/fontawesome-pro/svgs/solid/play.svg?raw";
import fasPause from "@fortawesome/fontawesome-pro/svgs/solid/pause.svg?raw";
import fasFwdStep from "@fortawesome/fontawesome-pro/svgs/solid/forward-step.svg?raw";
@@ -18,12 +17,12 @@ import fasFwdFast from "@fortawesome/fontawesome-pro/svgs/solid/forward-fast.svg
import fasBwdStep from "@fortawesome/fontawesome-pro/svgs/solid/backward-step.svg?raw";
import fasBwdFast from "@fortawesome/fontawesome-pro/svgs/solid/backward-fast.svg?raw";
import fasQuestion from "@fortawesome/fontawesome-pro/svgs/solid/question.svg?raw";
import farRotate from "@fortawesome/fontawesome-pro/svgs/regular/arrows-rotate.svg?raw";
import farScale from "@fortawesome/fontawesome-pro/svgs/regular/arrow-up-right-and-arrow-down-left-from-center.svg?raw";
import fasRotate from "@fortawesome/fontawesome-pro/svgs/solid/arrows-rotate.svg?raw";
import fasScale from "@fortawesome/fontawesome-pro/svgs/solid/arrow-up-right-and-arrow-down-left-from-center.svg?raw";
import fasCaretRight from "@fortawesome/fontawesome-pro/svgs/solid/caret-right.svg?raw";
import fasFloppyDisk from "@fortawesome/fontawesome-pro/svgs/solid/floppy-disk.svg?raw";
import farSkeleton from "@fortawesome/fontawesome-pro/svgs/regular/skeleton.svg?raw";
import farBone from "@fortawesome/fontawesome-pro/svgs/regular/bone.svg?raw";
import fasSkeleton from "@fortawesome/fontawesome-pro/svgs/regular/skeleton.svg?raw";
import fasBone from "@fortawesome/fontawesome-pro/svgs/regular/bone.svg?raw";
import fasBrightness from "@fortawesome/fontawesome-pro/svgs/solid/brightness.svg?raw";
import fasCheck from "@fortawesome/fontawesome-pro/svgs/solid/check.svg?raw";
import fasXmark from "@fortawesome/fontawesome-pro/svgs/solid/xmark.svg?raw";
@@ -33,23 +32,29 @@ import fasMinus from "@fortawesome/fontawesome-pro/svgs/solid/minus.svg?raw";
import fasListTree from "@fortawesome/fontawesome-pro/svgs/solid/list-tree.svg?raw";
import fasBars from "@fortawesome/fontawesome-pro/svgs/solid/bars.svg?raw";
import fasPlusLarge from "@fortawesome/fontawesome-pro/svgs/solid/plus-large.svg?raw";
import farFileImport from "@fortawesome/fontawesome-pro/svgs/regular/file-import.svg?raw";
import farPhotoFilmMusic from "@fortawesome/fontawesome-pro/svgs/regular/photo-film-music.svg?raw";
import fasFileImport from "@fortawesome/fontawesome-pro/svgs/regular/file-import.svg?raw";
import fasPhotoFilmMusic from "@fortawesome/fontawesome-pro/svgs/regular/photo-film-music.svg?raw";
import fasChevronDown from "@fortawesome/fontawesome-pro/svgs/solid/chevron-down.svg?raw";
import farVolume from "@fortawesome/fontawesome-pro/svgs/regular/volume.svg?raw";
import farFilm from "@fortawesome/fontawesome-pro/svgs/regular/film.svg?raw";
import fasVolume from "@fortawesome/fontawesome-pro/svgs/regular/volume.svg?raw";
import fasFilm from "@fortawesome/fontawesome-pro/svgs/regular/film.svg?raw";
import fasPersonRunning from "@fortawesome/fontawesome-pro/svgs/solid/person-running.svg?raw";
import farMountainSun from "@fortawesome/fontawesome-pro/svgs/regular/mountain-sun.svg?raw";
import farArrowRightToBracket from "@fortawesome/fontawesome-pro/svgs/regular/arrow-right-to-bracket.svg?raw";
import farMagnifyingGlass from "@fortawesome/fontawesome-pro/svgs/regular/magnifying-glass.svg?raw";
import fasMountainSun from "@fortawesome/fontawesome-pro/svgs/regular/mountain-sun.svg?raw";
import fasArrowRightToBracket from "@fortawesome/fontawesome-pro/svgs/regular/arrow-right-to-bracket.svg?raw";
import fasMagnifyingGlass from "@fortawesome/fontawesome-pro/svgs/regular/magnifying-glass.svg?raw";
import fasHouse from "@fortawesome/fontawesome-pro/svgs/solid/house.svg?raw";
import fasRecord from "@fortawesome/fontawesome-pro/svgs/solid/circle.svg?raw";
import fasUpload from "@fortawesome/fontawesome-pro/svgs/solid/upload.svg?raw";
import fasFilms from "@fortawesome/fontawesome-pro/svgs/solid/films.svg?raw";
import fasFile from "@fortawesome/fontawesome-pro/svgs/solid/file.svg?raw";
import fasTrash from "@fortawesome/fontawesome-pro/svgs/solid/trash.svg?raw";
import fasRightLeft from "@fortawesome/fontawesome-pro/svgs/solid/right-left.svg?raw";
import fasChevronRight from "@fortawesome/fontawesome-pro/svgs/solid/chevron-right.svg?raw";
import customCylinder from "../assets/icons/cylinder.svg?raw";
import customSphere from "../assets/icons/sphere.svg?raw";
import customTorus from "../assets/icons/torus.svg?raw";
import customCube from "../assets/icons/cube-solid.svg?raw";
import customCylinder from "../assets/icons/cylinder-solid.svg?raw";
import customSphere from "../assets/icons/sphere-solid.svg?raw";
import customTorus from "../assets/icons/torus-solid.svg?raw";
import customXformLocal from "../assets/icons/xform-local.svg?raw";
import styles from "./icon.element.scss?inline";
@@ -77,49 +82,54 @@ function renderSvg(iconId: string) {
const svgSrc = match (iconId, {
"bars": () => fasBars,
"bone": () => farBone,
"bone": () => fasBone,
"bwd-fast": () => fasBwdFast,
"bwd-step": () => fasBwdStep,
"caret-right": () => fasCaretRight,
"check": () => fasCheck,
"chevron-down": () => fasChevronDown,
"chevron-right": () => fasChevronRight,
"circle-check": () => fasCircleCheck,
"circle-question": () => fasCircleQuestion,
"circle-xmark": () => fasCircleXmark,
"crosshairs": () => farCrosshairs,
"cube": () => farCube,
"crosshairs": () => fasCrosshairs,
"cube": () => customCube,
"cylinder": () => customCylinder,
"figure": () => fasPersonRunning,
"file-import": () => farFileImport,
"film": () => farFilm,
"file": () => fasFile,
"file-import": () => fasFileImport,
"film": () => fasFilm,
"films": () => fasFilms,
"floppy-disk": () => fasFloppyDisk,
"fwd-fast": () => fasFwdFast,
"fwd-step": () => fasFwdStep,
"home": () => fasHouse,
"import": () => farArrowRightToBracket,
"import": () => fasArrowRightToBracket,
"key": () => fasKey,
"light": () => fasBrightness,
"list-tree": () => fasListTree,
"minus": () => fasMinus,
"globe": () => farGlobe,
"photo-film-music": () => farPhotoFilmMusic,
"globe": () => fasGlobe,
"photo-film-music": () => fasPhotoFilmMusic,
"play": () => fasPlay,
"pause": () => fasPause,
"plus-large": () => fasPlusLarge,
"question": () => fasQuestion,
"record": () => fasRecord,
"rotate": () => farRotate,
"scale": () => farScale,
"scene": () => farMountainSun,
"search": () => farMagnifyingGlass,
"skeleton": () => farSkeleton,
"rotate": () => fasRotate,
"scale": () => fasScale,
"scene": () => fasMountainSun,
"search": () => fasMagnifyingGlass,
"skeleton": () => fasSkeleton,
"sphere": () => customSphere,
"swap": () => fasRightLeft,
"trash": () => fasTrash,
"torus": () => customTorus,
"up-down-left-right": () => farUpDownLeftRight,
"up-down-left-right": () => fasUpDownLeftRight,
"upload": () => fasUpload,
"video": () => farVideo,
"volume": () => farVolume,
"video": () => fasVideo,
"volume": () => fasVolume,
"xform-local": () => customXformLocal,
"xmark": () => fasXmark,
_: () => null,
});
+3 -10
View File
@@ -5,24 +5,17 @@
padding: 0.5rem 0;
min-width: 220px;
background: #0006;
backdrop-filter: blur(16px);
background: var(--neutral-200);
overflow: hidden;
}
::slotted(sts-button) {
background: unset;
backdrop-filter: unset;
border-radius: unset;
}
::slotted(sts-button:hover) {
background: #0004;
// FIXME: https://github.com/w3c/csswg-drafts/issues/3896
&::part(icon) {
opacity: 0.75;
}
background: var(--neutral-300);
}
::slotted(hr) {
@@ -31,5 +24,5 @@
border: none;
height: 1px;
margin: 0.5rem 0;
background: #FFF1;
background: rgba(#FFF, 0.1);
}
+1 -1
View File
@@ -60,7 +60,7 @@ import panelStyles from "./menu.element.scss?inline";
export class MenuElement extends LitElement {
static override styles = css`
:host {
visibility: hidden;
display: none;
}
`;
+2 -16
View File
@@ -1,22 +1,8 @@
:host {
display: flex;
gap: 2px;
gap: 0.25rem;
}
::slotted(*) {
border-radius: var(--corner-radius);
}
::slotted(:first-child) {
border: {
top-left-radius: 8px;
bottom-left-radius: 8px;
}
}
::slotted(:last-child) {
border: {
top-right-radius: 8px;
bottom-right-radius: 8px;
}
border-radius: 0.5rem;
}
+13 -1
View File
@@ -1,4 +1,16 @@
:host {
display: flex;
gap: 16px;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
border-radius: 0.5rem;
background: var(--neutral-200);
}
::slotted(hr) {
display: block;
width: 2px;
height: 1.125rem;
border: none;
background: rgba(#FFF, 0.1);
}
+4 -18
View File
@@ -1,5 +1,5 @@
import { type DynamicProvider, inject, UniqueToken } from "@storyteller/framework";
import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit";
import { type DynamicProvider, inject, UniqueToken, observe } from "@storyteller/framework";
import { LitElement, html, nothing, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
@@ -34,23 +34,9 @@ export class TreeElement extends LitElement {
return !!this.id && this._selectionProvider?.selectedId === this.id
}
@observe(["selectedId"])
@inject(TREE_SELECTION_PROVIDER)
_selectionProvider?: TreeSelectionProvider;
override connectedCallback(): void {
this._selectionProvider?.addEventListener("property-changes", this.onProviderChanges);
super.connectedCallback();
}
override disconnectedCallback(): void {
this._selectionProvider?.removeEventListener("property-changes", this.onProviderChanges);
super.disconnectedCallback();
}
onProviderChanges = ({ detail: changes }: CustomEvent<PropertyValues<TreeSelectionProvider>>) => {
if (changes.has("selectedId"))
this.requestUpdate();
}
_selectionProvider!: TreeSelectionProvider;
toggleExpanded(): void {
this.expanded = !this.expanded;