@pokle/basecoat 0.3.10-beta2.pokle
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eleventy.js +47 -0
- package/.gitattributes +1 -0
- package/.gitignore +12 -0
- package/AGENTS.md +112 -0
- package/CONTRIBUTING.md +15 -0
- package/LICENSE.md +21 -0
- package/README.md +29 -0
- package/ROADMAP.md +20 -0
- package/docs/css/custom.css +92 -0
- package/docs/css/highlight.css +151 -0
- package/docs/css/styles.css +8 -0
- package/docs/css/themes/claude.css +95 -0
- package/docs/css/themes/doom-64.css +95 -0
- package/docs/css/themes/supabase.css +100 -0
- package/docs/src/_data/site.js +10 -0
- package/docs/src/_includes/layouts/base.njk +112 -0
- package/docs/src/_includes/layouts/layout.njk +15 -0
- package/docs/src/_includes/layouts/page.njk +21 -0
- package/docs/src/_includes/macros/code_block.njk +23 -0
- package/docs/src/_includes/macros/code_preview.njk +26 -0
- package/docs/src/_includes/macros/toc.njk +20 -0
- package/docs/src/_includes/partials/header.njk +64 -0
- package/docs/src/_includes/partials/kitchen-sink/accordion.njk +89 -0
- package/docs/src/_includes/partials/kitchen-sink/alert-dialog.njk +26 -0
- package/docs/src/_includes/partials/kitchen-sink/alert.njk +72 -0
- package/docs/src/_includes/partials/kitchen-sink/avatar.njk +37 -0
- package/docs/src/_includes/partials/kitchen-sink/badge.njk +47 -0
- package/docs/src/_includes/partials/kitchen-sink/breadcrumb.njk +42 -0
- package/docs/src/_includes/partials/kitchen-sink/button.njk +101 -0
- package/docs/src/_includes/partials/kitchen-sink/card.njk +147 -0
- package/docs/src/_includes/partials/kitchen-sink/checkbox.njk +34 -0
- package/docs/src/_includes/partials/kitchen-sink/combobox.njk +83 -0
- package/docs/src/_includes/partials/kitchen-sink/dialog.njk +65 -0
- package/docs/src/_includes/partials/kitchen-sink/dropdown-menu.njk +294 -0
- package/docs/src/_includes/partials/kitchen-sink/form.njk +106 -0
- package/docs/src/_includes/partials/kitchen-sink/input.njk +27 -0
- package/docs/src/_includes/partials/kitchen-sink/label.njk +30 -0
- package/docs/src/_includes/partials/kitchen-sink/pagination.njk +34 -0
- package/docs/src/_includes/partials/kitchen-sink/popover.njk +43 -0
- package/docs/src/_includes/partials/kitchen-sink/radio-group.njk +33 -0
- package/docs/src/_includes/partials/kitchen-sink/select.njk +99 -0
- package/docs/src/_includes/partials/kitchen-sink/skeleton.njk +40 -0
- package/docs/src/_includes/partials/kitchen-sink/slider.njk +38 -0
- package/docs/src/_includes/partials/kitchen-sink/switch.njk +27 -0
- package/docs/src/_includes/partials/kitchen-sink/table.njk +74 -0
- package/docs/src/_includes/partials/kitchen-sink/tabs.njk +105 -0
- package/docs/src/_includes/partials/kitchen-sink/textarea.njk +27 -0
- package/docs/src/_includes/partials/kitchen-sink/toast.njk +25 -0
- package/docs/src/_includes/partials/kitchen-sink/tooltip.njk +24 -0
- package/docs/src/_includes/partials/sidebar.njk +139 -0
- package/docs/src/assets/apple-touch-icon.png +0 -0
- package/docs/src/assets/favicon.svg +12 -0
- package/docs/src/assets/images/avatar-1.png +0 -0
- package/docs/src/assets/images/avatar-2.png +0 -0
- package/docs/src/assets/images/avatar-3.png +0 -0
- package/docs/src/assets/images/screenshot.png +0 -0
- package/docs/src/assets/social-screenshot.png +0 -0
- package/docs/src/assets/social.png +0 -0
- package/docs/src/assets/styles.css +6309 -0
- package/docs/src/components/accordion.njk +75 -0
- package/docs/src/components/alert-dialog.njk +119 -0
- package/docs/src/components/alert.njk +108 -0
- package/docs/src/components/avatar.njk +40 -0
- package/docs/src/components/badge.njk +93 -0
- package/docs/src/components/breadcrumb.njk +71 -0
- package/docs/src/components/button-group.njk +290 -0
- package/docs/src/components/button.njk +141 -0
- package/docs/src/components/card.njk +156 -0
- package/docs/src/components/carousel.njk +102 -0
- package/docs/src/components/chart.njk +814 -0
- package/docs/src/components/checkbox.njk +101 -0
- package/docs/src/components/combobox.njk +293 -0
- package/docs/src/components/command.njk +288 -0
- package/docs/src/components/dialog.njk +177 -0
- package/docs/src/components/dropdown-menu.njk +403 -0
- package/docs/src/components/empty.njk +157 -0
- package/docs/src/components/field.njk +459 -0
- package/docs/src/components/form.njk +79 -0
- package/docs/src/components/input-group.njk +372 -0
- package/docs/src/components/input.njk +90 -0
- package/docs/src/components/item.njk +320 -0
- package/docs/src/components/kbd.njk +76 -0
- package/docs/src/components/label.njk +41 -0
- package/docs/src/components/pagination.njk +48 -0
- package/docs/src/components/popover.njk +174 -0
- package/docs/src/components/progress.njk +44 -0
- package/docs/src/components/radio-group.njk +48 -0
- package/docs/src/components/select.njk +457 -0
- package/docs/src/components/sidebar.njk +219 -0
- package/docs/src/components/skeleton.njk +51 -0
- package/docs/src/components/slider.njk +47 -0
- package/docs/src/components/spinner.njk +214 -0
- package/docs/src/components/switch.njk +54 -0
- package/docs/src/components/table.njk +87 -0
- package/docs/src/components/tabs.njk +232 -0
- package/docs/src/components/textarea.njk +90 -0
- package/docs/src/components/theme-switcher.njk +111 -0
- package/docs/src/components/toast.njk +279 -0
- package/docs/src/components/tooltip.njk +53 -0
- package/docs/src/fragments/toast/error.njk +6 -0
- package/docs/src/fragments/toast/info.njk +5 -0
- package/docs/src/fragments/toast/success.njk +7 -0
- package/docs/src/fragments/toast/warning.njk +5 -0
- package/docs/src/index.njk +336 -0
- package/docs/src/installation.njk +275 -0
- package/docs/src/introduction.njk +63 -0
- package/docs/src/kitchen-sink.njk +52 -0
- package/docs/src/llms.txt +506 -0
- package/docs/src/robots.njk +7 -0
- package/docs/src/sitemap.njk +15 -0
- package/docs/src/test.njk +39 -0
- package/package.json +51 -0
- package/packages/cli/README.md +55 -0
- package/packages/cli/index.js +193 -0
- package/packages/cli/package.json +44 -0
- package/packages/css/README.md +63 -0
- package/packages/css/package.json +63 -0
- package/scripts/build.js +170 -0
- package/src/css/basecoat.cdn.css +2 -0
- package/src/css/basecoat.css +1310 -0
- package/src/jinja/command.html.jinja +206 -0
- package/src/jinja/dialog.html.jinja +94 -0
- package/src/jinja/dropdown-menu.html.jinja +124 -0
- package/src/jinja/popover.html.jinja +48 -0
- package/src/jinja/select.html.jinja +196 -0
- package/src/jinja/sidebar.html.jinja +144 -0
- package/src/jinja/tabs.html.jinja +78 -0
- package/src/jinja/toast.html.jinja +117 -0
- package/src/js/basecoat.js +99 -0
- package/src/js/command.js +175 -0
- package/src/js/dropdown-menu.js +171 -0
- package/src/js/popover.js +73 -0
- package/src/js/select.js +432 -0
- package/src/js/sidebar.js +104 -0
- package/src/js/tabs.js +63 -0
- package/src/js/toast.js +181 -0
- package/src/nunjucks/command.njk +206 -0
- package/src/nunjucks/dialog.njk +92 -0
- package/src/nunjucks/dropdown-menu.njk +124 -0
- package/src/nunjucks/popover.njk +48 -0
- package/src/nunjucks/select.njk +196 -0
- package/src/nunjucks/sidebar.njk +144 -0
- package/src/nunjucks/tabs.njk +78 -0
- package/src/nunjucks/toast.njk +117 -0
- package/wrangler.jsonc +7 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: layouts/page.njk
|
|
3
|
+
title: Select
|
|
4
|
+
description: Displays a list of options for the user to pick from—triggered by a button.
|
|
5
|
+
toc:
|
|
6
|
+
- label: Usage
|
|
7
|
+
id: usage
|
|
8
|
+
children:
|
|
9
|
+
- label: HTML
|
|
10
|
+
id: usage-html
|
|
11
|
+
- label: HTML + JavaScript
|
|
12
|
+
id: usage-html-js
|
|
13
|
+
children:
|
|
14
|
+
- label: "Step 1: Include the JavaScript files"
|
|
15
|
+
id: usage-html-js-1
|
|
16
|
+
- label: "Step 2: Add your select HTML"
|
|
17
|
+
id: usage-html-js-2
|
|
18
|
+
- label: HTML structure
|
|
19
|
+
id: usage-html-js-3
|
|
20
|
+
- label: JavaScript events
|
|
21
|
+
id: usage-html-js-4
|
|
22
|
+
- label: JavaScript methods
|
|
23
|
+
id: usage-html-js-5
|
|
24
|
+
- label: Jinja and Nunjucks
|
|
25
|
+
id: usage-macro
|
|
26
|
+
- label: Examples
|
|
27
|
+
id: examples
|
|
28
|
+
children:
|
|
29
|
+
- label: Scrollable
|
|
30
|
+
id: example-scrollable
|
|
31
|
+
- label: Disabled
|
|
32
|
+
id: example-disabled
|
|
33
|
+
- label: With icon
|
|
34
|
+
id: example-with-icon
|
|
35
|
+
- label: Multiple
|
|
36
|
+
id: example-multiple
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
{% from "macros/code_preview.njk" import code_preview %}
|
|
40
|
+
{% from "macros/code_block.njk" import code_block %}
|
|
41
|
+
{% from "select.njk" import select %}
|
|
42
|
+
|
|
43
|
+
{% set code_native %}<select class="select w-[180px]">
|
|
44
|
+
<optgroup label="Fruits">
|
|
45
|
+
<option>Apple</option>
|
|
46
|
+
<option>Banana</option>
|
|
47
|
+
<option>Blueberry</option>
|
|
48
|
+
<option>Grapes</option>
|
|
49
|
+
<option>Pineapple</option>
|
|
50
|
+
</optgroup>
|
|
51
|
+
</select>{% endset %}
|
|
52
|
+
{{ code_preview("select-native", code_native) }}
|
|
53
|
+
|
|
54
|
+
{% set code_html %}
|
|
55
|
+
{{ select(
|
|
56
|
+
trigger_attrs={"class": "w-[180px]"},
|
|
57
|
+
is_combobox=true,
|
|
58
|
+
multiple=true,
|
|
59
|
+
items=[
|
|
60
|
+
{
|
|
61
|
+
type: "group",
|
|
62
|
+
label: "Fruits",
|
|
63
|
+
items: [
|
|
64
|
+
{ type: "item", label: "Apple", attrs: {"data-force": "true"} },
|
|
65
|
+
{ type: "item", label: "Banana", attrs: {"data-keywords": "bread"} },
|
|
66
|
+
{ type: "item", label: "Blueberry" },
|
|
67
|
+
{ type: "item", value: "pineapple", label: "Grapes" },
|
|
68
|
+
{ type: "item", value: "pineapple", label: "Pineapple" }
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
) }}
|
|
73
|
+
{% endset %}
|
|
74
|
+
|
|
75
|
+
{% set code_script %}
|
|
76
|
+
{% endset %}
|
|
77
|
+
|
|
78
|
+
{{ code_preview("select", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
|
79
|
+
|
|
80
|
+
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
|
81
|
+
|
|
82
|
+
<h3 id="usage-html"><a href="#usage-html">HTML</a></h3>
|
|
83
|
+
|
|
84
|
+
<section class="prose">
|
|
85
|
+
<p>If you use a <code><select></code> element, just add the <code>select</code> class to it or have a parent with the <code>form</code> class (<a href="/components/form">read more about form</a>).</p>
|
|
86
|
+
</section>
|
|
87
|
+
|
|
88
|
+
{{ code_block(code_native) }}
|
|
89
|
+
|
|
90
|
+
<h3 id="usage-html-js"><a href="#usage-html-js">HTML + JavaScript</a></h3>
|
|
91
|
+
|
|
92
|
+
<h4 id="usage-html-js-1"><a href="#usage-html-js-1">Step 1: Include the JavaScript files</a></h4>
|
|
93
|
+
|
|
94
|
+
<section class="prose">
|
|
95
|
+
<p>You can either <a href="/installation/#install-cdn-all">include the JavaScript file for all the components</a>, or just the one for this component by adding this to the <code><head></code> of your page:</p>
|
|
96
|
+
</section>
|
|
97
|
+
|
|
98
|
+
{% set code_script %}<script src="https://cdn.jsdelivr.net/npm/basecoat-css@{{ pkg.version }}/dist/js/basecoat.min.js" defer></script>
|
|
99
|
+
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@{{ pkg.version }}/dist/js/select.min.js" defer></script>{% endset %}
|
|
100
|
+
{{ code_block(code_script | prettyHtml, "html") }}
|
|
101
|
+
|
|
102
|
+
<div class="flex flex-wrap gap-2 my-6">
|
|
103
|
+
<a class="badge-outline" href="/installation/#install-js">
|
|
104
|
+
Components with JavaScript
|
|
105
|
+
{% lucide "arrow-right" %}
|
|
106
|
+
</a>
|
|
107
|
+
<a class="badge-outline" href="/installation/#install-cli">
|
|
108
|
+
Use the CLI
|
|
109
|
+
{% lucide "arrow-right" %}
|
|
110
|
+
</a>
|
|
111
|
+
<a class="badge-outline" href="https://github.com/hunvreus/basecoat/blob/main/src/js/select.js" target="_blank">
|
|
112
|
+
select.js
|
|
113
|
+
{% lucide "arrow-right" %}
|
|
114
|
+
</a>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<h4 id="usage-html-js-2"><a href="#usage-html-js-2">Step 2: Add your select HTML</a></h4>
|
|
118
|
+
|
|
119
|
+
{{ code_block(code_html | prettyHtml, "html") }}
|
|
120
|
+
|
|
121
|
+
<h4 id="usage-html-js-3"><a href="#usage-html-js-3">HTML structure</a></h4>
|
|
122
|
+
|
|
123
|
+
<section class="prose">
|
|
124
|
+
<dl>
|
|
125
|
+
<dt><code class="highlight language-html"><div class="select"></code></dt>
|
|
126
|
+
<dd>
|
|
127
|
+
<p>Wraps around the entire component. Can have the following attributes:</p>
|
|
128
|
+
<ul>
|
|
129
|
+
<li><code>data-placeholder="{ TEXT }"</code> <span class="badge-secondary">Optional</span>: placeholder text shown when no options are selected (multiselect only).</li>
|
|
130
|
+
</ul>
|
|
131
|
+
<dl>
|
|
132
|
+
<dt><code class="highlight language-html"><button type="button"></code></dt>
|
|
133
|
+
<dd>
|
|
134
|
+
<p>The trigger to open the popover. Should have the following attributes:</p>
|
|
135
|
+
<ul>
|
|
136
|
+
<li><code>id="{BUTTON_ID}"</code>: linked to by the <code>aria-labelledby</code> attribute of the listbox.</li>
|
|
137
|
+
<li><code>aria-haspopup="listbox"</code>: indicates that the button opens a listbox.</li>
|
|
138
|
+
<li><code>aria-controls="{ LISTBOX_ID }"</code>: points to the listbox's id.</li>
|
|
139
|
+
<li><code>aria-expanded="false"</code>: tracks the popover's state.</li>
|
|
140
|
+
<li><code>aria-activedescendant="{ OPTION_ID }"</code> <span class="badge-secondary">Optional</span>: points to the active option's id.</li>
|
|
141
|
+
</ul>
|
|
142
|
+
</dd>
|
|
143
|
+
<dt><code class="highlight language-html"><div data-popover aria-hidden="true" id="{ POPOVER_ID }"></code></dt>
|
|
144
|
+
<dd>The popover content. You can set up the side and alignment using the <code>data-side</code> and <code>data-align</code> attributes (see <a href="/components/popover">Popover</a> component).
|
|
145
|
+
<dl>
|
|
146
|
+
<dt><code class="highlight language-html"><div role="listbox"></code></dt>
|
|
147
|
+
<dd>
|
|
148
|
+
<p>The listbox containing the options. Should have the following attributes:</p>
|
|
149
|
+
<ul>
|
|
150
|
+
<li><code>id="{ LISTBOX_ID }"</code>: refered to by the <code>aria-controls</code> attribute of the trigger.</li>
|
|
151
|
+
<li><code>aria-labelledby="{ BUTTON_ID }"</code>: linked to by the button's <code>id</code> attribute.</li>
|
|
152
|
+
<li><code>aria-multiselectable="true"</code> <span class="badge-secondary">Optional</span>: enables multiple selection mode.</li>
|
|
153
|
+
</ul>
|
|
154
|
+
<dl>
|
|
155
|
+
<dt><code class="highlight language-html"><div role="option" data-value="{ VALUE }"></code></dt>
|
|
156
|
+
<dd>
|
|
157
|
+
<p>Option that can be selected. Should have the following attributes:</p>
|
|
158
|
+
<ul>
|
|
159
|
+
<li><code>id="{ OPTION_ID }"</code> <span class="badge-secondary">Optional</span>: unique id for this option (needed if you use <code>aria-activedescendant</code> on the trigger).</li>
|
|
160
|
+
<li><code>data-value="{ VALUE }"</code>: the value for this option.</li>
|
|
161
|
+
<li><code>data-label="{ LABEL }"</code> <span class="badge-secondary">Optional</span>: the text label to use for this option when selected in multiple mode. If not provided, the option's text content will be used (HTML stripped).</li>
|
|
162
|
+
<li><code>aria-selected="true"</code> <span class="badge-secondary">Optional</span>: indicates this option is selected.</li>
|
|
163
|
+
</ul>
|
|
164
|
+
</dd>
|
|
165
|
+
<dt><code class="highlight language-html"><hr role="separator"></code> <span class="badge-secondary">Optional</span></dt>
|
|
166
|
+
<dd>Separator between groups/options.</dd>
|
|
167
|
+
<dt><code class="highlight language-html"><div role="group"></code> <span class="badge-secondary">Optional</span></dt>
|
|
168
|
+
<dd>Group of options, can have a <code>aria-labelledby</code> attribute to link to a heading.</dd>
|
|
169
|
+
<dt><code class="highlight language-html"><span role="heading"></code> <span class="badge-secondary">Optional</span></dt>
|
|
170
|
+
<dd>Group heading, must have an <code>id</code> attribute if you use the <code>aria-labelledby</code> attribute on the group.</dd>
|
|
171
|
+
</dl>
|
|
172
|
+
</dd>
|
|
173
|
+
</dl>
|
|
174
|
+
</dl>
|
|
175
|
+
</dd>
|
|
176
|
+
<dt><code class="highlight language-html"><input type="hidden" name="{ NAME }" value="{ VALUE }"></code></dt>
|
|
177
|
+
<dd>
|
|
178
|
+
<p>The hidden input that holds the selected value.</p>
|
|
179
|
+
<p>For single-select: contains the selected option's value as a string.</p>
|
|
180
|
+
<p>For multiselect: contains a <strong>JSON array</strong> of selected values (e.g., <code>["apple","banana"]</code>). When no options are selected, contains an empty array (<code>[]</code>).</p>
|
|
181
|
+
<p><strong>Backend handling:</strong> Parse the JSON value on the server side. For example:</p>
|
|
182
|
+
<ul>
|
|
183
|
+
<li><strong>Python/Flask:</strong> <code>values = json.loads(request.form.get('field', '[]'))</code></li>
|
|
184
|
+
<li><strong>PHP:</strong> <code>$values = json_decode($_POST['field'] ?? '[]', true);</code></li>
|
|
185
|
+
<li><strong>Node.js:</strong> <code>const values = JSON.parse(req.body.field || '[]');</code></li>
|
|
186
|
+
<li><strong>Ruby/Rails:</strong> <code>values = JSON.parse(params[:field] || '[]')</code></li>
|
|
187
|
+
</ul>
|
|
188
|
+
</dd>
|
|
189
|
+
</dl>
|
|
190
|
+
</section>
|
|
191
|
+
|
|
192
|
+
<h4 id="usage-html-js-4"><a href="#usage-html-js-4">JavaScript events</a></h4>
|
|
193
|
+
|
|
194
|
+
<section class="prose">
|
|
195
|
+
<dl>
|
|
196
|
+
<dt><code>basecoat:initialized</code></dt>
|
|
197
|
+
<dd>Once the component is fully initialized, it dispatches a custom (non-bubbling) <code>basecoat:initialized</code> event on itself.</dd>
|
|
198
|
+
<dt><code>basecoat:popover</code></dt>
|
|
199
|
+
<dd>When the popover opens, the component dispatches a custom (non-bubbling) <code>basecoat:popover</code> event on <code>document</code>. Other popover components (Combobox, Dropdown Menu, Popover and Select) listen for this to close any open popovers.</dd>
|
|
200
|
+
<dt><code>change</code></dt>
|
|
201
|
+
<dd>
|
|
202
|
+
<p>When the selected value changes, the component dispatches a custom (bubbling) <code>change</code> event on itself, with the selected value in <code>event.detail.value</code>:</p>
|
|
203
|
+
<ul>
|
|
204
|
+
<li>Single select: <code>{ detail: { value: "something" }}</code> (string)</li>
|
|
205
|
+
<li>Multiple select: <code>{ detail: { value: ["item1", "item2"] }}</code> (array)</li>
|
|
206
|
+
</ul>
|
|
207
|
+
</dd>
|
|
208
|
+
</dl>
|
|
209
|
+
</section>
|
|
210
|
+
|
|
211
|
+
<h4 id="usage-html-js-5"><a href="#usage-html-js-5">JavaScript methods and properties</a></h4>
|
|
212
|
+
|
|
213
|
+
<section class="prose">
|
|
214
|
+
<dl>
|
|
215
|
+
<dt><code>value</code> (property)</dt>
|
|
216
|
+
<dd>
|
|
217
|
+
<p>Get or set the current value. For single-select, this is a string. For multiselect, this is an array. The multiselect setter accepts both strings and arrays.</p>
|
|
218
|
+
|
|
219
|
+
{% set code_value %}<script>
|
|
220
|
+
const selectComponent = document.querySelector('#my-select');
|
|
221
|
+
selectComponent.addEventListener('basecoat:initialized', () => {
|
|
222
|
+
// Get value
|
|
223
|
+
console.log(selectComponent.value); // 'apple'
|
|
224
|
+
|
|
225
|
+
// Set value (single-select)
|
|
226
|
+
selectComponent.value = 'banana';
|
|
227
|
+
|
|
228
|
+
// Set value (multiselect - accepts string or array)
|
|
229
|
+
selectComponent.value = ['apple', 'banana'];
|
|
230
|
+
selectComponent.value = 'apple'; // normalized to ['apple']
|
|
231
|
+
});
|
|
232
|
+
</script>{% endset %}
|
|
233
|
+
{{ code_block(code_value | prettyHtml, "html") }}
|
|
234
|
+
</dd>
|
|
235
|
+
<dt><code>select(value)</code></dt>
|
|
236
|
+
<dd>
|
|
237
|
+
<p>Selects an option by value (i.e. the option with the matching <code>data-value</code> attribute). For single-select, this will close the popover. For multiselect, this adds the value to the selection if not already selected.</p>
|
|
238
|
+
|
|
239
|
+
{% set code_select %}<script>
|
|
240
|
+
const selectComponent = document.querySelector('#my-select');
|
|
241
|
+
selectComponent.addEventListener('basecoat:initialized', () => {
|
|
242
|
+
selectComponent.select('apple');
|
|
243
|
+
});
|
|
244
|
+
</script>{% endset %}
|
|
245
|
+
{{ code_block(code_select | prettyHtml, "html") }}
|
|
246
|
+
</dd>
|
|
247
|
+
<dt><code>deselect(value)</code> <span class="badge-secondary">Multiselect only</span></dt>
|
|
248
|
+
<dd>
|
|
249
|
+
<p>Removes a specific value from the selection. Only available when the component is in multiselect mode (<code>aria-multiselectable="true"</code>).</p>
|
|
250
|
+
|
|
251
|
+
{% set code_deselect %}<script>
|
|
252
|
+
const selectComponent = document.querySelector('#my-multiselect');
|
|
253
|
+
selectComponent.addEventListener('basecoat:initialized', () => {
|
|
254
|
+
selectComponent.deselect('apple');
|
|
255
|
+
});
|
|
256
|
+
</script>{% endset %}
|
|
257
|
+
{{ code_block(code_deselect | prettyHtml, "html") }}
|
|
258
|
+
</dd>
|
|
259
|
+
<dt><code>toggle(value)</code> <span class="badge-secondary">Multiselect only</span></dt>
|
|
260
|
+
<dd>
|
|
261
|
+
<p>Toggles a specific value in the selection (adds if not present, removes if present). Only available when the component is in multiselect mode (<code>aria-multiselectable="true"</code>).</p>
|
|
262
|
+
|
|
263
|
+
{% set code_toggle %}<script>
|
|
264
|
+
const selectComponent = document.querySelector('#my-multiselect');
|
|
265
|
+
selectComponent.addEventListener('basecoat:initialized', () => {
|
|
266
|
+
selectComponent.toggle('apple'); // adds if not selected, removes if selected
|
|
267
|
+
});
|
|
268
|
+
</script>{% endset %}
|
|
269
|
+
{{ code_block(code_toggle | prettyHtml, "html") }}
|
|
270
|
+
</dd>
|
|
271
|
+
<dt><code>selectAll()</code> <span class="badge-secondary">Multiselect only</span></dt>
|
|
272
|
+
<dd>
|
|
273
|
+
<p>Selects all available options. Only available when the component is in multiselect mode (<code>aria-multiselectable="true"</code>).</p>
|
|
274
|
+
|
|
275
|
+
{% set code_script_all %}<script>
|
|
276
|
+
const selectComponent = document.querySelector('#my-multiselect');
|
|
277
|
+
selectComponent.addEventListener('basecoat:initialized', () => {
|
|
278
|
+
selectComponent.selectAll();
|
|
279
|
+
});
|
|
280
|
+
</script>{% endset %}
|
|
281
|
+
{{ code_block(code_script_all | prettyHtml, "html") }}
|
|
282
|
+
</dd>
|
|
283
|
+
<dt><code>selectNone()</code> <span class="badge-secondary">Multiselect only</span></dt>
|
|
284
|
+
<dd>
|
|
285
|
+
<p>Deselects all options. Only available when the component is in multiselect mode (<code>aria-multiselectable="true"</code>).</p>
|
|
286
|
+
|
|
287
|
+
{% set code_script_none %}<script>
|
|
288
|
+
const selectComponent = document.querySelector('#my-multiselect');
|
|
289
|
+
selectComponent.addEventListener('basecoat:initialized', () => {
|
|
290
|
+
selectComponent.selectNone();
|
|
291
|
+
});
|
|
292
|
+
</script>{% endset %}
|
|
293
|
+
{{ code_block(code_script_none | prettyHtml, "html") }}
|
|
294
|
+
</dd>
|
|
295
|
+
<dt><code>selectByValue(value)</code></dt>
|
|
296
|
+
<dd>
|
|
297
|
+
<p><strong>Deprecated:</strong> Alias for <code>select(value)</code>. Kept for backward compatibility.</p>
|
|
298
|
+
</dd>
|
|
299
|
+
</dl>
|
|
300
|
+
</section>
|
|
301
|
+
|
|
302
|
+
<h3 id="usage-macro"><a href="#usage-macro">Jinja and Nunjucks</a></h3>
|
|
303
|
+
|
|
304
|
+
<div class="prose">
|
|
305
|
+
<p>You can use the <code class="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-xs">select()</code> Nunjucks or Jinja macro for this component.</p>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
<div class="flex flex-wrap gap-2 my-6">
|
|
309
|
+
<a class="badge-outline" href="/installation/#install-macros" target="_blank">
|
|
310
|
+
Use Nunjucks or Jinja macros
|
|
311
|
+
{% lucide "arrow-right" %}
|
|
312
|
+
</a>
|
|
313
|
+
<a class="badge-outline" href="https://github.com/hunvreus/basecoat/blob/main/src/jinja/select.html.jinja" target="_blank">
|
|
314
|
+
Jinja macro
|
|
315
|
+
{% lucide "arrow-right" %}
|
|
316
|
+
</a>
|
|
317
|
+
<a class="badge-outline" href="https://github.com/hunvreus/basecoat/blob/main/src/nunjucks/select.njk" target="_blank">
|
|
318
|
+
Nunjucks macro
|
|
319
|
+
{% lucide "arrow-right" %}
|
|
320
|
+
</a>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
{% set raw_code %}{% raw %}{{ select(
|
|
324
|
+
items=[
|
|
325
|
+
{
|
|
326
|
+
type: "group",
|
|
327
|
+
label: "Fruits",
|
|
328
|
+
items: [
|
|
329
|
+
{ type: "item", value: "apple", label: "Apple" },
|
|
330
|
+
{ type: "item", value: "banana", label: "Banana" },
|
|
331
|
+
{ type: "item", value: "blueberry", label: "Blueberry" },
|
|
332
|
+
{ type: "item", value: "grapes", label: "Grapes" },
|
|
333
|
+
{ type: "item", value: "pineapple", label: "Pineapple" }
|
|
334
|
+
]
|
|
335
|
+
}
|
|
336
|
+
]
|
|
337
|
+
) }}{% endraw %}{% endset %}
|
|
338
|
+
{{ code_block(raw_code, "jinja") }}
|
|
339
|
+
|
|
340
|
+
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
|
341
|
+
|
|
342
|
+
<h3 id="example-scrollable"><a href="#example-scrollable">Scrollable</a></h3>
|
|
343
|
+
|
|
344
|
+
{% set code %}
|
|
345
|
+
{% call select(
|
|
346
|
+
listbox_attrs={"class": "scrollbar overflow-y-auto max-h-64"}
|
|
347
|
+
) %}
|
|
348
|
+
{% for i in range(0, 99) %}
|
|
349
|
+
<div role="option" {% if i > 0 %}data-value="item-{{ i }}"{% endif %}>Item {{ i }}</div>
|
|
350
|
+
{% endfor %}
|
|
351
|
+
{% endcall %}
|
|
352
|
+
{% endset %}
|
|
353
|
+
|
|
354
|
+
{{ code_preview("select-scrollable", code | prettyHtml) }}
|
|
355
|
+
|
|
356
|
+
<h3 id="example-disabled"><a href="#example-disabled">Disabled</a></h3>
|
|
357
|
+
|
|
358
|
+
{% set code %}
|
|
359
|
+
{% call select(
|
|
360
|
+
trigger_attrs={"disabled": "disabled"}
|
|
361
|
+
) %}
|
|
362
|
+
<div role="option" data-value="disabled">Disabled</div>
|
|
363
|
+
{% endcall %}
|
|
364
|
+
{% endset %}
|
|
365
|
+
|
|
366
|
+
{{ code_preview("select-disabled", code | prettyHtml) }}
|
|
367
|
+
|
|
368
|
+
<h3 id="example-invalid-state"><a href="#example-invalid-state">Invalid State</a></h3>
|
|
369
|
+
|
|
370
|
+
{% set code %}
|
|
371
|
+
{{ select(
|
|
372
|
+
trigger_attrs={"aria-invalid": "true"},
|
|
373
|
+
items=[
|
|
374
|
+
{ value: "", label: "Select a role" },
|
|
375
|
+
{ value: "admin", label: "Admin" },
|
|
376
|
+
{ value: "editor", label: "Editor" },
|
|
377
|
+
{ value: "viewer", label: "Viewer" },
|
|
378
|
+
{ value: "guest", label: "Guest" }
|
|
379
|
+
]
|
|
380
|
+
) }}
|
|
381
|
+
{% endset %}
|
|
382
|
+
|
|
383
|
+
{{ code_preview("select-disabled", code | prettyHtml) }}
|
|
384
|
+
|
|
385
|
+
<h3 id="example-with-icon"><a href="#example-with-icon">With icon</a></h3>
|
|
386
|
+
|
|
387
|
+
{% set code %}
|
|
388
|
+
{% call select(
|
|
389
|
+
id="select-with-icons",
|
|
390
|
+
trigger_attrs={'class': 'w-[180px]'}
|
|
391
|
+
) %}
|
|
392
|
+
<div type="button" role="option" data-value="bar">
|
|
393
|
+
<span class="flex items-center gap-2">
|
|
394
|
+
{% lucide "chart-bar", {"class": "text-muted-foreground"} %}
|
|
395
|
+
Bar
|
|
396
|
+
</span>
|
|
397
|
+
</div>
|
|
398
|
+
<div type="button" role="option" data-value="line">
|
|
399
|
+
<span class="flex items-center gap-2">
|
|
400
|
+
{% lucide "chart-line", {"class": "text-muted-foreground"} %}
|
|
401
|
+
Line
|
|
402
|
+
</span>
|
|
403
|
+
</div>
|
|
404
|
+
<div type="button" role="option" data-value="pie">
|
|
405
|
+
<span class="flex items-center gap-2">
|
|
406
|
+
{% lucide "chart-pie", {"class": "text-muted-foreground"} %}
|
|
407
|
+
Pie
|
|
408
|
+
</span>
|
|
409
|
+
</div>
|
|
410
|
+
{% endcall %}
|
|
411
|
+
{% endset %}
|
|
412
|
+
|
|
413
|
+
{{ code_preview("select-with-icons", code | prettyHtml) }}
|
|
414
|
+
|
|
415
|
+
<h3 id="example-multiple"><a href="#example-multiple">Multiple</a></h3>
|
|
416
|
+
|
|
417
|
+
<section class="prose">
|
|
418
|
+
<p>Enable multiple selection by setting adding <code>aria-multiselectable="true"</code> to the <code>listbox</code>. The selected options are displayed as a comma-separated list in the trigger button. Use <code>data-label</code> to specify clean text labels for options that contain HTML (like icons), otherwise the text content will be extracted automatically.</p>
|
|
419
|
+
</section>
|
|
420
|
+
|
|
421
|
+
{% set code %}
|
|
422
|
+
{% call select(
|
|
423
|
+
id="select-multiple",
|
|
424
|
+
name="chart-types",
|
|
425
|
+
multiple=true,
|
|
426
|
+
placeholder="Select chart types...",
|
|
427
|
+
selected=["bar", "line"],
|
|
428
|
+
trigger_attrs={"class": "w-[220px]"}
|
|
429
|
+
) %}
|
|
430
|
+
<div role="option" data-value="bar" data-label="Bar">
|
|
431
|
+
<span class="flex items-center gap-2">
|
|
432
|
+
{% lucide "chart-bar", {"class": "text-muted-foreground"} %}
|
|
433
|
+
Bar
|
|
434
|
+
</span>
|
|
435
|
+
</div>
|
|
436
|
+
<div role="option" data-value="line" data-label="Line">
|
|
437
|
+
<span class="flex items-center gap-2">
|
|
438
|
+
{% lucide "chart-line", {"class": "text-muted-foreground"} %}
|
|
439
|
+
Line
|
|
440
|
+
</span>
|
|
441
|
+
</div>
|
|
442
|
+
<div role="option" data-value="pie" data-label="Pie">
|
|
443
|
+
<span class="flex items-center gap-2">
|
|
444
|
+
{% lucide "chart-pie", {"class": "text-muted-foreground"} %}
|
|
445
|
+
Pie
|
|
446
|
+
</span>
|
|
447
|
+
</div>
|
|
448
|
+
<div role="option" data-value="area" data-label="Area">
|
|
449
|
+
<span class="flex items-center gap-2">
|
|
450
|
+
{% lucide "chart-area", {"class": "text-muted-foreground"} %}
|
|
451
|
+
Area
|
|
452
|
+
</span>
|
|
453
|
+
</div>
|
|
454
|
+
{% endcall %}
|
|
455
|
+
{% endset %}
|
|
456
|
+
|
|
457
|
+
{{ code_preview("select-multiple", code | prettyHtml) }}
|