--- name: core-js description: >- Work on the framework's own JavaScript in `core/js/` — the `tabler.js` and `tabler-theme.js` bundles, the vendored Bootstrap component port, and their browser tests. Use when a Tabler behaviour needs adding or fixing (a `data-bs-toggle` handler, the theme switcher, a plugin initialiser), when a Bootstrap component's JS misbehaves, and before changing anything under `core/js/src/`. Not for demo-page scripts — that is the `astro-scripts` skill. --- # The framework JavaScript `core/js` builds two shipped bundles. Everything here is public API and is bound by a size budget. ## 1. Two entry points | Entry | Ships as | Holds | | -------------------- | ---------------------------------- | ---------------------------------------------------------------------------- | | `js/tabler.ts` | `tabler.js` / `.esm.js` (+ `.min`) | plugin initialisers, the Bootstrap components, the `tabler` helper namespace | | `js/tabler-theme.ts` | `tabler-theme.js` (+ variants) | the colour-mode/theme switcher only | `tabler-theme.js` is loaded right after `` and **not deferred**, so the chosen theme applies before the first paint. It stays tiny on purpose (bundlewatch: 1 kB raw, 800 B minified) — do not add anything to it that is not needed before paint. ## 2. `js/src/bootstrap/**` is a port, not our code That directory is Bootstrap's JavaScript rewritten in TypeScript, MIT headers kept, `VERSION = '5.3.8'`. Treat it as vendored: - Fix bugs the way upstream did, and keep the file's structure recognisable against `twbs/bootstrap`. Gratuitous restructuring makes the next upstream sync expensive. - `js/src/bootstrap.ts` is the single source of truth for what is exported and for the `bootstrap` namespace object. - A new or reworked component class follows the `bootstrap-component` skill (file order, typed config, Data API). - Coverage is configured to measure exactly this directory (`js/src/bootstrap/**`), and `js/tests/unit/*.spec.ts` mirrors upstream's suite — a change here is expected to come with its test. ## 3. Tabler's own modules Modules directly in `js/src/*.ts` (`autosize`, `countup`, `dropdown`, `input-mask`, `popover`, `sortable`, `switch-icon`, `tab`, `toast`, `tooltip`) are **side-effect initialisers**: importing them from `tabler.ts` wires the behaviour. The pattern is a `data-bs-toggle` query at import time: ```ts // js-docs-start switch-icon-init const switchesTriggerList: HTMLElement[] = [].slice.call(document.querySelectorAll('[data-bs-toggle="switch-icon"]')) switchesTriggerList.map(function (switchTriggerEl: HTMLElement) { switchTriggerEl.addEventListener('click', (e: MouseEvent) => { const active = switchTriggerEl.classList.toggle('active') switchTriggerEl.setAttribute('aria-pressed', active ? 'true' : 'false') }) }) // js-docs-end switch-icon-init ``` - The attribute API stays `data-bs-*`. Renaming it to `data-tblr-*` is a breaking change held for 2.0 — do not start it here. - Keep the accessible state in sync with the class (`aria-pressed`, `aria-expanded`), as above. - A new module must be imported from `js/tabler.ts`, or it never ships. - There is no shared colour helper: demo charts resolve `--tblr-*` colours to hex in `shared/components/demo/Chart.astro`. ## 4. Docs markers `js-docs-start ` / `js-docs-end ` mark the snippet a documentation page shows for that behaviour (`docs/components/CodeDocs.astro`, `docs/lib/llms.ts`). Keep the marked region self-contained and copy-pasteable, and check who references the name before renaming it. ## 5. Tests Tests run in a **real browser** — vitest browser mode with Playwright Chromium, not jsdom: ```bash pnpm --filter @tabler/core test:js pnpm --filter @tabler/core test:js:watch pnpm --filter @tabler/core test:js:coverage ``` - `js/tests/unit/**/*.spec.ts` — behaviour, using `js/tests/helpers/fixture.ts` to mount markup. - `js/tests/visual/*.html` — pages for looking at a component by hand. - The first run needs Playwright's browser installed; if it fails on a missing binary, install it rather than switching the config to jsdom. ## 6. Build and budget `vite` builds each entry as a library in `es` + `umd` (`BASE_NAME` selects the entry), then terser produces the `.min` variants with source maps. Sizes are enforced: | File | Limit | | ------------------------- | ----- | | `dist/js/tabler.js` | 64 kB | | `dist/js/tabler.min.js` | 48 kB | | `dist/js/tabler-theme.js` | 1 kB | ```bash pnpm --filter @tabler/core build pnpm run bundlewatch ``` Prefer a small dependency-free implementation over pulling a package in: every kilobyte here lands on every Tabler page. ## 7. Checklist - [ ] New module imported from `js/tabler.ts` (or deliberately kept out of the bundle) - [ ] `data-bs-*` attribute API unchanged; accessible state updated with the class - [ ] No export, option or event removed or renamed, and no new throw on input that used to work (`backward-compat`) - [ ] Bootstrap-port changes stay close to upstream and come with a `js/tests/unit` spec - [ ] `js-docs-*` markers intact and self-contained - [ ] `pnpm --filter @tabler/core test` (js + scss) clean - [ ] `pnpm run type-check` and `pnpm run lint:prettier` clean - [ ] `pnpm run bundlewatch` within budget, or the new limit justified in the PR - [ ] Docs page updated and changeset written