@aquera/nile-elements 2.0.9 → 2.0.11

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.
Files changed (142) hide show
  1. package/README.md +11 -0
  2. package/demo/app-shell.html +852 -0
  3. package/demo/nxtgen-classes.css +5 -5
  4. package/demo/nxtgen-dark.css +25 -25
  5. package/demo/nxtgen-properties.css +2 -2
  6. package/demo/nxtgen-utilities.css +5 -5
  7. package/demo/nxtgen.css +5 -5
  8. package/demo/utilities.css +2 -2
  9. package/demo/variables.css +2 -2
  10. package/dist/index.cjs.js +1 -1
  11. package/dist/index.esm.js +1 -1
  12. package/dist/index.js +594 -308
  13. package/dist/internal/app-shell-utility-control-styles.cjs.js +2 -0
  14. package/dist/internal/app-shell-utility-control-styles.cjs.js.map +1 -0
  15. package/dist/internal/app-shell-utility-control-styles.esm.js +16 -0
  16. package/dist/nile-app-shell/index.cjs.js +1 -1
  17. package/dist/nile-app-shell/index.esm.js +1 -1
  18. package/dist/nile-app-shell/nile-app-shell.cjs.js +1 -1
  19. package/dist/nile-app-shell/nile-app-shell.cjs.js.map +1 -1
  20. package/dist/nile-app-shell/nile-app-shell.css.cjs.js +1 -1
  21. package/dist/nile-app-shell/nile-app-shell.css.cjs.js.map +1 -1
  22. package/dist/nile-app-shell/nile-app-shell.css.esm.js +270 -92
  23. package/dist/nile-app-shell/nile-app-shell.esm.js +61 -10
  24. package/dist/nile-app-shell/shell-controller.cjs.js.map +1 -1
  25. package/dist/nile-app-shell-main/nile-app-shell-main.cjs.js.map +1 -1
  26. package/dist/nile-app-shell-nav-toggle/index.cjs.js +1 -1
  27. package/dist/nile-app-shell-nav-toggle/index.esm.js +1 -1
  28. package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.cjs.js +1 -1
  29. package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.cjs.js.map +1 -1
  30. package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.cjs.js +1 -1
  31. package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.cjs.js.map +1 -1
  32. package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.esm.js +7 -3
  33. package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.esm.js +3 -3
  34. package/dist/nile-app-shell-panel/index.cjs.js +1 -1
  35. package/dist/nile-app-shell-panel/index.esm.js +1 -1
  36. package/dist/nile-app-shell-panel/nile-app-shell-panel.cjs.js +1 -1
  37. package/dist/nile-app-shell-panel/nile-app-shell-panel.cjs.js.map +1 -1
  38. package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js +1 -1
  39. package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js.map +1 -1
  40. package/dist/nile-app-shell-panel/nile-app-shell-panel.css.esm.js +29 -7
  41. package/dist/nile-app-shell-panel/nile-app-shell-panel.esm.js +18 -5
  42. package/dist/nile-app-shell-side-nav/nile-app-shell-side-nav.cjs.js.map +1 -1
  43. package/dist/nile-app-shell-side-nav/nile-app-shell-side-nav.css.cjs.js.map +1 -1
  44. package/dist/nile-badge/nile-badge.css.cjs.js +1 -1
  45. package/dist/nile-badge/nile-badge.css.cjs.js.map +1 -1
  46. package/dist/nile-badge/nile-badge.css.esm.js +2 -2
  47. package/dist/nile-button-toggle/nile-button-toggle.css.cjs.js +1 -1
  48. package/dist/nile-button-toggle/nile-button-toggle.css.cjs.js.map +1 -1
  49. package/dist/nile-button-toggle/nile-button-toggle.css.esm.js +2 -2
  50. package/dist/nile-code-editor/nile-code-editor.cjs.js +1 -1
  51. package/dist/nile-code-editor/nile-code-editor.cjs.js.map +1 -1
  52. package/dist/nile-code-editor/nile-code-editor.esm.js +1 -1
  53. package/dist/nile-menu-item/nile-menu-item.css.cjs.js +1 -1
  54. package/dist/nile-menu-item/nile-menu-item.css.cjs.js.map +1 -1
  55. package/dist/nile-menu-item/nile-menu-item.css.esm.js +1 -1
  56. package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js +1 -1
  57. package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js.map +1 -1
  58. package/dist/nile-rich-text-editor/nile-rich-text-editor.css.esm.js +5 -2
  59. package/dist/nile-toast/nile-toast.css.cjs.js +1 -1
  60. package/dist/nile-toast/nile-toast.css.cjs.js.map +1 -1
  61. package/dist/nile-toast/nile-toast.css.esm.js +5 -5
  62. package/dist/src/internal/app-shell-utility-control-styles.d.ts +12 -0
  63. package/dist/src/internal/app-shell-utility-control-styles.js +29 -0
  64. package/dist/src/internal/app-shell-utility-control-styles.js.map +1 -0
  65. package/dist/src/nile-app-shell/nile-app-shell-regions.test.d.ts +3 -0
  66. package/dist/src/nile-app-shell/nile-app-shell-regions.test.js +206 -0
  67. package/dist/src/nile-app-shell/nile-app-shell-regions.test.js.map +1 -1
  68. package/dist/src/nile-app-shell/nile-app-shell.css.d.ts +1 -9
  69. package/dist/src/nile-app-shell/nile-app-shell.css.js +270 -99
  70. package/dist/src/nile-app-shell/nile-app-shell.css.js.map +1 -1
  71. package/dist/src/nile-app-shell/nile-app-shell.d.ts +90 -122
  72. package/dist/src/nile-app-shell/nile-app-shell.js +224 -143
  73. package/dist/src/nile-app-shell/nile-app-shell.js.map +1 -1
  74. package/dist/src/nile-app-shell/nile-app-shell.test.d.ts +3 -0
  75. package/dist/src/nile-app-shell/nile-app-shell.test.js +898 -29
  76. package/dist/src/nile-app-shell/nile-app-shell.test.js.map +1 -1
  77. package/dist/src/nile-app-shell/shell-controller.d.ts +1 -8
  78. package/dist/src/nile-app-shell/shell-controller.js +2 -14
  79. package/dist/src/nile-app-shell/shell-controller.js.map +1 -1
  80. package/dist/src/nile-app-shell-main/nile-app-shell-main.d.ts +2 -6
  81. package/dist/src/nile-app-shell-main/nile-app-shell-main.js +2 -6
  82. package/dist/src/nile-app-shell-main/nile-app-shell-main.js.map +1 -1
  83. package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.d.ts +1 -4
  84. package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.js +7 -5
  85. package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.js.map +1 -1
  86. package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.d.ts +4 -8
  87. package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.js +5 -6
  88. package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.js.map +1 -1
  89. package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js +28 -5
  90. package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js.map +1 -1
  91. package/dist/src/nile-app-shell-panel/nile-app-shell-panel.d.ts +18 -13
  92. package/dist/src/nile-app-shell-panel/nile-app-shell-panel.js +45 -16
  93. package/dist/src/nile-app-shell-panel/nile-app-shell-panel.js.map +1 -1
  94. package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.d.ts +1 -4
  95. package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.js +1 -4
  96. package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.js.map +1 -1
  97. package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.d.ts +4 -12
  98. package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.js +4 -12
  99. package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.js.map +1 -1
  100. package/dist/src/nile-badge/nile-badge.css.js +2 -2
  101. package/dist/src/nile-badge/nile-badge.css.js.map +1 -1
  102. package/dist/src/nile-button-toggle/nile-button-toggle.css.js +2 -2
  103. package/dist/src/nile-button-toggle/nile-button-toggle.css.js.map +1 -1
  104. package/dist/src/nile-code-editor/nile-code-editor.d.ts +1 -1
  105. package/dist/src/nile-code-editor/nile-code-editor.js +2 -2
  106. package/dist/src/nile-code-editor/nile-code-editor.js.map +1 -1
  107. package/dist/src/nile-menu-item/nile-menu-item.css.js +1 -1
  108. package/dist/src/nile-menu-item/nile-menu-item.css.js.map +1 -1
  109. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js +5 -2
  110. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js.map +1 -1
  111. package/dist/src/nile-toast/nile-toast.css.js +5 -5
  112. package/dist/src/nile-toast/nile-toast.css.js.map +1 -1
  113. package/dist/src/version.js +1 -1
  114. package/dist/src/version.js.map +1 -1
  115. package/dist/tsconfig.tsbuildinfo +1 -1
  116. package/dist/version.cjs.js +1 -1
  117. package/dist/version.cjs.js.map +1 -1
  118. package/dist/version.esm.js +1 -1
  119. package/package.json +1 -1
  120. package/plop-templates/lit/lit.test.ts.hbs +22 -0
  121. package/plop-templates/lit/lit.ts.hbs +10 -5
  122. package/plopfile.js +12 -0
  123. package/src/internal/app-shell-utility-control-styles.ts +30 -0
  124. package/src/nile-app-shell/nile-app-shell-regions.test.ts +248 -0
  125. package/src/nile-app-shell/nile-app-shell.css.ts +270 -99
  126. package/src/nile-app-shell/nile-app-shell.test.ts +1120 -29
  127. package/src/nile-app-shell/nile-app-shell.ts +241 -148
  128. package/src/nile-app-shell/shell-controller.ts +2 -14
  129. package/src/nile-app-shell-main/nile-app-shell-main.ts +2 -6
  130. package/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.ts +7 -5
  131. package/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.ts +7 -11
  132. package/src/nile-app-shell-panel/nile-app-shell-panel.css.ts +28 -5
  133. package/src/nile-app-shell-panel/nile-app-shell-panel.ts +44 -16
  134. package/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.ts +1 -4
  135. package/src/nile-app-shell-side-nav/nile-app-shell-side-nav.ts +4 -12
  136. package/src/nile-badge/nile-badge.css.ts +2 -2
  137. package/src/nile-button-toggle/nile-button-toggle.css.ts +2 -2
  138. package/src/nile-code-editor/nile-code-editor.ts +2 -2
  139. package/src/nile-menu-item/nile-menu-item.css.ts +1 -1
  140. package/src/nile-rich-text-editor/nile-rich-text-editor.css.ts +5 -2
  141. package/src/nile-toast/nile-toast.css.ts +5 -5
  142. package/vscode-html-custom-data.json +114 -37
