Skip to content

Releases: wheels-dev/wheels-basecoat

v3.0.0 — the killer-feature release

01 May 23:26
1b062a9

Choose a tag to compare

What's new

The v3.0 release positions wheels-basecoat as the killer feature of Wheels 4.0 — every common UI pattern has a one-line helper, every form has a Wheels-bound variant, every AI coding assistant can pick up the package and write idiomatic code without trial-and-error.

From "I have a Wheels app" to a polished UI

wheels packages add wheels-basecoat
cp -r vendor/wheels-basecoat/assets/basecoat public/assets/basecoat

Then in your view:

#uiErrorSummary(post)#
#startFormTag(action="create")#
    #uiBoundField(objectName="post", property="title", required=true)#
    #uiBoundField(objectName="post", property="body", type="textarea", rows=10)#
    #uiBoundField(objectName="post", property="status", type="select",
                  options="draft:Draft,published:Published,archived:Archived")#
    #uiBoundCheckbox(objectName="post", property="featured", switch=true)#
    #uiButton(text="Publish", type="submit", icon="check")#
#endFormTag()#

Six lines for a fully styled, model-bound, error-aware, Turbo-friendly form. Every helper renders shadcn/ui-quality basecoat-css 0.3.x markup, and they're all CSP-safe.

Highlights

AI / dev experience (the meta-killer-feature)

The package now ships a comprehensive CLAUDE.md + .ai/ documentation bundle that AI coding assistants read first. The result: an AI assistant working in any wheels-basecoat app can find the right helper, write idiomatic code, and avoid the known footguns on the first try.

  • CLAUDE.md — read order, package architecture, helper inventory, the 14 coding rules every generated CFML must follow.
  • .ai/HELPERS.md — formal signature reference for every public helper.
  • .ai/EXAMPLES.md — scenario-driven recipes (layout, posts CRUD, login/signup, settings, wizard, dashboard, ⌘K palette, Turbo Stream delete, resource scaffold).
  • .ai/SCAFFOLDS.md — copy-paste templates for every common page type.
  • .ai/PATTERNS.md — when-to-use decision trees.
  • .ai/PITFALLS.md — 14 known footguns with symptom + cause + fix.
  • .ai/ARCHITECTURE.md — design rationale, naming, the PackageLoader mixin gotcha, CSP safety, Hotwire integration, version history.
  • examples/showcase/ — drop-in mountable controller + view that gives every Wheels app a /basecoat-showcase URL with every helper rendered live.
  • INSTALL.md — three-step install guide.

Form binding round-trip is complete

Every common input type has a Wheels-bound helper that auto-resolves value, name, error, and label from the model:

Input type Helper
Text / textarea / select / date / etc. uiBoundField
Rich combobox (search, multi-select) uiBoundSelect
Range slider uiBoundSlider
Single boolean uiBoundCheckbox (with hidden falsy companion for unchecked submissions)
Multi-checkbox collection uiBoundCheckboxGroup
Single-choice radio uiBoundRadioGroup
File upload uiBoundFile (drag-and-drop)
Tag chips uiBoundTagInput
Model-level error rollup uiErrorSummary(model)

New helpers in v3.0

  • uiCallout — boxed inline note (info / tip / warning / success).
  • uiEmptyState — centered zero-data placeholder with optional CTA.
  • uiAccordion family — CSS-only collapsible sections.
  • uiTimeline family — vertical timeline with markers.
  • uiCodeBlock — styled code display with copy-to-clipboard.
  • uiTagInput + uiBoundTagInput — multi-value chip entry with autocomplete.
  • uiFileUpload + uiBoundFile — drag-and-drop file zone.
  • uiDatePicker — basecoat-styled date input with Lucee-quoted-datetime coercion.
  • uiPaginationFor(query) — pagination from a Wheels paginated query.
  • uiResourceTable(query, columns) — auto-build a table from a Wheels query.
  • uiResourceForm(model) — auto-build a Wheels-bound form from a model's properties.

Plus extras CSS for every new component, JS shim handlers, 4 new Lucide icons, comprehensive BasecoatV30Spec.cfc.

Cumulative since v2.0

