@boostdev/design-system-components 2.6.0 → 2.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.
Files changed (90) hide show
  1. package/AGENTS.md +102 -2
  2. package/dist/client.cjs +257 -219
  3. package/dist/client.css +587 -539
  4. package/dist/client.d.cts +27 -1
  5. package/dist/client.d.ts +27 -1
  6. package/dist/client.js +220 -183
  7. package/dist/index.cjs +257 -219
  8. package/dist/index.css +587 -539
  9. package/dist/index.d.cts +27 -1
  10. package/dist/index.d.ts +27 -1
  11. package/dist/index.js +220 -183
  12. package/dist/web-components/{chunk-T6AETZRP.js → chunk-3GFWLSLS.js} +1 -1
  13. package/dist/web-components/{chunk-N6IMUOY4.js → chunk-65JXQOBA.js} +3 -3
  14. package/dist/web-components/{chunk-ZTC6GRP7.js → chunk-BKIHQYJR.js} +1 -0
  15. package/dist/web-components/{chunk-X3FKVHLK.js → chunk-CM3KYZ6Z.js} +1 -1
  16. package/dist/web-components/{chunk-QLZ2362S.js → chunk-CZBIVR4V.js} +1 -1
  17. package/dist/web-components/{chunk-GER5UJOF.js → chunk-F5E3IT7G.js} +1 -3
  18. package/dist/web-components/{chunk-UFFCKVZE.js → chunk-FXURM6D5.js} +1 -1
  19. package/dist/web-components/{chunk-HHHRF2PS.js → chunk-IYGF6CD5.js} +1 -1
  20. package/dist/web-components/{chunk-OCODKRVZ.js → chunk-KUI55GFB.js} +2 -2
  21. package/dist/web-components/{chunk-ZNKEZIYE.js → chunk-NCPQ7AF3.js} +3 -2
  22. package/dist/web-components/{chunk-RTOS7LLG.js → chunk-PC3IOQAH.js} +3 -8
  23. package/dist/web-components/{chunk-JUKB3BUP.js → chunk-PXZWYO6Z.js} +1 -1
  24. package/dist/web-components/{chunk-EBJM3VD4.js → chunk-QBB6ZX4R.js} +1 -1
  25. package/dist/web-components/{chunk-ECW3HHWA.js → chunk-TQ7IQ4GZ.js} +7 -2
  26. package/dist/web-components/{chunk-AJSXNDAP.js → chunk-X46KL5BK.js} +19 -18
  27. package/dist/web-components/{chunk-XNA6WTXG.js → chunk-Y3POAKGS.js} +1 -1
  28. package/dist/web-components/{chunk-HGBNDR22.js → chunk-Y7V7LM6R.js} +1 -1
  29. package/dist/web-components/index.d.ts +56 -1
  30. package/dist/web-components/index.js +140 -19
  31. package/dist/web-components/interaction/bds-accordion-item.js +1 -1
  32. package/dist/web-components/interaction/bds-accordion.js +1 -1
  33. package/dist/web-components/interaction/bds-button.js +1 -1
  34. package/dist/web-components/interaction/bds-dialog.js +1 -1
  35. package/dist/web-components/interaction/bds-drawer.js +1 -1
  36. package/dist/web-components/interaction/bds-popover.js +1 -1
  37. package/dist/web-components/interaction/bds-tooltip.js +1 -1
  38. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  39. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  40. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  41. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  42. package/dist/web-components/interaction/form/bds-select.js +1 -1
  43. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  44. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  45. package/dist/web-components/ui/bds-alert.js +1 -1
  46. package/dist/web-components/ui/bds-card.d.ts +3 -9
  47. package/dist/web-components/ui/bds-card.js +1 -1
  48. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  49. package/package.json +4 -2
  50. package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +113 -0
  51. package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +96 -0
  52. package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +196 -0
  53. package/src/components/interaction/form/FieldGroup/FieldGroup.stories.tsx +99 -0
  54. package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +64 -0
  55. package/src/components/interaction/form/FieldGroup/index.ts +2 -0
  56. package/src/components/interaction/form/atoms/Message.module.css +4 -0
  57. package/src/components/layout/IconWrapper/IconWrapper.module.css +2 -2
  58. package/src/index.ts +2 -0
  59. package/src/test/token-contract.spec.ts +86 -0
  60. package/src/web-components/index.ts +2 -0
  61. package/src/web-components/interaction/bds-accordion-item.ts +1 -1
  62. package/src/web-components/interaction/bds-accordion.ts +1 -0
  63. package/src/web-components/interaction/bds-button.ts +1 -3
  64. package/src/web-components/interaction/bds-dialog.ts +3 -3
  65. package/src/web-components/interaction/bds-drawer.ts +2 -2
  66. package/src/web-components/interaction/bds-popover.ts +7 -2
  67. package/src/web-components/interaction/bds-tooltip.ts +1 -1
  68. package/src/web-components/interaction/form/BdsFieldGroup.mdx +67 -0
  69. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +110 -0
  70. package/src/web-components/interaction/form/bds-checkbox-group.ts +1 -0
  71. package/src/web-components/interaction/form/bds-checkbox.ts +1 -1
  72. package/src/web-components/interaction/form/bds-combobox.ts +1 -1
  73. package/src/web-components/interaction/form/bds-field-group.spec.ts +64 -0
  74. package/src/web-components/interaction/form/bds-field-group.ts +157 -0
  75. package/src/web-components/interaction/form/bds-form-input.ts +2 -1
  76. package/src/web-components/interaction/form/bds-number-input.ts +1 -1
  77. package/src/web-components/interaction/form/bds-radio-group.ts +1 -0
  78. package/src/web-components/interaction/form/bds-radio.ts +1 -1
  79. package/src/web-components/interaction/form/bds-select.ts +1 -1
  80. package/src/web-components/interaction/form/bds-switch.ts +1 -1
  81. package/src/web-components/interaction/form/bds-textarea.ts +1 -1
  82. package/src/web-components/ui/BdsCard.mdx +4 -3
  83. package/src/web-components/ui/BdsCard.stories.tsx +7 -11
  84. package/src/web-components/ui/BdsSkeleton.stories.tsx +4 -4
  85. package/src/web-components/ui/bds-alert.ts +3 -2
  86. package/src/web-components/ui/bds-card.spec.ts +3 -5
  87. package/src/web-components/ui/bds-card.ts +5 -12
  88. package/src/web-components/ui/bds-notification-banner.ts +19 -18
  89. package/src/web-components/ui/bds-pagination.ts +1 -1
  90. package/src/web-components/ui/bds-table.ts +4 -0
