@jsekulowicz/ds-components 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12965,7 +12965,7 @@
12965
12965
  {
12966
12966
  "kind": "variable",
12967
12967
  "name": "footerStyles",
12968
- "default": "css` :host { display: block; container-type: inline-size; } footer { display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap; gap: var(--ds-space-4); /* Fixed 36px height; symmetric 16px inline padding. Padding is declared via padding-inline only vertical centering is owned by the flexbox + fixed height. */ height: 36px; padding-inline: var(--ds-space-4); border-top: 1px solid var(--ds-color-border); color: var(--ds-color-fg-muted); font-family: var(--ds-font-body); font-size: var(--ds-font-size-sm); box-sizing: border-box; } .start, .middle, .end { display: flex; align-items: center; gap: var(--ds-space-3); min-width: 0; } .end { justify-content: flex-end; } @container (max-width: ${mobileBreakpoint}) { footer { gap: var(--ds-space-2); font-size: var(--ds-font-size-xs); } .start, .middle, .end { gap: var(--ds-space-2); } } `"
12968
+ "default": "css` :host { display: block; container-type: inline-size; } footer { /* Full-width chrome: fixed 36px height + border-top span the footer's full width regardless of the inner content cap. */ height: 36px; border-top: 1px solid var(--ds-color-border); color: var(--ds-color-fg-muted); font-family: var(--ds-font-body); font-size: var(--ds-font-size-sm); box-sizing: border-box; } .inner { /* Inner wrapper holds start / middle / end, optionally capped to align with a constrained content column above. 16px symmetric inline padding lives here so it scales with the (capped) content column, not the full-width chrome. */ height: 100%; width: 100%; max-width: var(--ds-footer-content-max-width, none); margin-inline: auto; display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap; gap: var(--ds-space-4); padding-inline: var(--ds-space-4); box-sizing: border-box; } .start, .middle, .end { display: flex; align-items: center; gap: var(--ds-space-3); min-width: 0; } .end { justify-content: flex-end; } @container (max-width: ${mobileBreakpoint}) { .inner { gap: var(--ds-space-2); font-size: var(--ds-font-size-xs); } .start, .middle, .end { gap: var(--ds-space-2); } } `"
12969
12969
  }
12970
12970
  ],
12971
12971
  "exports": [
@@ -12987,11 +12987,21 @@
12987
12987
  "kind": "class",
12988
12988
  "description": "",
12989
12989
  "name": "DsFooter",
12990
+ "cssProperties": [
12991
+ {
12992
+ "description": "Max width of the inner content (start + middle + end). Defaults to `none` (no cap). Set to e.g. `var(--ds-page-shell-max-width)` to align with a content column above.",
12993
+ "name": "--ds-footer-content-max-width"
12994
+ }
12995
+ ],
12990
12996
  "cssParts": [
12991
12997
  {
12992
- "description": "The internal `<footer>` element.",
12998
+ "description": "The internal `<footer>` element (full-width chrome).",
12993
12999
  "name": "root"
12994
13000
  },
13001
+ {
13002
+ "description": "The capped content wrapper holding start / middle / end.",
13003
+ "name": "inner"
13004
+ },
12995
13005
  {
12996
13006
  "description": "The start region wrapper.",
12997
13007
  "name": "start"
@@ -13026,7 +13036,7 @@
13026
13036
  },
13027
13037
  "tagName": "ds-footer",
13028
13038
  "customElement": true,
13029
- "summary": "Slots-only page footer. Lays out start / middle / end regions; wraps to a column on narrow widths."
13039
+ "summary": "Slots-only page footer. Lays out start / middle / end regions; wraps to a column on narrow widths.\n\nThe visible chrome (border-top + fixed height) always spans the full width of the\nfooter; the inner start / middle / end regions live in a centered `inner` wrapper\nwhose max-width is configurable via the `--ds-footer-content-max-width` custom\nproperty, so consumers (e.g. ds-page-shell) can align footer content with a\nconstrained content column above."
13030
13040
  }
13031
13041
  ],