@@ -1,16 +1,26 @@
1
- import{css as e}from"lit";const n=e`
1
+ import{css as e}from"lit";import{u as n}from"../internal/app-shell-utility-control-styles.esm.js";const i=e`
2
2
  :host {
3
- /* Geometry. Values come from design tokens wherever one exists; the bare
4
- pixels are shell geometry with no matching token. */
5
- --nile-app-shell-side-nav-width: 260px;
6
- --nile-app-shell-side-nav-rail-width: 64px;
7
- --nile-app-shell-gutter: var(--nile-spacing-md, var(--ng-spacing-md));
3
+ /* Geometry: design tokens where one exists, bare pixels where none does. */
4
+ /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */
5
+ --nile-app-shell-side-nav-width: var(
6
+ --nile-width-240px,
7
+ var(--ng-spacing-296, 240px)
8
+ );
9
+ --nile-app-shell-side-nav-rail-width: var(
10
+ --nile-width-70px,
11
+ var(--ng-spacing-68, 70px)
12
+ );
13
+ --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));
8
14
  --nile-app-shell-content-padding: var(
9
15
  --nile-spacing-3xl,
10
16
  var(--ng-spacing-3xl)
11
17
  );
12
- --nile-app-shell-top-bar-height: 56px;
13
- --nile-app-shell-tabs-height: 48px;
18
+ --nile-app-shell-top-bar-height: 68px;
19
+ /* The panel header keeps its own height, distinct from the page header. */
20
+ --nile-app-shell-panel-header-height: 56px;
21
+ --nile-app-shell-tabs-height: 33px;
22
+ /* The leading app icon is its own 20px size, not the 32px utility box. */
23
+ --nile-app-shell-app-icon-size: 20px;
14
24
  --nile-app-shell-panel-width: 480px;
