Add docs pages for the Datepicker and Tom Select form plugins (#2880)

This commit is contained in:
Bartosz-Do
2026-08-17 11:22:23 +02:00
committed by GitHub
parent 517ca8548e
commit 6e6084ad20
7 changed files with 335 additions and 2 deletions
@@ -3,6 +3,7 @@ title: Color picker
summary: A color picker lets users pick a color from a gradient, a set of swatches, or by typing a value. Use it in theme settings, tag colors, and any field that stores a color.
docs-libs: [coloris.js]
description: Let users pick a color in a form.
related: [/ui/forms/form-datepicker]
---
import Example from '@components/Example.astro';
import CdnImportPlugin from '@components/CdnImportPlugin.astro';
+150
View File
@@ -0,0 +1,150 @@
---
title: Date picker
summary: A date picker lets users pick a date from a calendar instead of typing it by hand. Use it for booking forms, event dates, deadlines, or any field that expects a specific date.
docs-libs: [litepicker]
description: Let users pick a date from a calendar with the Litepicker plugin, as a plain input, an icon input, or an inline calendar.
related: [/ui/forms/form-elements, /ui/forms/form-colorpicker]
---
import Example from '@components/Example.astro';
import CdnImportPlugin from '@components/CdnImportPlugin.astro';
import TabsPackage from '@components/TabsPackage.astro';
import Icon from '@ui/Icon.astro';
import { Code } from 'astro:components';
import { site } from '@shared/lib/site.ts';
## Overview
The date picker is a normal text input with the [Litepicker](https://litepicker.com/) plugin attached. Litepicker opens a calendar when the field is focused and writes the picked date back into the input, so the field still works in a form like any other text field.
<Example>
<input type="text" class="form-control" id="datepicker-overview" placeholder="Select a date" />
</Example>
## Installation
Install Litepicker with npm:
<TabsPackage name="litepicker" />
Or include it from a CDN:
<Code lang="html" code={`<script src="${site.cdnUrl}/dist/libs/litepicker/dist/litepicker.js"></script>`} />
Tabler restyles the calendar to match the rest of the interface. Those styles live in the vendors plugin, so include `tabler-vendors.css` as well:
<CdnImportPlugin plugins={['vendors']} />
## Usage
### Basic input
Add a text input with the `form-control` class, then attach Litepicker to it with its `element` option.
<Example codeOnly>
<input type="text" class="form-control" id="datepicker-basic" placeholder="Select a date" />
</Example>
```js
const picker = new Litepicker({
element: document.getElementById('datepicker-basic'),
});
```
### Icon input
Wrap the field in `.input-icon` and add a calendar icon, so users can see what the field is for at a glance. Use `.input-icon-addon` after the input to place the icon on the right, or before it to place the icon on the left.
<Example>
<div class="input-icon"> <input type="text" class="form-control" id="datepicker-icon" placeholder="Select a date" /> <span class="input-icon-addon"><Icon name="calendar" /></span> </div>
</Example>
<Example>
<div class="input-icon"> <span class="input-icon-addon"><Icon name="calendar" /></span> <input type="text" class="form-control" id="datepicker-icon-prepend" placeholder="Select a date" /> </div>
</Example>
### Inline calendar
Give Litepicker an empty `div` instead of an input, and pass `inlineMode: true`. The calendar then renders directly on the page instead of opening in a popover. Use this when the date is the main thing on the screen, for example a booking or availability page.
<Example>
<div class="datepicker-inline" id="datepicker-inline"></div>
</Example>
```js
const picker = new Litepicker({
element: document.getElementById('datepicker-inline'),
inlineMode: true,
});
```
## JavaScript
### Custom navigation icons
Litepicker's default previous/next month buttons are plain arrows. Tabler replaces them with [Tabler Icons](/icons) chevrons through the `buttonText` option, which accepts HTML for each button.
```js
const picker = new Litepicker({
element: document.getElementById('datepicker-basic'),
buttonText: {
previousMonth: '<svg class="icon" ...><!-- chevron-left --></svg>',
nextMonth: '<svg class="icon" ...><!-- chevron-right --></svg>',
},
});
```
Litepicker uses `buttonText` as the buttons' `innerHTML`, and the icon SVGs are `aria-hidden`, so the generated buttons have no accessible name on their own. Litepicker also re-renders these buttons on every open and every month change, so re-apply the labels on each `render` event instead of once at init:
```js
picker.on('render', () => {
picker.ui?.querySelector('.button-previous-month')?.setAttribute('aria-label', 'Previous month');
picker.ui?.querySelector('.button-next-month')?.setAttribute('aria-label', 'Next month');
});
```
### Common options
These are the options you will need most often. Litepicker has more, and they are listed in its [documentation](https://litepicker.com/#option).
| Option | What it does |
| --- | --- |
| `element` | The input or element Litepicker attaches to. |
| `inlineMode` | Renders the calendar on the page instead of in a popover. |
| `singleMode` | `true` picks one date; `false` picks a date range. |
| `format` | Format of the date shown in the field, for example `YYYY-MM-DD`. |
| `minDate` / `maxDate` | Limits the range of selectable dates. |
| `lockDays` | List of dates users cannot pick. |
| `numberOfColumns` / `numberOfMonths` | Shows more than one month at a time. |
| `buttonText` | HTML for the previous/next month and other buttons. |
## Accessibility
- Always add a `<label>` linked to the input with `for` and `id`. The calendar icon alone does not say what the field is for.
- Litepicker's month-navigation buttons carry no accessible name on their own — set `aria-label` on the `render` event, as shown above.
- Keep the typed value working. Users can type a date directly into the input; the picker is a shortcut, not the only way to set the value.
- The picker can be operated with the keyboard: focus the input to open it, use arrow keys to move between days, and <kbd>Enter</kbd> to pick a date.
<script>{`
window.addEventListener('load', function () {
if (typeof Litepicker === 'undefined') return;
function initPicker(el, options) {
if (!el) return;
var picker = new Litepicker(Object.assign({ element: el }, options));
picker.on('render', function () {
var prev = picker.ui && picker.ui.querySelector('.button-previous-month');
var next = picker.ui && picker.ui.querySelector('.button-next-month');
if (prev) prev.setAttribute('aria-label', 'Previous month');
if (next) next.setAttribute('aria-label', 'Next month');
});
return picker;
}
initPicker(document.getElementById('datepicker-overview'));
initPicker(document.getElementById('datepicker-basic'));
initPicker(document.getElementById('datepicker-icon'));
initPicker(document.getElementById('datepicker-icon-prepend'));
initPicker(document.getElementById('datepicker-inline'), { inlineMode: true });
});
`}</script>
+1 -1
View File
@@ -4,7 +4,7 @@ summary: Forms are one of the most important types of interaction with a website
docs-libs: [nouislider]
description: Build user-friendly forms with styled inputs, selects, checkboxes, and radios. Learn about states, sizes, and layout options.
order: 1
related: [/ui/forms/form-validation, /ui/forms/form-helpers, /ui/forms/form-fieldset]
related: [/ui/forms/form-validation, /ui/forms/form-helpers, /ui/forms/form-fieldset, /ui/forms/form-datepicker, /ui/forms/form-select-tomselect]
---
import Example from '@components/Example.astro';
import CodeDocs from '@components/CodeDocs.astro';
@@ -0,0 +1,169 @@
---
title: Advanced select (Tom Select)
summary: Tom Select turns a normal `<select>` into a searchable, keyboard-friendly dropdown. Use it for long option lists, multi-value fields, or options that need an avatar, flag, or badge next to the text.
docs-libs: [tom-select]
description: Build searchable single and multi-value selects with the Tom Select plugin, including optgroups, validation states, and rich options with avatars or flags.
related: [/ui/forms/form-selectboxes, /ui/forms/form-elements]
---
import Example from '@components/Example.astro';
import TabsPackage from '@components/TabsPackage.astro';
import { Code } from 'astro:components';
import { site } from '@shared/lib/site.ts';
## Overview
[Tom Select](https://tom-select.js.org/) attaches to a normal `<select class="form-select">` and replaces it with a searchable dropdown. The original `<select>` stays in the DOM and keeps its value, so it still works in a plain HTML form.
<Example>
<select class="form-select" id="select-overview" data-placeholder="Pick a fruit"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="cherry">Cherry</option> <option value="date">Date</option> <option value="elderberry">Elderberry</option> </select>
</Example>
## Installation
Install Tom Select with npm:
<TabsPackage name="tom-select" />
Or include it from a CDN. You need both the script and its stylesheet:
<Code
lang="html"
code={`<link rel="stylesheet" href="${site.cdnUrl}/dist/libs/tom-select/dist/css/tom-select.bootstrap5.min.css" />
<script src="${site.cdnUrl}/dist/libs/tom-select/dist/js/tom-select.base.min.js"></script>`}
/>
## Usage
### Basic select
Add `class="form-select"` to a `<select>`, give it an `id`, then attach Tom Select to that id.
<Example codeOnly>
<select class="form-select" id="select-basic"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="cherry">Cherry</option> </select>
</Example>
```js
new TomSelect('#select-basic', {
copyClassesToDropdown: false,
});
```
### Placeholder
Native `<select>` elements don't support the `placeholder` attribute, so add `data-placeholder` instead. Tom Select reads it and shows it as the empty-state text.
<Example>
<select class="form-select" id="select-placeholder" data-placeholder="Pick a fruit"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="cherry">Cherry</option> </select>
</Example>
### Multiple values
Add the `multiple` attribute to let users pick more than one option. Tom Select shows each pick as a removable tag.
<Example>
<select class="form-select" id="select-multiple" multiple data-placeholder="Pick fruits"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="cherry">Cherry</option> <option value="date">Date</option> <option value="elderberry">Elderberry</option> </select>
</Example>
```js
new TomSelect('#select-multiple', {
copyClassesToDropdown: false,
});
```
### Optgroups
Group related options with `<optgroup>`. Tom Select shows the group label in the dropdown and keeps it searchable.
<Example>
<select class="form-select" id="select-optgroup" data-placeholder="Pick a fruit"> <optgroup label="Citrus"> <option value="orange">Orange</option> <option value="lemon">Lemon</option> <option value="lime">Lime</option> </optgroup> <optgroup label="Berries"> <option value="strawberry">Strawberry</option> <option value="blueberry">Blueberry</option> <option value="raspberry">Raspberry</option> </optgroup> </select>
</Example>
### Validation states
Add `.is-valid` or `.is-invalid` to the `<select>` to show a validation state. Tom Select carries the class over to its own wrapper, so the field still shows the usual green or red styling.
<Example column>
<div class="mb-3"> <label class="form-label">Valid select</label> <select class="form-select is-valid" id="select-valid" data-placeholder="Pick a fruit"> <option value="apple" selected>Apple</option> <option value="banana">Banana</option> </select> </div> <div> <label class="form-label">Invalid select</label> <select class="form-select is-invalid" id="select-invalid" data-placeholder="Pick a fruit"> <option value="apple">Apple</option> <option value="banana">Banana</option> </select> </div>
</Example>
### Rich options
An option can carry extra markup — an avatar, a flag, a badge — through a `data-custom-properties` attribute. Read it in a custom `render.option` / `render.item` function and show it next to the option text.
<Example>
<select class="form-select" id="select-avatar" data-placeholder="Assign to…"> <option value="1" data-custom-properties='<span class="avatar avatar-xs">JD</span>'>Jane Doe</option> <option value="2" data-custom-properties='<span class="avatar avatar-xs">MS</span>'>Mark Smith</option> <option value="3" data-custom-properties='<span class="avatar avatar-xs">AK</span>'>Amy Kim</option> </select>
</Example>
<Example>
<select class="form-select" id="select-flag" data-placeholder="Pick a country"> <option value="us" data-custom-properties='<span class="flag flag-xs flag-country-us"></span>'>United States</option> <option value="gb" data-custom-properties='<span class="flag flag-xs flag-country-gb"></span>'>United Kingdom</option> <option value="de" data-custom-properties='<span class="flag flag-xs flag-country-de"></span>'>Germany</option> <option value="fr" data-custom-properties='<span class="flag flag-xs flag-country-fr"></span>'>France</option> </select>
</Example>
```js
function renderOption(data, escape) {
if (data.customProperties) {
return `<div class="dropdown-item"><span class="dropdown-item-indicator">${data.customProperties}</span>${escape(data.text)}</div>`;
}
return `<div>${escape(data.text)}</div>`;
}
new TomSelect('#select-avatar', {
copyClassesToDropdown: false,
dropdownParent: 'body',
render: {
item: renderOption,
option: renderOption,
},
});
```
Tom Select turns a `data-custom-properties` attribute into `data.customProperties` on the option object, so `render.option` and `render.item` can read it. `escape()` keeps user-supplied text safe when it is inserted as HTML.
### Common options
These are the options you will need most often. Tom Select has more, and they are listed in its [documentation](https://tom-select.js.org/docs/).
| Option | What it does |
| --- | --- |
| `copyClassesToDropdown` | Copies the `<select>` classes onto the dropdown. Tabler keeps this `false` and styles the dropdown itself. |
| `dropdownParent` | Where the dropdown is appended in the DOM, for example `'body'` so it is not clipped by a card or modal. |
| `maxItems` | Maximum number of selected items on a multi-value select. |
| `create` | `true` lets users type a value that is not in the option list. |
| `plugins` | List of Tom Select plugins to enable, for example `remove_button`. |
| `render.option` / `render.item` | Custom render functions for a dropdown option and a selected item. |
## Accessibility
- Always add a `<label>` linked to the `<select>` with `for` and `id`. Tom Select's generated markup does not replace the need for a label.
- The dropdown can be operated with the keyboard: type to search, arrow keys to move between options, <kbd>Enter</kbd> to pick one, and <kbd>Backspace</kbd> to remove the last tag on a multi-value select.
- When using `render.option`, keep enough text content in the rendered HTML — an avatar or flag alone does not tell a screen reader user which option it is.
- Escape user-supplied text in custom render functions with the `escape` argument, so option text can never break out of the generated HTML.
<script>{`
window.addEventListener('load', function () {
if (typeof TomSelect === 'undefined') return;
function renderOption(data, escape) {
if (data.customProperties) {
return '<div class="dropdown-item"><span class="dropdown-item-indicator">' + data.customProperties + '</span>' + escape(data.text) + '</div>';
}
return '<div>' + escape(data.text) + '</div>';
}
['select-overview', 'select-basic', 'select-placeholder', 'select-multiple', 'select-optgroup', 'select-valid', 'select-invalid'].forEach(function (id) {
var el = document.getElementById(id);
if (el) new TomSelect(el, { copyClassesToDropdown: false, dropdownParent: 'body' });
});
['select-avatar', 'select-flag'].forEach(function (id) {
var el = document.getElementById(id);
if (el) {
new TomSelect(el, {
copyClassesToDropdown: false,
dropdownParent: 'body',
render: { item: renderOption, option: renderOption },
});
}
});
});
`}</script>
+1 -1
View File
@@ -3,7 +3,7 @@ title: Form selectgroup
summary: Use selectgroup to make your form more intuitive by providing users with a set of options to choose from. You can add simple selectgroup with a label, use icons only or icons with labels. Alternatively, you can use pill selectgroup if they go well with your design.
description: Offer sets of options with select groups - labeled, icon-only, or pill-shaped controls built on checkboxes and radios.
css-plugins: [payments]
related: [/ui/forms/form-image-check, /ui/forms/form-color-check]
related: [/ui/forms/form-select-tomselect, /ui/forms/form-image-check, /ui/forms/form-color-check]
---
import Example from '@components/Example.astro';
import { site } from '@shared/lib/site';