13032
13042
  "exports": [
@@ -13505,7 +13515,7 @@
13505
13515
  {
13506
13516
  "kind": "variable",
13507
13517
  "name": "topBarStyles",
13508
- "default": "css` :host { display: block; } nav { display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-3); /* Fixed 48px height at every viewport; 16px symmetric inline padding. Padding is declared via padding-inline only vertical centering is owned by the flexbox + fixed height. */ height: 48px; padding-inline: var(--ds-space-4); background: var(--ds-top-bar-bg, var(--ds-color-bg)); border-bottom: 1px solid var(--ds-color-border); font-family: var(--ds-font-body); color: var(--ds-color-fg); box-sizing: border-box; } .brand { display: flex; align-items: center; gap: var(--ds-space-2); min-width: 0; font-family: var(--ds-font-display); font-size: var(--ds-font-size-lg); color: var(--ds-color-fg); } .actions { display: flex; align-items: center; gap: var(--ds-space-2); } `"
13518
+ "default": "css` :host { display: block; } nav { /* Full-width chrome: background, border-bottom, and the fixed responsive height live on the nav itself so they always span the parent's full width regardless of the inner content cap. */ height: 48px; background: var(--ds-top-bar-bg, var(--ds-color-bg)); border-bottom: 1px solid var(--ds-color-border); font-family: var(--ds-font-body); color: var(--ds-color-fg); box-sizing: border-box; } .inner { /* Inner wrapper holds brand + actions, optionally capped to align with a constrained content column below the bar. 16px symmetric inline padding lives here so it scales with the (capped) content column, not the full-width chrome. */ height: 100%; width: 100%; max-width: var(--ds-top-bar-content-max-width, none); margin-inline: auto; display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-3); padding-inline: var(--ds-space-4); box-sizing: border-box; } .brand { display: flex; align-items: center; gap: var(--ds-space-2); min-width: 0; font-family: var(--ds-font-display); font-size: var(--ds-font-size-lg); color: var(--ds-color-fg); } .actions { display: flex; align-items: center; gap: var(--ds-space-2); } `"
13509
13519
  }
13510
13520
  ],
13511
13521
  "exports": [
@@ -13531,13 +13541,21 @@
13531
13541
  {
13532
13542
  "description": "Background color of the bar. Defaults to `var(--ds-color-bg)`. Override (e.g. to `transparent`) when nesting inside a container that paints its own background underneath, such as a sticky shell with `backdrop-filter`.",
13533
13543
  "name": "--ds-top-bar-bg"
13544
+ },
13545
+ {
13546
+ "description": "Max width of the inner content (brand + actions). Defaults to `none` (no cap). Set to e.g. `var(--ds-page-shell-max-width)` to align with a content column below.",
13547
+ "name": "--ds-top-bar-content-max-width"
13534
13548
  }
13535
13549
  ],
13536
13550
  "cssParts": [
13537
13551
  {
13538
- "description": "The internal `<nav>` landmark element.",
13552
+ "description": "The internal `<nav>` landmark element (full-width chrome).",
13539
13553
  "name": "bar"
13540
13554
  },
13555
+ {
13556
+ "description": "The capped content wrapper holding brand + actions.",
13557
+ "name": "inner"
13558
+ },
13541
13559
  {
13542
13560
  "description": "The brand wrapper.",
13543
13561
  "name": "brand"
@@ -13584,7 +13602,7 @@
13584
13602
  },
13585
13603
  "tagName": "ds-top-bar",
13586
13604
  "customElement": true,
13587
- "summary": "Application chrome bar with a left brand region and a right actions region.\n\nThe bar is intentionally minimal: it does not own primary navigation. Pair it with\n`ds-sidenav` (typically inside `ds-page-shell`) for navigation. The bar has a fixed\n48px height at every viewport and a symmetric 16px inline padding."
13605
+ "summary": "Application chrome bar with a left brand region and a right actions region.\n\nThe bar is intentionally minimal: it does not own primary navigation. Pair it with\n`ds-sidenav` (typically inside `ds-page-shell`) for navigation. The bar has a fixed\n48px height at every viewport and a symmetric 16px inline padding.\n\nThe visible chrome (background + border-bottom) always spans the full width of the\nbar; the inner brand + actions content is held in a centered `inner` wrapper whose\nmax-width is configurable via the `--ds-top-bar-content-max-width` custom property,\nso consumers (e.g. ds-page-shell) can align the bar's content with a constrained\ncontent column below."
13588
13606
  }
13589
13607
  ],