15
25
  --nile-app-shell-panel-min-width: 360px;
16
26
  --nile-app-shell-aside-width: 320px;
@@ -18,9 +28,10 @@ import{css as e}from"lit";const n=e`
18
28
  --nile-app-shell-content-min-width: 640px;
19
29
  --nile-app-shell-min-width: 768px;
20
30
  --nile-app-shell-centered-width: 824px;
31
+ /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */
21
32
  --nile-app-shell-utility-size: var(
22
33
  --nile-spacing-4xl,
23
- var(--ng-spacing-4xl)
34
+ var(--ng-spacing-4xl, 32px)
24
35
  );
25
36
  --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));
26
37
  --nile-app-shell-duration: var(
@@ -60,8 +71,7 @@ import{css as e}from"lit";const n=e`
60
71
  height: 100dvh;
61
72
  }
62
73
 
63
- /* Effective rail state, set by the component: the user's preference, or a
64
- forced rail at narrow widths. */
74
+ /* Effective rail state: the user's preference, or a forced rail when narrow. */
65
75
  :host([rail]) {
66
76
  --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);
67
77
  }
@@ -70,10 +80,19 @@ import{css as e}from"lit";const n=e`
70
80
  --_side-nav-track: 0px;
71
81
  }
72
82
 
83
+ /* The Description axis: a present description adds the 8px its second line occupies. */
84
+ :host([has-description]) {
85
+ --nile-app-shell-top-bar-height: 76px;
86
+ }
87
+
73
88
  /* The top bar compresses before the content does. */
74
89
  @media (max-height: 600px) {
75
90
  :host {
76
- --nile-app-shell-top-bar-height: 48px;
91
+ --nile-app-shell-top-bar-height: 56px;
92
+ }
93
+
94
+ :host([has-description]) {
95
+ --nile-app-shell-top-bar-height: 64px;
77
96
  }
78
97
  }
79
98
 
@@ -101,13 +120,12 @@ import{css as e}from"lit";const n=e`
101
120
  display: none;
