aboutsummaryrefslogtreecommitdiff
path: root/static/widgets/search
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-11-13 14:56:02 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2025-11-13 14:56:02 +0100
commitc7b02f02ad0a7e2888f2d7d3599719e59bbd1ee2 (patch)
tree9f782daf2e2ff78559958f15e0b9ffe5ece78334 /static/widgets/search
parent7ee9d320e6ba9a84542d838892c43cf98b268552 (diff)
frontend: design prototype
Diffstat (limited to 'static/widgets/search')
-rw-r--r--static/widgets/search/index.css50
-rw-r--r--static/widgets/search/index.js67
2 files changed, 117 insertions, 0 deletions
diff --git a/static/widgets/search/index.css b/static/widgets/search/index.css
new file mode 100644
index 0000000..2bb940e
--- /dev/null
+++ b/static/widgets/search/index.css
@@ -0,0 +1,50 @@
+:host {
+ position: fixed;
+ top: 0;
+ left: 0;
+}
+
+#container {
+ position: fixed;
+ top: -200px;
+ left: 5px;
+ right: 5px;
+ height: 100px;
+ background: #fff9;
+ backdrop-filter: blur(10px);
+ border-radius: var(--border-radius);
+ transition: top 0.1s ease;
+ padding: 10px;
+ display: grid;
+ gap: 10px;
+ box-shadow: var(--shadow);
+}
+
+#container.visible {
+ top: 5px;
+}
+
+#title {
+ font-size: 1.2em;
+ align-content: center;
+ padding-left: 5px;
+ user-select: none;
+}
+
+#search-box {
+ width: 100%;
+ display: grid;
+ grid-template-columns: auto 50px;
+}
+
+input {
+ border-top-right-radius: 0px !important;
+ border-bottom-right-radius: 0px !important;
+}
+
+button {
+ width: 50px;
+ border-top-left-radius: 0px !important;
+ border-bottom-left-radius: 0px !important;
+ height: 42px;
+}
diff --git a/static/widgets/search/index.js b/static/widgets/search/index.js
new file mode 100644
index 0000000..324141b
--- /dev/null
+++ b/static/widgets/search/index.js
@@ -0,0 +1,67 @@
+import * as sfw from 'sfw';
+const { Div, Input, Button } = sfw.element.native;
+
+import icons from '../../icons/index.js';
+
+const css = await sfw.css(import.meta.url, './index.css');
+
+export default class Search extends sfw.element.Container {
+ #container
+ #search
+
+ constructor() {
+ super({ css });
+
+ this.onsubmit = () => {}
+ this.onhide = () => {}
+
+ this.onclick = (e) => e.stopPropagation();
+ this.hide = () => {
+ this.#container.classList.remove('visible');
+ document.removeEventListener('click', this.hide);
+ this.onhide();
+ };
+
+ this.body.append(
+ this.#container = Div.new({
+ id: 'container',
+ children: [
+ Div.new({ innerText: 'Search', id: 'title' }),
+ Div.new({
+ id: 'search-box',
+ children: [
+ this.#search = Input.new({
+ type: 'search',
+ onsearch: () => this.submit(),
+ onkeydown: (event) => {
+ if (event.key === 'Enter') {
+ this.submit();
+ }
+ }
+ }),
+ Button.new({
+ children: [ icons.search ],
+ onclick: () => this.submit(),
+ }),
+ ]
+ })
+ ]
+ })
+ );
+ }
+
+ submit() {
+ this.onsubmit(this.#search.value);
+ this.#search.blur();
+ this.hide();
+ }
+
+ toggle() {
+ this.#container.classList.toggle('visible');
+
+ if (this.#container.classList.contains('visible')) {
+ this.#search.focus()
+ document.addEventListener('click', this.hide)
+ }
+ }
+}