From 1bed8e4b74eed78c40b532d83c5ad08c7dc1f779 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Wed, 30 Sep 2026 16:18:13 +0530 Subject: [PATCH] feat(ui): component redesign pass and fixes, release ui 0.8.87 Redesign - Shared field foundation rules (duplicated across 15 form components and emitted globally) are now identical everywhere, so later copies no longer silently override earlier redesigns. - Drawn checkbox and radio controls, white switch thumbs (the thumb was the text colour, a black blob in light mode), recessed field wells, keycap actions in Modal, Drawer, Popover, Toaster, Pagination, Stepper, DataTable. - Menus (Dropdown, ContextMenu, Popover, Select dropdown, Navbar panels) share one flat raised panel with neutral hover rows and mono section labels. - Alerts with an accent rail and icon chip; card headers without the grey band; accordion, collapse, list, list group, timeline, stats, metrics, chat, skeleton, avatar group, clipboard, splitter, section, sidebar, navbar and upload progress restyled. - Chart rebuilt: nice y-axis ticks, gridlines, rounded bars, line and area modes, hover tooltips, hidden series leave the scale. Fixes - Checkbox and radio labels toggle their input again (empty for="" broke it). - TimePicker kept every clicked time pressed; only the chosen hour and minute are pressed now, and nothing is pressed before a value exists. - ColorPicker hex readout now follows the picked colour. - Disabled FileInput no longer shows the native file-input text. - Date and time panels float instead of pushing content. - ContextMenu opened at the pointer closes on scroll. - Drawer left/top/bottom placements slide from their own edge again. - Image-only Card no longer renders an empty body strip. - Timeline supports item.time, current/upcoming states, sizes and compact/alternate variants; showcase demos use distinct variants. - ChatBubble: delivery receipts (sending/sent/delivered/read/failed/error) and meta aligned to its bubble. Co-Authored-By: Claude Opus 5.5 --- bun.lock | 2 +- .../component-showcase/app/pages/base.wrn | 2 +- .../app/pages/components/chat-bubble.wrn | 148 +++++++- .../app/pages/components/drawer.wrn | 40 ++- .../app/pages/components/section.wrn | 11 +- .../app/pages/components/timeline.wrn | 10 +- .../component-showcase/app/pages/index.wrn | 4 +- .../component-showcase/app/pages/layout.wrn | 2 +- .../component-showcase/app/pages/overlays.wrn | 2 +- .../scripts/generate-showcase.mjs | 2 +- .../scripts/showcase-profiles.mjs | 30 +- .../component-showcase/showcase-manifest.json | 4 +- packages/ui/components/Accordion.wrn | 31 +- packages/ui/components/AdvancedSelect.wrn | 19 +- packages/ui/components/AnnouncementBar.wrn | 8 +- packages/ui/components/AuthForm.wrn | 2 +- packages/ui/components/AuthSplitLayout.wrn | 2 +- packages/ui/components/AvatarGroup.wrn | 79 +++-- packages/ui/components/BackToTop.wrn | 1 - packages/ui/components/Blockquote.wrn | 6 +- packages/ui/components/Breadcrumb.wrn | 45 ++- packages/ui/components/ButtonGroup.wrn | 2 +- packages/ui/components/CTASection.wrn | 9 +- packages/ui/components/Card.wrn | 46 ++- packages/ui/components/Carousel.wrn | 2 +- packages/ui/components/Chart.wrn | 322 +++++++++++++++--- packages/ui/components/ChatBubble.wrn | 127 +++++-- packages/ui/components/Clipboard.wrn | 98 +++++- packages/ui/components/Collapse.wrn | 108 ++++-- packages/ui/components/ColorPicker.wrn | 195 ++++++++--- packages/ui/components/Combobox.wrn | 4 +- packages/ui/components/ContextMenu.wrn | 90 ++--- packages/ui/components/DataTable.wrn | 131 ++++--- packages/ui/components/DatePicker.wrn | 233 +++++++++---- packages/ui/components/DeviceFrame.wrn | 2 +- packages/ui/components/Drawer.wrn | 58 ++-- packages/ui/components/Dropdown.wrn | 98 +++--- packages/ui/components/FeatureCard.wrn | 22 +- packages/ui/components/FeatureGrid.wrn | 2 +- packages/ui/components/FileInput.wrn | 180 +++++++--- packages/ui/components/FileUploadProgress.wrn | 279 ++++++++++++--- packages/ui/components/Hero.wrn | 1 - packages/ui/components/InputGroup.wrn | 173 +++++++--- packages/ui/components/InputNumber.wrn | 66 +++- packages/ui/components/Kbd.wrn | 18 +- packages/ui/components/LayoutSplitter.wrn | 78 ++++- packages/ui/components/LegendIndicator.wrn | 26 +- packages/ui/components/List.wrn | 126 ++++++- packages/ui/components/ListGroup.wrn | 29 +- packages/ui/components/MetricCard.wrn | 98 +++--- packages/ui/components/MetricGrid.wrn | 9 +- packages/ui/components/Modal.wrn | 76 +++-- packages/ui/components/Nav.wrn | 34 +- packages/ui/components/Navbar.wrn | 141 ++++---- packages/ui/components/PageHeader.wrn | 1 - packages/ui/components/Pagination.wrn | 44 ++- packages/ui/components/PinInput.wrn | 45 ++- packages/ui/components/Popover.wrn | 88 ++--- packages/ui/components/PortalDashboard.wrn | 2 +- packages/ui/components/PreferenceSwitcher.wrn | 2 +- packages/ui/components/RangeSlider.wrn | 190 +++++++---- packages/ui/components/Rating.wrn | 26 +- packages/ui/components/Scrollspy.wrn | 9 +- packages/ui/components/SearchBox.wrn | 41 ++- packages/ui/components/Section.wrn | 70 ++++ packages/ui/components/Sidebar.wrn | 79 +++-- packages/ui/components/SplitHero.wrn | 9 +- packages/ui/components/StatsBar.wrn | 70 ++-- packages/ui/components/Stepper.wrn | 112 ++++-- packages/ui/components/StrongPassword.wrn | 184 ++++++---- packages/ui/components/TimePicker.wrn | 187 +++++++--- packages/ui/components/Timeline.wrn | 188 +++++++++- packages/ui/components/Toaster.wrn | 33 +- packages/ui/components/ToggleCount.wrn | 61 ++-- packages/ui/components/TogglePassword.wrn | 168 +++++---- packages/ui/components/TreeView.wrn | 43 ++- packages/ui/components/alert.wrn | 53 +-- packages/ui/components/avatar.wrn | 32 +- packages/ui/components/badge.wrn | 35 +- packages/ui/components/checkbox.wrn | 202 ++++++++--- packages/ui/components/input.wrn | 133 +++++--- packages/ui/components/progress.wrn | 39 ++- packages/ui/components/radio.wrn | 190 ++++++++--- packages/ui/components/select.wrn | 146 +++++--- packages/ui/components/skeleton.wrn | 82 +++-- packages/ui/components/spinner.wrn | 5 +- packages/ui/components/switch.wrn | 183 ++++++---- packages/ui/components/textarea.wrn | 135 +++++--- packages/ui/components/tooltip.wrn | 22 +- packages/ui/package.json | 2 +- packages/ui/styles/SelectStyles.wrn | 97 +++--- packages/ui/test/component-audit.test.ts | 4 +- packages/ui/test/ui.test.ts | 9 +- 93 files changed, 4439 insertions(+), 1915 deletions(-) diff --git a/bun.lock b/bun.lock index 85c4171e..cc1f47ee 100644 --- a/bun.lock +++ b/bun.lock @@ -749,7 +749,7 @@ }, "packages/ui": { "name": "@wrnexus/ui", - "version": "0.8.86", + "version": "0.8.87", "dependencies": { "@wrnexus/core": "workspace:*", }, diff --git a/examples/component-showcase/app/pages/base.wrn b/examples/component-showcase/app/pages/base.wrn index 46c41920..e8fe247a 100644 --- a/examples/component-showcase/app/pages/base.wrn +++ b/examples/component-showcase/app/pages/base.wrn @@ -116,7 +116,7 @@ page BaseShowcase {
-
+
Base

Chat Bubble

Theme-aware, responsive chat bubble component.

diff --git a/examples/component-showcase/app/pages/components/chat-bubble.wrn b/examples/component-showcase/app/pages/components/chat-bubble.wrn index ccdfe7a2..bead6e53 100644 --- a/examples/component-showcase/app/pages/components/chat-bubble.wrn +++ b/examples/component-showcase/app/pages/components/chat-bubble.wrn @@ -5,7 +5,7 @@ page ChatBubbleDetail { state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary" state playground_title = ctx.url.searchParams.get("pg_title") ?? "" state playground_description = ctx.url.searchParams.get("pg_description") ?? "" - state playground_items = JSON.parse(ctx.url.searchParams.get("pg_items") ?? "[{\"text\":\"Hi Maya, is the new dashboard ready to review?\",\"direction\":\"incoming\",\"timestamp\":\"10:24\"},{\"text\":\"Yes! I have shared the latest version with you.\",\"direction\":\"outgoing\",\"timestamp\":\"10:25\",\"status\":\"Delivered\"},{\"text\":\"Thanks, I will take a look this afternoon.\",\"direction\":\"incoming\",\"timestamp\":\"10:26\"}]") + state playground_items = JSON.parse(ctx.url.searchParams.get("pg_items") ?? "[{\"text\":\"Hi Maya, is the new dashboard ready to review?\",\"direction\":\"incoming\",\"timestamp\":\"10:24\"},{\"text\":\"Yes! I have shared the latest version with you.\",\"direction\":\"outgoing\",\"timestamp\":\"10:25\",\"receipt\":\"read\"},{\"text\":\"Thanks, I will take a look this afternoon.\",\"direction\":\"incoming\",\"timestamp\":\"10:26\"},{\"text\":\"Great. The release notes are attached too.\",\"direction\":\"outgoing\",\"timestamp\":\"10:27\",\"receipt\":\"delivered\"},{\"text\":\"One more screenshot coming up.\",\"direction\":\"outgoing\",\"timestamp\":\"10:28\",\"receipt\":\"sent\"},{\"text\":\"Uploading the final export now.\",\"direction\":\"outgoing\",\"timestamp\":\"10:29\",\"receipt\":\"sending\"},{\"text\":\"Here is the invoice PDF.\",\"direction\":\"outgoing\",\"timestamp\":\"10:30\",\"receipt\":\"failed\",\"status\":\"Not delivered\",\"actionLabel\":\"Retry\"}]") state playground_oneSided = (ctx.url.searchParams.get("pg_oneSided") ?? "false") === "true" state playground_showAvatars = (ctx.url.searchParams.get("pg_showAvatars") ?? "false") === "true" state playground_showMetadata = (ctx.url.searchParams.get("pg_showMetadata") ?? "true") === "true" @@ -48,12 +48,38 @@ page ChatBubbleDetail { "text": "Yes! I have shared the latest version with you.", "direction": "outgoing", "timestamp": "10:25", - "status": "Delivered" + "receipt": "read" }, { "text": "Thanks, I will take a look this afternoon.", "direction": "incoming", "timestamp": "10:26" + }, + { + "text": "Great. The release notes are attached too.", + "direction": "outgoing", + "timestamp": "10:27", + "receipt": "delivered" + }, + { + "text": "One more screenshot coming up.", + "direction": "outgoing", + "timestamp": "10:28", + "receipt": "sent" + }, + { + "text": "Uploading the final export now.", + "direction": "outgoing", + "timestamp": "10:29", + "receipt": "sending" + }, + { + "text": "Here is the invoice PDF.", + "direction": "outgoing", + "timestamp": "10:30", + "receipt": "failed", + "status": "Not delivered", + "actionLabel": "Retry" } ] view { @@ -79,12 +105,38 @@ page ChatBubbleDetail { "text": "Yes! I have shared the latest version with you.", "direction": "outgoing", "timestamp": "10:25", - "status": "Delivered" + "receipt": "read" }, { "text": "Thanks, I will take a look this afternoon.", "direction": "incoming", "timestamp": "10:26" + }, + { + "text": "Great. The release notes are attached too.", + "direction": "outgoing", + "timestamp": "10:27", + "receipt": "delivered" + }, + { + "text": "One more screenshot coming up.", + "direction": "outgoing", + "timestamp": "10:28", + "receipt": "sent" + }, + { + "text": "Uploading the final export now.", + "direction": "outgoing", + "timestamp": "10:29", + "receipt": "sending" + }, + { + "text": "Here is the invoice PDF.", + "direction": "outgoing", + "timestamp": "10:30", + "receipt": "failed", + "status": "Not delivered", + "actionLabel": "Retry" } ]
@@ -102,7 +154,7 @@ page ChatBubbleDetail {
Live preview
-
+
Component usage.wrn
@@ -117,12 +169,38 @@ page ChatBubbleDetail { "text": "Yes! I have shared the latest version with you.", "direction": "outgoing", "timestamp": "10:25", - "status": "Delivered" + "receipt": "read" }, { "text": "Thanks, I will take a look this afternoon.", "direction": "incoming", "timestamp": "10:26" + }, + { + "text": "Great. The release notes are attached too.", + "direction": "outgoing", + "timestamp": "10:27", + "receipt": "delivered" + }, + { + "text": "One more screenshot coming up.", + "direction": "outgoing", + "timestamp": "10:28", + "receipt": "sent" + }, + { + "text": "Uploading the final export now.", + "direction": "outgoing", + "timestamp": "10:29", + "receipt": "sending" + }, + { + "text": "Here is the invoice PDF.", + "direction": "outgoing", + "timestamp": "10:30", + "receipt": "failed", + "status": "Not delivered", + "actionLabel": "Retry" } ] view { @@ -144,7 +222,7 @@ page ChatBubbleDetail {
Live preview
-
+
Component usage.wrn
@@ -159,12 +237,38 @@ page ChatBubbleDetail { "text": "Yes! I have shared the latest version with you.", "direction": "outgoing", "timestamp": "10:25", - "status": "Delivered" + "receipt": "read" }, { "text": "Thanks, I will take a look this afternoon.", "direction": "incoming", "timestamp": "10:26" + }, + { + "text": "Great. The release notes are attached too.", + "direction": "outgoing", + "timestamp": "10:27", + "receipt": "delivered" + }, + { + "text": "One more screenshot coming up.", + "direction": "outgoing", + "timestamp": "10:28", + "receipt": "sent" + }, + { + "text": "Uploading the final export now.", + "direction": "outgoing", + "timestamp": "10:29", + "receipt": "sending" + }, + { + "text": "Here is the invoice PDF.", + "direction": "outgoing", + "timestamp": "10:30", + "receipt": "failed", + "status": "Not delivered", + "actionLabel": "Retry" } ] view { @@ -186,7 +290,7 @@ page ChatBubbleDetail {
Live preview
-
+
Component usage.wrn
@@ -201,12 +305,38 @@ page ChatBubbleDetail { "text": "Yes! I have shared the latest version with you.", "direction": "outgoing", "timestamp": "10:25", - "status": "Delivered" + "receipt": "read" }, { "text": "Thanks, I will take a look this afternoon.", "direction": "incoming", "timestamp": "10:26" + }, + { + "text": "Great. The release notes are attached too.", + "direction": "outgoing", + "timestamp": "10:27", + "receipt": "delivered" + }, + { + "text": "One more screenshot coming up.", + "direction": "outgoing", + "timestamp": "10:28", + "receipt": "sent" + }, + { + "text": "Uploading the final export now.", + "direction": "outgoing", + "timestamp": "10:29", + "receipt": "sending" + }, + { + "text": "Here is the invoice PDF.", + "direction": "outgoing", + "timestamp": "10:30", + "receipt": "failed", + "status": "Not delivered", + "actionLabel": "Retry" } ] view { diff --git a/examples/component-showcase/app/pages/components/drawer.wrn b/examples/component-showcase/app/pages/components/drawer.wrn index 2036c8e9..0df47a1b 100644 --- a/examples/component-showcase/app/pages/components/drawer.wrn +++ b/examples/component-showcase/app/pages/components/drawer.wrn @@ -179,6 +179,44 @@ page DrawerDetail { <div data-slot="footer"> <div class="showcase-slot">footer slot</div> </div> +</Drawer> +
+ +
+
+
+
Compact

Top notice drawer

Slide a panel down from the top edge for announcements, search, or quick settings.

+ 04 +
+
+
+
Live preview
+

Click the trigger to open the drawer

+

Save your work before the window starts.

+
+
+
Component usage.wrn
+
<Drawer
+  placement="top"
+  size="sm"
+  variant="success"
+  title="Scheduled maintenance"
+  description="The workspace will be read-only on Sunday from 02:00 to 03:00 UTC."
+  icon="icon-[lucide--trash-2]"
+  label="Advanced example"
+  closeLabel="Advanced example"
+  triggerLabel="Open top drawer"
+  triggerIcon="icon-[lucide--panel-top-open]">
+  <div data-slot="trigger">
+    <div class="showcase-slot">trigger slot</div>
+  </div>
+  <div data-slot="header">
+    <div class="showcase-slot">header slot</div>
+  </div>
+  <div class="showcase-overlay-content"><p>Save your work before the window starts.</p></div>
+  <div data-slot="footer">
+    <div class="showcase-slot">footer slot</div>
+  </div>
 </Drawer>
@@ -205,7 +243,7 @@ if (component) registerOutputHandler(component, "cancel", (payload) =>
Component API

Props and configuration

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

PropTypeDefaultRequired
openbooleanfalseNo
defaultOpenbooleanfalseNo
placementstring"right"No
sizestring"md"No
colorstring"primary"No
variantstring"default"No
titlestring"Drawer"No
descriptionstring""No
iconstring""No
labelstring"Drawer"No
closeLabelstring"Close drawer"No
showClosebooleantrueNo
closeOnBackdropbooleantrueNo
closeOnEscapebooleantrueNo
durationnumber260No
overlaybooleantrueNo
scrollablebooleantrueNo
triggerLabelstring""No
triggerIconstring""No
classstring""No