If you're upgrading from v1.x, v3.0 also brings everything that landed in v2.0 → v2.4:

  • v2.0 — bundled basecoat-css 0.3.11 + basecoat-js + CSP-safe shim, uiBoundField, toasts (basecoatFlashToasts reads Wheels' flash()), popover, avatar, kbd, button group, fieldset, dark mode (uiThemeToggle + pre-paint script), Turbo Stream helpers (turboStream / turboStreamHeader), argument validation throwing WheelsBasecoat.InvalidArgument.
  • v2.1 — Tabs / Dropdown / Sidebar reworked to ARIA roles + basecoat-js contracts.
  • v2.2 — extras CSS for breadcrumb / pagination / steps / rating / radio, uiCommand family + uiCommandDialog (⌘K palette), uiSelect rich combobox.
  • v2.3uiSlider + uiBoundSlider, uiSteps wizard family, uiBoundSelect.
  • v2.4uiBoundCheckbox (with falsy companion), uiBoundCheckboxGroup, uiBoundRadioGroup, uiErrorSummary, uiRating.

See CHANGELOG.md for the full per-version detail.

Installation

wheels packages add wheels-basecoat
cp -r vendor/wheels-basecoat/assets/basecoat public/assets/basecoat
wheels reload

Then in app/views/layout.cfm:

<head>
    <cfoutput>
        #basecoatThemeScript()#
        #csrfMetaTags()#
        #basecoatIncludes()#
    </cfoutput>
</head>
<body>
    ...
    <cfoutput>#basecoatFlashToasts()#</cfoutput>
</body>

See INSTALL.md for the full guide and examples/showcase/README.md for the optional live showcase mount.

Compatibility

  • Wheels 4.0+
  • Lucee 7.0+ or Adobe ColdFusion 2021+
  • basecoat-css 0.3.11 (bundled, pinned)

Migration from v1.x

The package API is mostly source-compatible across v1 → v3, but bundled-asset publishing is new and the helper output markup has been brought up to basecoat-css 0.3.x's semantic structure (cards now emit <header>/<section>/<footer>, alerts are flat children, tabs use ARIA roles, dropdown uses popover JS, sidebar uses semantic nav).

Apps that wrote custom CSS targeting the old class names (.card-header, .card-content, .card-footer, .tabs-list, .tabs-trigger, .sidebar-section) will need to re-target the semantic / ARIA selectors that basecoat-css 0.3.x uses.

The form-binding family (uiBound*) is purely additive — apps using uiField continue to work unchanged.

Acknowledgements

Built primarily during a single Wheels Tutorial fresh-VM bake session. The session surfaced the 14 footguns now documented in .ai/PITFALLS.md, drove the Wheels integration story (form binding, flash toasts, model introspection), and produced the showcase + AI/dev docs bundle that makes the package as approachable for AI assistants as it is for developers.

v1.0.4

30 Apr 14:24
9beb102

Choose a tag to compare

Fixes Lucee 7 fresh-install load failure by dropping the redundant mixin="controller" attribute from Basecoat.cfc. See CHANGELOG for full context including a retraction of the 1.0.3 changelog's incorrect claim that the attribute was a no-op.

wheels-basecoat 1.0.3

30 Apr 04:35
70f6657

Choose a tag to compare

Fixed

Switch $uiBuildId and $uiLucideIcon from privatepublic on Basecoat.cfc.

Wheels' PackageLoader.$collectMixins integrates only PUBLIC methods of the package CFC into the target scope (controllers in our case). When the public sibling helpers — uiField, uiInput, uiCheckbox, uiButton(icon=...), uiAlert, uiPagination, etc. — invoked the $-prefixed helpers from the mixed-in scope, those calls had no resolution path and failed at runtime with:

No matching function [$UIBUILDID] found

(and the symmetrical [$UILUCIDEICON] variant from icon-rendering helpers). Hitting any page that rendered a form via uiField therefore 500'd on a fresh install of 1.0.2.

The leading $ keeps signalling "internal — don't call from app code"; the access-modifier change just lets PackageLoader carry the helpers across the mixin boundary alongside the public callers that depend on them.

Note on the 1.0.2 changelog

The 1.0.2 changelog asserted that Lucee 7 was rejecting the mixin="controller" component-level attribute outright, blocking compilation. That diagnosis was incorrect — verified post-release on Lucee 7.0.0.395, the package compiles fine and PackageLoader loads it successfully with the attribute in place. The actual blocker preventing helper rendering was always this private-helper visibility issue, fixed in 1.0.3.

Source

Discovered during a Wheels Tutorial fresh-VM bake; verified end-to-end on Lucee 7.0.0.395 — wheels packages add wheels-basecoat activates cleanly, form renders via uiField, /posts/1 returns 200 instead of the previous 500.

Install

Once wheels-dev/wheels-packages registry update merges and the mirror-tarball workflow completes:

wheels packages add wheels-basecoat

Existing 1.0.2 installs can upgrade with:

wheels packages update wheels-basecoat --yes
wheels stop && wheels start

(Note: wheels reload does not re-run onApplicationStart, so PackageLoader doesn't re-integrate the new public methods — a cold restart is required.)

wheels-basecoat 1.0.2

29 Apr 20:49

Choose a tag to compare

Fixed

Drop view from the component-level mixin attribute on Basecoat.cfc. Lucee 7 enforces native trait composition on component mixin="..." and tries to load each comma-separated value as a CFML component path; there is no view.cfc on the path, so the whole component failed to compile with a misleading can't find component [vendor.wheels-basecoat.Basecoat] error.

Net effect on Lucee 7: every wheels packages add wheels-basecoat install resulted in a successful extract but no helper activation. Helpers like #uiButton(...)#, #uiCard(...)#, #uiField(...)# all returned function not found. After this fix the package activates cleanly.

The package.json's provides.mixins: "controller" field remains the actual source of truth — the component-level attribute was a legacy convention obsolete on Lucee 7. Lucee 5/6 don't enforce native mixin composition the same way, which is why this went undetected until Wheels 4.0 made Lucee 7 the default.

Source

Install

Once wheels-dev/wheels-packages#8 (registry update) merges and the mirror-tarball workflow completes:

wheels packages add wheels-basecoat

wheels-basecoat 1.0.1

29 Apr 20:49

Choose a tag to compare

Documentation patch release. Clarifies controller-scope mixin inheritance in views. (See #1.)

wheels-basecoat v1.0.0

23 Apr 19:53

Choose a tag to compare

Initial standalone release, extracted from the Wheels monorepo at packages/basecoat with preserved git history.

Published to the wheels-dev/wheels-packages registry for installation via wheels packages install wheels-basecoat (coming in Wheels 4.1).

See CHANGELOG.md for details.