diff --git a/bun.lock b/bun.lock index a9d651c3..8a04dd29 100644 --- a/bun.lock +++ b/bun.lock @@ -688,7 +688,7 @@ }, "packages/ui": { "name": "@wrnexus/ui", - "version": "0.8.26", + "version": "0.8.27", "dependencies": { "@wrnexus/core": "workspace:*", }, diff --git a/docs/ui-visual-contract-0.8.json b/docs/ui-visual-contract-0.8.json index 3b0c2e6e..e872b4d0 100644 --- a/docs/ui-visual-contract-0.8.json +++ b/docs/ui-visual-contract-0.8.json @@ -60,7 +60,7 @@ "packages/ui/components/MetricGrid.wrn": "1fcebf51dcbe8520fe16bda904c1ef206c25c3900438d53877492c64ea21a1a5", "packages/ui/components/Modal.wrn": "7fa4b877772736f29f690e24d8742922b310397ef3083f0b78acb67a9f0d14b2", "packages/ui/components/Nav.wrn": "c45b0ecb42250f4b3ede33c8932a025f789dda9ef48dbf332459ae458163e69a", - "packages/ui/components/Navbar.wrn": "9095876ad737e9d85c6ba38963b777c29b54c095f024c4e7f4325067039fe07f", + "packages/ui/components/Navbar.wrn": "ce33334b98a363ea2c3e4ba111077ff2f3dc875f87e839729cce365789de6f65", "packages/ui/components/PageHeader.wrn": "321cde36ce8d521a57901033d46e8b437f42e558cca27f49ca26f7172aff1d54", "packages/ui/components/Pagination.wrn": "d54226705d4556f76ee5f0d6ae82d101ca6d006397756d547a9aa5954415ba39", "packages/ui/components/PinInput.wrn": "4dc398456f6392d7925db941debb484c7cb0358ecef527f696fe5ec4800a7602", diff --git a/packages/ui/COMPONENTS.md b/packages/ui/COMPONENTS.md index 09de0529..02f51fcb 100644 --- a/packages/ui/COMPONENTS.md +++ b/packages/ui/COMPONENTS.md @@ -826,7 +826,7 @@ 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"`, `collapseAt: string = "900px"`, `mobilePanel: string = "content"`, `mobileUtilitiesPosition: string = "header"`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `translationPrefix: string = ""`, `class: string = ""` +- 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`, `floating: boolean = false`, `startFloating: string = "0px"`, `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 })` diff --git a/packages/ui/component-reference.json b/packages/ui/component-reference.json index e3be0ab1..c28029f9 100644 --- a/packages/ui/component-reference.json +++ b/packages/ui/component-reference.json @@ -9095,6 +9095,20 @@ "default": "false", "options": [] }, + { + "name": "floating", + "type": "boolean", + "required": false, + "default": "false", + "options": [] + }, + { + "name": "startFloating", + "type": "string", + "required": false, + "default": "\"0px\"", + "options": [] + }, { "name": "openOnHover", "type": "boolean", diff --git a/packages/ui/components/Navbar.wrn b/packages/ui/components/Navbar.wrn index 6b9a3354..75caa739 100644 --- a/packages/ui/components/Navbar.wrn +++ b/packages/ui/components/Navbar.wrn @@ -17,6 +17,8 @@ size: string = "default" actions: unknown[] = [] active: string = "" sticky: boolean = false + floating: boolean = false + startFloating: string = "0px" openOnHover: boolean = false maxWidth: string = "full" mobileLabel: string = "Toggle navigation" @@ -76,7 +78,7 @@ size: string = "default" } view { -
+
@@ -165,7 +167,7 @@ size: string = "default" /* Full application navigation */ .wrn-navbar { position: relative; - z-index: 40; + z-index: 1000; width: 100%; color: var(--wrn-color-text); background: color-mix(in srgb, var(--wrn-color-surface) 96%, transparent); @@ -178,6 +180,14 @@ size: string = "default" backdrop-filter: blur(16px); } + .wrn-navbar--floating { + position: sticky; + z-index: 1000; + top: var(--wrn-navbar-floating-start, 0px); + box-shadow: 0 10px 30px rgb(15 23 42 / 0.08); + backdrop-filter: blur(16px); + } + .wrn-navbar__topbar:not(:has(> *)) { display: none; } @@ -369,6 +379,7 @@ size: string = "default" .wrn-navbar__panel { position: absolute; + z-index: 1100; top: calc(100% + 0.55rem); left: 50%; display: grid; diff --git a/packages/ui/package.json b/packages/ui/package.json index f874e24b..b887985e 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ui", - "version": "0.8.26", + "version": "0.8.27", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/ui/test/ui-redesign-contract.test.ts b/packages/ui/test/ui-redesign-contract.test.ts index 20ec73de..859f3075 100644 --- a/packages/ui/test/ui-redesign-contract.test.ts +++ b/packages/ui/test/ui-redesign-contract.test.ts @@ -126,6 +126,18 @@ describe("@wrnexus/ui redesign component pack", () => { expect(source).not.toContain(".wrn-navbar__topbar:not(:empty)"); }); + test("Navbar supports in-flow floating and elevated menu panels", async () => { + const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8"); + const ast = parse(source); + const defaults = new Map(ast.props.map((prop) => [prop.name, prop.default])); + + expect(defaults.get("floating")).toBe("false"); + expect(defaults.get("startFloating")).toBe('"0px"'); + expect(source).toContain("wrn-navbar--floating"); + expect(source).toContain("--wrn-navbar-floating-start"); + expect(source).toContain("z-index: 1100"); + }); + test("CTASection exposes responsive section spacing", async () => { const source = await readFile(join(componentsDir, "CTASection.wrn"), "utf8"); const ast = parse(source);