From 4c4518e0ba54039e4bb4e5a2d3b1e800aff557ff Mon Sep 17 00:00:00 2001 From: Kirill Kolesnikov Date: Fri, 4 Sep 2026 21:34:50 +0700 Subject: [PATCH 1/6] Give CmIcon its own stylesheet, and import what App.vue actually uses Two separate bugs, both hiding the same two components in the showcase. CmIcon's generated SVG carries no width, height, fill, or stroke of its own -- the outline shapes (regular/light/thin) have neither attribute at all, because in the source they were painted by the wrapper element they sat inside, not by themselves. icon.js's extraction regex kept only viewBox from that wrapper and dropped everything else, discovered by rendering the same icon through the original VueForge component and diffing the two tags directly rather than guessing: the source carried width/height via a CSS-variable fallback, fill=none unconditionally, and stroke/stroke-width/stroke-linecap/stroke-linejoin for every variant but solid, with stroke-width 2/1.5/1 for regular/light/thin. None of that needed to move into the generator or either adapter -- the classes it needs (cm-icon, cm-icon--regular, and so on) were already being rendered -- it only needed a stylesheet, which never existed. Separately, App.vue used and in its template without importing either from @codemonster-ru/ui-vue. Vue does not resolve template tags against a global namespace; a name not imported in

CodeMonster UI showcase

- Components and layouts with no VueForge ancestor. The VueForge playground stays frozen against its reference - commit, so anything without a predecessor to match is demonstrated here instead. + Every component and layout in @codemonster-ru/ui-vue and @codemonster-ru/ui-layouts, + rendered live by the Vue adapter. Some carry a VueForge ancestor and some don't -- that distinction lives in + each component's own history, not in whether it's demonstrated here.

@@ -137,6 +238,351 @@ const tableOfContentsItems = [ +
+

Accordion

+

Disclosure panels sharing one set of expanded ids, so more than one can open.

+ +
+ +
+

Alert

+

An inline, non-dismissable status message with a tone.

+ + A new version of this workspace is available. + Check your connection and try again. + +
+ +
+

Avatar

+

A person or entity, by image, then initials, then a fallback slot.

+
+ + +
+
+ +
+

Badge

+

A small count or status mark, meant to sit on or beside another element.

+
+ 3 + ! +
+
+ +
+

Breadcrumbs

+

A trail back up the hierarchy, with the current page marked, not linked.

+ +
+ +
+

Button

+

Variant carries intent, not just color; loading disables the control itself.

+
+ Save + Cancel + Delete + Loading +
+
+ +
+

Card

+

A titled surface. Header and footer regions appear only when given content.

+ +

The last commit built successfully and is ready to review.

+ +
+
+ +
+

Checkbox

+

A tri-state-capable control; indeterminate is visual only, not a value.

+ +
+ +
+

Command palette

+

A searchable action list opened as a modal dialog, filtered as you type.

+ Open command palette + +
+ +
+

Container

+

Centers content and caps its width at one of a fixed set of sizes.

+ + This content is centered and width-capped. + +
+ +
+

Data table

+

+ Columns, rows, sorting, selection, and pagination as data, not markup you assemble by hand. +

+ +
+ +
+

Date picker

+

A native date input styled to match the rest of the control set.

+ +
+ +
+

Divider

+

A semantic separator; orientation flips both its ARIA role and its geometry.

+ +
+ +
+

Dialog

+

A modal built on the native <dialog> element, dismissible by default.

+ Open dialog + +

Archived projects can be restored for 30 days, then they're deleted.

+ +
+
+ +
+

Dropdown

+

A button that opens a menu, closing on selection, outside click, or Escape.

+ +
+ +
+

Drawer

+

A modal that slides in from a screen edge instead of appearing centered.

+ Open drawer + +

Drawer content goes here -- a form, a list, whatever the side panel needs to hold.

+
+
+ +
+

Field

+

+ Wraps one control with a label, description, and error, wiring their ids together as + aria-describedby. +

+ + + +
+ +
+

Fieldset

+

Groups related controls -- checkboxes, radios -- under one required legend.

+ + + +
+ +
+

Grid

+

+ A CSS grid primitive that auto-fits columns by default; a cm-grid-cols-* utility fixes the count. +

+ +
1
+
2
+
3
+
+
+ +
+

Icon button

+

A square button carrying only an icon; label supplies its name.

+
+ + + +
+
+ +
+

Input

+

Text entry, with an optional clear button and, for passwords, a reveal toggle.

+ +
+ +
+

Inline

+

A flex row primitive for laying out a run of small elements.

+ + Platform + Stable + Internal + +
+ + + +
+

Menu

+

A standalone list of actions with roving tabindex; Dropdown renders one of these.

+ +
+ +
+

Popover

+

An anchored panel for arbitrary content, as opposed to Dropdown's fixed menu.

+ +

Anything can go in a popover's panel -- text, a form, another component.

+
+
+ +
+

Progress bar

+

A determinate or indeterminate horizontal progress meter.

+ + + + +
+ +
+

Progress spinner

+

An indeterminate circular spinner, for a spot too small for a bar.

+ +
+ +
+

Radio

+

A mutually exclusive choice; grouping comes from a shared name.

+
+ + +
+
+ +
+

Select

+

A native select styled to match the rest of the control set.

+ +
+ +
+

Section

+

A landmark and vertical-rhythm primitive; surface adds a background.

+ A section with the surface variant. +
+ +
+

Skeleton

+

A loading placeholder shaped like the content it stands in for.

+ + + + +
+ +
+

Stack

+

A flex column primitive, stretched and gapped by default.

+ +
1
+
2
+
+
+ +
+

Switch

+

+ An on/off control with immediate effect, unlike Checkbox's deferred-until-submit norm. +

+ +
+ +
+

Table

+

+ Plain markup in header/body/footer slots; DataTable builds this from data instead. +

+ + + + Report.pdf + Kirill + + + Roadmap.md + Aisha + + +
+ +
+

Tabs

+

One panel visible at a time, switched with a roving-tabindex tablist.

+ +
+ +
+

Textarea

+

Multi-line text entry, sharing Input's size and validation states.

+ +
+ +
+

Tooltip

+

Shown on focus or hover, never as the only way to reach information.

+ +
+

App shell

@@ -148,7 +594,12 @@ const tableOfContentsItems = [ diff --git a/examples/ui-showcase/src/main.ts b/examples/ui-showcase/src/main.ts index 10ccca44..8b3d134b 100644 --- a/examples/ui-showcase/src/main.ts +++ b/examples/ui-showcase/src/main.ts @@ -9,6 +9,7 @@ import '@codemonster-ru/ui-css/fonts.css'; // CmThemeSwitch was flipping the attribute and the token values correctly, but nothing on the page // was ever reading them. The Razor example already loads this same bundle wholesale. import '@codemonster-ru/ui-css/styles.css'; +import '@codemonster-ru/ui-utilities/utilities.css'; import App from './App.vue'; import './showcase.css'; diff --git a/package-lock.json b/package-lock.json index 80e337cb..3905cc43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,7 @@ "@codemonster-ru/ui-icons": "file:../../packages/icons", "@codemonster-ru/ui-layouts": "file:../../packages/layouts", "@codemonster-ru/ui-tokens": "file:../../packages/tokens", + "@codemonster-ru/ui-utilities": "file:../../packages/utilities", "@codemonster-ru/ui-vue": "file:../../packages/vue", "vue": "^3.5.20" },