@@ -1,39 +1,39 @@
1
1
  import {
2
2
  BdsSwitch
3
- } from "./chunk-XNA6WTXG.js";
3
+ } from "./chunk-Y3POAKGS.js";
4
4
  import {
5
5
  BdsTextarea
6
- } from "./chunk-EBJM3VD4.js";
6
+ } from "./chunk-QBB6ZX4R.js";
7
7
  import {
8
8
  BdsCheckbox
9
- } from "./chunk-T6AETZRP.js";
9
+ } from "./chunk-3GFWLSLS.js";
10
10
  import {
11
11
  BdsCombobox
12
- } from "./chunk-QLZ2362S.js";
12
+ } from "./chunk-CZBIVR4V.js";
13
13
  import {
14
14
  BdsFileInput
15
15
  } from "./chunk-PY62FTRW.js";
16
16
  import {
17
17
  BdsNumberInput
18
- } from "./chunk-JUKB3BUP.js";
18
+ } from "./chunk-PXZWYO6Z.js";
19
19
  import {
20
20
  BdsRadio
21
- } from "./chunk-HHHRF2PS.js";
21
+ } from "./chunk-IYGF6CD5.js";
22
22
  import {
23
23
  BdsSegmentedControl
24
24
  } from "./chunk-2FGATTGT.js";
