Skip to content

Commit

Permalink
feat(ui): custom dropdown el
Browse files Browse the repository at this point in the history
- using web components api
  • Loading branch information
EGRrqq committed Feb 6, 2024
1 parent 0236eda commit 7be29b9
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 141 deletions.
74 changes: 39 additions & 35 deletions src/index.html
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Little Notes</title>
</head>

<body>
<!-- good opportunity to practice web components -->
<article class="menu">
<button class="menu__item--onTop" id="menu__toggle-btn">M</button>

<section class="menu__item--onTop menu-dropdown--isClosed" id="menu-dropdown" data-is-open="false"
aria-hidden="true">
<button id="menu-dropdown__open">open</button>
<button id="menu-dropdown__save">save to</button>
<hr class="menu-dropdown__divider">
<button id="menu-dropdown__clear">clear canvas</button>
</section>
</article>

<article class="tool-settings">
<section class="tool-settings__item--onTop" id="tool-settings-dropdown">
<input type="color">
<input type="range">

<div>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Little Notes</title>
</head>

<body>
<canvas-dropdown isopen="false">
<span slot="dropdown__btn-text">M</span>

<button id="menu__open" slot="dropdown__section-el">open</button>
<button id="menu__save" slot="dropdown__section-el">save to</button>
<hr class="menu__divider" slot="dropdown__section-el" />
<button id="menu__clear" slot="dropdown__section-el">clear canvas</button>
</canvas-dropdown>

<canvas-dropdown id="settings-dropdown" isopen="false">
<span slot="dropdown__btn-text">S</span>

<input slot="dropdown__section-el" type="color" />
<input slot="dropdown__section-el" type="range" />

<div slot="dropdown__section-el">
<label for="line-cap">line cap:</label>
<select name="line-cap" id="line-cap">
<option value="butt">Butt</option>
Expand All @@ -36,19 +32,27 @@
</select>
</div>

<div>
<div slot="dropdown__section-el">
<label for="line-join">line join:</label>
<select name="line-join" id="line-join">
<option value="bevel">Bevel</option>
<option value="miter">Miter</option>
<option value="round">Round</option>
</select>
</div>
</section>
</article>
</canvas-dropdown>

<template id="dropdown">
<button id="dropdown__btn">
<slot name="dropdown__btn-text">toggle btn</slot>
</button>

<canvas id="board"></canvas>
<script type="module" src="/index.ts"></script>
</body>
<section id="dropdown__section">
<slot name="dropdown__section-el"></slot>
</section>
</template>

<canvas id="board"></canvas>
<script type="module" src="/index.ts"></script>
</body>
</html>
11 changes: 2 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,18 @@ import { Pen, ToolsController } from "./canvasController/tools";
import { CacheController } from "./canvasController/canvasData/cache";
import {
clearBtnController,
dropdownController,
openBtnController,
saveBtnController,
switchBtnController,
} from "./uiController";
import { loadData, saveData } from "./canvasController/canvasData/manipulate";
import { formatDate } from "./canvasController/helpers";
import { WindowData } from "./canvasController/windowData/windowDataController";
import { Dropdown } from "./uiController/menu";

const board = document.getElementById("board") as HTMLCanvasElement;
const boardController = new CanvasController(board);
const windowData = new WindowData();

const toggleClass = "menu-dropdown--isClosed";