13590
13608
  "exports": [
@@ -13815,7 +13833,7 @@
13815
13833
  {
13816
13834
  "kind": "variable",
13817
13835
  "name": "pageShellStyles",
13818
- "default": "css` :host { --ds-page-shell-max-width: 90rem; display: flex; flex-direction: column; position: relative; min-height: 100vh; overflow-x: clip; background: var(--ds-color-bg); color: var(--ds-color-fg); font-family: var(--ds-font-body); } header { position: sticky; top: 0; background: color-mix(in oklab, var(--ds-color-bg) 92%, transparent); backdrop-filter: blur(12px); z-index: var(--ds-z-index-sticky); } /* The header composes ds-top-bar; let the top-bar own height, padding, border-bottom, and layout. We just make its background transparent so the sticky header's blurred bg shows through. */ .chrome { --ds-top-bar-bg: transparent; } footer { display: block; } .shell-body { flex: 1; width: 100%; max-width: var(--ds-page-shell-max-width); margin-inline: auto; display: grid; grid-template-columns: auto 1fr auto; min-height: 0; } :host([aside-empty]) .shell-body { grid-template-columns: 1fr auto; } :host([aside-end-empty]) .shell-body { grid-template-columns: auto 1fr; } :host([aside-empty][aside-end-empty]) .shell-body { grid-template-columns: 1fr; } aside { display: flex; overflow-x: clip; overflow-y: auto; min-height: 0; scrollbar-color: var(--ds-color-fg-subtle) transparent; scrollbar-width: thin; /* No scrollbar-gutter reservation: the aside sits flush with its column edge so the consumer's <main> solely owns the gap. The scrollbar appears on demand when the aside genuinely overflows. */ } :host([aside-empty]) aside[part=\"aside\"], :host([aside-empty]) .mobile-backdrop { display: none; } :host([aside-end-empty]) aside[part=\"aside-end\"] { display: none; } main { padding: var(--ds-space-5); overflow: auto; min-width: 0; min-height: 0; scrollbar-color: var(--ds-color-fg-subtle) transparent; scrollbar-width: thin; /* Reserve scrollbar gutters on both inline sides so the inline-start and inline-end visible empty bands stay equal in width whether the vertical scrollbar is present or not. */ scrollbar-gutter: stable both-edges; } @media (max-width: ${belowDesktopBreakpoint}) { main { padding-block: var(--ds-space-4); padding-inline: var(--ds-space-4); } } .menu-toggle { display: none; } .menu-toggle::part(button), .drawer-close::part(button) { min-width: var(--ds-size-sm); width: var(--ds-size-sm); padding: 0; } :host([mobile-layout]) .menu-toggle { display: inline-flex; } .mobile-backdrop { display: none; } .drawer-header { display: none; } .drawer-brand { display: none; } .drawer-close { display: none; } :host([mobile-layout]) .shell-body { grid-template-columns: 1fr; } :host([mobile-layout]) aside[part=\"aside-end\"] { /* Secondary inline-end region is not surfaced in the mobile drawer in v1. Consumers can opt back in by overriding via ::part(aside-end). */ display: none; } :host([mobile-layout]) aside[part=\"aside\"] { position: absolute; top: 0; left: 0; width: 16rem; display: flex; flex-direction: column; height: 100%; background: var(--ds-color-bg); border-right: 0; z-index: var(--ds-z-index-modal); transform: translateX(-100%); transition: transform var(--ds-duration-slow) var(--ds-easing-standard); scrollbar-gutter: auto; overflow: hidden; box-sizing: border-box; } :host([mobile-layout][data-mobile-nav-open]) aside[part=\"aside\"] { transform: translateX(0); } :host([mobile-layout]) .drawer-header { display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-3); padding: var(--ds-space-2) var(--ds-space-4); } :host([mobile-layout]) .drawer-brand { display: inline-flex; align-items: center; flex: 1; min-width: 0; font-family: var(--ds-font-display); font-size: var(--ds-font-size-lg); letter-spacing: var(--ds-letter-spacing-display); } :host([mobile-layout]) slot[name='drawer-brand']::slotted(*) { max-width: 100%; } :host([mobile-layout]) .drawer-close { display: inline-flex; flex: 0 0 auto; margin: 0; } :host([mobile-layout]) aside[part=\"aside\"] ::slotted(ds-sidenav) { width: 100% !important; max-width: 100% !important; flex: 1 1 auto; min-width: 0; min-height: 0; height: auto !important; } :host([mobile-layout][data-mobile-nav-open]) .mobile-backdrop { display: block; position: absolute; inset: 0; border: 0; margin: 0; padding: 0; background: color-mix(in oklab, var(--ds-color-fg) 26%, transparent); z-index: var(--ds-z-index-overlay); } `"
13836
+ "default": "css` :host { --ds-page-shell-max-width: 90rem; display: flex; flex-direction: column; position: relative; height: 100vh; height: 100dvh; overflow-x: clip; background: var(--ds-color-bg); color: var(--ds-color-fg); font-family: var(--ds-font-body); } header { position: sticky; top: 0; background: color-mix(in oklab, var(--ds-color-bg) 92%, transparent); backdrop-filter: blur(12px); z-index: var(--ds-z-index-sticky); } /* The header composes ds-top-bar; let the top-bar own height, padding, border-bottom, and layout. We just (a) make its background transparent so the sticky header's blurred bg shows through, and (b) constrain its inner brand + actions content to the same max-width as the shell-body below so the bar's brand left-aligns with the aside, and its actions right-align with the aside-end (or the right edge of main when no aside-end is slotted). */ .chrome { --ds-top-bar-bg: transparent; --ds-top-bar-content-max-width: var(--ds-page-shell-max-width); } /* Same treatment for a slotted ds-footer: cap its inner content to the shell-body's max-width so footer content aligns with the column above. Consumers who slot a non-ds-footer custom element can override the property themselves. */ ::slotted(ds-footer) { --ds-footer-content-max-width: var(--ds-page-shell-max-width); } footer { display: block; } .shell-body { flex: 1; width: 100%; max-width: var(--ds-page-shell-max-width); margin-inline: auto; display: grid; grid-template-columns: auto 1fr auto; min-height: 0; } :host([aside-empty]) .shell-body { grid-template-columns: 1fr auto; } :host([aside-end-empty]) .shell-body { grid-template-columns: auto 1fr; } :host([aside-empty][aside-end-empty]) .shell-body { grid-template-columns: 1fr; } aside { display: flex; overflow-x: clip; overflow-y: auto; min-height: 0; scrollbar-color: var(--ds-color-fg-subtle) transparent; scrollbar-width: thin; /* No scrollbar-gutter reservation: the aside sits flush with its column edge so the consumer's <main> solely owns the gap. The scrollbar appears on demand when the aside genuinely overflows. */ } :host([aside-empty]) aside[part=\"aside\"], :host([aside-empty]) .mobile-backdrop { display: none; } :host([aside-end-empty]) aside[part=\"aside-end\"] { display: none; } main { padding: var(--ds-space-5); overflow: auto; min-width: 0; min-height: 0; scrollbar-color: var(--ds-color-fg-subtle) transparent; scrollbar-width: thin; /* Reserve scrollbar gutters on both inline sides so the inline-start and inline-end visible empty bands stay equal in width whether the vertical scrollbar is present or not. */ scrollbar-gutter: stable both-edges; } @media (max-width: ${belowDesktopBreakpoint}) { main { padding-block: var(--ds-space-4); padding-inline: var(--ds-space-4); } } .menu-toggle { display: none; } .menu-toggle::part(button), .drawer-close::part(button) { min-width: var(--ds-size-sm); width: var(--ds-size-sm); padding: 0; } :host([mobile-layout]) .menu-toggle { display: inline-flex; } .mobile-backdrop { display: none; } .drawer-header { display: none; } .drawer-brand { display: none; } .drawer-close { display: none; } :host([mobile-layout]) .shell-body { grid-template-columns: 1fr; } :host([mobile-layout]) aside[part=\"aside-end\"] { /* Secondary inline-end region is not surfaced in the mobile drawer in v1. Consumers can opt back in by overriding via ::part(aside-end). */ display: none; } :host([mobile-layout]) aside[part=\"aside\"] { position: absolute; top: 0; left: 0; width: 16rem; display: flex; flex-direction: column; height: 100%; background: var(--ds-color-bg); border-right: 0; z-index: var(--ds-z-index-modal); transform: translateX(-100%); transition: transform var(--ds-duration-slow) var(--ds-easing-standard); scrollbar-gutter: auto; overflow: hidden; box-sizing: border-box; } :host([mobile-layout][data-mobile-nav-open]) aside[part=\"aside\"] { transform: translateX(0); } :host([mobile-layout]) .drawer-header { display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-3); padding: var(--ds-space-2) var(--ds-space-4); } :host([mobile-layout]) .drawer-brand { display: inline-flex; align-items: center; flex: 1; min-width: 0; font-family: var(--ds-font-display); font-size: var(--ds-font-size-lg); letter-spacing: var(--ds-letter-spacing-display); } :host([mobile-layout]) slot[name='drawer-brand']::slotted(*) { max-width: 100%; } :host([mobile-layout]) .drawer-close { display: inline-flex; flex: 0 0 auto; margin: 0; } :host([mobile-layout]) aside[part=\"aside\"] ::slotted(ds-sidenav) { width: 100% !important; max-width: 100% !important; flex: 1 1 auto; min-width: 0; min-height: 0; height: auto !important; } :host([mobile-layout][data-mobile-nav-open]) .mobile-backdrop { display: block; position: absolute; inset: 0; border: 0; margin: 0; padding: 0; background: color-mix(in oklab, var(--ds-color-fg) 26%, transparent); z-index: var(--ds-z-index-overlay); } `"
13819
13837
  }
13820
13838
  ],
