Skip to content

1.0.0 🎉

Choose a tag to compare

@hunvreus hunvreus released this 28 Jun 02:49
· 8 commits to main since this release

Basecoat 1.0.0 is the first stable release of Basecoat as a Tailwind CSS, vanilla HTML, CSS, and JavaScript implementation of shadcn/ui's visual language for non-React stacks.

This is a large release. It reshapes the package, public component APIs, style system, JavaScript lifecycle, docs, and template story around a stable 1.0 foundation.

What is Basecoat?

Basecoat brings the shadcn/ui look and component conventions to plain HTML, Tailwind CSS, and small vanilla JavaScript.

It is not a React, Radix, Base UI, cn-*, or data-slot DOM port. The goal is to map shadcn/ui concepts onto simpler semantic markup that works well in server-rendered apps, template engines, HTMX-style apps, and other non-React stacks.

Highlights

One package

Basecoat now ships as a single npm package:

npm install basecoat-css

The old CLI workspace has been removed. Templates now ship directly inside basecoat-css, so package assets, CSS, JS, and template macros all share one version.

Template paths:

  • node_modules/basecoat-css/templates/nunjucks
  • node_modules/basecoat-css/templates/jinja

If you previously used basecoat-cli, install basecoat-css instead and copy the template files from the package.

Smaller public APIs

Basecoat 1.0 moves toward canonical root classes, semantic HTML, and documented data-* attributes.

Examples:

<button class="btn" data-variant="outline">Button</button>
<span class="badge" data-variant="secondary">Badge</span>
<div class="card" data-size="sm">...</div>
<div class="alert" data-variant="destructive">...</div>

Several pre-1.0 composed class APIs were replaced by this smaller, more regular API.

If you need legacy aliases during migration, load the optional compatibility stylesheet after Basecoat:

@import "tailwindcss";
@import "basecoat-css";
@import "basecoat-css/compat";

Standalone style packs

Style packs are now standalone bundles. Do not load the default/Vega bundle and then override it with another style.

Available style packs:

  • Vega
  • Nova
  • Maia
  • Lyra
  • Mira
  • Luma
  • Sera
  • Rhea

Examples:

@import "tailwindcss";
@import "basecoat-css";
@import "tailwindcss";
@import "basecoat-css/maia";

Base and component-only imports are also available for custom styling:

@import "basecoat-css/base";
@import "basecoat-css/components";

CDN builds

Basecoat includes standalone CDN-ready CSS bundles:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0/dist/basecoat.cdn.min.css" />

Named style bundles are available too:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@1.0.0/dist/basecoat-maia.cdn.min.css" />

Expanded component coverage

Basecoat 1.0 adds, stabilizes, or substantially reworks many components and docs pages, including:

  • Accordion
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • Card
  • Chart beta
  • Checkbox
  • Combobox
  • Command
  • Dialog
  • Drawer beta
  • Dropdown Menu
  • Empty
  • Field
  • Input
  • Input Group
  • Item
  • Kbd
  • Label
  • Native Select
  • Pagination
  • Popover
  • Progress
  • Radio Group
  • Scroll Area
  • Select
  • Sidebar
  • Skeleton
  • Slider
  • Spinner
  • Switch
  • Table
  • Tabs
  • Textarea
  • Theme Switcher
  • Toast
  • Tooltip

Many components were realigned with current shadcn/ui visual styles across all style packs.

JavaScript lifecycle cleanup

Basecoat JavaScript now initializes only uninitialized components by default:

window.basecoat.initAll()
window.basecoat.init("select")

Removed component roots clean up their listeners and runtime state through internal destroy hooks.

Several dynamic components now expose refresh() methods for rescanning child items:

  • Command
  • Select
  • Combobox
  • Dropdown Menu
  • Tabs

Method-based APIs

Document-level command events for Toast, Sidebar, and Theme were removed.

Use explicit methods instead:

document.getElementById("toaster")?.toast(config)
document.getElementById("sidebar")?.toggle()
window.basecoat.theme.toggle()

Templates included in the package

Basecoat now ships Nunjucks and Jinja templates inside basecoat-css.

Copy them from:

cp -R node_modules/basecoat-css/templates/nunjucks ./templates/basecoat
cp -R node_modules/basecoat-css/templates/jinja ./templates/basecoat

New docs site

The docs site was rebuilt on ReallySimpleDocs/Astro with:

  • updated installation docs
  • component-specific usage pages
  • style switching
  • template documentation
  • sitemap and robots support
  • custom 404 page
  • Cloudflare Workers deployment support

Breaking changes

  • Removed the basecoat-cli workspace.
  • Removed the old .form convenience selector.
  • Changed Button, Badge, Card, Avatar, and Alert visual APIs to root classes plus documented data-* attributes.
  • Changed icon-only Button sizing to upstream-aligned data-size="icon|icon-xs|icon-sm|icon-lg".
  • Changed Combobox markup and behavior to an input-first structure.
  • Removed Combobox data-multiple; use aria-multiselectable="true" on the listbox.
  • Changed Command markup to the migrated Basecoat structure.
  • Removed Combobox-specific search-header behavior from Select.
  • Removed built-in document command events for Toast, Sidebar, and Theme.
  • Reworked style loading so non-default style packs are standalone bundles.

Migration notes

Forms

The old .form wrapper is gone. Compose forms from Field, Fieldset, Label, Input, Textarea, Select, Native Select, Checkbox, Radio Group, and Switch.

If you need the old convenience behavior temporarily, define it in your app:

.form label { @apply label; }
.form input { @apply input; }
.form textarea { @apply textarea; }
.form select { @apply select; }

Legacy aliases

Use the compatibility stylesheet while migrating older markup:

@import "tailwindcss";
@import "basecoat-css";
@import "basecoat-css/compat";

Removed document events

If you need to bridge old document events temporarily:

document.addEventListener("basecoat:toast", (event) => {
  document.getElementById("toaster")?.toast(event.detail?.config || {})
})

document.addEventListener("basecoat:sidebar", (event) => {
  const sidebar = document.getElementById(event.detail?.id || "sidebar")
  const action = event.detail?.action || "toggle"
  if (["open", "close", "toggle"].includes(action)) sidebar?.[action]()
})

document.addEventListener("basecoat:theme", (event) => {
  const mode = event.detail?.mode
  mode ? window.basecoat.theme.set(mode) : window.basecoat.theme.toggle()
})

Fixes and polish

  • Fixed destructive Alert descriptions/content using muted text instead of destructive text across all style packs.
  • Fixed dark-mode unchecked Switch thumb colors across all style packs.
  • Improved Combobox single selection reopening behavior.
  • Improved Combobox multiple chips and remove buttons.
  • Updated Table examples to avoid inline overlay menus inside scrollable table containers.
  • Documented the Table overflow limitation.
  • Updated Scroll Area examples to use Card surfaces.
  • Narrowed dark-mode generated selectors to html.dark.
  • Simplified Select component selectors.
  • Fixed Input Group dropdown stacking.
  • Fixed Sidebar nested item styling.
  • Fixed command preview styling.
  • Fixed Drawer side positioning and border radius handling.

Known beta components

Chart and Drawer remain marked beta. They are usable, but their APIs and generated behavior may still change before being considered fully stable.