102
121
  }
103
122
 
104
- /*
105
- * The nav and the page share one surface, and the shell owns the track
106
- * width, so a slotted sidebar fills the track and drops its own background
107
- * and edge. Set --nile-app-shell-side-nav-bg to put a surface back.
108
- */
123
+ /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */
124
+ /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted
125
+ nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in
126
+ nile-app-shell-regions.test.ts lock the two together; change both or neither. */
109
127
  ::slotted([slot='side-nav']) {
110
- width: 100% !important;
128
+ width: 100%;
111
129
  height: 100%;
112
130
  background: var(--nile-app-shell-side-nav-bg, transparent) !important;
113
131
  border-right: var(--nile-app-shell-side-nav-border, 0) !important;
@@ -122,19 +140,19 @@ import{css as e}from"lit";const n=e`
122
140
  min-width: 0;
123
141
  gap: var(--nile-app-shell-gutter);
124
142
  padding: var(--nile-app-shell-gutter);
143
+ /* Flush against the nav track; the gutter insets the other three sides. */
144
+ padding-inline-start: 0;
125
145
  box-sizing: border-box;
126
146
  }
127
147
 
148
+ /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */
149
+ :host(:not([has-side-nav])) .content-section {
150
+ padding-inline-start: var(--nile-app-shell-gutter);
151
+ }
152
+
128
153
  .container {
129
154
  box-sizing: border-box;
130
- /*
131
- * The floor is the flex basis, not a min-width: a hard min-width cannot
132
- * yield, so the row overflows and :host's overflow:hidden clips the
133
- * regions after it. As a basis the container holds the floor while there
134
- * is room and gives way when there is not. The shell keeps a docked panel
135
- * off the row until it fits (see _dockRequirement), so the give-way path
136
- * is the last resort, not the usual one.
137
- */
155
+ /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */
138
156
  flex: 1 1 var(--nile-app-shell-content-min-width);
139
157
  display: flex;
140
158
  flex-direction: column;
@@ -142,24 +160,15 @@ import{css as e}from"lit";const n=e`
142
160
  overflow: hidden;
143
161
  background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));