25
25
  import {
26
26
  BdsSelect
27
- } from "./chunk-X3FKVHLK.js";
27
+ } from "./chunk-CM3KYZ6Z.js";
28
28
  import {
29
29
  BdsSlider
30
30
  } from "./chunk-7FMR53BW.js";
31
31
  import {
32
32
  BdsDrawer
33
- } from "./chunk-OCODKRVZ.js";
33
+ } from "./chunk-KUI55GFB.js";
34
34
  import {
35
35
  BdsPopover
36
- } from "./chunk-ECW3HHWA.js";
36
+ } from "./chunk-TQ7IQ4GZ.js";
37
37
  import {
38
38
  BdsSkipLink
39
39
  } from "./chunk-BQLZ7I4G.js";
@@ -51,7 +51,7 @@ import {
51
51
  } from "./chunk-YLVTEY23.js";
52
52
  import {
53
53
  BdsTooltip
54
- } from "./chunk-HGBNDR22.js";
54
+ } from "./chunk-Y7V7LM6R.js";
55
55
  import {
56
56
  BdsSeparator
57
57
  } from "./chunk-VMMVWLXL.js";
@@ -63,19 +63,19 @@ import {
63
63
  } from "./chunk-SOQQ7RVJ.js";
64
64
  import {
65
65
  BdsAccordion
66
- } from "./chunk-ZTC6GRP7.js";
66
+ } from "./chunk-BKIHQYJR.js";
67
67
  import {
68
68
  BdsAccordionItem
69
- } from "./chunk-UFFCKVZE.js";
69
+ } from "./chunk-FXURM6D5.js";
70
70
  import {
71
71
  BdsButton
72
- } from "./chunk-GER5UJOF.js";
72
+ } from "./chunk-F5E3IT7G.js";
73
73
  import {
74
74
  BdsCollapsible
75
75
  } from "./chunk-6I2DBFQ7.js";
76
76
  import {
77
77
  BdsDialog
78
- } from "./chunk-N6IMUOY4.js";
78
+ } from "./chunk-65JXQOBA.js";
79
79
  import {
80
80
  BdsIconWrapper
81
81
  } from "./chunk-5TFWOPLH.js";
@@ -87,7 +87,7 @@ import {
87
87
  } from "./chunk-5R6IFELV.js";
88
88
  import {
89
89
  BdsNotificationBanner
90
- } from "./chunk-AJSXNDAP.js";
90
+ } from "./chunk-X46KL5BK.js";
91
91
  import {
92
92
  BdsProgress
93
93
  } from "./chunk-ITHLKR7Q.js";
@@ -104,7 +104,7 @@ import "./chunk-QPOKHLMQ.js";
104
104
  import "./chunk-3S42DZ7W.js";
105
105
  import {
106
106
  BdsAlert
107
- } from "./chunk-ZNKEZIYE.js";
107
+ } from "./chunk-NCPQ7AF3.js";
108
108
  import {
109
109
  BdsAvatar
110
110
  } from "./chunk-57TRNCWQ.js";
@@ -116,11 +116,12 @@ import {
116
116
  } from "./chunk-Q4T5BJT6.js";
117
117
  import {
118
118
  BdsCard
119
- } from "./chunk-RTOS7LLG.js";
119
+ } from "./chunk-PC3IOQAH.js";
120
120
  import {
121
121
  BdsDescriptionList
122
122
  } from "./chunk-AGKJTMJI.js";
