baseline-foundry 0.1.3

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 (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +588 -0
  3. package/config/experiments/ibm-plex-engine-smoke.json +115 -0
  4. package/config/experiments/ubuntu-engine-smoke.json +115 -0
  5. package/config/foundation-theme.json +117 -0
  6. package/config/tiers/app.json +120 -0
  7. package/config/tiers/documentation.json +120 -0
  8. package/config/tiers/editorial.json +120 -0
  9. package/config/tiers/os.json +120 -0
  10. package/dist/accordion.d.ts +5 -0
  11. package/dist/accordion.js +32 -0
  12. package/dist/application-layout.d.ts +4 -0
  13. package/dist/application-layout.js +181 -0
  14. package/dist/baseline-grid-overlay.d.ts +5 -0
  15. package/dist/baseline-grid-overlay.js +50 -0
  16. package/dist/baseline-grid-theme.d.ts +3 -0
  17. package/dist/baseline-grid-theme.js +3 -0
  18. package/dist/baseline-grid.d.ts +7 -0
  19. package/dist/baseline-grid.js +35 -0
  20. package/dist/build.d.ts +21 -0
  21. package/dist/build.js +440 -0
  22. package/dist/code-snippet.d.ts +6 -0
  23. package/dist/code-snippet.js +95 -0
  24. package/dist/contextual-menu.d.ts +4 -0
  25. package/dist/contextual-menu.js +156 -0
  26. package/dist/css-app-tier.d.ts +1 -0
  27. package/dist/css-app-tier.js +77 -0
  28. package/dist/css-components/article-pagination.d.ts +13 -0
  29. package/dist/css-components/article-pagination.js +151 -0
  30. package/dist/css-components/button-actions.d.ts +7 -0
  31. package/dist/css-components/button-actions.js +165 -0
  32. package/dist/css-components/cards-options.d.ts +6 -0
  33. package/dist/css-components/cards-options.js +180 -0
  34. package/dist/css-components/chip-badge-status.d.ts +10 -0
  35. package/dist/css-components/chip-badge-status.js +162 -0
  36. package/dist/css-components/content-card.d.ts +25 -0
  37. package/dist/css-components/content-card.js +517 -0
  38. package/dist/css-components/control-row.d.ts +2 -0
  39. package/dist/css-components/control-row.js +18 -0
  40. package/dist/css-components/cta-figure-aspect.d.ts +1 -0
  41. package/dist/css-components/cta-figure-aspect.js +123 -0
  42. package/dist/css-components/document-navigation.d.ts +13 -0
  43. package/dist/css-components/document-navigation.js +400 -0
  44. package/dist/css-components/editorial-content.d.ts +6 -0
  45. package/dist/css-components/editorial-content.js +52 -0
  46. package/dist/css-components/icon.d.ts +1 -0
  47. package/dist/css-components/icon.js +75 -0
  48. package/dist/css-components/interactive-feedback.d.ts +2 -0
  49. package/dist/css-components/interactive-feedback.js +230 -0
  50. package/dist/css-components/interactive-tables.d.ts +7 -0
  51. package/dist/css-components/interactive-tables.js +164 -0
  52. package/dist/css-components/linked-logo-site-layout.d.ts +21 -0
  53. package/dist/css-components/linked-logo-site-layout.js +214 -0
  54. package/dist/css-components/list-tree.d.ts +5 -0
  55. package/dist/css-components/list-tree.js +98 -0
  56. package/dist/css-components/list.d.ts +3 -0
  57. package/dist/css-components/list.js +119 -0
  58. package/dist/css-components/logo-media.d.ts +16 -0
  59. package/dist/css-components/logo-media.js +219 -0
  60. package/dist/css-components/navigation-layout.d.ts +5 -0
  61. package/dist/css-components/navigation-layout.js +151 -0
  62. package/dist/css-components/panel.d.ts +6 -0
  63. package/dist/css-components/panel.js +148 -0
  64. package/dist/css-components/search-box-and-filter.d.ts +9 -0
  65. package/dist/css-components/search-box-and-filter.js +267 -0
  66. package/dist/css-components/sites-editorial-ports.d.ts +19 -0
  67. package/dist/css-components/sites-editorial-ports.js +264 -0
  68. package/dist/css-components/sites-foundation.d.ts +17 -0
  69. package/dist/css-components/sites-foundation.js +173 -0
  70. package/dist/css-components/sites-rich-lists.d.ts +18 -0
  71. package/dist/css-components/sites-rich-lists.js +364 -0
  72. package/dist/css-components/static-content-ports.d.ts +14 -0
  73. package/dist/css-components/static-content-ports.js +206 -0
  74. package/dist/css-components/tab-section.d.ts +19 -0
  75. package/dist/css-components/tab-section.js +103 -0
  76. package/dist/css-components/table.d.ts +7 -0
  77. package/dist/css-components/table.js +79 -0
  78. package/dist/css-components/tabs-choice-breadcrumbs.d.ts +9 -0
  79. package/dist/css-components/tabs-choice-breadcrumbs.js +307 -0
  80. package/dist/css-components/tiered-list-equal-height-row.d.ts +1 -0
  81. package/dist/css-components/tiered-list-equal-height-row.js +286 -0
  82. package/dist/css-components.d.ts +2 -0
  83. package/dist/css-components.js +2701 -0
  84. package/dist/css-grid.d.ts +1 -0
  85. package/dist/css-grid.js +179 -0
  86. package/dist/css.d.ts +6 -0
  87. package/dist/css.js +431 -0
  88. package/dist/experiments/ibm-plex-engine-smoke/styles.css +8969 -0
  89. package/dist/experiments/ibm-plex-engine-smoke/surfaces.json +604 -0
  90. package/dist/experiments/ibm-plex-engine-smoke/tokens.json +217 -0
  91. package/dist/in-page-navigation.d.ts +7 -0
  92. package/dist/in-page-navigation.js +136 -0
  93. package/dist/index.d.ts +37 -0
  94. package/dist/index.js +18 -0
  95. package/dist/interactive-feedback.d.ts +14 -0
  96. package/dist/interactive-feedback.js +96 -0
  97. package/dist/interactive-tables.d.ts +28 -0
  98. package/dist/interactive-tables.js +184 -0
  99. package/dist/list-tree.d.ts +4 -0
  100. package/dist/list-tree.js +44 -0
  101. package/dist/panel-drawer.d.ts +4 -0
  102. package/dist/panel-drawer.js +171 -0
  103. package/dist/presets/app-tier/styles.css +9459 -0
  104. package/dist/presets/app-tier/surfaces.json +1225 -0
  105. package/dist/presets/app-tier/tokens.json +221 -0
  106. package/dist/presets/prose/styles.css +9442 -0
  107. package/dist/presets/prose/surfaces.json +1225 -0
  108. package/dist/presets/prose/tokens.json +221 -0
  109. package/dist/presets.d.ts +6 -0
  110. package/dist/presets.js +27 -0
  111. package/dist/range-controls.d.ts +9 -0
  112. package/dist/range-controls.js +73 -0
  113. package/dist/resizable-aside.d.ts +4 -0
  114. package/dist/resizable-aside.js +328 -0
  115. package/dist/side-navigation.d.ts +4 -0
  116. package/dist/side-navigation.js +219 -0
  117. package/dist/styles.css +9442 -0
  118. package/dist/surfaces.json +1225 -0
  119. package/dist/tabs.d.ts +4 -0
  120. package/dist/tabs.js +88 -0
  121. package/dist/tier-registry.d.ts +10 -0
  122. package/dist/tier-registry.js +25 -0
  123. package/dist/tiers/app/styles.css +9459 -0
  124. package/dist/tiers/app/surfaces.json +1225 -0
  125. package/dist/tiers/app/tokens.json +221 -0
  126. package/dist/tiers/documentation/styles.css +9442 -0
  127. package/dist/tiers/documentation/surfaces.json +1225 -0
  128. package/dist/tiers/documentation/tokens.json +221 -0
  129. package/dist/tiers/editorial/styles.css +9442 -0
  130. package/dist/tiers/editorial/surfaces.json +1225 -0
  131. package/dist/tiers/editorial/tokens.json +221 -0
  132. package/dist/tiers/os/styles.css +9442 -0
  133. package/dist/tiers/os/surfaces.json +1225 -0
  134. package/dist/tiers/os/tokens.json +221 -0
  135. package/dist/tokens.json +221 -0
  136. package/dist/tooltip.d.ts +4 -0
  137. package/dist/tooltip.js +70 -0
  138. package/dist/top-navigation.d.ts +4 -0
  139. package/dist/top-navigation.js +354 -0
  140. package/dist/types.d.ts +155 -0
  141. package/dist/types.js +1 -0
  142. package/dist/vanilla-theme-colors.d.ts +5 -0
  143. package/dist/vanilla-theme-colors.js +208 -0
  144. package/docs/publishing.md +66 -0
  145. package/package.json +108 -0
@@ -0,0 +1,230 @@
1
+ /** Credential and transient-feedback compositions built on BF controls and type roles. */
2
+ export function interactiveFeedbackCss() {
3
+ return `/* ------------------------------------------------------------------ */
4
+ /* Credential reveal and repeated validation */
5
+ /* ------------------------------------------------------------------ */
6
+
7
+ :where(.bf-theme) :where(.bf-credential) {
8
+ min-inline-size: 0;
9
+ }
10
+
11
+ :where(.bf-theme) :where(.bf-credential-header) {
12
+ align-items: flex-start;
13
+ display: flex;
14
+ gap: var(--bf-space-2);
15
+ justify-content: space-between;
16
+ min-inline-size: 0;
17
+ }
18
+
19
+ :where(.bf-theme) :where(.bf-credential-header > .bf-form-label) {
20
+ flex: 1 1 auto;
21
+ min-inline-size: 0;
22
+ }
23
+
24
+ /* This button is a control inside the field heading, so the composition
25
+ explicitly trims the standalone control's trailing flow compensation. */
26
+ :where(.bf-theme) :where(.bf-password-reveal) {
27
+ border: 0;
28
+ flex: 0 0 auto;
29
+ margin-block-end: 0;
30
+ /* This attached action shares the label row. Its borderless base uses the
31
+ paired body nudges directly, preserving the row's occupied grid block. */
32
+ padding-block: var(--bf-body-nudge-start) var(--bf-body-nudge-end);
33
+ }
34
+
35
+ :where(.bf-theme) :where(.bf-password-reveal > .bf-password-reveal-icon) {
36
+ background-color: currentColor;
37
+ background-image: none;
38
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.002c2.946 0 5.612 1.666 8 4.998-2.388 3.332-5.054 4.998-8 4.998C5.054 12.998 2.388 11.332 0 8c2.388-3.332 5.054-4.998 8-4.998zM8 5a3 3 0 1 0 0 6 3 3 0 0 0 0-6zm0 1.49a1.51 1.51 0 1 1 0 3.02 1.51 1.51 0 0 1 0-3.02z'/%3E%3C/svg%3E");
39
+ mask-position: center;
40
+ mask-repeat: no-repeat;
41
+ mask-size: contain;
42
+ }
43
+
44
+ :where(.bf-theme) :where(.bf-password-reveal[aria-pressed='true'] > .bf-password-reveal-icon) {
45
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m13.938.624 1.06 1.06-2.653 2.653c1.27.823 2.475 2.026 3.616 3.61v.106l-.193.264C13.44 11.44 10.851 13 8 13a7.654 7.654 0 0 1-3.479-.839l-2.354 2.354-1.06-1.06L13.937.624zm-2.682 4.802L9.714 6.969a2 2 0 0 1-2.745 2.745L5.653 11.03a6.114 6.114 0 0 0 2.098.465L8 11.5c2.076 0 4.03-1.042 5.893-3.233L14.115 8l-.222-.267c-.858-1.01-1.736-1.775-2.637-2.307zM8 3c.608 0 1.203.07 1.787.213L8.482 4.519a6.072 6.072 0 0 0-.233-.014L8 4.5c-2.076 0-4.03 1.042-5.893 3.233L1.884 8l.223.267c.428.503.86.946 1.3 1.33l-1.062 1.061C1.535 9.938.754 9.052 0 8c2.388-3.333 5.054-5 8-5z'/%3E%3C/svg%3E");
46
+ }
47
+
48
+ /* Revealed readonly credentials stay legible; the generic readonly treatment
49
+ remains correct for ordinary text fields outside this explicit composition. */
50
+ :where(.bf-theme) :where(.bf-credential input[type='text'][readonly]) {
51
+ color: var(--bf-color-text-default);
52
+ }
53
+
54
+ :where(.bf-theme) :where(.bf-credential-validation) {
55
+ align-content: start;
56
+ display: grid;
57
+ gap: var(--bf-space-1);
58
+ list-style: none;
59
+ margin-block: 0;
60
+ padding-inline-start: 0;
61
+ }
62
+
63
+ :where(.bf-theme) :where(.bf-credential-validation > .bf-validation) {
64
+ align-content: start;
65
+ display: grid;
66
+ margin-block: 0;
67
+ min-inline-size: 0;
68
+ }
69
+
70
+ /* ------------------------------------------------------------------ */
71
+ /* Notification — transient status feedback, distinct from bf-notice */
72
+ /* ------------------------------------------------------------------ */
73
+
74
+ :where(.bf-theme) :where(.bf-notification, .bf-notification.is-information, .bf-notification.is-positive, .bf-notification.is-caution, .bf-notification.is-negative) {
75
+ --bf-notification-accent: var(--bf-color-border-information);
76
+ background: var(--bf-color-background-default);
77
+ border: var(--bf-border-width) solid var(--bf-color-border-default);
78
+ border-inline-start: var(--bf-bar-thickness) solid var(--bf-notification-accent);
79
+ color: var(--bf-color-text-default);
80
+ margin-block: 0 var(--bf-space-3);
81
+ max-inline-size: 100%;
82
+ min-inline-size: 0;
83
+ overflow-wrap: anywhere;
84
+ padding-block: calc(var(--bf-space-1) - var(--bf-border-width));
85
+ padding-inline: calc((var(--bf-space-2) * 2) + var(--bf-icon-size-default)) 0;
86
+ position: relative;
87
+ }
88
+
89
+ :where(.bf-theme) :where(.bf-notification.is-positive) {
90
+ --bf-notification-accent: var(--bf-color-border-positive);
91
+ }
92
+
93
+ :where(.bf-theme) :where(.bf-notification.is-caution) {
94
+ --bf-notification-accent: var(--bf-color-border-caution);
95
+ }
96
+
97
+ :where(.bf-theme) :where(.bf-notification.is-negative) {
98
+ --bf-notification-accent: var(--bf-color-border-negative);
99
+ }
100
+
101
+ :where(.bf-theme) :where(.bf-notification[hidden]) {
102
+ display: none;
103
+ }
104
+
105
+ :where(.bf-theme) :where(.bf-notification.is-borderless) {
106
+ border: 0;
107
+ padding-block: 0;
108
+ padding-inline: calc(var(--bf-space-2) * 2) 0;
109
+ }
110
+
111
+ :where(.bf-theme) :where(.bf-notification-icon) {
112
+ background-color: var(--bf-notification-accent);
113
+ background-image: none;
114
+ inset-block-start: calc(var(--bf-space-1) + ((var(--bf-body-line-height) - var(--bf-icon-size-default)) / 2) + var(--bf-body-nudge-start));
115
+ inset-inline-start: var(--bf-space-2);
116
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm0 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm-.75 5.25h1.5v5h-1.5v-5zM8 3.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2z'/%3E%3C/svg%3E");
117
+ mask-position: center;
118
+ mask-repeat: no-repeat;
119
+ mask-size: contain;
120
+ position: absolute;
121
+ }
122
+
123
+ :where(.bf-theme) :where(.bf-notification.is-positive > .bf-notification-icon) {
124
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm0 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm2.814 2.45 1.203.897-5.537 7.43-3.485-3.694 1.09-1.03 2.259 2.394 4.47-5.997z'/%3E%3C/svg%3E");
125
+ }
126
+
127
+ :where(.bf-theme) :where(.bf-notification.is-caution > .bf-notification-icon) {
128
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8.865 1.5 15.77 13.5a1 1 0 0 1-.866 1.5H1.096a1 1 0 0 1-.866-1.5l6.905-12a1 1 0 0 1 1.73 0zM8 3.49 2.392 13.5h11.216L8 3.49zm-.75 3.01h1.5v3.75h-1.5V6.5zM8 11.25a1 1 0 1 1 0 2 1 1 0 0 1 0-2z'/%3E%3C/svg%3E");
129
+ }
130
+
131
+ :where(.bf-theme) :where(.bf-notification.is-negative > .bf-notification-icon) {
132
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm0 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm2.282 3.138 1.06 1.061L9.052 7.99l2.291 2.292-1.061 1.06L7.99 9.052l-2.291 2.291-1.061-1.061L6.929 7.99 4.638 5.699l1.061-1.061L7.99 6.929l2.292-2.291z'/%3E%3C/svg%3E");
133
+ }
134
+
135
+ :where(.bf-theme) :where(.bf-notification.is-borderless > .bf-notification-icon) {
136
+ inset-block-start: calc(((var(--bf-body-line-height) - var(--bf-icon-size-default)) / 2) + var(--bf-body-nudge-start));
137
+ inset-inline-start: 0;
138
+ }
139
+
140
+ :where(.bf-theme) :where(.bf-notification-content, .bf-notification-meta) {
141
+ max-inline-size: 100%;
142
+ min-inline-size: 0;
143
+ }
144
+
145
+ :where(.bf-theme) :where(.bf-notification-content) {
146
+ margin-block-end: calc(var(--bf-space-2) - var(--bf-body-nudge-start));
147
+ padding-block-start: var(--bf-body-nudge-start);
148
+ padding-inline-end: var(--bf-space-4);
149
+ }
150
+
151
+ :where(.bf-theme) :where(.bf-notification-title, .bf-notification-message, .bf-notification-timestamp) {
152
+ font-family: var(--bf-body-font-family);
153
+ font-size: var(--bf-body-font-size);
154
+ font-style: var(--bf-body-font-style);
155
+ line-height: var(--bf-body-line-height);
156
+ max-inline-size: 100%;
157
+ }
158
+
159
+ :where(.bf-theme) :where(.bf-notification-title) {
160
+ font-weight: 600;
161
+ margin-block: 0;
162
+ padding-block: 0;
163
+ }
164
+
165
+ :where(.bf-theme) :where(.bf-notification-message) {
166
+ font-weight: var(--bf-body-font-weight);
167
+ margin-block: 0;
168
+ padding-block: 0;
169
+ }
170
+
171
+ :where(.bf-theme) :where(.bf-notification.is-inline .bf-notification-title, .bf-notification.is-inline .bf-notification-message) {
172
+ display: inline;
173
+ }
174
+
175
+ :where(.bf-theme) :where(.bf-notification-close) {
176
+ block-size: calc((var(--bf-space-1) * 2) + var(--bf-icon-size-default));
177
+ border: 0;
178
+ inline-size: var(--bf-icon-size-default);
179
+ margin-block-end: 0;
180
+ padding: 0;
181
+ position: absolute;
182
+ inset-block-start: var(--bf-space-1);
183
+ inset-inline-end: var(--bf-space-1);
184
+ }
185
+
186
+ :where(.bf-theme) :where(.bf-notification.is-borderless .bf-notification-close) {
187
+ inset-block-start: 0;
188
+ inset-inline-end: 0;
189
+ }
190
+
191
+ :where(.bf-theme) :where(.bf-notification-meta) {
192
+ align-items: flex-start;
193
+ border-block-start: var(--bf-border-width) solid var(--bf-color-border-low-contrast);
194
+ display: flex;
195
+ flex-wrap: wrap;
196
+ gap: var(--bf-space-1) var(--bf-space-2);
197
+ justify-content: space-between;
198
+ margin-block-end: var(--bf-space-1);
199
+ padding-block-start: calc(var(--bf-space-1) - var(--bf-border-width));
200
+ padding-inline-end: var(--bf-space-2);
201
+ }
202
+
203
+ :where(.bf-theme) :where(.bf-notification.is-inline .bf-notification-meta) {
204
+ border-block-start: 0;
205
+ padding-block-start: 0;
206
+ }
207
+
208
+ :where(.bf-theme) :where(.bf-notification-timestamp) {
209
+ color: var(--bf-color-text-muted);
210
+ font-weight: var(--bf-body-font-weight);
211
+ margin-block: 0 calc(var(--bf-space-2) - var(--bf-body-nudge-start));
212
+ padding-block: var(--bf-body-nudge-start) 0;
213
+ }
214
+
215
+ :where(.bf-theme) :where(.bf-notification-actions) {
216
+ align-items: flex-start;
217
+ display: flex;
218
+ flex-wrap: wrap;
219
+ gap: var(--bf-space-1) var(--bf-space-2);
220
+ margin-inline-start: auto;
221
+ min-inline-size: 0;
222
+ }
223
+
224
+ :where(.bf-theme) :where(.bf-notification-actions > .bf-button.is-link) {
225
+ flex: 0 0 auto;
226
+ margin-block-end: calc(var(--bf-space-2) - var(--bf-body-nudge-start));
227
+ padding-block: var(--bf-body-nudge-start) 0;
228
+ }
229
+ `;
230
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Interactive table presentation layered on the existing bf-table contract.
3
+ *
4
+ * Vanilla remains the geometry reference, while BF owns type and vertical
5
+ * rhythm through its tier tokens. Runtime hooks never participate in styling.
6
+ */
7
+ export declare function interactiveTablesCss(): string;
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Interactive table presentation layered on the existing bf-table contract.
3
+ *
4
+ * Vanilla remains the geometry reference, while BF owns type and vertical
5
+ * rhythm through its tier tokens. Runtime hooks never participate in styling.
6
+ */
7
+ export function interactiveTablesCss() {
8
+ return `:where(.bf-theme) :where(.bf-table.is-sortable th[aria-sort]) {
9
+ color: var(--bf-color-text-default);
10
+ cursor: pointer;
11
+ outline-color: var(--bf-color-focus);
12
+ white-space: nowrap;
13
+ }
14
+
15
+ :where(.bf-theme) :where(.bf-table-sort-button) {
16
+ appearance: none;
17
+ background: transparent;
18
+ border: 0;
19
+ color: inherit;
20
+ cursor: inherit;
21
+ display: inline-block;
22
+ font: inherit;
23
+ margin: -2px calc(var(--bf-space-half) * -1);
24
+ max-inline-size: 100%;
25
+ overflow: hidden;
26
+ padding: 2px var(--bf-space-half);
27
+ text-align: inherit;
28
+ text-decoration: inherit;
29
+ text-overflow: inherit;
30
+ vertical-align: inherit;
31
+ white-space: inherit;
32
+ }
33
+
34
+ :where(.bf-theme) :where(.bf-table.is-sortable th[aria-sort]:hover, .bf-table-sort-button:focus-visible) {
35
+ color: var(--bf-color-link-default);
36
+ text-decoration: underline;
37
+ text-decoration-thickness: 1px;
38
+ text-underline-offset: 0.075em;
39
+ }
40
+
41
+ :where(.bf-theme) :where(.bf-table-sort-button:focus:not(:focus-visible)) {
42
+ outline: none;
43
+ }
44
+
45
+ :where(.bf-theme) :where(.bf-table-sort-button:focus-visible) {
46
+ outline: 2px solid var(--bf-color-focus);
47
+ outline-offset: -2px;
48
+ }
49
+
50
+ :where(.bf-theme) :where(.bf-table.is-sortable th[aria-sort='ascending'], .bf-table.is-sortable th[aria-sort='descending'])::after {
51
+ background-image: var(--bf-ui-icon-chevron-down);
52
+ background-position: center;
53
+ background-repeat: no-repeat;
54
+ background-size: contain;
55
+ block-size: var(--bf-icon-size-default);
56
+ content: "";
57
+ display: inline-block;
58
+ inline-size: var(--bf-icon-size-default);
59
+ margin-inline-start: var(--bf-space-half);
60
+ vertical-align: calc((1cap - var(--bf-icon-size-default)) / 2);
61
+ }
62
+
63
+ :where(.bf-theme) :where(.bf-table.is-sortable th[aria-sort='ascending'])::after {
64
+ transform: rotate(180deg);
65
+ }
66
+
67
+ :where(.bf-theme) :where(.bf-table.is-expanding .bf-table-expand-toggle) {
68
+ margin-block-end: 0;
69
+ white-space: nowrap;
70
+ }
71
+
72
+ :where(.bf-theme) :where(.bf-table-expanding-row[hidden]) {
73
+ display: none;
74
+ }
75
+
76
+ :where(.bf-theme) .bf-table.is-expanding .bf-table-expanding-cell {
77
+ overflow: visible;
78
+ /* Complete the ordinary start-nudge inset with the paired end nudge while
79
+ consuming the row rule inside it, so wrapped detail rows stay on-grid. */
80
+ padding-block-end: calc(var(--bf-space-1) + var(--bf-body-nudge-end) - var(--bf-table-row-border-size));
81
+ white-space: normal;
82
+ }
83
+
84
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame) {
85
+ container-type: inline-size;
86
+ min-inline-size: 0;
87
+ }
88
+
89
+ :where(.bf-theme) :where(.bf-table-card-label) {
90
+ display: none;
91
+ }
92
+
93
+ @container (width < 64.75rem) {
94
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card) {
95
+ display: block;
96
+ }
97
+
98
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card > thead) {
99
+ block-size: 1px;
100
+ clip-path: inset(50%);
101
+ inline-size: 1px;
102
+ overflow: hidden;
103
+ position: absolute;
104
+ white-space: nowrap;
105
+ }
106
+
107
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card > tbody) {
108
+ display: grid;
109
+ gap: 0 var(--bf-space-3);
110
+ grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
111
+ inline-size: 100%;
112
+ }
113
+
114
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card > tbody > tr) {
115
+ border: var(--bf-border-width) solid var(--bf-color-border-default);
116
+ display: block;
117
+ margin-block-end: calc(var(--bf-space-3) - (var(--bf-border-width) * 2));
118
+ min-inline-size: 0;
119
+ padding-inline: var(--bf-space-2);
120
+ }
121
+
122
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card > tbody > tr > :where(th, td)) {
123
+ border-block-end-color: transparent;
124
+ display: block;
125
+ inline-size: 100%;
126
+ min-inline-size: 0;
127
+ overflow: hidden;
128
+ padding-inline: 0;
129
+ position: relative;
130
+ text-align: start;
131
+ text-overflow: ellipsis;
132
+ white-space: nowrap;
133
+ word-break: break-word;
134
+ }
135
+
136
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card > tbody > tr > :where(th, td):not(:first-child))::before {
137
+ background: var(--bf-color-border-low-contrast);
138
+ block-size: var(--bf-border-width);
139
+ content: "";
140
+ inset-block-start: 0;
141
+ inset-inline: 0;
142
+ position: absolute;
143
+ }
144
+
145
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card .bf-table-card-label) {
146
+ color: var(--bf-color-text-default);
147
+ display: block;
148
+ font-family: var(--bf-body-font-family);
149
+ font-size: var(--bf-body-font-size);
150
+ font-style: var(--bf-body-font-style);
151
+ font-weight: 550;
152
+ line-height: var(--bf-body-line-height);
153
+ margin-block-end: var(--bf-space-1);
154
+ overflow: hidden;
155
+ text-overflow: ellipsis;
156
+ white-space: nowrap;
157
+ }
158
+
159
+ :where(.bf-theme) :where(.bf-table-mobile-card-frame > .bf-table.is-mobile-card :where(th, td).is-overflow-visible) {
160
+ overflow: visible;
161
+ }
162
+ }
163
+ `;
164
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Vanilla Sites parity: linked-logo section and the sticky-footer layout.
3
+ *
4
+ * The Sites macro places its heading and linked-logo block at full width,
5
+ * 50/50, or 25/75. BF keeps that relationship as a small structural grid:
6
+ * 1/1 and 1/3 are proportions rather than a recreation of Vanilla grid-span
7
+ * utilities. The cards deliberately compose the existing `bf-logo-section`
8
+ * link/mark contract; the additional card slots are semantic link content,
9
+ * not the deprecated `logo-block` API.
10
+ *
11
+ * Vanilla → BF mapping (Vanilla's 8px spacing unit):
12
+ * - linked-logo image container: retained 16:9 aspect relationship;
13
+ * - muted rule to copy: 8px → `--bf-space-1`, compensating its border;
14
+ * - grid gutter: 24px / 32px breakpoint values → existing
15
+ * `--bf-grid-gap-inline` (BF's tier-aware grid geometry);
16
+ * - macro section boundaries: existing shallow/default/deep section tokens.
17
+ *
18
+ * The site layout is intentionally opt-in on `bf-page-shell`: it never
19
+ * changes the document body merely because a tier stylesheet is imported.
20
+ */
21
+ export declare function linkedLogoSiteLayoutCss(): string;
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Vanilla Sites parity: linked-logo section and the sticky-footer layout.
3
+ *
4
+ * The Sites macro places its heading and linked-logo block at full width,
5
+ * 50/50, or 25/75. BF keeps that relationship as a small structural grid:
6
+ * 1/1 and 1/3 are proportions rather than a recreation of Vanilla grid-span
7
+ * utilities. The cards deliberately compose the existing `bf-logo-section`
8
+ * link/mark contract; the additional card slots are semantic link content,
9
+ * not the deprecated `logo-block` API.
10
+ *
11
+ * Vanilla → BF mapping (Vanilla's 8px spacing unit):
12
+ * - linked-logo image container: retained 16:9 aspect relationship;
13
+ * - muted rule to copy: 8px → `--bf-space-1`, compensating its border;
14
+ * - grid gutter: 24px / 32px breakpoint values → existing
15
+ * `--bf-grid-gap-inline` (BF's tier-aware grid geometry);
16
+ * - macro section boundaries: existing shallow/default/deep section tokens.
17
+ *
18
+ * The site layout is intentionally opt-in on `bf-page-shell`: it never
19
+ * changes the document body merely because a tier stylesheet is imported.
20
+ */
21
+ export function linkedLogoSiteLayoutCss() {
22
+ return `/* ------------------------------------------------------------------ */
23
+ /* Linked logo section — Sites composition of BF logo and content slots. */
24
+ /* ------------------------------------------------------------------ */
25
+
26
+ :where(.bf-theme) :where(.bf-linked-logo-section) {
27
+ container-name: bf-linked-logo-section;
28
+ container-type: inline-size;
29
+ margin-block-end: var(--bf-section-space);
30
+ min-inline-size: 0;
31
+ }
32
+
33
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-shallow) {
34
+ margin-block-end: var(--bf-section-space-shallow);
35
+ }
36
+
37
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-deep) {
38
+ margin-block-end: var(--bf-section-space-deep);
39
+ }
40
+
41
+ :where(.bf-theme) :where(.bf-linked-logo-section-layout) {
42
+ display: grid;
43
+ grid-template-columns: minmax(0, 1fr);
44
+ min-inline-size: 0;
45
+ }
46
+
47
+ :where(.bf-theme) :where(.bf-linked-logo-section-header, .bf-linked-logo-section-content) {
48
+ min-inline-size: 0;
49
+ overflow-wrap: anywhere;
50
+ }
51
+
52
+ /* The card list is a contextual use of bf-logo-section. Its links and marks
53
+ preserve that component's focus and accessible-image treatment, while a
54
+ grid gives the Sites pattern its 16:9 linked destinations. */
55
+ :where(.bf-theme) :where(.bf-linked-logo-section) :where(.bf-logo-section.bf-linked-logo-section-logos) {
56
+ margin-block-end: 0;
57
+ }
58
+
59
+ :where(.bf-theme) :where(.bf-linked-logo-section-logos) :where(.bf-logo-section-items) {
60
+ align-items: stretch;
61
+ column-gap: var(--bf-grid-gap-inline);
62
+ display: grid;
63
+ grid-template-columns: minmax(0, 1fr);
64
+ padding-block: 0;
65
+ row-gap: var(--bf-section-space-shallow);
66
+ }
67
+
68
+ :where(.bf-theme) :where(.bf-linked-logo-section-logos) :where(.bf-logo-section-item) {
69
+ block-size: auto;
70
+ inline-size: auto;
71
+ margin-block: 0;
72
+ max-inline-size: none;
73
+ }
74
+
75
+ :where(.bf-theme) :where(.bf-linked-logo-section-card) {
76
+ align-content: start;
77
+ align-items: stretch;
78
+ color: inherit;
79
+ container-type: inline-size;
80
+ display: grid;
81
+ grid-template-rows: auto auto auto;
82
+ inline-size: 100%;
83
+ min-inline-size: 0;
84
+ text-decoration: none;
85
+ }
86
+
87
+ :where(.bf-theme) :where(.bf-linked-logo-section-card:hover) :where(.bf-linked-logo-section-card-copy) {
88
+ text-decoration: underline;
89
+ }
90
+
91
+ :where(.bf-theme) :where(.bf-linked-logo-section-mark) {
92
+ aspect-ratio: 16 / 9;
93
+ background: var(--bf-color-background-active);
94
+ display: grid;
95
+ inline-size: 100%;
96
+ max-inline-size: 100%;
97
+ min-inline-size: 0;
98
+ overflow: hidden;
99
+ place-items: center;
100
+ }
101
+
102
+ /* Card tracks are fluid, so an exact 16:9 mark is often a fractional number
103
+ of baselines tall. Keep the visual ratio exact and put only the residual
104
+ rhythm compensation after the mark; the copy keeps its own semantic
105
+ spacing and the occupied card still lands on the tier grid. */
106
+ @supports (margin-block-end: round(up, 1px, 1px)) {
107
+ :where(.bf-theme) :where(.bf-linked-logo-section-mark) {
108
+ margin-block-end: calc(
109
+ round(up, calc(100cqi * 9 / 16), var(--bf-baseline))
110
+ - calc(100cqi * 9 / 16)
111
+ );
112
+ }
113
+ }
114
+
115
+ :where(.bf-theme) :where(.bf-linked-logo-section-mark) > :where(img, svg) {
116
+ block-size: 100%;
117
+ display: block;
118
+ inline-size: 100%;
119
+ max-inline-size: 100%;
120
+ min-inline-size: 0;
121
+ object-fit: contain;
122
+ }
123
+
124
+ :where(.bf-theme) :where(.bf-linked-logo-section-card-rule) {
125
+ border-block-start: var(--bf-border-width) solid var(--bf-color-border-low-contrast);
126
+ display: block;
127
+ margin-block-start: var(--bf-space-1);
128
+ }
129
+
130
+ /* A span inherits the real body role from the page; it owns only the
131
+ relationship to its preceding divider, not an alternative type scale. */
132
+ :where(.bf-theme) :where(.bf-linked-logo-section-card-copy) {
133
+ display: block;
134
+ margin-block-start: calc(var(--bf-space-1) - var(--bf-border-width));
135
+ overflow-wrap: anywhere;
136
+ }
137
+
138
+ /* Vanilla's linked-logo block moves from one to two cards per row at the
139
+ 4-column medium grid. The section itself does not split until the 8-column
140
+ large grid: its macro uses large-only grid columns for the 50/50 and 25/75
141
+ rails. The root establishes the query context; only descendants change. */
142
+ @container bf-linked-logo-section (width >= 38.75rem) {
143
+ :where(.bf-theme) :where(.bf-linked-logo-section-logos) :where(.bf-logo-section-items) {
144
+ grid-template-columns: repeat(2, minmax(0, 1fr));
145
+ }
146
+ }
147
+
148
+ @container bf-linked-logo-section (width >= 64.75rem) {
149
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-50-50) :where(.bf-linked-logo-section-layout) {
150
+ column-gap: var(--bf-grid-gap-inline);
151
+ grid-template-columns: repeat(2, minmax(0, 1fr));
152
+ }
153
+
154
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-25-75) :where(.bf-linked-logo-section-layout) {
155
+ column-gap: var(--bf-grid-gap-inline);
156
+ grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
157
+ }
158
+
159
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-full) :where(.bf-linked-logo-section-logos) :where(.bf-logo-section-items) {
160
+ grid-template-columns: repeat(4, minmax(0, 1fr));
161
+ }
162
+
163
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-50-50) :where(.bf-linked-logo-section-logos) :where(.bf-logo-section-items) {
164
+ grid-template-columns: repeat(2, minmax(0, 1fr));
165
+ }
166
+
167
+ :where(.bf-theme) :where(.bf-linked-logo-section.is-25-75) :where(.bf-linked-logo-section-logos) :where(.bf-logo-section-items) {
168
+ grid-template-columns: repeat(3, minmax(0, 1fr));
169
+ }
170
+ }
171
+
172
+ /* ------------------------------------------------------------------ */
173
+ /* Site / sticky-footer layout. */
174
+ /* ------------------------------------------------------------------ */
175
+
176
+ /* The sticky-footer contract is explicitly opt-in, so it remains useful at
177
+ every viewport width. The descendant selector intentionally retains the
178
+ shell classes' specificity: a shell may also be a bf-panel-content region,
179
+ whose later min-block-size reset must not disable the site layout. */
180
+ :where(.bf-theme.bf-page-shell.is-site-layout),
181
+ :where(.bf-theme) .bf-page-shell.is-site-layout {
182
+ display: flex;
183
+ flex-direction: column;
184
+ min-block-size: 100dvb;
185
+ }
186
+
187
+ :where(.bf-theme.bf-page-shell.is-site-layout) > :where(.bf-site-main),
188
+ :where(.bf-theme) .bf-page-shell.is-site-layout > :where(.bf-site-main) {
189
+ flex: 0 0 auto;
190
+ min-inline-size: 0;
191
+ }
192
+
193
+ /* When a site main also consumes panel padding, pull its first text line up
194
+ one baseline so it shares the tagged navigation brand's optical top. */
195
+ :where(.bf-theme.bf-page-shell.is-site-layout) > :where(.bf-site-main.bf-panel-content),
196
+ :where(.bf-theme) .bf-page-shell.is-site-layout > :where(.bf-site-main.bf-panel-content) {
197
+ padding-block-start: calc(var(--bf-panel-padding-block) - var(--bf-baseline));
198
+ }
199
+
200
+ /* An application main already represents the available viewport remainder
201
+ and owns scrolling. A directly nested site shell fills that region instead
202
+ of claiming a second dynamic viewport; long content can still grow the
203
+ shell beyond the region and remains reachable through bf-main. */
204
+ :where(.bf-theme.bf-application) > :where(.bf-main) > .bf-page-shell.is-site-layout,
205
+ :where(.bf-theme) :where(.bf-application) > :where(.bf-main) > .bf-page-shell.is-site-layout {
206
+ min-block-size: 100%;
207
+ }
208
+
209
+ :where(.bf-theme.bf-page-shell.is-site-layout) > :where(.bf-site-footer.is-sticky),
210
+ :where(.bf-theme) .bf-page-shell.is-site-layout > :where(.bf-site-footer.is-sticky) {
211
+ margin-block-start: auto;
212
+ }
213
+ `;
214
+ }
@@ -0,0 +1,5 @@
1
+ type ListTreeCssOptions = {
2
+ bodyTypeStyles: string;
3
+ };
4
+ export declare function listTreeCss(options: ListTreeCssOptions): string;
5
+ export {};