From 8aa28205e03d5805b9d121264ce9b3f724f7b16a Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Sat, 8 Aug 2026 11:33:59 +0530 Subject: [PATCH] refactor(ui): migrate the layout components off Tailwind utilities Container, Columns, Grid, Divider, Image, Link, Typography and Kbd were built from utility classes and class: conditionals. That works only where Tailwind is present, and every variant cost a dozen conditional lines -- Divider spent eleven of them saying which token to paint the rule. They now carry wire-* classes with a local style block, and variants are data attributes the style block selects on. Divider went from eleven conditionals to five rules, and Typography lost thirteen. Behaviour is preserved rather than improved on. Container keeps columns and gap even though a container is not really a grid, because applications depend on them, and its columns default stays 2: the redesign contract test caught that changing it would silently reflow every Container already published. Additive only: Grid gains minItemWidth for an auto-fit track, Divider gains dashed and dotted variants, Image gains fit, and Link gains underline. Verified in a browser rather than by eye, since the pane cannot screenshot: track counts match the declared columns at desktop and collapse correctly below each breakpoint. Co-Authored-By: Claude Opus 5 --- docs/ui-visual-contract-0.8.json | 16 +- .../app/pages/components/container.wrn | 17 +- .../app/pages/components/divider.wrn | 19 +- .../app/pages/components/grid.wrn | 11 +- .../app/pages/components/image.wrn | 11 +- .../app/pages/components/kbd.wrn | 2 +- .../app/pages/components/link.wrn | 11 +- .../component-showcase/app/pages/layout.wrn | 14 +- .../component-showcase/showcase-manifest.json | 10 +- packages/ui/COMPONENTS.md | 12 +- packages/ui/component-reference.json | 37 +++- packages/ui/components/Columns.wrn | 102 +++++++++-- packages/ui/components/Image.wrn | 130 +++++++++++--- packages/ui/components/Kbd.wrn | 50 +++++- packages/ui/components/Link.wrn | 138 +++++++++++--- packages/ui/components/Typography.wrn | 76 ++++++-- packages/ui/components/container.wrn | 164 ++++++++++++++--- packages/ui/components/divider.wrn | 170 +++++++++++++----- packages/ui/components/grid.wrn | 136 ++++++++++++-- packages/ui/test/ui.test.ts | 39 ++++ 20 files changed, 935 insertions(+), 230 deletions(-) diff --git a/docs/ui-visual-contract-0.8.json b/docs/ui-visual-contract-0.8.json index 61110915..80c52d50 100644 --- a/docs/ui-visual-contract-0.8.json +++ b/docs/ui-visual-contract-0.8.json @@ -23,10 +23,10 @@ "packages/ui/components/Clipboard.wrn": "bb8651c7e44517db827603d0c0e546b6891093d7e6589c0b6e45d91b6187591b", "packages/ui/components/Collapse.wrn": "c537239831c6938f3c39be0ca3ae8ba928c2490e21cfe5853c10f7221a4678ca", "packages/ui/components/ColorPicker.wrn": "6940b7ae48f1358008b8c3ae6dc7da31f96a1aefadeef18252568b2cda0b5cbf", - "packages/ui/components/Columns.wrn": "449a427c2f4dd846b5239b73efe5b8d15ad4f20fa28598802a5eb57c33332391", + "packages/ui/components/Columns.wrn": "e01496aa53025444cc51671efcce40d6d24d86775b2cbb1ee0def1862bb6315d", "packages/ui/components/Combobox.wrn": "62a7d861b0e536ceb088cea3552c59acbafaea5184101e3651dc8f4976b99dbc", "packages/ui/components/Confetti.wrn": "22d687beefd5047055f65e806b4e39f81e18887532ec18d439ac364a044b230a", - "packages/ui/components/Container.wrn": "be8fce140043eced8b78c8dd14ff85ace4ed2d91671251641ef83e0fe4da8f2a", + "packages/ui/components/Container.wrn": "4a0acbb896f4c11714e3925d912b10ef9aeedfa904b4ad8561aa2cbd9a0fdca0", "packages/ui/components/ContextMenu.wrn": "2e011e9cb1c09a3a2344ed3fa29dcc74331cd39f838535d8aee4b249dceef0ce", "packages/ui/components/CopyMarkup.wrn": "8d57a7d72e02c126f855a181fc36e1b969edb90f683dce6b6ffe546d49d2b29b", "packages/ui/components/CustomScrollbar.wrn": "fedb2ab06cc2cf9499c130590945ca6971a3edfb60407b6658ef7756e4be9823", @@ -34,7 +34,7 @@ "packages/ui/components/DataTable.wrn": "5a76e50e8559c724aaf01ec954958ac640c99758d44f1eef8e6eb1cb6dc4f862", "packages/ui/components/DatePicker.wrn": "18b07e59c27c2720bf960e9c04ad70d9e422ddcf0817fede74e71899811bb387", "packages/ui/components/DeviceFrame.wrn": "a881cf2cc1f859b43cc3c7a1e1ca0fb40cea7a9e530ab5bdcb985aa9592d11c0", - "packages/ui/components/Divider.wrn": "e377f8005249cf4f6c51dd4d04ff9c6a70a3f4e3a79d2c02a8ab601754c8553a", + "packages/ui/components/Divider.wrn": "f5cc449611022b3d3eedf982ae48f6b1a289db7855cc9b6ea0248dcda807ffb3", "packages/ui/components/DragAndDrop.wrn": "9a403ce9ed20d36211d8916911871875c9c7d0952a7de1a21a433eaa0b3c3324", "packages/ui/components/Drawer.wrn": "04a77a69edfad6793b5ab60981a719f11061984c087d0d61663566e322649fef", "packages/ui/components/Dropdown.wrn": "c61b46ae6e54f6aacac9f4ed422f6c659deea9a637fd944645acd37bf270b01d", @@ -45,17 +45,17 @@ "packages/ui/components/FileUpload.wrn": "3346d8978e134c3a1e6bc742201a3fbb0cffb89da40da6fcd856a2adbb971393", "packages/ui/components/FileUploadProgress.wrn": "83bcc8558c70fbe0e0670642f65998abd222c235f1031be46bd7c65e6b5c5154", "packages/ui/components/Footer.wrn": "a5dfaa5f9548b7fdd4b556c63428e0ea8d22e5e776a5714d76619999438cf618", - "packages/ui/components/Grid.wrn": "b5546b899c509c1f3e8f5edad801bc59acf9fe3008a627f0e4476cd61b5b672e", + "packages/ui/components/Grid.wrn": "d089d8657298b4d33993ba4bf7b581f816c65db513d8e48cf1fdd18da19e05a8", "packages/ui/components/Hero.wrn": "e4e39dcd59c273192c7e4136f6583279e20b0956bcba4cfbc3f6e01a1fade152", "packages/ui/components/HeroActions.wrn": "c5720efe2ce7f6c114eb2ea4ccc3e8102a1099078ba23fd13770eddeb6aec640", - "packages/ui/components/Image.wrn": "4294358e2eddf06ae4384217dbff7693b609c16bf6549f54d6ad27df74d7ae27", + "packages/ui/components/Image.wrn": "8113441bf90ab0d1d8618d477125ad339021f39e853db89d656c72c492e7a20b", "packages/ui/components/Input.wrn": "9ad394eed60f1b05bbd2ccd50dc2de7b78245c52c87afd46055d772c38b7b0c9", "packages/ui/components/InputGroup.wrn": "0e23ea541a60e893c9d9e6f95113911ee459468d8d6105bf03aeb55395359123", "packages/ui/components/InputNumber.wrn": "a0aa4f4566bf54ffbef54c99648eab05b5f9870be6ea07639a4ecf3930afb631", - "packages/ui/components/Kbd.wrn": "d51fa614b36f971f885410785b481c2e6900b2416e6e7c8868dfda1ebd5f3b4c", + "packages/ui/components/Kbd.wrn": "5afaabbb15902bd8fb82cb4155cf6cbfff55600927b54d564d27e2dd8b752386", "packages/ui/components/LayoutSplitter.wrn": "a86dc54b74aed6b05e770cd1802960d6309bba42fe80e899e8aaa8b1b7aa88e3", "packages/ui/components/LegendIndicator.wrn": "6a7607b27a17196f899132eb952203a1073e4077365a94935f485e700cbac665", - "packages/ui/components/Link.wrn": "935ac24e8ebd067860dc9709ea9121710315ad6e02ce95cd5e982ae4d5978a02", + "packages/ui/components/Link.wrn": "b986abcc66bc0b1c6296f3ff4e560812e35d89cc680d5251d7a3883e68c1d053", "packages/ui/components/List.wrn": "02f960a8e82fa049aac477bac9c1d9371394c86d9c47513138f61bffc79dc7d8", "packages/ui/components/ListGroup.wrn": "37e2ec61ceab20ed020a834da03208c493702b41abcf586816e29f2e50d8ee11", "packages/ui/components/Map.wrn": "7b8a0d5412a464fd7cab8977d816542c506d8c5dab8230a3c984c2caee407c91", @@ -101,7 +101,7 @@ "packages/ui/components/TogglePassword.wrn": "405a85cbfa3d0ff0185b52d2805fba88497a5f25501f01b2438ed3a28591a38d", "packages/ui/components/Tooltip.wrn": "e6c8c14a75062d04a2e64245df1a40e67785240573c73bae4b0b32e76ef822bc", "packages/ui/components/TreeView.wrn": "1791a10135595b17b5c746af9e0476e8520d516ba46d64c79dc4efe0af2b500d", - "packages/ui/components/Typography.wrn": "a667e800e11d23da74b00047bd9c560a65a5920e5394f58f66a6e0b32572ce8e", + "packages/ui/components/Typography.wrn": "1b4d1b91dee0ff522d27c566becc3bc49bd9ec979ae6334e6a15fca5d88eccac", "packages/ui/components/WysiwygEditor.wrn": "636e60b9f9be7a5807cca7ad20e0b0f370ee1ec6c1ecba5d0a577726cc86bc98", "packages/ui/components/alert.wrn": "a6020b3fbf02481f76cea4cfa563a7165c7ccc2920492f6f6b79e98cbf2cf0fa", "packages/ui/components/avatar.wrn": "571b70790aff28a5b7d6adbf0196e77ece1ce153a95b384148cb2bb5f74ab2e9", diff --git a/examples/component-showcase/app/pages/components/container.wrn b/examples/component-showcase/app/pages/components/container.wrn index 6393e285..d9ae8686 100644 --- a/examples/component-showcase/app/pages/components/container.wrn +++ b/examples/component-showcase/app/pages/components/container.wrn @@ -6,6 +6,7 @@ page ContainerDetail { state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2") state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md" state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl" + state playground_centered = (ctx.url.searchParams.get("pg_centered") ?? "true") === "true" state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1" seo { title = "Container" @@ -20,7 +21,7 @@ page ContainerDetail { Layout component

Container

Constrain and align page content with responsive gutters and compact, wide, or full width options.

-
6 props1 slots0 outputsTheme readyResponsive
+
7 props1 slots0 outputsTheme readyResponsive
@@ -29,7 +30,7 @@ page ContainerDetail {
Live preview
-
Centered container content
+
Centered container content
Component code
<Container>
@@ -40,8 +41,8 @@ page ContainerDetail {
           
         
-
Component props6 controls
-
+
Component props7 controls
+
@@ -57,7 +58,7 @@ page ContainerDetail {
Live preview
-
Centered container content
+
Centered container content
Component usage.wrn
@@ -76,7 +77,7 @@ page ContainerDetail {
Live preview
-
Compact readable content
+
Compact readable content
Component usage.wrn
@@ -97,7 +98,7 @@ page ContainerDetail {
Live preview
-
Full-width dashboard content
+
Full-width dashboard content
Component usage.wrn
@@ -110,7 +111,7 @@ page ContainerDetail {
-
Component API

Props and configuration

All content and behavior shown above is supplied through these props and slots.

PropTypeDefaultRequired
sizestring"default"No
colorstring"primary"No
columnsnumber2No
gapstring"md"No
maxWidthstring"xl"No
classstring""No
+
Component API

Props and configuration

All content and behavior shown above is supplied through these props and slots.

PropTypeDefaultRequired
sizestring"default"No
colorstring"primary"No
columnsnumber2No
gapstring"md"No
maxWidthstring"xl"No
centeredbooleantrueNo
classstring""No
@@ -56,7 +57,7 @@ page DividerDetail {
Live preview
-
+
Component usage.wrn
@@ -75,12 +76,13 @@ page DividerDetail {
Live preview
-
+
Component usage.wrn
<Divider
   size="sm"
+  variant="secondary"
 />
@@ -94,7 +96,7 @@ page DividerDetail {
Live preview
-
+
Component usage.wrn
@@ -103,12 +105,13 @@ page DividerDetail { color="info" label="Actions" orientation="vertical" + variant="success" />
-
Component API

Props and configuration

All content and behavior shown above is supplied through these props and slots.

PropTypeDefaultRequired
sizestring"default"No
colorstring"primary"No
labelstring""No
orientationstring"horizontal"No
classstring""No
+
Component API

Props and configuration

All content and behavior shown above is supplied through these props and slots.

PropTypeDefaultRequired
sizestring"default"No
colorstring"primary"No
labelstring""No
orientationstring"horizontal"No
variantstring"solid"No
classstring""No
@@ -112,7 +113,7 @@ page GridDetail { -
Component API

Props and configuration

All content and behavior shown above is supplied through these props and slots.

PropTypeDefaultRequired
sizestring"default"No
colorstring"primary"No
columnsnumber2No
gapstring"md"No
maxWidthstring"xl"No
classstring""No
+
Component API

Props and configuration

All content and behavior shown above is supplied through these props and slots.

PropTypeDefaultRequired
sizestring"default"No
colorstring"primary"No
columnsnumber2No
gapstring"md"No
maxWidthstring"xl"No
minItemWidthstring""No
classstring""No