144
162
  border: var(--nile-border-width-1, var(--ng-border-width-1)) solid
145
- var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
163
+ var(--nile-colors-neutral-500, var(--ng-colors-border-primary));
146
164
  border-radius: var(--nile-app-shell-radius);
147
165
  box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));
148
- /*
149
- * The container — not the viewport — is the sizing context for page
150
- * content. See the content-container note below for querying it.
151
- */
166
+ /* The container, not the viewport, is the sizing context for page content. */
152
167
  container-type: inline-size;
153
168
  container-name: nile-content;
154
169
  }
155
170
 
156
- /*
157
- * Container queries cannot cross a shadow boundary: a rule in the page's
158
- * stylesheet cannot see a container declared in here. The
159
- * content-container attribute moves the context onto the slotted page root instead, so page CSS can
160
- * write an @container nile-content query. It brings layout containment with
161
- * it, so it is opt-in.
162
- */
171
+ /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */
163
172
  :host([content-container]) slot:not([name])::slotted(*) {
164
173
  container-type: inline-size;
165
174
  container-name: nile-content;
@@ -183,12 +192,7 @@ import{css as e}from"lit";const n=e`
183
192
  padding-inline: var(--nile-app-shell-content-padding);
184
193
  }
185
194
 
186
- /* Inside the container the bar carries the rule that separates it from the
187
- page body; spanning the shell it carries the container's edge instead. */
188
- .container > .top-bar {
189
- border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid
190
- var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
191
- }
195
+ /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */
192
196
 
193
197
  .shell-top-bar {
194
198
  grid-area: top-bar;
@@ -212,6 +216,171 @@ import{css as e}from"lit";const n=e`
212
216
  flex: 1 1 auto;
213
217
  }
214
218
 
