Open trusktr opened 8 months ago
Thank you for using Tweakpane!
Interesting, but currently I don't plan to use custom elements because it will prevent quick hacks like this: https://github.com/cocopon/tweakpane/issues/508
User can easily customize the pane with CSS and JS, and this would be one of the nice things of Tweakpane.
@cocopon Hello! Custom Elements are only a way to organize code, adding a declarative interface, but it would not prevent that from being possible. We would just need to think about how we would want to expose the customization.
quick hacks like this: https://github.com/cocopon/tweakpane/issues/508
If you have any more samples, paste here for reference, so we can think about them.
It can purposefully be designed to be extendable. For example:
<tweak-pane>
<tweak-number name="count" value="10" min="0" max="100">
<button class="my-reset-button" slot="suffix"></button>
</tweak-number>
</tweak-pane>
Or similar. That's equivalent of the above hack
Plus, we can leave all ShadowRoots open, so full control by JS is still possible as before.
const myButton = document.createElement('button')
// DOM is fully accessible.
tweakpaneElement.shadowRoot
.querySelector('.some-element')
.append(myButton)
And for example, we can also make sure the JS API is fully exposed:
<tweak-pane id="one"></tweak-pane>
<script type="module">
import {Pane} from 'tweakpane'
const tweakElement = document.querySelector('#one')
const tweakpane = tweakElement.pane
console.log(tweakpane instanceof Pane) // true
</script>
etc
User can easily customize the pane with CSS and JS
There are various ways to allow CSS overrides for full control:
import {addStyle} from 'tweakpane'
addStyle(`.foo {color: red}`)
const sheet = new CSSStyleSheet()
sheet.replaceSync(`.bar {color: blue}`)
addStyle(sheet)
addStyle(new URL('./path/to/foo.css', import.meta.url))
tweak-pane { --folder-header-color: pink; }
<div part="header">...</div>
and then user can style:
<tweak-pane id="myPane"></tweak-pane>
<style>
#myPane::part(header) {
color: cyan
}
</style>
All elements could accept a stylesheet
attribute/property that accepts CSS string, CSSStyleSheet, or URL to a stylesheet
stylesheet
documentation further below).this is nice because it allows a variety of ways to style the whole tweakpane instance. Not just in plain HTML, but via JS f.e.
const sheet = new CSSStyleSheet();
sheet.replaceSync(`...`)
// plain JS varieties:
tweakpaneElement.stylesheet = `.foo {color: deeppink}`
tweakpaneElement.stylesheet = document.querySelector('link#tweakpane-style') // <link> element
tweakpaneElement.stylesheet = document.querySelector('style#tweakpane-style') // <style> element
tweakpaneElement.stylesheet = sheet
// Or in any declarative framework such as React JSX, Vue, Svelte, etc:
return <tweak-pane stylesheet={`.lorem {background: purple}`}>...</tweak-pane>
return <tweak-pane stylesheet={linkElement}>...</tweak-pane>
return <tweak-pane stylesheet={styleElement}>...</tweak-pane>
return <tweak-pane stylesheet={sheet}>...</tweak-pane>
The stylesheet can apply to all elements used within a tweak-pane element (i.e. global for that instance). So it would be possible to have two panes with different themes, for example:
<tweak-pane id="paneOne">...</tweak-pane>
<tweak-pane id="paneTwo">...</tweak-pane>
<script>
paneOne.stylesheet = new URL('./path/to/tweakpane-theme-1.css', location.href)
paneTwo.stylesheet = new URL('./path/to/tweakpane-theme-2.css', location.href)
</script>
Basically we can totally do it, without blocking style, without blocking JS hacks, etc, but making it be fully compatible with web dev's favorite frameworks, allowing them to control tweakpane easily with reactive-declarative paradigms.
A popular example in the wild is Shoelace, a component library written as Custom Elements (very recently raised $700k on kickstarter!). But Shoelace is not as specialized as Tweak Pane for making parameter-heavy panels.
Hello! This lib is awesome! I've been wanting something like this, but in the form of Custom Elements, so that it can be supported no matter what project I'm working in, while staying in declarative-reactive paradigms of the current app.
Would you be interested in Tweakpan elements?
For example, based on the Number example, It could look like the following in an HTML file:
For simplicity, someone might want to integrate into HTML (or React/Vue/Solid/etc) by using only the root element, but letting it create the pane without specifying the child elements:
HTML:
Solid.js (and similar, f.e. JSX, React, Preact, etc):
Lit (with
html
template tag):etc, etc, etc.
By making a set of Custom Elements, we can automatically support all declarative-reactive frameworks.
TweakPane is already written as plain JS components, so what we would do is wrap the API in custom elements.
For example, here's what it would start to look like using Lume Element (my lib for defining Custom Elements more simply), but you can also imagine using another Custom Element lib like Lit:
Furthermore, we can provide TypeScript types for JSX type checking in Solid, React, etc. For example, here's how I hook Lume 3D elements into JSX and DOM type defs:
https://github.com/lume/lume/blob/a5ea06101174ed3f8fc165b82a76d1521ae7f5ce/src/cameras/CameraRig.ts#L425-L437
and React users can import the React type:
https://github.com/lume/lume/blob/a5ea06101174ed3f8fc165b82a76d1521ae7f5ce/src/cameras/CameraRig.react-jsx.d.ts
We can similarly hook up type defs for other systems that also rely on
JSX
(Svelte and Vue use JSX type defs for their templating even though the syntax is not JSX).Basically we can write components once, run within any declarative-reactive framework, and the only framework-specific thing we need to do is provide the type hookup for TS users.