Theming
The same widget wearing four design systems — variables only, no stylesheet fork.
<div class="demo demo--wide">
<div class="demo-seg" role="tablist" id="brands">
<button type="button" data-brand="devix" class="is-active">Devix</button>
<button type="button" data-brand="shadcn">shadcn</button>
<button type="button" data-brand="bootstrap">Bootstrap</button>
<button type="button" data-brand="material">Material</button>
</div>
<div class="demo-field" id="field">
<label class="demo-label" for="assignee">Assignee</label>
<select id="assignee" name="assignee"></select>
</div>
<pre class="demo-out" id="css"></pre>
</div>
import { createSelect } from 'https://devix.pk/cdn/oss/select@1.0.0/index.js';
const SNIPPETS = {
devix: '/* the defaults */',
shadcn: '.dxs, .dxs-panel {\n --dxs-radius: 6px;\n --dxs-accent: #18181b;\n --dxs-option-selected: #f4f4f5;\n}',
bootstrap: '.dxs, .dxs-panel {\n --dxs-height: 38px;\n --dxs-accent: #0d6efd;\n --dxs-font-size: 15px;\n}',
material: '.dxs, .dxs-panel {\n --dxs-height: 40px;\n --dxs-radius: 4px;\n --dxs-accent: #6750a4;\n --dxs-option-height: 40px;\n}',
};
createSelect(document.getElementById('assignee'), {
options: [
{ value: 'aisha', label: 'Aisha Khan', description: 'Owner' },
{ value: 'bilal', label: 'Bilal Ahmed', description: 'Editor' },
{ value: 'chen', label: 'Chen Wei', description: 'Editor' },
{ value: 'dana', label: 'Dana Ali', description: 'Viewer' },
],
value: 'aisha',
searchable: true,
});
const field = document.getElementById('field');
const css = document.getElementById('css');
const apply = (brand) => {
// The panel is portalled into the top layer, so the brand goes on <html> as well as the field.
field.dataset.brand = brand;
document.documentElement.dataset.brand = brand;
css.textContent = SNIPPETS[brand];
};
document.getElementById('brands').addEventListener('click', (event) => {
const button = event.target.closest('button[data-brand]');
if (!button) return;
for (const other of document.querySelectorAll('#brands button')) other.classList.toggle('is-active', other === button);
apply(button.dataset.brand);
});
apply('devix');
@import url('https://devix.pk/cdn/oss/select@1.0.0/select.min.css');
/* Each brand is a handful of variables on the widget and its panel. */
[data-brand='shadcn'] {
--dxs-radius: 6px; --dxs-accent: #18181b; --dxs-option-selected: #f4f4f5;
--dxs-panel-radius: 8px; --dxs-panel-shadow: 0 8px 24px rgb(0 0 0 / .1);
}
[data-brand='bootstrap'] {
--dxs-height: 38px; --dxs-radius: 6px; --dxs-accent: #0d6efd; --dxs-font-size: 15px;
--dxs-panel-radius: 6px;
}
[data-brand='material'] {
--dxs-height: 40px; --dxs-radius: 4px; --dxs-accent: #6750a4; --dxs-panel-radius: 4px;
--dxs-option-height: 40px; --dxs-panel-shadow: 0 3px 6px rgb(0 0 0 / .16);
}