219
+ /* The title block: the header's own heading, the Leading axis and the badge; renders before the top-bar slot. */
220
+ .title-area {
221
+ display: flex;
222
+ /* Top-aligned, not centred: the leading element belongs to the title's row, not the title-plus-description stack. */
223
+ align-items: flex-start;
224
+ gap: var(--nile-spacing-md, var(--ng-spacing-md));
225
+ min-width: 0;
226
+ }
227
+
228
+ /* The leading line box: exactly the page title's line height, centring whatever leading control sits in it. */
229
+ .leading {
230
+ flex: 0 0 auto;
231
+ display: inline-flex;
232
+ align-items: center;
233
+ gap: var(--nile-spacing-md, var(--ng-spacing-md));
234
+ min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));
235
+ }
236
+
237
+ .title-stack {
238
+ display: flex;
239
+ flex-direction: column;
240
+ justify-content: center;
241
+ gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));
242
+ min-width: 0;
243
+ }
244
+
245
+ .title-row {
246
+ display: flex;
247
+ align-items: center;
248
+ gap: var(--nile-spacing-md, var(--ng-spacing-md));
249
+ min-width: 0;
250
+ }
251
+
252
+ .page-title {
253
+ margin: 0;
254
+ min-width: 0;
255
+ font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
256
+ font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));
257
+ line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));
258
+ font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));
259
+ color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
260
+ white-space: nowrap;
261
+ overflow: hidden;
262
+ text-overflow: ellipsis;
263
+ }
264
+
265
+ .description {
266
+ margin: 0;
267
+ min-width: 0;
268
+ font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
269
+ font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));
270
+ line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));
271
+ font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));
272
+ color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));
273
+ white-space: nowrap;
274
+ overflow: hidden;
275
+ text-overflow: ellipsis;
276
+ }
277
+
278
+ /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */
279
+ .badge {
280
+ flex: 0 0 auto;
281
+ display: inline-flex;
282
+ align-items: center;
283
+ padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));
284
+ padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));
285
+ border: var(--nile-border-width-1, var(--ng-border-width-1)) solid
286
+ var(
287
+ --nile-colors-neutral-400,
288
+ var(--ng-componentcolors-utility-gray-200)
289
+ );
290
+ border-radius: var(--nile-radius-full, var(--ng-radius-full));
291
+ background: var(
292
+ --nile-colors-neutral-100,
293
+ var(--ng-componentcolors-utility-gray-50)
294
+ );
295
+ color: var(
296
+ --nile-colors-dark-500,
297
+ var(--ng-componentcolors-utility-gray-700)
298
+ );
299
+ font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
300
+ font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));
301
+ line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));
302
+ font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));
303
+ white-space: nowrap;
304
+ }
305
+
306
+ /* Leading=Back: drawn as a breadcrumb label; the shell owns no history, so pressing it only emits nile-header-back. */
307
+ .back {
308
+ flex: 0 0 auto;
309
+ display: inline-flex;
310
+ align-items: center;
311
+ gap: var(--nile-spacing-xs, var(--ng-spacing-xs));
312
+ margin: 0;
313
+ padding: 0;
314
+ border: 0;
315
+ background: none;
316
+ cursor: pointer;
317
+ font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
318
+ font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));
319
+ line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));
320
+ font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));
321
+ color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));
322
+ }
323
+
324
+ .back:hover {
325
+ color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
326
+ }
327
+
328
+ .crumb-divider {
329
+ flex: 0 0 auto;
330
+ display: inline-flex;
331
+ align-items: center;
332
+ color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));
333
+ }
334
+
335
+ /* Leading=AppIcon: a 20px block before the title; the page slots the mark, the shell owns the box, surface and radius. */
336
+ .app-icon {
337
+ position: relative;
338
+ flex: 0 0 auto;
339
+ display: inline-flex;
340
+ align-items: center;
341
+ justify-content: center;
342
+ width: var(--nile-app-shell-app-icon-size);
343
+ height: var(--nile-app-shell-app-icon-size);
344
+ border-radius: var(--nile-radius-sm, var(--ng-radius-sm));
345
+ overflow: hidden;
346
+ }
347
+
348
+ /* The slotted mark fills the wrapper edge to edge, clipped to the box. */
349
+ .app-icon slot::slotted(*) {
350
+ width: 100%;
351
+ height: 100%;
352
+ display: block;
353
+ object-fit: cover;
354
+ }
355
+
356
+ /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */
357
+ .app-icon::before {
358
+ content: '';
359
+ position: absolute;
360
+ inset: 0;
361
+ border-radius: inherit;
362
+ pointer-events: none;
363
+ z-index: 1;
364
+ background: linear-gradient(
365
+ 180deg,
366
+ rgb(255 255 255 / 12%) 0%,
367
+ rgb(255 255 255 / 0%) 100%
368
+ );
369
+ mask: var(
370
+ --ng-mask-rim,
371
+ linear-gradient(#000 0 0) content-box,
372
+ linear-gradient(#000 0 0)
373
+ );
374
+ mask-composite: var(--ng-mask-composite-exclude, exclude);
375
+ padding: 1.4px;
376
+ }
377
+
378
+ :host(:not([leading='app-icon'])) .app-icon,
379
+ :host(:not([leading='back'])) .back,
380
+ :host(:not([leading='back'])) .crumb-divider {
381
+ display: none;
382
+ }
383
+
215
384
  .top-bar-actions {
216
385
  display: flex;
217
386
  align-items: center;
@@ -219,25 +388,12 @@ import{css as e}from"lit";const n=e`
219
388
  margin-inline-start: auto;
220
389
  }
221
390
 
222
- /*
223
- * An empty flex item still takes the row's gap before it, which pulls the
224
- * bar's content 16px short of the padding edge and leaves a sliver of bare
225
- * container at the end of the header. Nothing in the group, no box.
226
- */
391
+ /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */
227
392
  :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {
228
393
  display: none;
229
394
  }
230
395
 
231
- /*
232
- * The Ask button. The one control in the bar the shell renders itself: it
233
- * turns on the panel being mounted and it calls openPanel(), neither of
234
- * which slotted markup can reach.
235
- *
236
- * It is a stock <nile-button variant="primary">: the shell sets no surface,
237
- * radius, height or type of its own, so the button's appearance — and its
238
- * focus ring, hover, disabled and loading states — stays the component's.
239
- * The only rule here is the flex behaviour it needs as a top-bar item.
240
- */
396
+ /* The Ask button: a stock <nile-button variant="primary"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */
241
397
  .ask {
242
398
  flex: 0 0 auto;
243
399
  }
@@ -260,12 +416,9 @@ import{css as e}from"lit";const n=e`
260
416
  gap: var(--nile-spacing-lg, var(--ng-spacing-lg));
261
417
  }
262
418
 
263
- /*
264
- * Lands the 24px glyph box, not nile-button's 38px circle, on the
265
- * container's 24px origin: (38 - 24) / 2 = 7.
266
- */
419
+ /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */
267
420
  .nav-toggle {
268
- margin-inline-start: -7px;
421
+ margin-inline-start: -6px;
269
422
  }
270
423
 
271
424
  .rule {
@@ -278,13 +431,14 @@ import{css as e}from"lit";const n=e`
278
431
  );
279
432
  }
280
433
 
434
+ /* ------------------------------------------------------- utility controls */
435
+
436
+ /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */
437
+ ${n}
438
+
281
439
  /* --------------------------------------------------------------- tab strip */
282
440
 
283
- /*
284
- * Hoisted out of the scroller so it never scrolls away. It sits flush under
285
- * the top bar — the header carries no bottom rule of its own, so the two read
286
- * as one block of chrome, with the single rule living at the strip's bottom.
287
- */
441
+ /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */
288
442
  .tabs {
289
443
  box-sizing: border-box;
290
444
  flex: 0 0 auto;
@@ -292,6 +446,7 @@ import{css as e}from"lit";const n=e`
292
446
  align-items: stretch;
293
447
  gap: var(--nile-spacing-xs, var(--ng-spacing-xs));
294
448
  min-width: 0;
449
+ /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */
295
450
  min-height: var(--nile-app-shell-tabs-height);
296
451
  padding-inline: var(--nile-app-shell-content-padding);
297
452
  /* The strip carries the rule for the whole header block. */
@@ -301,14 +456,32 @@ import{css as e}from"lit";const n=e`
301
456
  scrollbar-width: none;
302
457
  }
303
458
 
459
+ /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */
460
+ ::slotted([slot='tabs']) {
461
+ --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))
462
+ var(--nile-spacing-xs, var(--ng-spacing-xs))
463
+ var(--nile-spacing-lg, var(--ng-spacing-lg))
464
+ var(--nile-spacing-xs, var(--ng-spacing-xs));
465
+ }
466
+
304
467
  .tabs::-webkit-scrollbar {
305
468
  display: none;
306
469
  }
307
470
 
308
- :host(:not([has-tabs])) .tabs {
471
+ :host(:not([has-tabs])) .tabs,
472
+ :host([notabs]) .tabs {
309
473
  display: none;
310
474
  }
311
475
 
476
+ /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */
477
+ /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */
478
+ ::slotted(nile-nav-tab-group[slot='tabs']) {
479
+ --track-width: 0px;
480
+ flex: 1 1 auto;
481
+ min-width: 0;
482
+ align-self: flex-end;
483
+ }
484
+
312
485
  /* ------------------------------------------------------------------- main */
313
486
 
314
487
  .main {
@@ -318,7 +491,9 @@ import{css as e}from"lit";const n=e`
318
491
  flex-direction: column;
319
492
  min-height: 0;
320
493
  overflow: auto;
494
+ /* Top and sides only: the page runs to the container's bottom edge. */
321
495
  padding: var(--nile-app-shell-content-padding);
496
+ padding-block-end: 0;
322
497
  }
323
498
 
324
499
  .main:focus {
@@ -336,13 +511,7 @@ import{css as e}from"lit";const n=e`
336
511
 
337
512
  /* Centred when short, scrolls from the top when tall. */
338
513
  :host([content-align='centered']) .main-inner {
339
- /*
340
- * width:100% + max-width leaves free space for the auto inline margins to
341
- * split; dropping the width would let the auto margins cancel the flex
342
- * stretch and shrink-wrap the column to its widest child. The block margins
343
- * centre it while it is short and compute to 0 once it is taller, so a tall
344
- * page scrolls from the top rather than clipping.
345
- */
514
+ /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */
346
515
  width: 100%;
347
516
  max-width: var(--nile-app-shell-centered-width);
348
517
  margin: auto;
@@ -352,8 +521,7 @@ import{css as e}from"lit";const n=e`
352
521
 
353
522
  .aside {
354
523
  box-sizing: border-box;
355
- /* Gives before the page does, down to its own floor, for the same reason
356
- the panel does: the page is the last region to be asked for room. */
524
+ /* Gives before the page does, down to its own floor. */
357
525
  flex: 0 1 var(--nile-app-shell-aside-width);
358
526
  min-width: var(--nile-app-shell-aside-min-width);
359
527
  display: flex;
@@ -375,13 +543,7 @@ import{css as e}from"lit";const n=e`
375
543
 
376
544
  .panel {
377
545
  box-sizing: border-box;
378
- /*
379
- * The panel pushes the page, it never covers it, so it has to be able to
380
- * give a little: full width while the row can afford it, then shrinking to
381
- * its min. Here the floor can be a real min-width — the container's floor
382
- * is a flex basis that yields all the way, so the row still cannot
383
- * overflow into :host's clip once the panel stops giving.
384
- */
546
+ /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */
385
547
  flex: 0 1 var(--nile-app-shell-panel-width);
386
548
  width: var(--nile-app-shell-panel-width);
387
549
  min-width: var(--nile-app-shell-panel-min-width);
@@ -435,13 +597,28 @@ import{css as e}from"lit";const n=e`
435
597
  flex: 0 0 auto;
436
598
  display: flex;
437
599
  align-items: center;
438
- gap: var(--nile-spacing-lg, var(--ng-spacing-lg));
439
- height: var(--nile-app-shell-top-bar-height);
440
- padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));
600
+ gap: var(--nile-spacing-md, var(--ng-spacing-md));
601
+ height: var(--nile-app-shell-panel-header-height);
602
+ padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));
441
603
  border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid
