diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-11-13 14:56:02 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-11-13 14:56:02 +0100 |
| commit | c7b02f02ad0a7e2888f2d7d3599719e59bbd1ee2 (patch) | |
| tree | 9f782daf2e2ff78559958f15e0b9ffe5ece78334 /static/widgets/editable | |
| parent | 7ee9d320e6ba9a84542d838892c43cf98b268552 (diff) | |
frontend: design prototype
Diffstat (limited to 'static/widgets/editable')
| -rw-r--r-- | static/widgets/editable/index.css | 36 | ||||
| -rw-r--r-- | static/widgets/editable/index.js | 65 |
2 files changed, 101 insertions, 0 deletions
diff --git a/static/widgets/editable/index.css b/static/widgets/editable/index.css new file mode 100644 index 0000000..b474370 --- /dev/null +++ b/static/widgets/editable/index.css @@ -0,0 +1,36 @@ + +#container { + width: 100%; + background: var(--card-background); + box-shadow: var(--shadow); + border-radius: var(--border-radius); + display: grid; + grid-template-columns: min-content auto min-content; +} + +#container label { + user-select: none; + font-weight: bold; + background: var(--primary); + color: var(--fg-primary); + align-content: center; + padding: 10px; + border-top-left-radius: var(--border-radius); + border-bottom-left-radius: var(--border-radius); +} + +#container input { + background: var(--card-background); + user-select: none; + font-size: 1em; +} + +#container input:read-only { + caret-color: transparent; +} + +#edit { + width: 35px; + padding: 10px; + cursor: pointer; +} diff --git a/static/widgets/editable/index.js b/static/widgets/editable/index.js new file mode 100644 index 0000000..8a72aff --- /dev/null +++ b/static/widgets/editable/index.js @@ -0,0 +1,65 @@ +import * as sfw from 'sfw'; +const { Div, Label, Input } = sfw.element.native; + +import icons from '../../icons/index.js'; + +const css = await sfw.css(import.meta.url, './index.css'); + +export default class Editable extends sfw.element.Container { + #label + #input + #edit + + constructor() { + super({ css }); + + this.body.append( + Div.new({ + id: 'container', + children: [ + this.#label = Label.new({ htmlFor: 'input' }), + this.#input = Input.new({ + readOnly: true, + onkeydown: (e) => { + if (e.key === 'Enter') { + this.#input.readOnly = true; + this.#update() + } + }, + }), + this.#edit = Div.new({ + id: 'edit', + children: [ icons.edit ], + onclick: () => { + this.#input.readOnly = !this.#input.readOnly; + this.#update(); + } + }), + ], + }) + ); + } + + #update() { + this.#edit.innerHTML = ''; + this.#edit.append( + this.#input.readOnly ? icons.edit : icons.check + ); + + if (!this.#input.readOnly) { + this.#input.select(); + } + } + + set title(value) { + this.#label.innerText = value; + } + + set value(value) { + this.#input.value = value; + } + + set type(type) { + this.#input.type = type; + } +} |