summaryrefslogtreecommitdiff
path: root/apps/web/src/components/toolbar
diff options
context:
space:
mode:
authorJosh Kingsley <josh@joshkingsley.me>2025-11-24 15:46:22 +0200
committerJosh Kingsley <josh@joshkingsley.me>2025-11-24 15:46:22 +0200
commitd724cc0bf6ff6d351319e6fb00f5184a04e16ac0 (patch)
treecb43253479df5db8f4844e17e68a48ea5a212df4 /apps/web/src/components/toolbar
parent7c966e105cd9f65853de1aba0ecce63aa56aca0b (diff)
chore: improve dev tasks
Diffstat (limited to 'apps/web/src/components/toolbar')
-rw-r--r--apps/web/src/components/toolbar/index.css48
-rw-r--r--apps/web/src/components/toolbar/index.ts70
2 files changed, 118 insertions, 0 deletions
diff --git a/apps/web/src/components/toolbar/index.css b/apps/web/src/components/toolbar/index.css
new file mode 100644
index 0000000..653c326
--- /dev/null
+++ b/apps/web/src/components/toolbar/index.css
@@ -0,0 +1,48 @@
+@layer components {
+ ntv-toolbar {
+ display: flex;
+ border-radius: 99999px;
+ background: var(--color-neutral-900);
+ width: min-content;
+ }
+
+ ntv-toolbar > section {
+ display: flex;
+ gap: 0.25rem;
+ padding: 0.325rem;
+ }
+
+ ntv-toolbar button {
+ border-radius: 99999px;
+ background: var(--color-neutral-800);
+ padding: 0 0.5rem;
+ height: 1.25rem;
+ color: white;
+ font-weight: 600;
+ font-size: 0.75rem;
+ }
+
+ ntv-toolbar button:hover {
+ background: var(--color-green-400);
+ color: var(--color-neutral-900);
+ }
+
+ ntv-toolbar button[data-icon] {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ aspect-ratio: 1;
+ height: 1.25rem;
+ }
+
+ ntv-toolbar input {
+ border: 1px solid var(--color-neutral-700);
+ border-radius: 4px;
+ background: var(--color-neutral-900);
+ width: 2.5rem;
+ height: 1.25rem;
+ color: white;
+ font-size: 0.75rem;
+ text-align: center;
+ }
+}
diff --git a/apps/web/src/components/toolbar/index.ts b/apps/web/src/components/toolbar/index.ts
new file mode 100644
index 0000000..b8a383d
--- /dev/null
+++ b/apps/web/src/components/toolbar/index.ts
@@ -0,0 +1,70 @@
+import NotiveElement, { customElement, eventHandler } from "../../element";
+import h from "../../html";
+import { minus16Icon, plus16Icon } from "../icons";
+import "./index.css";
+
+export class SubdivisionsChangeEvent extends Event {
+ static readonly TYPE = "ntv:toolbar:subdivisionschange";
+
+ constructor(public subdivisions: number | undefined) {
+ super(SubdivisionsChangeEvent.TYPE);
+ }
+}
+
+@customElement("ntv-toolbar")
+class NotiveToolbarElement extends NotiveElement {
+ #subdivisionsInputEl: HTMLInputElement = h.input({
+ title: "Subdivisions",
+ disabled: true,
+ });
+
+ get subdivisions(): number | undefined {
+ if (this.#subdivisionsInputEl.value === "") return;
+ return parseInt(this.#subdivisionsInputEl.value);
+ }
+
+ set subdivisions(n: number | undefined) {
+ const m = n && Math.max(n, 1);
+ this.#subdivisionsInputEl.value = m === undefined ? "" : m.toString();
+ }
+
+ @eventHandler(SubdivisionsChangeEvent.TYPE)
+ onsubdivisionschange?: (event: SubdivisionsChangeEvent) => any;
+
+ connectedCallback() {
+ this.append(
+ h.section(
+ h.button(
+ {
+ dataset: { icon: "" },
+ onclick: () => {
+ if (!this.subdivisions) return;
+ this.subdivisions = this.subdivisions - 1;
+ this.dispatchEvent(
+ new SubdivisionsChangeEvent(this.subdivisions),
+ );
+ },
+ },
+ h.span(minus16Icon()),
+ ),
+ this.#subdivisionsInputEl,
+ h.button(
+ {
+ dataset: { icon: "" },
+ onclick: () => {
+ if (!this.subdivisions) return;
+ this.subdivisions = this.subdivisions + 1;
+ this.dispatchEvent(
+ new SubdivisionsChangeEvent(this.subdivisions),
+ );
+ },
+ },
+ h.span(plus16Icon()),
+ ),
+ ),
+ h.section(h.button("Play")),
+ );
+ }
+}
+
+export default NotiveToolbarElement.makeFactory();