442
604
  var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
443
605
  }
444
606
 
607
+ /* The back control for a panel sub-view; stands where the brand mark does in the root view. */
608
+ .panel-back {
609
+ flex: 0 0 auto;
610
+ margin-inline-start: -6px;
611
+ }
612
+
613
+ /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */
614
+ .panel-close {
615
+ margin-inline-end: -6px;
616
+ }
617
+
618
+ :host([panelback]) .panel-mark {
619
+ display: none;
620
+ }
621
+
445
622
  .panel-heading {
446
623
  display: flex;
447
624
  align-items: center;
@@ -488,7 +665,8 @@ import{css as e}from"lit";const n=e`
488
665
  flex: 1 1 auto;
489
666
  min-height: 0;
490
667
  overflow: auto;
491
- padding: var(--nile-spacing-xl, var(--ng-spacing-xl));
668
+ /* 16 under the header, 24 on the sides and bottom. */
669
+ padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));
492
670
  display: flex;
493
671
  flex-direction: column;
494
672
  gap: var(--nile-spacing-xl, var(--ng-spacing-xl));
@@ -496,7 +674,7 @@ import{css as e}from"lit";const n=e`
496
674
 
497
675
  .panel-footer {
498
676
  flex: 0 0 auto;
499
- padding: var(--nile-spacing-xl, var(--ng-spacing-xl));
677
+ padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));
500
678
  border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid
501
679
  var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
502
680
  }
@@ -551,4 +729,4 @@ import{css as e}from"lit";const n=e`
551
729
  transition: none;
552
730
  }
553
731
  }
554
- `;export{n as s};
732
+ `;export{i as s};