From f9e285b1821344745d9eceb646ad1277d1fc5ddf Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Mon, 24 Aug 2026 19:44:26 +0530 Subject: [PATCH] feat(ui): own responsive marketing layout APIs --- bun.lock | 2 +- docs/ui-visual-contract-0.8.json | 20 +- packages/ui/COMPONENTS.md | 22 +- packages/ui/component-reference.json | 382 +++++++++++++++++- packages/ui/components/AnnouncementBar.wrn | 21 + packages/ui/components/CTASection.wrn | 17 +- packages/ui/components/Card.wrn | 14 +- packages/ui/components/FeatureIconCard.wrn | 11 +- packages/ui/components/Footer.wrn | 6 + packages/ui/components/Navbar.wrn | 64 ++- packages/ui/components/PreferenceSwitcher.wrn | 37 +- packages/ui/components/Scrollspy.wrn | 8 + packages/ui/components/SplitHero.wrn | 16 + packages/ui/components/StatsBar.wrn | 12 + packages/ui/package.json | 2 +- 15 files changed, 589 insertions(+), 45 deletions(-) diff --git a/bun.lock b/bun.lock index 3aa67c29..a9d651c3 100644 --- a/bun.lock +++ b/bun.lock @@ -688,7 +688,7 @@ }, "packages/ui": { "name": "@wrnexus/ui", - "version": "0.8.25", + "version": "0.8.26", "dependencies": { "@wrnexus/core": "workspace:*", }, diff --git a/docs/ui-visual-contract-0.8.json b/docs/ui-visual-contract-0.8.json index 9071dcc9..3b0c2e6e 100644 --- a/docs/ui-visual-contract-0.8.json +++ b/docs/ui-visual-contract-0.8.json @@ -4,7 +4,7 @@ "artifacts": { "packages/ui/components/Accordion.wrn": "09251f76a2f9385e97eb67e06c0cf868e1771ac5f420647221bec5160287034b", "packages/ui/components/AdvancedSelect.wrn": "b952b894a5b35050fc2f6e43c4182101eeee05c75662e2aca4abfe61512b305b", - "packages/ui/components/AnnouncementBar.wrn": "cb66b8d0619ee798a115b43f0ad93fda93dfb46571589e7a9f0a8d65ec3c84c9", + "packages/ui/components/AnnouncementBar.wrn": "a44f9ecf2cfbda2bbb71a81a50a3666de9ba3f9d185bc28f0035d5eebc602fad", "packages/ui/components/AuthForm.wrn": "46a3e1db1c9e69efc52473cbf2fababdcbfe7144e7571469638d2c3addd4d7f0", "packages/ui/components/AuthSplitLayout.wrn": "724938921bc38cc5a0422de69c237b630f099f2df94c66977362b048e4a420a5", "packages/ui/components/AvatarGroup.wrn": "30b702e06a1adff8b9bae32820206020e086a69560cbdcbadb19f04f25951f97", @@ -12,8 +12,8 @@ "packages/ui/components/Blockquote.wrn": "3761bf13babb6eb07ce7392258ee439ef5478064cf589eff63f945b950e00d2e", "packages/ui/components/Breadcrumb.wrn": "9f6c23550ebfc635c36ca8660953775170b4a471c0cd0206b9a7ba760994980a", "packages/ui/components/ButtonGroup.wrn": "fc23565ad56bd8483fcb777d9e02ccba2f9ea476c085754d42503bb83b718f72", - "packages/ui/components/CTASection.wrn": "f5289a08c14359e947eb49293f8a1ed36475bb07ff8c5247edc87c1469465de5", - "packages/ui/components/Card.wrn": "3cc2ff238bda279c169026a462236144ad11ec0046deef00ab00e001a07e8a4c", + "packages/ui/components/CTASection.wrn": "f6872b980432d5ee9d88388250be9838ccce51bd706349b283ef472ee692b237", + "packages/ui/components/Card.wrn": "be8cd6a438d1ede4c284a302b76f0fbc235a2423b83a7ced21131763fecc8a90", "packages/ui/components/Carousel.wrn": "e7d921f802aa19210f3f415b59b70750a2c8d78e30684ad334809741c70a6bf9", "packages/ui/components/Chart.wrn": "07bc01247b5a1c2b82c2ba8386b7fcdbf480efead75d52b7da04d471072c7ee4", "packages/ui/components/ChatBubble.wrn": "d71f7d6567d76ac0eb3ecc8e2e567fec12bb3236ea05f4d0a72286abc0b7cbb1", @@ -36,10 +36,10 @@ "packages/ui/components/Dropdown.wrn": "978367a9dde22448cc664d686e4dd9c579fe8ba0b2cf02d610d95a3501f8dbb0", "packages/ui/components/FeatureCard.wrn": "1bc548c115f924a0c7ade4c557852757083755c60ca0ee747b150a7cca3ebced", "packages/ui/components/FeatureGrid.wrn": "15b5d6f9ddb7e3697682e7247fdf3c2dd080b770335f84ba9fab2692166fe897", - "packages/ui/components/FeatureIconCard.wrn": "3b4f3fa62c6729e686886a5b848e26c255766684829cec2b715967b4e73d6f07", + "packages/ui/components/FeatureIconCard.wrn": "5f65d64235babc3e653a5695204412202015e6f3ffadca566fc18c7f9ce70428", "packages/ui/components/FileInput.wrn": "866a292a3280527bf429893469e7c50f7cf38965d8adb37b45a35ede1606d5b8", "packages/ui/components/FileUploadProgress.wrn": "e5da29c562a521cdd6bb50b8f4d217aa1ab981d7b2a2432af47391472f0a8034", - "packages/ui/components/Footer.wrn": "f7c5a77064a09e244f689d42475c4c20143f4c8859cac451c10a50c14652db33", + "packages/ui/components/Footer.wrn": "e3515e05ef3ef51e6dad71d67ddfe110c80fdcf69e952aecdc7973e69d4f08c7", "packages/ui/components/Grid.wrn": "83d4f5f2656d539538723f5791ba3c238901432e9d8c55c74f068d3eb5a74517", "packages/ui/components/Hero.wrn": "345478b212701817ff57060f87982a987baf01a7179c979768e1cd4218b50900", "packages/ui/components/HeroActions.wrn": "67cd31400ccb6abdbbf16219267dee946b44b064b79f25276d20ceb7d6e8a790", @@ -60,23 +60,23 @@ "packages/ui/components/MetricGrid.wrn": "1fcebf51dcbe8520fe16bda904c1ef206c25c3900438d53877492c64ea21a1a5", "packages/ui/components/Modal.wrn": "7fa4b877772736f29f690e24d8742922b310397ef3083f0b78acb67a9f0d14b2", "packages/ui/components/Nav.wrn": "c45b0ecb42250f4b3ede33c8932a025f789dda9ef48dbf332459ae458163e69a", - "packages/ui/components/Navbar.wrn": "24dc14494fd48090da3545207926c295d3a6f1afd53c6ca26994dabca7a91ee0", + "packages/ui/components/Navbar.wrn": "9095876ad737e9d85c6ba38963b777c29b54c095f024c4e7f4325067039fe07f", "packages/ui/components/PageHeader.wrn": "321cde36ce8d521a57901033d46e8b437f42e558cca27f49ca26f7172aff1d54", "packages/ui/components/Pagination.wrn": "d54226705d4556f76ee5f0d6ae82d101ca6d006397756d547a9aa5954415ba39", "packages/ui/components/PinInput.wrn": "4dc398456f6392d7925db941debb484c7cb0358ecef527f696fe5ec4800a7602", "packages/ui/components/Popover.wrn": "1246b99b4236bc7109a5d1427d013bb07bbea7a2da4f821517d2545ee0b5c019", "packages/ui/components/PortalDashboard.wrn": "f04171eb1f8cabef06de3c20e4694b766def3407e1e20d2c9aaebc9bb7da03ee", - "packages/ui/components/PreferenceSwitcher.wrn": "77229e15449182563ebf49159507139928eb74e799e4438e00e9aa81fd60f982", + "packages/ui/components/PreferenceSwitcher.wrn": "519cf911390f529fff3fd16e11fb58e79d618fe851902202dc37552ee1182395", "packages/ui/components/PublicPageShell.wrn": "3d3f25c03d48f3d3d7e3c567e79cb137c7fce1867e054fd6d440fa1d2e961077", "packages/ui/components/RangeSlider.wrn": "bbf646c5d5a89a62986290db811d77b8f635ebcaea9ca2d334b569aa5edc785b", "packages/ui/components/Rating.wrn": "902b55c64e3798f3097f09b1558d1a2372f66d4f760662de085783108ee04587", - "packages/ui/components/Scrollspy.wrn": "fb1b2014c7caca2d001d80952cc238c06f1722602f6c55f72281d13310f1bee2", + "packages/ui/components/Scrollspy.wrn": "4b452fcbd524feda9c9f2c81894ee01747a51888e3b86fafb37c5d4d192a3a51", "packages/ui/components/SearchBox.wrn": "3f88340e0b69c0cd552023c72bd22dc511bc00422d46060097bcf0777e683675", "packages/ui/components/Section.wrn": "78da13eb8bc1acafe8e6151cbaeed4baaac2ab860e3209f1d13c467f279d2e68", "packages/ui/components/SectionHeader.wrn": "aca2df8eb35806096f5b9af466b018e5c22a19422e8665f488380da577a0ceb5", "packages/ui/components/Sidebar.wrn": "e0250a973aea589a4d7dcc8b30dd01f22592bf22ba012e54a672b2a2288d8af6", - "packages/ui/components/SplitHero.wrn": "843387dc7b920b3cf6a1b2b785b8653c281982e524479edc2638a89381ff3577", - "packages/ui/components/StatsBar.wrn": "69e6592cbd48ba893ac3a495076c73c14f1779078b26fcb6d89e74ee4ea18d23", + "packages/ui/components/SplitHero.wrn": "7127cb869d1228522d066e028818dd9e512de8b6dd8f99e3dec500e6da5a3cb0", + "packages/ui/components/StatsBar.wrn": "6fabcb4374b1e074f58ebcaba968f235c8a3409762163aea51298e2515a14435", "packages/ui/components/Stepper.wrn": "7ec0902acd7cb74b44d490215b6421dae9a41731735ad1e9aec17e8bfc3fa142", "packages/ui/components/StrongPassword.wrn": "407eabcc13affc9323a346ddba8e39c81b885a59ef7043d2bd5567d4b7553282", "packages/ui/components/StyledIcon.wrn": "0874f9a234b053a7c8b9c6983be5d664453a64c4576dff1a049101e249a2866d", diff --git a/packages/ui/COMPONENTS.md b/packages/ui/COMPONENTS.md index d079a424..09de0529 100644 --- a/packages/ui/COMPONENTS.md +++ b/packages/ui/COMPONENTS.md @@ -146,7 +146,7 @@ Theme-aware, responsive button group component. Group related content in a responsive themed surface with title, description, content, and supporting slots. - Mount: `data-component="Card"` -- Props: `title: string = "Card title"`, `titleKey: string = ""`, `subtitle: string = ""`, `subtitleKey: string = ""`, `description: string = ""`, `descriptionKey: string = ""`, `header: string = ""`, `footer: string = ""`, `imageSrc: string = ""`, `imageAlt: string = ""`, `imagePosition: string = "top"`, `actionLabel: string = ""`, `actionLabelKey: string = ""`, `actionHref: string = ""`, `headerActions: unknown[] = []`, `navigation: unknown[] = []`, `activeNav: string = ""`, `mobileNavigation: boolean = false`, `alertTitle: string = ""`, `alertDescription: string = ""`, `empty: boolean = false`, `emptyTitle: string = "No data to show"`, `emptyIcon: string = "icon-[lucide--inbox]"`, `items: unknown[] = []`, `size: string = "md"`, `color: string = "primary"`, `variant: string = "default"`, `layout: string = "vertical"`, `align: string = "left"`, `hover: string = "none"`, `scrollable: boolean = false`, `maxHeight: string = "18rem"`, `dismissible: boolean = false`, `ariaLabel: string = ""`, `class: string = ""` +- Props: `title: string = ""`, `icon: string = ""`, `titleKey: string = ""`, `subtitle: string = ""`, `subtitleKey: string = ""`, `description: string = ""`, `descriptionKey: string = ""`, `header: string = ""`, `footer: string = ""`, `imageSrc: string = ""`, `imageAlt: string = ""`, `imagePosition: string = "top"`, `actionLabel: string = ""`, `actionLabelKey: string = ""`, `actionHref: string = ""`, `headerActions: unknown[] = []`, `navigation: unknown[] = []`, `activeNav: string = ""`, `mobileNavigation: boolean = false`, `alertTitle: string = ""`, `alertDescription: string = ""`, `empty: boolean = false`, `emptyTitle: string = "No data to show"`, `emptyIcon: string = "icon-[lucide--inbox]"`, `items: unknown[] = []`, `size: string = "md"`, `color: string = "primary"`, `variant: string = "default"`, `layout: string = "vertical"`, `align: string = "left"`, `hover: string = "none"`, `radius: string = "default"`, `shadow: string = "default"`, `equalHeight: boolean = false`, `scrollable: boolean = false`, `maxHeight: string = "18rem"`, `dismissible: boolean = false`, `ariaLabel: string = ""`, `class: string = ""` - Slots: `default` - Outputs: `click({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `action({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `navigate({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `dismiss({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `load({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `error({ error: Error | string; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | Error | string)` @@ -337,7 +337,7 @@ Reusable portal dashboard component. Reusable preference switcher component. - Mount: `data-component="PreferenceSwitcher"` -- Props: `size: string = "default"`, `color: string = "primary"`, `themeLabel: string = "Theme"`, `colorLabel: string = "Accent color"`, `languageLabel: string = "Language"`, `languages: string = [`, `colors: string = [`, `compact: boolean = true`, `class: string = ""` +- Props: `size: string = "default"`, `color: string = "primary"`, `themeLabel: string = "Theme"`, `colorLabel: string = "Accent color"`, `languageLabel: string = "Language"`, `languages: string = [`, `colors: string = [`, `compact: boolean = true`, `iconOnly: boolean = true`, `themeIcon: string = "icon-[lucide--sun-moon]"`, `colorIcon: string = "icon-[lucide--palette]"`, `languageIcon: string = "icon-[lucide--languages]"`, `panelPlacement: string = "bottom-end"`, `mobilePanel: string = "dropdown"`, `showCurrentLanguage: boolean = true`, `class: string = ""` - Slots: None - Outputs: `theme({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `color({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `language({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])` @@ -375,7 +375,7 @@ Arrange operational metrics, KPIs, public statistics, or service indicators in a Present a compact responsive strip of key facts, counts, performance indicators, or trust signals. - Mount: `data-component="StatsBar"` -- Props: `items: unknown[] = []`, `columns: number = 4`, `compact: boolean = true`, `dividers: boolean = true`, `icons: boolean = true`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "raised"`, `maxWidth: string = "xl"`, `class: string = ""` +- Props: `items: unknown[] = []`, `columns: number = 4`, `compact: boolean = true`, `dividers: boolean = true`, `icons: boolean = true`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "raised"`, `maxWidth: string = "xl"`, `radius: string = "default"`, `shadow: string = "default"`, `gutter: string = "md"`, `outerSpacing: string = "none"`, `mobileColumns: number = 1`, `class: string = ""` - Slots: None - Outputs: None @@ -606,7 +606,7 @@ Arrange feature cards, services, solutions, or benefits in a responsive equal-he Render structured responsive footer navigation, pre and post content, copyright content, links, and public events. - Mount: `data-component="Footer"` -- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Footer navigation"`, `items: unknown[] = []`, `columns: number = 3`, `maxWidth: string = "compact"`, `copyright: string = ""`, `copyrightKey: string = ""`, `translationPrefix: string = ""`, `class: string = ""` +- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Footer navigation"`, `items: unknown[] = []`, `columns: number = 3`, `maxWidth: string = "compact"`, `mobileColumns: number = 2`, `mobileCopyrightAlign: string = "center"`, `copyright: string = ""`, `copyrightKey: string = ""`, `translationPrefix: string = ""`, `class: string = ""` - Slots: `pre-footer`, `post-footer`, `copyright-left`, `copyright-right` - Outputs: `select({ value?: string | number | boolean | null; values?: Array; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`, `action({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })` @@ -698,7 +698,7 @@ Apply consistent readable responsive typography, widths, columns, spacing, and e Publish a responsive notice with badge, icon, supporting copy, action, dismiss behavior, and width controls. - Mount: `data-component="AnnouncementBar"` -- Props: `badge: string = ""`, `badgeIcon: string = ""`, `message: string = "Announcement"`, `description: string = ""`, `icon: string = "icon-[lucide--megaphone]"`, `actionLabel: string = ""`, `actionHref: string = ""`, `actionIcon: string = ""`, `dismissible: boolean = false`, `dismissLabel: string = "Dismiss announcement"`, `sticky: boolean = false`, `compact: boolean = false`, `size: string = "default"`, `width: string = "default"`, `color: string = "primary"`, `variant: string = "soft"`, `role: string = "status"`, `live: string = "polite"`, `class: string = ""` +- Props: `badge: string = ""`, `badgeIcon: string = ""`, `message: string = "Announcement"`, `description: string = ""`, `icon: string = "icon-[lucide--megaphone]"`, `actionLabel: string = ""`, `actionHref: string = ""`, `actionIcon: string = ""`, `dismissible: boolean = false`, `dismissLabel: string = "Dismiss announcement"`, `sticky: boolean = false`, `compact: boolean = false`, `flush: boolean = false`, `mobileCompact: boolean = false`, `mobileMessageLines: number = 2`, `hideBadgeOnMobile: boolean = false`, `hideDescriptionOnMobile: boolean = false`, `mobileActionSize: string = "default"`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `size: string = "default"`, `width: string = "default"`, `color: string = "primary"`, `variant: string = "soft"`, `role: string = "status"`, `live: string = "polite"`, `class: string = ""` - Slots: None - Outputs: `dismiss({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })` @@ -707,7 +707,7 @@ Publish a responsive notice with badge, icon, supporting copy, action, dismiss b Close a page or major section with conversion-focused copy, actions, and optional supporting visual content. - Mount: `data-component="CTASection"` -- Props: `eyebrow: string = ""`, `title: string = "Ready to get started?"`, `description: string = ""`, `icon: string = ""`, `align: string = "center"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "solid"`, `spacing: string = "none"`, `primaryLabel: string = "Get started"`, `primaryHref: string = "#"`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualPosition: string = "right"`, `maxWidth: string = "xl"`, `fullBleed: boolean = false`, `class: string = ""` +- Props: `eyebrow: string = ""`, `title: string = "Ready to get started?"`, `description: string = ""`, `icon: string = ""`, `align: string = "center"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "solid"`, `spacing: string = "none"`, `radius: string = "default"`, `titleMaxWidth: string = ""`, `contentPadding: string = "default"`, `mobilePadding: string = "default"`, `mobileActions: string = "stack"`, `primaryLabel: string = "Get started"`, `primaryHref: string = "#"`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualPosition: string = "right"`, `maxWidth: string = "xl"`, `fullBleed: boolean = false`, `class: string = ""` - Slots: `default`, `actions`, `visual`, `footer` - Outputs: None @@ -725,7 +725,7 @@ Present one linked feature or service with media, icon, badge, description, and Present a compact feature or benefit with a styled icon, title, description, badge, and optional link. - Mount: `data-component="FeatureIconCard"` -- Props: `icon: string = "icon-[lucide--sparkles]"`, `iconSize: string = "md"`, `iconVariant: string = "soft"`, `title: string = "Feature"`, `description: string = ""`, `href: string = ""`, `actionLabel: string = "Explore"`, `badge: string = ""`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `align: string = "left"`, `hover: string = "lift"`, `class: string = ""` +- Props: `icon: string = "icon-[lucide--sparkles]"`, `iconSize: string = "md"`, `iconVariant: string = "soft"`, `title: string = "Feature"`, `description: string = ""`, `href: string = ""`, `actionLabel: string = "Explore"`, `badge: string = ""`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `align: string = "left"`, `hover: string = "lift"`, `radius: string = "default"`, `shadow: string = "default"`, `clickableSurface: boolean = false`, `descriptionTone: string = "default"`, `class: string = ""` - Slots: `default`, `footer` - Outputs: None @@ -770,7 +770,7 @@ Introduce an internal or public page with breadcrumbs, icon, title, description, Build a responsive two-column introduction balancing descriptive content with a visual, image, or structured data panel. - Mount: `data-component="SplitHero"` -- Props: `eyebrow: string = ""`, `eyebrowIcon: string = "icon-[lucide--sparkles]"`, `title: string = "A better digital experience"`, `highlight: string = ""`, `description: string = ""`, `primaryLabel: string = ""`, `primaryHref: string = ""`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `visualPosition: string = "right"`, `reverse: boolean = false`, `ratio: string = "balanced"`, `align: string = "left"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `maxWidth: string = "xl"`, `fullBleed: boolean = true`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualEyebrow: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualStyle: string = "panel"`, `trustItems: unknown[] = []`, `class: string = ""` +- Props: `eyebrow: string = ""`, `eyebrowIcon: string = "icon-[lucide--sparkles]"`, `title: string = "A better digital experience"`, `highlight: string = ""`, `description: string = ""`, `primaryLabel: string = ""`, `primaryHref: string = ""`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `visualPosition: string = "right"`, `reverse: boolean = false`, `ratio: string = "balanced"`, `align: string = "left"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `maxWidth: string = "xl"`, `fullBleed: boolean = true`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `titleSize: string = "default"`, `titleMaxWidth: string = ""`, `descriptionWeight: string = "default"`, `mobileTitleSize: string = "default"`, `mobileStack: boolean = true`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualEyebrow: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualStyle: string = "panel"`, `trustItems: unknown[] = []`, `class: string = ""` - Slots: `default`, `actions`, `trust`, `visual` - Outputs: None @@ -826,8 +826,8 @@ Theme-aware, responsive nav component. Theme-aware, responsive navbar component. - Mount: `data-component="Navbar"` -- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Primary navigation"`, `topbarLabel: string = "Utility navigation"`, `brand: Record = {}`, `items: unknown[] = []`, `actions: unknown[] = []`, `active: string = ""`, `sticky: boolean = false`, `openOnHover: boolean = false`, `maxWidth: string = "full"`, `mobileLabel: string = "Toggle navigation"`, `translationPrefix: string = ""`, `class: string = ""` -- Slots: `topbar`, `actions` +- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Primary navigation"`, `topbarLabel: string = "Utility navigation"`, `brand: Record = {}`, `items: unknown[] = []`, `actions: unknown[] = []`, `active: string = ""`, `sticky: boolean = false`, `openOnHover: boolean = false`, `maxWidth: string = "full"`, `mobileLabel: string = "Toggle navigation"`, `collapseAt: string = "900px"`, `mobilePanel: string = "content"`, `mobileUtilitiesPosition: string = "header"`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `translationPrefix: string = ""`, `class: string = ""` +- Slots: `topbar`, `actions`, `utilities` - Outputs: `toggle({ open: boolean })`, `open({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `close({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `select({ item: string | number | boolean | null | object; value: string | number | boolean; level: string })`, `action({ item: string | number | boolean | null | object; value: string | number | boolean })` ### Pagination @@ -844,7 +844,7 @@ Theme-aware, responsive pagination component. Theme-aware, responsive scrollspy component. - Mount: `data-component="Scrollspy"` -- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `label: string = "On this page"`, `heading: string = ""`, `class: string = ""` +- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `label: string = "On this page"`, `heading: string = ""`, `sticky: boolean = false`, `topOffset: string = "6rem"`, `sectionOffset: string = "7rem"`, `collapseAt: string = "800px"`, `class: string = ""` - Slots: `default` - Outputs: `change({ href: string; label: string })` diff --git a/packages/ui/component-reference.json b/packages/ui/component-reference.json index e027e6b7..e3be0ab1 100644 --- a/packages/ui/component-reference.json +++ b/packages/ui/component-reference.json @@ -806,6 +806,69 @@ "default": "false", "options": [] }, + { + "name": "flush", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "mobileCompact", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "mobileMessageLines", + "type": "number", + "required": false, + "default": "2", + "options": [] + }, + { + "name": "hideBadgeOnMobile", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "hideDescriptionOnMobile", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "mobileActionSize", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "gutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "contentGutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "flushMobile", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, { "name": "size", "type": "string", @@ -2187,6 +2250,41 @@ "default": "\"none\"", "options": [] }, + { + "name": "radius", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "titleMaxWidth", + "type": "string", + "required": false, + "default": "\"\"", + "options": [] + }, + { + "name": "contentPadding", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "mobilePadding", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "mobileActions", + "type": "string", + "required": false, + "default": "\"stack\"", + "options": [] + }, { "name": "primaryLabel", "type": "string", @@ -2322,7 +2420,14 @@ "name": "title", "type": "string", "required": false, - "default": "\"Card title\"", + "default": "\"\"", + "options": [] + }, + { + "name": "icon", + "type": "string", + "required": false, + "default": "\"\"", "options": [] }, { @@ -2528,6 +2633,27 @@ "default": "\"none\"", "options": [] }, + { + "name": "radius", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "shadow", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "equalHeight", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, { "name": "scrollable", "type": "boolean", @@ -5868,6 +5994,34 @@ "default": "\"lift\"", "options": [] }, + { + "name": "radius", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "shadow", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "clickableSurface", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "descriptionTone", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, { "name": "class", "type": "string", @@ -6233,6 +6387,20 @@ "default": "\"compact\"", "options": [] }, + { + "name": "mobileColumns", + "type": "number", + "required": false, + "default": "2", + "options": [] + }, + { + "name": "mobileCopyrightAlign", + "type": "string", + "required": false, + "default": "\"center\"", + "options": [] + }, { "name": "copyright", "type": "string", @@ -8948,6 +9116,48 @@ "default": "\"Toggle navigation\"", "options": [] }, + { + "name": "collapseAt", + "type": "string", + "required": false, + "default": "\"900px\"", + "options": [] + }, + { + "name": "mobilePanel", + "type": "string", + "required": false, + "default": "\"content\"", + "options": [] + }, + { + "name": "mobileUtilitiesPosition", + "type": "string", + "required": false, + "default": "\"header\"", + "options": [] + }, + { + "name": "gutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "contentGutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "flushMobile", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, { "name": "translationPrefix", "type": "string", @@ -8963,7 +9173,7 @@ "options": [] } ], - "slots": ["topbar", "actions"], + "slots": ["topbar", "actions", "utilities"], "outputs": [ { "name": "toggle", @@ -9882,6 +10092,55 @@ "default": "true", "options": [] }, + { + "name": "iconOnly", + "type": "boolean", + "required": false, + "default": "true", + "options": [] + }, + { + "name": "themeIcon", + "type": "string", + "required": false, + "default": "\"icon-[lucide--sun-moon]\"", + "options": [] + }, + { + "name": "colorIcon", + "type": "string", + "required": false, + "default": "\"icon-[lucide--palette]\"", + "options": [] + }, + { + "name": "languageIcon", + "type": "string", + "required": false, + "default": "\"icon-[lucide--languages]\"", + "options": [] + }, + { + "name": "panelPlacement", + "type": "string", + "required": false, + "default": "\"bottom-end\"", + "options": [] + }, + { + "name": "mobilePanel", + "type": "string", + "required": false, + "default": "\"dropdown\"", + "options": [] + }, + { + "name": "showCurrentLanguage", + "type": "boolean", + "required": false, + "default": "true", + "options": [] + }, { "name": "class", "type": "string", @@ -10588,6 +10847,34 @@ "default": "\"\"", "options": [] }, + { + "name": "sticky", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "topOffset", + "type": "string", + "required": false, + "default": "\"6rem\"", + "options": [] + }, + { + "name": "sectionOffset", + "type": "string", + "required": false, + "default": "\"7rem\"", + "options": [] + }, + { + "name": "collapseAt", + "type": "string", + "required": false, + "default": "\"800px\"", + "options": [] + }, { "name": "class", "type": "string", @@ -11402,6 +11689,62 @@ "default": "true", "options": [] }, + { + "name": "gutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "contentGutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "flushMobile", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "titleSize", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "titleMaxWidth", + "type": "string", + "required": false, + "default": "\"\"", + "options": [] + }, + { + "name": "descriptionWeight", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "mobileTitleSize", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "mobileStack", + "type": "boolean", + "required": false, + "default": "true", + "options": [] + }, { "name": "backgroundImage", "type": "string", @@ -11554,6 +11897,41 @@ "default": "\"xl\"", "options": [] }, + { + "name": "radius", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "shadow", + "type": "string", + "required": false, + "default": "\"default\"", + "options": [] + }, + { + "name": "gutter", + "type": "string", + "required": false, + "default": "\"md\"", + "options": [] + }, + { + "name": "outerSpacing", + "type": "string", + "required": false, + "default": "\"none\"", + "options": [] + }, + { + "name": "mobileColumns", + "type": "number", + "required": false, + "default": "1", + "options": [] + }, { "name": "class", "type": "string", diff --git a/packages/ui/components/AnnouncementBar.wrn b/packages/ui/components/AnnouncementBar.wrn index aa3ed5a6..df81b548 100644 --- a/packages/ui/components/AnnouncementBar.wrn +++ b/packages/ui/components/AnnouncementBar.wrn @@ -16,6 +16,15 @@ badge: string = "" dismissLabel: string = "Dismiss announcement" sticky: boolean = false compact: boolean = false + flush: boolean = false + mobileCompact: boolean = false + mobileMessageLines: number = 2 + hideBadgeOnMobile: boolean = false + hideDescriptionOnMobile: boolean = false + mobileActionSize: string = "default" + gutter: string = "md" + contentGutter: string = "md" + flushMobile: boolean = false size: string = "default" width: string = "default" color: string = "primary" @@ -36,6 +45,7 @@ badge: string = "" data-color='{color}' data-variant='{variant}' data-compact='{compact}' + data-flush='{flush ? "true" : "false"}' data-mobile-compact='{mobileCompact ? "true" : "false"}' data-mobile-message-lines='{mobileMessageLines}' data-hide-badge-mobile='{hideBadgeOnMobile ? "true" : "false"}' data-hide-description-mobile='{hideDescriptionOnMobile ? "true" : "false"}' data-mobile-action-size='{mobileActionSize}' data-gutter='{gutter}' data-content-gutter='{contentGutter}' data-flush-mobile='{flushMobile ? "true" : "false"}' data-sticky='{sticky}' data-show='{!dismissed}' aria-hidden='{dismissed ? "true" : "false"}' @@ -163,6 +173,8 @@ badge: string = "" margin-inline: auto; } + .wrn-announcement[data-flush="true"] .wrn-announcement__surface { border-radius: 0; box-shadow: none; } + .wrn-announcement[data-width="wide"] .wrn-announcement__surface { width: min(calc(100% - 2rem), 90rem); } @@ -573,6 +585,15 @@ badge: string = "" } @media (max-width: 639px) { + .wrn-announcement[data-mobile-compact="true"] .wrn-announcement__inner, + .wrn-announcement[data-compact="true"] .wrn-announcement__inner { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.65rem; } + .wrn-announcement[data-hide-badge-mobile="true"] .wrn-announcement__badge, + .wrn-announcement[data-mobile-compact="true"] .wrn-announcement__badge { display: none; } + .wrn-announcement[data-hide-description-mobile="true"] .wrn-announcement__description, + .wrn-announcement[data-mobile-compact="true"] .wrn-announcement__description { display: none; } + .wrn-announcement[data-mobile-message-lines="2"] .wrn-announcement__message { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; } + .wrn-announcement[data-mobile-action-size="sm"] .wrn-announcement__action { min-height: 2.25rem; padding-inline: 0.7rem; } + .wrn-announcement[data-flush-mobile="false"] .wrn-announcement__inner { padding-inline: 1rem; } .wrn-announcement__surface, .wrn-announcement[data-width="wide"] .wrn-announcement__surface { width: calc(100% - 1rem); diff --git a/packages/ui/components/CTASection.wrn b/packages/ui/components/CTASection.wrn index 038fcd62..e8af2024 100644 --- a/packages/ui/components/CTASection.wrn +++ b/packages/ui/components/CTASection.wrn @@ -9,6 +9,11 @@ component CTASection { color: string = "primary" variant: string = "solid" spacing: string = "none" + radius: string = "default" + titleMaxWidth: string = "" + contentPadding: string = "default" + mobilePadding: string = "default" + mobileActions: string = "stack" primaryLabel: string = "Get started" primaryHref: string = "#" primaryIcon: string = "" @@ -37,6 +42,8 @@ component CTASection { data-color='{color}' data-variant='{variant}' data-spacing='{spacing}' + data-radius='{radius}' data-content-padding='{contentPadding}' data-mobile-padding='{mobilePadding}' data-mobile-actions='{mobileActions}' + style='--wrn-cta-title-max-width: {titleMaxWidth || "18ch"}' data-max-width='{maxWidth}' data-full-bleed='{fullBleed ? "true" : "false"}' data-visual-position='{visualPosition}' @@ -288,6 +295,8 @@ component CTASection { 0 1px 0 color-mix(in srgb, white 5%, transparent) inset, 0 24px 70px color-mix(in srgb, black 15%, transparent); } + .wrn-cta-section[data-radius="xl"] .wrn-cta-section__surface { border-radius: 1.5rem; } + .wrn-cta-section[data-content-padding="lg"] .wrn-cta-section__surface { padding: 3.5rem clamp(1.5rem, 5vw, 4rem); } .wrn-cta-section[data-size="compact"] .wrn-cta-section__surface, .wrn-cta-section[data-size="sm"] .wrn-cta-section__surface { @@ -429,7 +438,7 @@ component CTASection { } .wrn-cta-section__title { - max-width: 18ch; + max-width: var(--wrn-cta-title-max-width); margin: 0.75rem 0 0; color: var(--wrn-color-text); font-size: clamp(2rem, 5vw, 4rem); @@ -665,11 +674,11 @@ component CTASection { line-height: 1.5; } - .wrn-cta-section__footer:empty { + .wrn-cta-section__footer:not(:has(> *)) { display: none; } - .wrn-cta-section__footer:not(:empty) { + .wrn-cta-section__footer:has(> *) { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent); @@ -699,6 +708,8 @@ component CTASection { } @media (max-width: 639px) { + .wrn-cta-section[data-mobile-padding="md"] .wrn-cta-section__surface { padding: 2.5rem 1.25rem; } + .wrn-cta-section[data-mobile-actions="inline"] .wrn-cta-section__action { width: auto; } .wrn-cta-section__surface { padding: 1.6rem; border-radius: 1.2rem; diff --git a/packages/ui/components/Card.wrn b/packages/ui/components/Card.wrn index 38586080..185726b8 100644 --- a/packages/ui/components/Card.wrn +++ b/packages/ui/components/Card.wrn @@ -9,7 +9,8 @@ component Card { } props { - title: string = "Card title" + title: string = "" + icon: string = "" titleKey: string = "" subtitle: string = "" subtitleKey: string = "" @@ -39,6 +40,9 @@ component Card { layout: string = "vertical" align: string = "left" hover: string = "none" + radius: string = "default" + shadow: string = "default" + equalHeight: boolean = false scrollable: boolean = false maxHeight: string = "18rem" dismissible: boolean = false @@ -84,6 +88,7 @@ component Card { data-layout='{layout}' data-hover='{hover}' data-align='{align}' + data-radius='{radius}' data-shadow='{shadow}' data-equal-height='{equalHeight ? "true" : "false"}' class='wrn-component wrn-next--card wrn-component--color-{color} wrn-component--size-{size} wrn-next--variant-{variant} {class}' > {#if items.length > 0} @@ -271,6 +276,7 @@ component Card {

{emptyTitle}

{:else} + {#if icon}{/if} {#if description}

{description}

{/if} @@ -343,6 +349,12 @@ component Card { .wrn-next--card[data-size="sm"] { --wrn-card-padding: 0.85rem; } + .wrn-next--card[data-size="compact"] .wrn-next__card-body { padding: 1rem; } + .wrn-next--card[data-radius="lg"] > .wrn-next__card-panel { border-radius: 1rem; } + .wrn-next--card[data-shadow="none"] > .wrn-next__card-panel { box-shadow: none; } + .wrn-next--card[data-equal-height="true"], .wrn-next--card[data-equal-height="true"] > .wrn-next__card-panel { height: 100%; } + .wrn-next--card[data-layout="horizontal"] .wrn-next__card-body { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 0.8rem; } + .wrn-next__card-icon { display: grid; width: 2.35rem; height: 2.35rem; place-items: center; border-radius: 0.7rem; color: var(--wrn-color-primary); background: color-mix(in srgb, var(--wrn-color-primary) 12%, transparent); font-size: 1.15rem; } .wrn-next--card[data-size="lg"] { --wrn-card-padding: 1.75rem; diff --git a/packages/ui/components/FeatureIconCard.wrn b/packages/ui/components/FeatureIconCard.wrn index 0e77c6a8..e6a0db86 100644 --- a/packages/ui/components/FeatureIconCard.wrn +++ b/packages/ui/components/FeatureIconCard.wrn @@ -15,13 +15,17 @@ component FeatureIconCard { variant: string = "default" align: string = "left" hover: string = "lift" + radius: string = "default" + shadow: string = "default" + clickableSurface: boolean = false + descriptionTone: string = "default" class: string = "" } view {
} @@ -198,6 +206,17 @@ size: string = "default" gap: 1.5rem; } + .wrn-navbar[data-gutter="sm"] .wrn-navbar__main { padding-inline: 1rem; } + .wrn-navbar[data-gutter="lg"] .wrn-navbar__main { padding-inline: clamp(1.5rem, 5vw, 4rem); } + + .wrn-navbar__utilities { + display: inline-flex; + align-items: center; + flex: none; + } + + .wrn-navbar__utilities:not(:has(> *)) { display: none; } + .wrn-navbar--width-full .wrn-navbar__main { width: 100%; max-width: none; @@ -532,12 +551,15 @@ size: string = "default" background: var(--wrn-color-surface); border-bottom: 1px solid var(--wrn-color-border); box-shadow: 0 16px 32px rgb(15 23 42 / 0.12); - height: calc(100dvh - 3.5rem); + height: auto; max-height: calc(100dvh - 3.5rem); overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; } + .wrn-navbar[data-mobile-panel="sheet"] .wrn-navbar__collapse { + height: calc(100dvh - 3.5rem); + } .wrn-navbar__collapse.is-open { display: flex; } @@ -582,7 +604,37 @@ size: string = "default" } } + @media (max-width: 1100px) and (min-width: 901px) { + .wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__toggle { display: block; } + .wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__collapse { + position: absolute; + top: 100%; + right: 0; + left: 0; + display: none; + max-height: calc(100dvh - 3.5rem); + padding: 0.75rem 1rem 1rem; + align-items: stretch; + flex-direction: column; + overflow-y: auto; + background: var(--wrn-color-surface); + border-bottom: 1px solid var(--wrn-color-border); + box-shadow: 0 16px 32px rgb(15 23 42 / 0.12); + } + .wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__collapse.is-open { display: flex; } + .wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__menus, + .wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__actions { + width: 100%; + align-items: stretch; + flex: none; + flex-direction: column; + } + .wrn-navbar[data-collapse-at="1100px"] :is(.wrn-navbar__menu-link, .wrn-navbar__dropdown > summary, .wrn-navbar__action) { width: 100%; } + .wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__panel { position: static; width: 100%; max-width: none; transform: none; } + } + @media (max-width: 600px) { + .wrn-navbar[data-flush-mobile="false"] .wrn-navbar__main { padding-inline: 1rem; } .wrn-navbar__brand-copy small { display: none; } diff --git a/packages/ui/components/PreferenceSwitcher.wrn b/packages/ui/components/PreferenceSwitcher.wrn index 8992f78f..7d61bb90 100644 --- a/packages/ui/components/PreferenceSwitcher.wrn +++ b/packages/ui/components/PreferenceSwitcher.wrn @@ -25,6 +25,13 @@ size: string = "default" {"label": "Amber", "value": "amber", "hex": "#d97706"} ] compact: boolean = true + iconOnly: boolean = true + themeIcon: string = "icon-[lucide--sun-moon]" + colorIcon: string = "icon-[lucide--palette]" + languageIcon: string = "icon-[lucide--languages]" + panelPlacement: string = "bottom-end" + mobilePanel: string = "dropdown" + showCurrentLanguage: boolean = true class: string = "" } @@ -37,11 +44,11 @@ size: string = "default" } view { -
+
- - {#if !compact}{themeLabel}{/if} + + {#if !iconOnly && !compact}{themeLabel}{/if}
{themeLabel} @@ -54,8 +61,8 @@ size: string = "default"
- - {#if !compact}{colorLabel}{/if} + + {#if !iconOnly && !compact}{colorLabel}{/if}
{colorLabel} @@ -69,9 +76,9 @@ size: string = "default"
- - - {#if !compact}{languageLabel}{/if} + + {#if showCurrentLanguage}{/if} + {#if !iconOnly && !compact}{languageLabel}{/if}
{languageLabel} @@ -157,6 +164,9 @@ size: string = "default" animation: wrn-component-enter 160ms ease both; } + .wrn-preferences[data-panel-placement="bottom-start"] .wrn-preferences__panel { right: auto; left: 0; } + .wrn-preferences[data-panel-placement="bottom-center"] .wrn-preferences__panel { right: auto; left: 50%; transform: translateX(-50%); } + .wrn-preferences__panel > strong { padding-inline: 0.25rem; font-size: 0.7rem; @@ -242,7 +252,7 @@ size: string = "default" } @media (max-width: 640px) { - .wrn-preferences__panel { + .wrn-preferences[data-mobile-panel="sheet"] .wrn-preferences__panel { position: fixed; top: auto; right: 1rem; @@ -250,6 +260,15 @@ size: string = "default" left: 1rem; width: auto; } + .wrn-preferences[data-mobile-panel="dropdown"] .wrn-preferences__panel { + position: absolute; + top: calc(100% + 0.5rem); + right: 0; + bottom: auto; + left: auto; + width: max-content; + max-width: min(22rem, calc(100vw - 2rem)); + } } /* Shared component foundation. */ diff --git a/packages/ui/components/Scrollspy.wrn b/packages/ui/components/Scrollspy.wrn index c3b6eba2..4f51f702 100644 --- a/packages/ui/components/Scrollspy.wrn +++ b/packages/ui/components/Scrollspy.wrn @@ -24,6 +24,10 @@ component Scrollspy { active: string = "" label: string = "On this page" heading: string = "" + sticky: boolean = false + topOffset: string = "6rem" + sectionOffset: string = "7rem" + collapseAt: string = "800px" class: string = "" } @@ -44,6 +48,7 @@ component Scrollspy { class='wrn-scrollspy {class}' data-color='{color}' data-size='{size}' + data-sticky='{sticky ? "true" : "false"}' data-collapse-at='{collapseAt}' style='--wrn-scrollspy-top: {topOffset}; --wrn-scrollspy-section-offset: {sectionOffset};' data-wrn-scrollspy="true" role="navigation" aria-label='{label}' @@ -74,6 +79,8 @@ component Scrollspy { --scrollspy-accent: var(--wrn-color-primary); max-width: 100%; } + .wrn-scrollspy[data-sticky="true"] { position: sticky; top: var(--wrn-scrollspy-top); height: max-content; } + .wrn-scrollspy__link { scroll-margin-top: var(--wrn-scrollspy-section-offset); } .wrn-scrollspy:not(:has(.wrn-scrollspy__item)):not(:has(slot > *)) { display: none; @@ -152,6 +159,7 @@ component Scrollspy { * line rather than a screenful. */ @media (max-width: 767px) { + .wrn-scrollspy[data-collapse-at="800px"] { position: static; } .wrn-scrollspy__list { grid-auto-flow: column; grid-auto-columns: max-content; diff --git a/packages/ui/components/SplitHero.wrn b/packages/ui/components/SplitHero.wrn index 55cd976e..2823667e 100644 --- a/packages/ui/components/SplitHero.wrn +++ b/packages/ui/components/SplitHero.wrn @@ -20,6 +20,14 @@ component SplitHero { variant: string = "default" maxWidth: string = "xl" fullBleed: boolean = true + gutter: string = "md" + contentGutter: string = "md" + flushMobile: boolean = false + titleSize: string = "default" + titleMaxWidth: string = "" + descriptionWeight: string = "default" + mobileTitleSize: string = "default" + mobileStack: boolean = true backgroundImage: string = "" visualImage: string = "" visualAlt: string = "" @@ -45,6 +53,8 @@ component SplitHero { data-variant='{variant}' data-max-width='{maxWidth}' data-full-bleed='{fullBleed ? "true" : "false"}' + data-gutter='{gutter}' data-content-gutter='{contentGutter}' data-flush-mobile='{flushMobile ? "true" : "false"}' data-title-size='{titleSize}' data-description-weight='{descriptionWeight}' data-mobile-title-size='{mobileTitleSize}' data-mobile-stack='{mobileStack ? "true" : "false"}' + style='--wrn-split-title-max-width: {titleMaxWidth || "18ch"}' data-visual-style='{visualStyle}' class='wrn-split-hero {class}' > @@ -413,6 +423,7 @@ component SplitHero { } .wrn-split-hero__title { + max-width: var(--wrn-split-title-max-width); max-width: 15ch; margin: 1.45rem 0 0; color: var(--wrn-color-text); @@ -421,6 +432,8 @@ component SplitHero { line-height: 1.02; letter-spacing: -0.05em; } + .wrn-split-hero[data-title-size="xl"] .wrn-split-hero__title { font-size: clamp(3rem, 5.5vw, 5rem); } + .wrn-split-hero[data-description-weight="medium"] .wrn-split-hero__description { font-weight: 500; } .wrn-split-hero[data-size="compact"] .wrn-split-hero__title, .wrn-split-hero[data-size="sm"] .wrn-split-hero__title { @@ -771,6 +784,7 @@ component SplitHero { .wrn-split-hero[data-ratio="content"] .wrn-split-hero__layout { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); } + .wrn-split-hero[data-ratio="wide-copy"] .wrn-split-hero__layout { grid-template-columns: minmax(0, 1.12fr) minmax(20rem, 0.88fr); } .wrn-split-hero[data-ratio="visual"] .wrn-split-hero__layout { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); @@ -786,6 +800,8 @@ component SplitHero { } @media (max-width: 639px) { + .wrn-split-hero[data-flush-mobile="false"] .wrn-split-hero__inner { width: calc(100% - 2rem); } + .wrn-split-hero[data-mobile-title-size="lg"] .wrn-split-hero__title { font-size: clamp(2.5rem, 12vw, 3.5rem); } .wrn-split-hero__inner { padding-block: 3.25rem; } diff --git a/packages/ui/components/StatsBar.wrn b/packages/ui/components/StatsBar.wrn index ad524c52..83299565 100644 --- a/packages/ui/components/StatsBar.wrn +++ b/packages/ui/components/StatsBar.wrn @@ -9,6 +9,11 @@ component StatsBar { color: string = "primary" variant: string = "raised" maxWidth: string = "xl" + radius: string = "default" + shadow: string = "default" + gutter: string = "md" + outerSpacing: string = "none" + mobileColumns: number = 1 class: string = "" } @@ -24,6 +29,7 @@ component StatsBar { data-color='{color}' data-variant='{variant}' data-max-width='{maxWidth}' + data-radius='{radius}' data-shadow='{shadow}' data-gutter='{gutter}' data-outer-spacing='{outerSpacing}' data-mobile-columns='{mobileColumns}' class='wrn-stats-bar {class}' aria-label="Key statistics" > @@ -149,6 +155,10 @@ component StatsBar { width: min(calc(100% - 2rem), 80rem); margin-inline: auto; } + .wrn-stats-bar[data-outer-spacing="md"] { margin-block: 2rem; } + .wrn-stats-bar[data-radius="xl"] .wrn-stats-bar__surface { overflow: hidden; border-radius: 1.25rem; } + .wrn-stats-bar[data-shadow="sm"] .wrn-stats-bar__surface { box-shadow: 0 10px 30px rgb(15 23 42 / 0.05); } + .wrn-stats-bar[data-variant="card"] .wrn-stats-bar__surface { border: 1px solid var(--wrn-color-border); background: var(--wrn-color-surface); } .wrn-stats-bar[data-max-width="compact"] .wrn-stats-bar__inner { width: min(calc(100% - 2rem), 64rem); @@ -480,6 +490,8 @@ component StatsBar { } @media (max-width: 639px) { + .wrn-stats-bar[data-mobile-columns="1"] .wrn-stats-bar__surface { grid-template-columns: 1fr; } + .wrn-stats-bar[data-gutter="md"] .wrn-stats-bar__inner { width: calc(100% - 2rem); } .wrn-stats-bar[data-max-width="full"] .wrn-stats-bar__surface { border-inline: 0; border-radius: 0; diff --git a/packages/ui/package.json b/packages/ui/package.json index cada755d..f874e24b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ui", - "version": "0.8.25", + "version": "0.8.26", "private": true, "type": "module", "main": "src/index.ts",