Ready-made components for the HTML you already write.
Write data-tuc-datepicker on an input and it becomes a calendar. The same goes for searchable
select, masks, modals and tables — no build and no dependencies. It works with any back-end that renders HTML:
Django, Laravel, Rails, Phoenix, ASP.NET, Go or Node, and with HTMX too.
Installation
Two files and nothing else. Pick the path that fits your project — none of them requires a build step on your side.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/JuniorCarlini/tucano@v0.37.2/dist/tucano.min.css">
<script src="https://cdn.jsdelivr.net/gh/JuniorCarlini/tucano@v0.37.2/dist/tucano.min.js" defer></script>Always pin the version. @latest stays cached on jsDelivr for a long time and silently serves an old build.
Copy the dist/ folder into your project's static files. In Django:
{% load static %}
<link rel="stylesheet" href="{% static 'tucano/tucano.min.css' %}">
<script src="{% static 'tucano/tucano.min.js' %}" defer></script>npm install tucanoimport { DatePicker, Select, toast } from 'tucano';
import 'tucano/css';With npm your bundler keeps only what you import: the date picker alone is a third of the package. Importing
from tucano does not auto-initialize fields — call Tucano.init(document) or import
tucano/auto.
How it works
The HTML you already write keeps owning the value. The component only swaps the look and adds the behavior.
data-tuc-* attribute on the <input> or <select> in your template.htmx:afterSwap — without a line of JavaScript.name, required and multiple values work as always.<input type="text" name="due_date" data-tuc-datepicker>
<select name="state" data-tuc-select>...</select>
<input type="text" name="card" data-tuc-mask="card">Dates and numbers follow your page's language
The date picker reads <html lang> for month names, weekdays and date format, and currency masks take a currency code. Labels and placeholders can go in your template, like data-placeholder="Search customers...", and the texts the components write on their own — Portuguese by default — change with Tucano.setTexts().
Plays well with your project's Tailwind
The package does not ship the preflight, and the components carry their own reset: your CSS does not break the components, and the components do not touch your project.
Texts in other languages
The texts the components write on their own — the calendar's "Limpar", the select's "Buscar...", the modal's
"Fechar", the labels read by screen readers — come in Portuguese, and Tucano.setTexts() replaces any of
them, per group. Whatever you leave out stays as it was, and each instance's own option
(data-placeholder, emptyText, prevText) still wins. The package ships no
language dictionaries.
// Before the components mount. With a deferred script, inside DOMContentLoaded.
document.addEventListener('DOMContentLoaded', () => {
Tucano.setTexts({
datepicker: { clear: 'Clear', apply: 'Apply', previousMonth: 'Previous month',
nextMonth: 'Next month', placeholderLetters: 'ymdhms' },
select: { searchPlaceholder: 'Search...', emptyText: 'No results',
remove: (label) => `Remove ${label}` },
modal: { close: 'Close' },
toast: { close: 'Close' },
});
});A text is read when the component mounts, so what is already on screen does not change. Where the sentence depends
on a number or a name, the value is a function. Groups are named after the components — datepicker,
select, colorpicker, upload, mask, toast,
modal, drawer, table, pagination, editor and
prose — and Tucano.getTexts() returns a copy of all of them. The keys, with each default,
are in llms.txt. This site does the same: on every page in English, the
components speak English.
Components
Each one has its own page with examples, the Django way, keyboard support and the full API. For an AI
assistant, point it to the llms.txt reference.