123
123
  import {
124
+ A,
124
125
  T,
125
126
  i,
126
127
  i2
@@ -621,6 +622,10 @@ var BdsTable = class extends i2 {
621
622
  .wrapper {
622
623
  overflow-inline: auto;
623
624
  -webkit-overflow-scrolling: touch;
625
+ border: var(--table_border, none);
626
+ border-radius: var(--table_radius, var(--bds-border_radius--s));
627
+ --bdc_color: var(--bds-color_bg--subtle);
628
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
624
629
  }
625
630
 
626
631
  ::slotted(table) {
@@ -723,7 +728,7 @@ var BdsPagination = class extends i2 {
723
728
  cursor: pointer;
724
729
  color: var(--bds-color_on-bg);
725
730
  transition: var(--bds-animation_transition);
726
- --bdc_color: transparent;
731
+ --bdc_color: var(--pagination_border-color, transparent);
727
732
  --bdc-outline_radius: var(--bds-border_radius--xs);
728
733
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--bdc-outline_shadow);
729
734
  }
@@ -881,6 +886,7 @@ var BdsCheckboxGroup = class extends i2 {
881
886
 
882
887
  .message--hint {
883
888
  color: var(--bds-color_on-bg--subtle);
889
+ font-style: italic;
884
890
  }
885
891
  `;
886
892
  static properties = {
@@ -957,6 +963,7 @@ var BdsRadioGroup = class extends i2 {
957
963
 
958
964
  .message--hint {
959
965
  color: var(--bds-color_on-bg--subtle);
966
+ font-style: italic;
960
967
  }
961
968
  `;
962
969
  static properties = {
@@ -1007,6 +1014,118 @@ var BdsRadioGroup = class extends i2 {
1007
1014
  };
1008
1015
  customElements.define("bds-radio-group", BdsRadioGroup);
1009
1016
 
1017
+ // src/web-components/interaction/form/bds-field-group.ts
1018
+ var BdsFieldGroup = class extends i2 {
1019
+ static styles = i`
1020
+ :host {
1021
+ display: block;
1022
+
1023
+ /* Establish an inline-size containment context so the @container rule
1024
+ queries the host's own width — independent of the viewport. */
1025
+ container-type: inline-size;
1026
+ container-name: field-group;
1027
+
1028
+ /* Auto-derived collapse threshold (mirror of the React component).
1029
+ --fieldGroup_field-count is set inline by _onSlotChange; the other
1030
+ tokens use foundation-default fallbacks so the calc rebuilds when
1031
+ a consumer overrides --fieldGroup_min-field-width or _gap. */
1032
+ --fieldGroup_collapse-threshold:
1033
+ calc(
1034
+ var(--fieldGroup_field-count, 1)
1035
+ * var(--fieldGroup_min-field-width, 12rem)
1036
+ + (var(--fieldGroup_field-count, 1) - 1)
1037
+ * var(--fieldGroup_gap, var(--bds-space_m))
1038
+ );
1039
+ }
1040
+
1041
+ fieldset {
1042
+ border: 0;
1043
+ margin: 0;
1044
+ padding: 0;
1045
+ min-inline-size: 0;
1046
+ }
1047
+
1048
+ .legend {
1049
+ inline-size: 100%;
1050
+ padding-inline: 0;
1051
+
1052
+ padding-block:
1053
+ var(--fieldGroup_legend-padding-block, var(--bds-space_xs));
1054
+ margin-block-end:
1055
+ var(--fieldGroup_legend-gap, var(--bds-space_m));
1056
+ border-block-end:
1057
+ var(--fieldGroup_legend-border-block-end, 1px solid var(--bds-color_bg--subtle));
1058
+
1059
+ color:
1060
+ var(--fieldGroup_legend-color, var(--bds-color_on-bg));
1061
+ font-family: var(--bds-font_family--body);
1062
+ font-size:
1063
+ var(--fieldGroup_legend-font-size, var(--bds-font_size--heading-3));
1064
+ font-weight:
1065
+ var(--fieldGroup_legend-font-weight, var(--bds-font_weight--semibold));
1066
+ line-height:
1067
+ var(--fieldGroup_legend-line-height, var(--bds-font_line-height--heading));
1068
+ }
1069
+
1070
+ .fields {
1071
+ display: flex;
1072
+ flex-direction: column;
1073
+ gap: var(--fieldGroup_gap, var(--bds-space_m));
1074
+ }
1075
+
1076
+ :host([variant='horizontal']) .fields {
1077
+ flex-flow: row wrap;
1078
+ }
1079
+
1080
+ :host([variant='horizontal']) .fields ::slotted(*) {
1081
+ flex: 1 1 var(--fieldGroup_min-field-width, 12rem);
1082
+ min-inline-size: 0;
1083
+ }
1084
+
1085
+ /* Auto-collapse: when the host's inline-size can't fit a complete
1086
+ horizontal row, switch to a single-column stack. Threshold scales
1087
+ with the actual slotted-element count (see :host calc above). */
1088
+ @container field-group (max-inline-size: var(--fieldGroup_collapse-threshold)) {
1089
+ :host([variant='horizontal']) .fields {
1090
+ flex-direction: column;
1091
+ }
1092
+
1093
+ :host([variant='horizontal']) .fields ::slotted(*) {
1094
+ flex: 1 1 auto;
1095
+ }
1096
+ }
1097
+ `;
1098
+ static properties = {
1099
+ variant: { type: String, reflect: true },
1100
+ legend: { type: String },
1101
+ disabled: { type: Boolean, reflect: true }
1102
+ };
1103
+ constructor() {
1104
+ super();
1105
+ this.variant = "horizontal";
1106
+ this.legend = "";
1107
+ this.disabled = false;
1108
+ }
1109
+ // Arrow-bound for stable identity (unused here but matches the
1110
+ // bds-popover / bds-button conventions for handlers attached in render).
1111
+ _onSlotChange = (e) => {
1112
+ const slot = e.target;
1113
+ const count = slot.assignedElements().length;
1114
+ this.style.setProperty("--fieldGroup_field-count", String(count));
1115
+ };
1116
+ render() {
1117
+ return T`
1118
+ <fieldset ?disabled=${this.disabled}>
1119
+ ${this.legend ? T`<legend class="legend">${this.legend}</legend>` : A}
1120
+ <div class="fields">
1121
+ <slot @slotchange=${this._onSlotChange}></slot>
1122
+ </div>
1123
+ </fieldset>
1124
+ `;
1125
+ }
1126
+ };
1127
+ customElements.define("bds-field-group", BdsFieldGroup);
1128
+
1010
1129
  // src/web-components/interaction/form/bds-form-input.ts
1011
1130
  var BdsFormInput = class extends i2 {
1012
1131
  static formAssociated = true;
@@ -1038,7 +1157,7 @@ var BdsFormInput = class extends i2 {
1038
1157
  position: relative;
1039
1158
  display: flex;
1040
1159
  align-items: center;
1041
- --bdc_color: currentcolor;
1160
+ --bdc_color: var(--formInput_border-color, currentcolor);
1042
1161
  --bdc-outline_radius: var(--bds-border_radius--xs);
1043
1162
 
1044
1163
  border-radius: var(--formInput_radius, var(--bdc-outline_radius));
@@ -1118,6 +1237,7 @@ var BdsFormInput = class extends i2 {
1118
1237
 
1119
1238
  .message--hint {
1120
1239
  color: var(--bds-color_on-bg--subtle);
1240
+ font-style: italic;
1121
1241
  }
1122
1242
  `;
1123
1243
  static properties = {
@@ -2068,6 +2188,7 @@ export {
2068
2188
  BdsDrawer,
2069
2189
  BdsDropdownMenu,
2070
2190
  BdsDropdownMenuItem,
2191
+ BdsFieldGroup,
2071
2192
  BdsFileInput,
2072
2193
  BdsFormInput,
2073
2194
  BdsGrid,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsAccordionItem
3
- } from "../chunk-UFFCKVZE.js";
3
+ } from "../chunk-FXURM6D5.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsAccordionItem
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsAccordion
3
- } from "../chunk-ZTC6GRP7.js";
3
+ } from "../chunk-BKIHQYJR.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsAccordion
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsButton
3
- } from "../chunk-GER5UJOF.js";
3
+ } from "../chunk-F5E3IT7G.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsButton
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsDialog
3
- } from "../chunk-N6IMUOY4.js";
3
+ } from "../chunk-65JXQOBA.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsDialog
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsDrawer
3
- } from "../chunk-OCODKRVZ.js";
3
+ } from "../chunk-KUI55GFB.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsDrawer
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsPopover
3
- } from "../chunk-ECW3HHWA.js";
3
+ } from "../chunk-TQ7IQ4GZ.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsPopover
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsTooltip
3
- } from "../chunk-HGBNDR22.js";
3
+ } from "../chunk-Y7V7LM6R.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsTooltip
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsCheckbox
3
- } from "../../chunk-T6AETZRP.js";
3
+ } from "../../chunk-3GFWLSLS.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsCheckbox
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsCombobox
3
- } from "../../chunk-QLZ2362S.js";
3
+ } from "../../chunk-CZBIVR4V.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsCombobox
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsNumberInput
3
- } from "../../chunk-JUKB3BUP.js";
3
+ } from "../../chunk-PXZWYO6Z.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsNumberInput
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsRadio
3
- } from "../../chunk-HHHRF2PS.js";
3
+ } from "../../chunk-IYGF6CD5.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsRadio
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsSelect
3
- } from "../../chunk-X3FKVHLK.js";
3
+ } from "../../chunk-CM3KYZ6Z.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsSelect
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsSwitch
3
- } from "../../chunk-XNA6WTXG.js";
3
+ } from "../../chunk-Y3POAKGS.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsSwitch
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsTextarea
3
- } from "../../chunk-EBJM3VD4.js";
3
+ } from "../../chunk-QBB6ZX4R.js";
4
4
  import "../../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsTextarea
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsAlert
3
- } from "../chunk-ZNKEZIYE.js";
3
+ } from "../chunk-NCPQ7AF3.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsAlert
@@ -2,14 +2,13 @@ import * as lit from 'lit';
2
2
  import { LitElement } from 'lit';
3
3
 
4
4
  type CardVariant = 'default' | 'elevated' | 'outlined';
5
- type CardPadding = 'none' | 'small' | 'medium' | 'large';
6
5
  type CardTextAlign = 'start' | 'center' | 'end';
7
6
  /**
8
7
  * `<bds-card>` — framework-agnostic Card layout custom element.
9
8
  *
10
9
  * Attributes:
11
10
  * variant — "default" (default) | "elevated" | "outlined"
12
- * padding "none" | "small" | "medium" (default) | "large"
11
+ * --card_padding CSS custom property to override padding (default: var(--bds-space_m))
13
12
  * text-align — "start" (default) | "center" | "end"
14
13
  * clickable — boolean; renders as a <button> with hover/active effects
15
14
  * aria-label — accessible label (useful when clickable)
@@ -21,7 +20,7 @@ type CardTextAlign = 'start' | 'center' | 'end';
21
20
  * bds-click — fired (bubbles, composed) when the card button is clicked
22
21
  *
23
22
  * @example
24
- * <bds-card variant="elevated" padding="large">
23
+ * <bds-card variant="elevated" style="--card_padding: var(--bds-space_l)">
25
24
  * <p>Card content</p>
26
25
  * </bds-card>
27
26
  *
@@ -36,10 +35,6 @@ declare class BdsCard extends LitElement {
36
35
  type: StringConstructor;
37
36
  reflect: boolean;
38
37
  };
39
- padding: {
40
- type: StringConstructor;
41
- reflect: boolean;
42
- };
43
38
  textAlign: {
44
39
  type: StringConstructor;
45
40
  attribute: string;
@@ -55,7 +50,6 @@ declare class BdsCard extends LitElement {
55
50
  };
56
51
  };
57
52
  variant: CardVariant;
58
- padding: CardPadding;
59
53
  textAlign: CardTextAlign;
60
54
  clickable: boolean;
61
55
  ariaLabel: string;
@@ -69,4 +63,4 @@ declare global {
69
63
  }
70
64
  }
71
65
 
72
- export { BdsCard, type CardPadding, type CardTextAlign, type CardVariant };
66
+ export { BdsCard, type CardTextAlign, type CardVariant };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsCard
3
- } from "../chunk-RTOS7LLG.js";
3
+ } from "../chunk-PC3IOQAH.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsCard
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsNotificationBanner
3
- } from "../chunk-AJSXNDAP.js";
3
+ } from "../chunk-X46KL5BK.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsNotificationBanner
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boostdev/design-system-components",
3
- "version": "2.6.0",
3
+ "version": "2.7.1",
4
4
  "description": "BoostDev React component library: accessible, token-driven components built on @boostdev/design-system-foundation",
5
5
  "keywords": [
6
6
  "React",
@@ -306,6 +306,7 @@
306
306
  "storybook-addon-tag-badges": "^1.4.0",
307
307
  "stylelint": "^16",
308
308
  "stylelint-config-standard": "^37",
309
+ "stylelint-declaration-strict-value": "^1.11.1",
309
310
  "tsup": "^8",
310
311
  "tsx": "^4",
311
312
  "typescript": "^5.8",
@@ -335,5 +336,6 @@
335
336
  ],
336
337
  "dependencies": {
337
338
  "@oddbird/css-anchor-positioning": "^0.9.0"
338
- }
339
+ },
340
+ "packageManager": "pnpm@11.0.8"
339
341
  }
@@ -0,0 +1,113 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './FieldGroup.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # FieldGroup
7
+
8
+ Semantically groups related form fields under a single `<fieldset>` and lays them out either horizontally (with a CSS container query that collapses to a vertical stack when the FieldGroup itself is too narrow) or vertically.
9
+
10
+ Use this any time multiple fields belong to the same conceptual section — contact details, address, search filters, registration step — and you want them grouped for screen readers AND visually arranged on a single row when there's room.
11
+
12
+ ## When to use
13
+
14
+ - Two or more related form fields that should sit side by side on wide screens.
15
+ - Sections inside a longer form that need a visual + semantic boundary.
16
+ - A fieldset whose layout should adapt to its **container's** width, not the viewport's (e.g. a form rendered inside a sidebar or dialog).
17
+
18
+ ## When **not** to use
19
+
20
+ - A group of related checkboxes — use `CheckboxGroup` instead (it manages legend + error/hint slots specifically for the boolean-list case).
21
+ - A group of related radio inputs — use `RadioGroup`.
22
+ - A single field — wrap nothing; just render the field.
23
+
24
+ ## Variants
25
+
26
+ - **`horizontal`** (default) — fields flow into a row; each claims at least `--fieldGroup_min-field-width`. When the FieldGroup's own inline-size drops below the **auto-derived** threshold (`N × min-field-width + (N − 1) × gap`, where `N` is the actual number of children), the layout collapses to a single column via a CSS container query. A 2-field group collapses earlier than a 5-field group; you don't have to tune anything per call site.
27
+ - **`vertical`** — fields always stack one per row.
28
+
29
+ <Canvas of={Stories.Horizontal} />
30
+ <Canvas of={Stories.Vertical} />
31
+
32
+ ### Container query in action
33
+
34
+ The collapse-to-vertical threshold measures the **FieldGroup itself**, not the viewport. The FieldGroup below sits inside a 20 rem wrapper, so the same horizontal variant collapses cleanly to a single column even though the page is wide.
35
+
36
+ <Canvas of={Stories.HorizontalCollapsesInNarrowContainer} />
37
+
38
+ ### Mixed inputs
39
+
40
+ Any form input works as a child — `FormInput`, `Select`, `Combobox`, `NumberInput`, `Textarea`, `Switch`, etc.
41
+
42
+ <Canvas of={Stories.WithSelectAndInputs} />
43
+
44
+ ### Without a legend
45
+
46
+ Omit `legend` and provide an `aria-label` (or `aria-labelledby`) on the fieldset directly when the surrounding context already names the group.
47
+
48
+ <Canvas of={Stories.WithoutLegend} />
49
+
50
+ ### Disabled
51
+
52
+ The native `disabled` attribute on the fieldset disables every form control inside it without per-field wiring.
53
+
54
+ <Canvas of={Stories.Disabled} />
55
+
56
+ ## Props
57
+
58
+ <ArgTypes of={Stories} />
59
+
60
+ ## HTML attribute forwarding
61
+
62
+ Extends `FieldsetHTMLAttributes<HTMLFieldSetElement>`; spreads all unrecognised props onto the root `<fieldset>` (`id`, `name`, `form`, `disabled`, `aria-*`, `data-*`, every DOM event handler, etc.). The consumer-provided `className` is merged with the internal classes via `cn()`.
63
+
64
+ ## CSS variables
65
+
66
+ All public override tokens. Set on the FieldGroup or any ancestor; they cascade.
67
+
68
+ ### Layout
69
+
70
+ | Variable | Default | Description |
71
+ |----------|---------|-------------|
72
+ | `--fieldGroup_gap` | `var(--bds-space_m)` | Gap between fields. |
73
+ | `--fieldGroup_min-field-width` | `12rem` | Minimum width each field claims in horizontal mode before wrapping. |
74
+
75
+ ### Legend
76
+
77
+ | Variable | Default | Description |
78
+ |----------|---------|-------------|
79
+ | `--fieldGroup_legend-color` | `var(--bds-color_on-bg)` | Legend text colour. |
80
+ | `--fieldGroup_legend-font-size` | `var(--bds-font_size--heading-3)` | Legend font size. |
81
+ | `--fieldGroup_legend-font-weight` | `var(--bds-font_weight--semibold)` | Legend font weight. |
82
+ | `--fieldGroup_legend-line-height` | `var(--bds-font_line-height--heading)` | Legend line height. |
83
+ | `--fieldGroup_legend-padding-block` | `var(--bds-space_xs)` | Legend block padding. |
84
+ | `--fieldGroup_legend-gap` | `var(--bds-space_m)` | Space below the legend before the fields. |
85
+ | `--fieldGroup_legend-border-block-end` | `1px solid var(--bds-color_bg--subtle)` | Subtle separator under the legend. Set to `none` to remove. |
86
+
87
+ ## Accessibility
88
+
89
+ - Renders as `<fieldset>` so assistive tech announces the legend before each field, and the native `disabled` attribute cascades to all descendants.
90
+ - When `legend` is omitted, you must provide `aria-label` or `aria-labelledby` on the FieldGroup so the group still has an accessible name.
91
+ - The container query is a layout-only change — DOM order stays in source order, so the tab/reading order is unaffected by the horizontal-to-vertical switch.
92
+
93
+ ## How the responsive layout works
94
+
95
+ The horizontal variant uses `display: flex; flex-flow: row wrap;` with each child claiming at least `--fieldGroup_min-field-width`. This handles natural wrapping across multiple rows.
96
+
97
+ Layered on top, a CSS [`@container`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@container) query forces a clean single-column layout when the FieldGroup itself is narrower than the **auto-derived** collapse threshold:
98
+
99
+ ```css
100
+ --fieldGroup_collapse-threshold:
101
+ calc(
102
+ var(--fieldGroup_field-count) * var(--fieldGroup_min-field-width)
103
+ + (var(--fieldGroup_field-count) - 1) * var(--fieldGroup_gap)
104
+ );
105
+
106
+ @container field-group (max-inline-size: var(--fieldGroup_collapse-threshold)) {
107
+ .fieldGroup.--variant_horizontal .fields { flex-direction: column; }
108
+ }
109
+ ```
110
+
111
+ `--fieldGroup_field-count` is set by the React component as an inline `style` custom property derived from `Children.count(children)`, so the threshold scales with the actual content. A 2-field group collapses around `2 × 12rem + 1 × gap`; a 5-field group collapses around `5 × 12rem + 4 × gap`. No magic numbers per call site.
112
+
113
+ Because the query is bound to the FieldGroup's own inline-size (via `container-type: inline-size`), the same FieldGroup behaves correctly whether you place it in a sidebar, a modal, a 2-up grid cell, or a full-width page — with zero media-query wiring at the call site.