if (boardController.ctx) {
// available tools
const pen = new Pen(boardController.ctx);
Expand Down Expand Up @@ -66,11 +63,7 @@ if (boardController.ctx) {

// ui setup
function uiSetup() {
switchBtnController.onClick(() => {
dropdownController.toggleIsOpen();
dropdownController.toggleClass(toggleClass);
dropdownController.toggleAriaHidden();
});
customElements.define("canvas-dropdown", Dropdown);

saveBtnController.onClick(() => {
const curDate = formatDate(new Date());
Expand Down
27 changes: 2 additions & 25 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,40 +41,17 @@ button:hover {
box-shadow: inset 0 0 20px 20px rgba(0, 0, 0, 0.1);
}

.menu,
.tool-settings {
position: absolute;

margin: var(--content-padding);
}

.tool-settings {
#settings-dropdown {
bottom: 0;
}

.menu__item--onTop,
.tool-settings__item--onTop {
position: relative;
z-index: 1;
}

#menu-dropdown {
display: grid;

margin-top: calc(var(--content-padding) / 2);
}

#tool-settings-dropdown {
display: grid;
gap: 1rem;

background-color: white;
}

.menu-dropdown--isClosed {
display: none !important;
}

.menu-dropdown__divider {
.menu__divider {
border: solid;
}
16 changes: 3 additions & 13 deletions src/uiController/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
import { UiBtnController } from "./UiBtnController";
import { DropdownController } from "./menu";

const switchBtn = document.getElementById(
"menu__toggle-btn"
) as HTMLButtonElement;

const openBtn = document.getElementById(
"menu-dropdown__open"
"menu__open"
) as HTMLButtonElement;

const saveBtn = document.getElementById(
"menu-dropdown__save"
"menu__save"
) as HTMLButtonElement;

const clearBtn = document.getElementById(
"menu-dropdown__clear"
"menu__clear"
) as HTMLButtonElement;

const dropdown = document.getElementById("menu-dropdown") as HTMLElement;

export const switchBtnController = new UiBtnController(switchBtn);

export const dropdownController = new DropdownController(dropdown);
export const openBtnController = new UiBtnController(openBtn);
export const saveBtnController = new UiBtnController(saveBtn);
export const clearBtnController = new UiBtnController(clearBtn);
110 changes: 110 additions & 0 deletions src/uiController/menu/Dropdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
interface ICustomElement {
_internals: ElementInternals;

connectedCallback: () => void;
disconnectedCallback: () => void;
adoptedCallback: () => void;
attributeChangedCallback: (
name: observedAttributes,
oldValue: string,
newValue: string
) => void;
}

type observedAttributes = "isopen";

export class Dropdown extends HTMLElement implements Partial<ICustomElement> {
static observedAttributes: observedAttributes[] = ["isopen"];

constructor() {
super();
}

connectedCallback() {
const shadow = this.attachShadow({ mode: "open" });
const template = document.getElementById("dropdown") as HTMLTemplateElement;

const style = new CSSStyleSheet();
style.replaceSync(`
:host {
position: absolute;
margin: var(--content-padding) !important;
}
#dropdown__section {
display: grid;
margin-top: calc(var(--content-padding) / 2);
}
.dropdown--onTop {
position: relative;
z-index: 1;
}
.dropdown--isClosed {
display: none !important;
}
`);

shadow.appendChild(template?.content.cloneNode(true));
shadow.adoptedStyleSheets = [style];

this.dropdownBtn.classList.add("dropdown--onTop");
this.dropdownBtn.addEventListener("click", this.toggleIsOpen);

this.dropdownSection.classList.add("dropdown--onTop");
this.dropdownSection.classList.add("dropdown--isClosed");
this.dropdownSection.ariaHidden = "true";
}

attributeChangedCallback(
//@ts-ignore
name: observedAttributes,
oldValue: string,
newValue: string
): void {
if (!oldValue) return;

switch (newValue) {
case "true":
this.dropdownSection.classList.remove("dropdown--isClosed");
this.dropdownSection.ariaHidden = "false";
break;
case "false":
this.dropdownSection.classList.add("dropdown--isClosed");
this.dropdownSection.ariaHidden = "true";
break;
default:
break;
}
}

disconnectedCallback() {
this.dropdownBtn.removeEventListener("click", this.toggleIsOpen);
}

toggleIsOpen = () => {
switch (this.getAttribute("isopen")) {
case "true":
this.setAttribute("isopen", "false");
break;
case "false":
this.setAttribute("isopen", "true");
break;
default:
break;
}
};

get dropdownBtn() {
return this.shadowRoot?.getElementById(
"dropdown__btn"
) as HTMLButtonElement;
}

get dropdownSection() {
return this.shadowRoot?.getElementById("dropdown__section") as HTMLElement;
}
}
58 changes: 0 additions & 58 deletions src/uiController/menu/dropdown.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/uiController/menu/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { DropdownController } from "./dropdown";
export { Dropdown } from "./Dropdown";

0 comments on commit 7be29b9

Please sign in to comment.