13821
13839
  "exports": [
@@ -3,13 +3,24 @@ import { DsElement } from '@jsekulowicz/ds-core';
3
3
  /**
4
4
  * @tag ds-footer
5
5
  * @summary Slots-only page footer. Lays out start / middle / end regions; wraps to a column on narrow widths.
6
+ *
7
+ * The visible chrome (border-top + fixed height) always spans the full width of the
8
+ * footer; the inner start / middle / end regions live in a centered `inner` wrapper
9
+ * whose max-width is configurable via the `--ds-footer-content-max-width` custom
10
+ * property, so consumers (e.g. ds-page-shell) can align footer content with a
11
+ * constrained content column above.
12
+ *
6
13
  * @slot start - Left region. Typical use: copyright text.
7
14
  * @slot default - Middle region.
8
15
  * @slot end - Right region. Typical use: nav links, social icons.
9
- * @csspart root - The internal `<footer>` element.
16
+ * @csspart root - The internal `<footer>` element (full-width chrome).
17
+ * @csspart inner - The capped content wrapper holding start / middle / end.
10
18
  * @csspart start - The start region wrapper.
11
19
  * @csspart middle - The middle region wrapper.
12
20
  * @csspart end - The end region wrapper.
21
+ * @cssprop --ds-footer-content-max-width - Max width of the inner content
22
+ * (start + middle + end). Defaults to `none` (no cap). Set to e.g.
23
+ * `var(--ds-page-shell-max-width)` to align with a content column above.
13
24
  */
14
25
  export declare class DsFooter extends DsElement {
15
26
  static styles: import("lit").CSSResult[];
@@ -1 +1 @@
1
- {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../src/organisms/footer/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD;;;;;;;;;;GAUG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,4BAAuC;IAEpD,MAAM,IAAI,cAAc;CAOlC"}
1
+ {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../src/organisms/footer/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,4BAAuC;IAEpD,MAAM,IAAI,cAAc;CASlC"}
@@ -4,21 +4,34 @@ import { footerStyles } from './footer.styles.js';
4
4
  /**
5
5
  * @tag ds-footer
6
6
  * @summary Slots-only page footer. Lays out start / middle / end regions; wraps to a column on narrow widths.
7
+ *
8
+ * The visible chrome (border-top + fixed height) always spans the full width of the
9
+ * footer; the inner start / middle / end regions live in a centered `inner` wrapper
10
+ * whose max-width is configurable via the `--ds-footer-content-max-width` custom
11
+ * property, so consumers (e.g. ds-page-shell) can align footer content with a
12
+ * constrained content column above.
13
+ *
7
14
  * @slot start - Left region. Typical use: copyright text.
8
15
  * @slot default - Middle region.
9
16
  * @slot end - Right region. Typical use: nav links, social icons.
10
- * @csspart root - The internal `<footer>` element.
17
+ * @csspart root - The internal `<footer>` element (full-width chrome).
18
+ * @csspart inner - The capped content wrapper holding start / middle / end.
11
19
  * @csspart start - The start region wrapper.
12
20
  * @csspart middle - The middle region wrapper.
13
21
  * @csspart end - The end region wrapper.
22
+ * @cssprop --ds-footer-content-max-width - Max width of the inner content
23
+ * (start + middle + end). Defaults to `none` (no cap). Set to e.g.
24
+ * `var(--ds-page-shell-max-width)` to align with a content column above.
14
25
  */
15
26
  export class DsFooter extends DsElement {
16
27
  static { this.styles = [...DsElement.styles, footerStyles]; }
17
28
  render() {
18
29
  return html `<footer part="root">
19
- <div class="start" part="start"><slot name="start"></slot></div>
20
- <div class="middle" part="middle"><slot></slot></div>
21
- <div class="end" part="end"><slot name="end"></slot></div>
30
+ <div class="inner" part="inner">
31
+ <div class="start" part="start"><slot name="start"></slot></div>
32
+ <div class="middle" part="middle"><slot></slot></div>
33
+ <div class="end" part="end"><slot name="end"></slot></div>
34
+ </div>
22
35
  </footer>`;
23
36
  }
24
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../src/organisms/footer/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,QAAS,SAAQ,SAAS;aACrB,WAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAEpD,MAAM;QACb,OAAO,IAAI,CAAA;;;;cAID,CAAC;IACb,CAAC"}
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../src/organisms/footer/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,QAAS,SAAQ,SAAS;aACrB,WAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAEpD,MAAM;QACb,OAAO,IAAI,CAAA;;;;;;cAMD,CAAC;IACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"footer.styles.d.ts","sourceRoot":"","sources":["../../../src/organisms/footer/footer.styles.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,yBA4CxB,CAAC"}
1
+ {"version":3,"file":"footer.styles.d.ts","sourceRoot":"","sources":["../../../src/organisms/footer/footer.styles.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,yBAsDxB,CAAC"}
@@ -7,20 +7,30 @@ export const footerStyles = css `
7
7
  container-type: inline-size;
8
8
  }
9
9
  footer {
10
+ /* Full-width chrome: fixed 36px height + border-top span the
11
+ footer's full width regardless of the inner content cap. */
12
+ height: 36px;
13
+ border-top: 1px solid var(--ds-color-border);
14
+ color: var(--ds-color-fg-muted);
15
+ font-family: var(--ds-font-body);
16
+ font-size: var(--ds-font-size-sm);
17
+ box-sizing: border-box;
18
+ }
19
+ .inner {
20
+ /* Inner wrapper holds start / middle / end, optionally capped to
21
+ align with a constrained content column above. 16px symmetric
22
+ inline padding lives here so it scales with the (capped) content
23
+ column, not the full-width chrome. */
24
+ height: 100%;
25
+ width: 100%;
26
+ max-width: var(--ds-footer-content-max-width, none);
27
+ margin-inline: auto;
10
28
  display: flex;
11
29
  align-items: center;
12
30
  justify-content: space-between;
13
31
  flex-wrap: nowrap;
14
32
  gap: var(--ds-space-4);
15
- /* Fixed 36px height; symmetric 16px inline padding. Padding is
16
- declared via padding-inline only — vertical centering is owned by
17
- the flexbox + fixed height. */
18
- height: 36px;
19
33
  padding-inline: var(--ds-space-4);
20
- border-top: 1px solid var(--ds-color-border);
21
- color: var(--ds-color-fg-muted);
22
- font-family: var(--ds-font-body);
23
- font-size: var(--ds-font-size-sm);
24
34
  box-sizing: border-box;
25
35
  }
26
36
  .start,
@@ -35,7 +45,7 @@ export const footerStyles = css `
35
45
  justify-content: flex-end;
36
46
  }
37
47
  @container (max-width: ${mobileBreakpoint}) {
38
- footer {
48
+ .inner {
39
49
  gap: var(--ds-space-2);
40
50
  font-size: var(--ds-font-size-xs);
41
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"footer.styles.js","sourceRoot":"","sources":["../../../src/organisms/footer/footer.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,gBAAgB,GAAG,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAiCJ,gBAAgB;;;;;;;;;;;CAW1C,CAAC"}
1
+ {"version":3,"file":"footer.styles.js","sourceRoot":"","sources":["../../../src/organisms/footer/footer.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,gBAAgB,GAAG,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA2CJ,gBAAgB;;;;;;;;;;;CAW1C,CAAC"}
@@ -8,14 +8,24 @@ import { DsElement } from '@jsekulowicz/ds-core';
8
8
  * `ds-sidenav` (typically inside `ds-page-shell`) for navigation. The bar has a fixed
9
9
  * 48px height at every viewport and a symmetric 16px inline padding.
10
10
  *
11
+ * The visible chrome (background + border-bottom) always spans the full width of the
12
+ * bar; the inner brand + actions content is held in a centered `inner` wrapper whose
13
+ * max-width is configurable via the `--ds-top-bar-content-max-width` custom property,
14
+ * so consumers (e.g. ds-page-shell) can align the bar's content with a constrained
15
+ * content column below.
16
+ *
11
17
  * @slot brand - Logo, wordmark, and/or page title (left).
12
18
  * @slot actions - Buttons, account menus, drawer toggle, etc. (right).
13
- * @csspart bar - The internal `<nav>` landmark element.
19
+ * @csspart bar - The internal `<nav>` landmark element (full-width chrome).
20
+ * @csspart inner - The capped content wrapper holding brand + actions.
14
21
  * @csspart brand - The brand wrapper.
15
22
  * @csspart actions - The actions wrapper.
16
23
  * @cssprop --ds-top-bar-bg - Background color of the bar. Defaults to `var(--ds-color-bg)`.
17
24
  * Override (e.g. to `transparent`) when nesting inside a container that paints its own
18
25
  * background underneath, such as a sticky shell with `backdrop-filter`.
26
+ * @cssprop --ds-top-bar-content-max-width - Max width of the inner content (brand +
27
+ * actions). Defaults to `none` (no cap). Set to e.g. `var(--ds-page-shell-max-width)`
28
+ * to align with a content column below.
19
29
  */
20
30
  export declare class DsTopBar extends DsElement {
21
31
  static styles: import("lit").CSSResult[];
@@ -1 +1 @@
1
- {"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,4BAAuC;IAEjD,KAAK,SAAa;IAErB,MAAM,IAAI,cAAc;CAMlC"}
1
+ {"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,4BAAuC;IAEjD,KAAK,SAAa;IAErB,MAAM,IAAI,cAAc;CAQlC"}
@@ -16,14 +16,24 @@ import { topBarStyles } from './top-bar.styles.js';
16
16
  * `ds-sidenav` (typically inside `ds-page-shell`) for navigation. The bar has a fixed
17
17
  * 48px height at every viewport and a symmetric 16px inline padding.
18
18
  *
19
+ * The visible chrome (background + border-bottom) always spans the full width of the
20
+ * bar; the inner brand + actions content is held in a centered `inner` wrapper whose
21
+ * max-width is configurable via the `--ds-top-bar-content-max-width` custom property,
22
+ * so consumers (e.g. ds-page-shell) can align the bar's content with a constrained
23
+ * content column below.
24
+ *
19
25
  * @slot brand - Logo, wordmark, and/or page title (left).
20
26
  * @slot actions - Buttons, account menus, drawer toggle, etc. (right).
21
- * @csspart bar - The internal `<nav>` landmark element.
27
+ * @csspart bar - The internal `<nav>` landmark element (full-width chrome).
28
+ * @csspart inner - The capped content wrapper holding brand + actions.
22
29
  * @csspart brand - The brand wrapper.
23
30
  * @csspart actions - The actions wrapper.
24
31
  * @cssprop --ds-top-bar-bg - Background color of the bar. Defaults to `var(--ds-color-bg)`.
25
32
  * Override (e.g. to `transparent`) when nesting inside a container that paints its own
26
33
  * background underneath, such as a sticky shell with `backdrop-filter`.
34
+ * @cssprop --ds-top-bar-content-max-width - Max width of the inner content (brand +
35
+ * actions). Defaults to `none` (no cap). Set to e.g. `var(--ds-page-shell-max-width)`
36
+ * to align with a content column below.
27
37
  */
28
38
  export class DsTopBar extends DsElement {
29
39
  constructor() {
@@ -33,8 +43,10 @@ export class DsTopBar extends DsElement {
33
43
  static { this.styles = [...DsElement.styles, topBarStyles]; }
34
44
  render() {
35
45
  return html `<nav part="bar" aria-label=${this.label}>
36
- <div class="brand" part="brand"><slot name="brand"></slot></div>
37
- <div class="actions" part="actions"><slot name="actions"></slot></div>
46
+ <div class="inner" part="inner">
47
+ <div class="brand" part="brand"><slot name="brand"></slot></div>
48
+ <div class="actions" part="actions"><slot name="actions"></slot></div>
49
+ </div>
38
50
  </nav>`;
39
51
  }
40
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"top-bar.js","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,QAAS,SAAQ,SAAS;IAAvC;;QAGc,UAAK,GAAG,SAAS,CAAC;IAQhC,CAAC;aAViB,WAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,AAAtC,CAAuC;IAIpD,MAAM;QACb,OAAO,IAAI,CAAA,8BAA8B,IAAI,CAAC,KAAK;;;WAG5C,CAAC;IACV,CAAC;;AAPW;IAAX,QAAQ,EAAE;uCAAmB"}
1
+ {"version":3,"file":"top-bar.js","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,QAAS,SAAQ,SAAS;IAAvC;;QAGc,UAAK,GAAG,SAAS,CAAC;IAUhC,CAAC;aAZiB,WAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,AAAtC,CAAuC;IAIpD,MAAM;QACb,OAAO,IAAI,CAAA,8BAA8B,IAAI,CAAC,KAAK;;;;;WAK5C,CAAC;IACV,CAAC;;AATW;IAAX,QAAQ,EAAE;uCAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"top-bar.styles.d.ts","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,yBAkCxB,CAAC"}
1
+ {"version":3,"file":"top-bar.styles.d.ts","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,yBA6CxB,CAAC"}
@@ -4,21 +4,32 @@ export const topBarStyles = css `
4
4
  display: block;
5
5
  }
6
6
  nav {
7
- display: flex;
8
- align-items: center;
9
- justify-content: space-between;
10
- gap: var(--ds-space-3);
11
- /* Fixed 48px height at every viewport; 16px symmetric inline
12
- padding. Padding is declared via padding-inline only — vertical
13
- centering is owned by the flexbox + fixed height. */
7
+ /* Full-width chrome: background, border-bottom, and the fixed
8
+ responsive height live on the nav itself so they always span
9
+ the parent's full width regardless of the inner content cap. */
14
10
  height: 48px;
15
- padding-inline: var(--ds-space-4);
16
11
  background: var(--ds-top-bar-bg, var(--ds-color-bg));
17
12
  border-bottom: 1px solid var(--ds-color-border);
18
13
  font-family: var(--ds-font-body);
19
14
  color: var(--ds-color-fg);
20
15
  box-sizing: border-box;
21
16
  }
17
+ .inner {
18
+ /* Inner wrapper holds brand + actions, optionally capped to align
19
+ with a constrained content column below the bar. 16px symmetric
20
+ inline padding lives here so it scales with the (capped) content
21
+ column, not the full-width chrome. */
22
+ height: 100%;
23
+ width: 100%;
24
+ max-width: var(--ds-top-bar-content-max-width, none);
25
+ margin-inline: auto;
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: space-between;
29
+ gap: var(--ds-space-3);
30
+ padding-inline: var(--ds-space-4);
31
+ box-sizing: border-box;
32
+ }
22
33
  .brand {
23
34
  display: flex;
24
35
  align-items: center;
@@ -1 +1 @@
1
- {"version":3,"file":"top-bar.styles.js","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkC9B,CAAC"}
1
+ {"version":3,"file":"top-bar.styles.js","sourceRoot":"","sources":["../../../src/organisms/top-bar/top-bar.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6C9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"page-shell.styles.d.ts","sourceRoot":"","sources":["../../../src/templates/page-shell/page-shell.styles.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,yBAgM3B,CAAC"}
1
+ {"version":3,"file":"page-shell.styles.d.ts","sourceRoot":"","sources":["../../../src/templates/page-shell/page-shell.styles.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,yBA8M3B,CAAC"}
@@ -8,7 +8,8 @@ export const pageShellStyles = css `
8
8
  display: flex;
9
9
  flex-direction: column;
10
10
  position: relative;
11
- min-height: 100vh;
11
+ height: 100vh;
12
+ height: 100dvh;
12
13
  overflow-x: clip;
13
14
  background: var(--ds-color-bg);
14
15
  color: var(--ds-color-fg);
@@ -24,10 +25,23 @@ export const pageShellStyles = css `
24
25
  }
25
26
 
26
27
  /* The header composes ds-top-bar; let the top-bar own height, padding,
27
- border-bottom, and layout. We just make its background transparent so
28
- the sticky header's blurred bg shows through. */
28
+ border-bottom, and layout. We just (a) make its background transparent
29
+ so the sticky header's blurred bg shows through, and (b) constrain its
30
+ inner brand + actions content to the same max-width as the shell-body
31
+ below so the bar's brand left-aligns with the aside, and its actions
32
+ right-align with the aside-end (or the right edge of main when no
33
+ aside-end is slotted). */
29
34
  .chrome {
30
35
  --ds-top-bar-bg: transparent;
36
+ --ds-top-bar-content-max-width: var(--ds-page-shell-max-width);
37
+ }
38
+
39
+ /* Same treatment for a slotted ds-footer: cap its inner content to the
40
+ shell-body's max-width so footer content aligns with the column above.
41
+ Consumers who slot a non-ds-footer custom element can override the
42
+ property themselves. */
43
+ ::slotted(ds-footer) {
44
+ --ds-footer-content-max-width: var(--ds-page-shell-max-width);
31
45
  }
32
46
 
33
47
  footer {
@@ -1 +1 @@
1
- {"version":3,"file":"page-shell.styles.js","sourceRoot":"","sources":["../../../src/templates/page-shell/page-shell.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,sBAAsB,GAAG,SAAS,CAAC,QAAQ,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAyFX,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuG5C,CAAC"}
1
+ {"version":3,"file":"page-shell.styles.js","sourceRoot":"","sources":["../../../src/templates/page-shell/page-shell.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,sBAAsB,GAAG,SAAS,CAAC,QAAQ,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAuGX,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuG5C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsekulowicz/ds-components",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "Lit web components for the Design System Library (atoms, molecules, organisms, templates, pages).",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -385,8 +385,8 @@
385
385
  ],
386
386
  "dependencies": {
387
387
  "lit": "^3.2.1",
388
- "@jsekulowicz/ds-tokens": "0.5.0",
389
- "@jsekulowicz/ds-core": "0.5.0"
388
+ "@jsekulowicz/ds-core": "0.5.0",
389
+ "@jsekulowicz/ds-tokens": "0.5.0"
390
390
  },
391
391
  "devDependencies": {
392
392
  "heroicons": "2.2.0",