@carbon/web-components 2.55.0-rc.0 → 2.55.0

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 (100) hide show
  1. package/custom-elements.json +133 -30
  2. package/es/components/button/button.d.ts.map +1 -1
  3. package/es/components/button/button.js +6 -4
  4. package/es/components/button/button.js.map +1 -1
  5. package/es/components/menu/menu-item.d.ts.map +1 -1
  6. package/es/components/menu/menu-item.js +3 -3
  7. package/es/components/menu/menu-item.js.map +1 -1
  8. package/es/components/multi-select/multi-select.d.ts +4 -0
  9. package/es/components/multi-select/multi-select.d.ts.map +1 -1
  10. package/es/components/multi-select/multi-select.js +4 -1
  11. package/es/components/multi-select/multi-select.js.map +1 -1
  12. package/es/components/overflow-menu/overflow-menu-item.d.ts.map +1 -1
  13. package/es/components/overflow-menu/overflow-menu-item.js +4 -3
  14. package/es/components/overflow-menu/overflow-menu-item.js.map +1 -1
  15. package/es/components/tabs/defs.d.ts +26 -0
  16. package/es/components/tabs/defs.d.ts.map +1 -1
  17. package/es/components/tabs/defs.js +28 -1
  18. package/es/components/tabs/defs.js.map +1 -1
  19. package/es/components/tabs/index.d.ts +1 -0
  20. package/es/components/tabs/index.d.ts.map +1 -1
  21. package/es/components/tabs/index.js +1 -0
  22. package/es/components/tabs/stories/tabs-wrapper.d.ts +5 -0
  23. package/es/components/tabs/stories/tabs-wrapper.d.ts.map +1 -1
  24. package/es/components/tabs/stories/tabs-wrapper.js +2 -0
  25. package/es/components/tabs/stories/tabs-wrapper.js.map +1 -1
  26. package/es/components/tabs/tab.d.ts +26 -0
  27. package/es/components/tabs/tab.d.ts.map +1 -1
  28. package/es/components/tabs/tab.js +41 -7
  29. package/es/components/tabs/tab.js.map +1 -1
  30. package/es/components/tabs/tabs-vertical.d.ts +29 -0
  31. package/es/components/tabs/tabs-vertical.d.ts.map +1 -0
  32. package/es/components/tabs/tabs-vertical.js +113 -0
  33. package/es/components/tabs/tabs-vertical.js.map +1 -0
  34. package/es/components/tabs/tabs.d.ts +22 -4
  35. package/es/components/tabs/tabs.d.ts.map +1 -1
  36. package/es/components/tabs/tabs.js +50 -9
  37. package/es/components/tabs/tabs.js.map +1 -1
  38. package/es/components/tabs/tabs.scss.js +1 -1
  39. package/es/components/tabs/tabs.scss.js.map +1 -1
  40. package/es-custom/components/button/button.d.ts.map +1 -1
  41. package/es-custom/components/button/button.js +6 -4
  42. package/es-custom/components/button/button.js.map +1 -1
  43. package/es-custom/components/menu/menu-item.d.ts.map +1 -1
  44. package/es-custom/components/menu/menu-item.js +3 -3
  45. package/es-custom/components/menu/menu-item.js.map +1 -1
  46. package/es-custom/components/multi-select/multi-select.d.ts +4 -0
  47. package/es-custom/components/multi-select/multi-select.d.ts.map +1 -1
  48. package/es-custom/components/multi-select/multi-select.js +4 -1
  49. package/es-custom/components/multi-select/multi-select.js.map +1 -1
  50. package/es-custom/components/overflow-menu/overflow-menu-item.d.ts.map +1 -1
  51. package/es-custom/components/overflow-menu/overflow-menu-item.js +4 -3
  52. package/es-custom/components/overflow-menu/overflow-menu-item.js.map +1 -1
  53. package/es-custom/components/tabs/defs.d.ts +26 -0
  54. package/es-custom/components/tabs/defs.d.ts.map +1 -1
  55. package/es-custom/components/tabs/defs.js +28 -1
  56. package/es-custom/components/tabs/defs.js.map +1 -1
  57. package/es-custom/components/tabs/index.d.ts +1 -0
  58. package/es-custom/components/tabs/index.d.ts.map +1 -1
  59. package/es-custom/components/tabs/index.js +1 -0
  60. package/es-custom/components/tabs/stories/tabs-wrapper.d.ts +5 -0
  61. package/es-custom/components/tabs/stories/tabs-wrapper.d.ts.map +1 -1
  62. package/es-custom/components/tabs/stories/tabs-wrapper.js +2 -0
  63. package/es-custom/components/tabs/stories/tabs-wrapper.js.map +1 -1
  64. package/es-custom/components/tabs/tab.d.ts +26 -0
  65. package/es-custom/components/tabs/tab.d.ts.map +1 -1
  66. package/es-custom/components/tabs/tab.js +41 -7
  67. package/es-custom/components/tabs/tab.js.map +1 -1
  68. package/es-custom/components/tabs/tabs-vertical.d.ts +29 -0
  69. package/es-custom/components/tabs/tabs-vertical.d.ts.map +1 -0
  70. package/es-custom/components/tabs/tabs-vertical.js +113 -0
  71. package/es-custom/components/tabs/tabs-vertical.js.map +1 -0
  72. package/es-custom/components/tabs/tabs.d.ts +22 -4
  73. package/es-custom/components/tabs/tabs.d.ts.map +1 -1
  74. package/es-custom/components/tabs/tabs.js +50 -9
  75. package/es-custom/components/tabs/tabs.js.map +1 -1
  76. package/es-custom/components/tabs/tabs.scss.js +1 -1
  77. package/es-custom/components/tabs/tabs.scss.js.map +1 -1
  78. package/lib/components/button/button.d.ts.map +1 -1
  79. package/lib/components/menu/menu-item.d.ts.map +1 -1
  80. package/lib/components/multi-select/multi-select.d.ts +4 -0
  81. package/lib/components/multi-select/multi-select.d.ts.map +1 -1
  82. package/lib/components/overflow-menu/overflow-menu-item.d.ts.map +1 -1
  83. package/lib/components/tabs/defs.d.ts +26 -0
  84. package/lib/components/tabs/defs.d.ts.map +1 -1
  85. package/lib/components/tabs/defs.js +29 -0
  86. package/lib/components/tabs/defs.js.map +1 -1
  87. package/lib/components/tabs/index.d.ts +1 -0
  88. package/lib/components/tabs/index.d.ts.map +1 -1
  89. package/lib/components/tabs/stories/tabs-wrapper.d.ts +5 -0
  90. package/lib/components/tabs/stories/tabs-wrapper.d.ts.map +1 -1
  91. package/lib/components/tabs/tab.d.ts +26 -0
  92. package/lib/components/tabs/tab.d.ts.map +1 -1
  93. package/lib/components/tabs/tabs-vertical.d.ts +29 -0
  94. package/lib/components/tabs/tabs-vertical.d.ts.map +1 -0
  95. package/lib/components/tabs/tabs.d.ts +22 -4
  96. package/lib/components/tabs/tabs.d.ts.map +1 -1
  97. package/package.json +7 -7
  98. package/scss/components/tabs/tabs-story.scss +5 -0
  99. package/scss/components/tabs/tabs.scss +168 -5
  100. package/telemetry.yml +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"tabs-wrapper.js","names":["customElement"],"sources":["../../../../src/components/tabs/stories/tabs-wrapper.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { LitElement, html } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { carbonElement as customElement } from '../../../globals/decorators/carbon-element';\nimport { prefix } from '../../../globals/settings';\nimport { TABS_TYPE } from '../tabs';\nimport { iconLoader } from '../../../globals/internal/icon-loader';\nimport Dashboard16 from '@carbon/icons/es/dashboard/16.js';\nimport CloudMonitoring16 from '@carbon/icons/es/cloud--monitoring/16.js';\nimport Activity16 from '@carbon/icons/es/activity/16.js';\nimport Settings16 from '@carbon/icons/es/settings/16.js';\nimport '../../button';\n\n/**\n * Wrapper component for dismissable tabs story with state management\n */\n@customElement('tabs-story-wrapper')\nexport class DismissableTabsWrapper extends LitElement {\n /**\n * Whether to render tabs with icons\n */\n @property({ type: Boolean, attribute: 'with-icons' })\n withIcons = false;\n\n private _defaultTabs = [\n { id: 'all', label: 'Dashboard', value: 'all', icon: Dashboard16 },\n {\n id: 'cloudFoundry',\n label: 'Monitoring',\n value: 'cloudFoundry',\n icon: CloudMonitoring16,\n },\n { id: 'staging', label: 'Activity', value: 'staging', icon: Activity16 },\n {\n id: 'dea',\n label: 'Settings',\n value: 'dea',\n disabled: true,\n icon: Settings16,\n },\n ];\n /**\n * Array of tab configurations\n */\n @state()\n private _tabs = this._defaultTabs;\n\n /**\n * Whether tabs are disabled\n */\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * Whether tabs are contained\n */\n @property({ type: Boolean })\n contained = false;\n /**\n * Whether the rendered Tab children should be dismissable.\n */\n @property({ type: Boolean })\n dismissable = true;\n\n /**\n * Selection mode\n */\n @property({ attribute: 'selection-mode' })\n selectionMode = 'automatic';\n\n /**\n * Selected index for the initially selected content\n */\n @property({ attribute: 'selected-index' })\n selectedIndex = 0;\n\n /**\n * Handle tab dismissed event\n */\n private _handleDismissed(event: CustomEvent) {\n const { index } = event.detail;\n this._tabs = this._tabs.filter((_, i) => i !== index);\n }\n\n /**\n * Handle before selected event\n */\n private _handleBeforeSelected(event: CustomEvent) {\n if (this.disabled) {\n event.preventDefault();\n }\n }\n\n private resetTabs() {\n this._tabs = [...this._defaultTabs];\n }\n\n render() {\n const { resetTabs } = this;\n return html`\n <cds-button style=\"margin-bottom: 3rem\" @click=\"${resetTabs}\">\n Reset\n </cds-button>\n <cds-tabs\n ?disabled=\"${this.disabled}\"\n selection-mode=\"${this.selectionMode}\"\n selected-index=\"${this.selectedIndex}\"\n type=\"${this.contained ? TABS_TYPE.CONTAINED : TABS_TYPE.REGULAR}\"\n ?dismissable=\"${this.dismissable}\"\n value=\"all\"\n @cds-tab-closed=\"${this._handleDismissed}\"\n @cds-tabs-beingselected=\"${this._handleBeforeSelected}\">\n ${this._tabs.map(\n (tab) => html`\n <cds-tab\n id=\"tab-${tab.id}\"\n target=\"panel-${tab.id}\"\n value=\"${tab.value}\"\n ?disabled=\"${tab.disabled}\">\n ${this.withIcons ? iconLoader(tab.icon) : ''} ${tab.label}\n </cds-tab>\n `\n )}\n </cds-tabs>\n <div class=\"${prefix}-ce-demo-devenv--tab-panels\">\n ${this._tabs.map(\n (tab) => html`\n <div\n id=\"panel-${tab.id}\"\n role=\"tabpanel\"\n aria-labelledby=\"tab-${tab.id}\"\n hidden>\n ${tab.label}\n </div>\n `\n )}\n </div>\n `;\n }\n\n /**\n * Disable shadow DOM to inherit styles from parent\n */\n createRenderRoot() {\n return this;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBO,IAAA,yBAAA,MAAM,+BAA+B,WAAW;;;mBAKzC;sBAEW;GACrB;IAAE,IAAI;IAAO,OAAO;IAAa,OAAO;IAAO,MAAM;IAAa;GAClE;IACE,IAAI;IACJ,OAAO;IACP,OAAO;IACP,MAAM;IACP;GACD;IAAE,IAAI;IAAW,OAAO;IAAY,OAAO;IAAW,MAAM;IAAY;GACxE;IACE,IAAI;IACJ,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACP;GACF;eAKe,KAAK;kBAMV;mBAMC;qBAKE;uBAME;uBAMA;;;;;CAKhB,iBAAyB,OAAoB;EAC3C,MAAM,EAAE,UAAU,MAAM;AACxB,OAAK,QAAQ,KAAK,MAAM,QAAQ,GAAG,MAAM,MAAM,MAAM;;;;;CAMvD,sBAA8B,OAAoB;AAChD,MAAI,KAAK,SACP,OAAM,gBAAgB;;CAI1B,YAAoB;AAClB,OAAK,QAAQ,CAAC,GAAG,KAAK,aAAa;;CAGrC,SAAS;EACP,MAAM,EAAE,cAAc;AACtB,SAAO,IAAI;wDACyC,UAAU;;;;qBAI7C,KAAK,SAAS;0BACT,KAAK,cAAc;0BACnB,KAAK,cAAc;gBAC7B,KAAK,YAAA,cAAA,GAAoD;wBACjD,KAAK,YAAY;;2BAEd,KAAK,iBAAiB;mCACd,KAAK,sBAAsB;UACpD,KAAK,MAAM,KACV,QAAQ,IAAI;;wBAEC,IAAI,GAAG;8BACD,IAAI,GAAG;uBACd,IAAI,MAAM;2BACN,IAAI,SAAS;gBACxB,KAAK,YAAY,WAAW,IAAI,KAAK,GAAG,GAAG,GAAG,IAAI,MAAM;;YAG/D,CAAC;;0BAEiB;UACjB,KAAK,MAAM,KACV,QAAQ,IAAI;;0BAEG,IAAI,GAAG;;qCAEI,IAAI,GAAG;;gBAE5B,IAAI,MAAM;;YAGjB,CAAC;;;;;;;CAQR,mBAAmB;AACjB,SAAO;;;YA3HR,SAAS;CAAE,MAAM;CAAS,WAAW;CAAc,CAAC,CAAA,EAAA,uBAAA,WAAA,aAAA,KAAA,EAAA;YAuBpD,OAAO,CAAA,EAAA,uBAAA,WAAA,SAAA,KAAA,EAAA;YAMP,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,uBAAA,WAAA,YAAA,KAAA,EAAA;YAM3B,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,uBAAA,WAAA,aAAA,KAAA,EAAA;YAK3B,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,uBAAA,WAAA,eAAA,KAAA,EAAA;YAM3B,SAAS,EAAE,WAAW,kBAAkB,CAAC,CAAA,EAAA,uBAAA,WAAA,iBAAA,KAAA,EAAA;YAMzC,SAAS,EAAE,WAAW,kBAAkB,CAAC,CAAA,EAAA,uBAAA,WAAA,iBAAA,KAAA,EAAA;qCAzD3CA,cAAc,qBAAqB,CAAA,EAAA,uBAAA"}
1
+ {"version":3,"file":"tabs-wrapper.js","names":["customElement"],"sources":["../../../../src/components/tabs/stories/tabs-wrapper.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { LitElement, html } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { carbonElement as customElement } from '../../../globals/decorators/carbon-element';\nimport { prefix } from '../../../globals/settings';\nimport { TABS_TYPE } from '../tabs';\nimport { TABS_SIZE } from '../defs';\nimport { iconLoader } from '../../../globals/internal/icon-loader';\nimport Dashboard16 from '@carbon/icons/es/dashboard/16.js';\nimport CloudMonitoring16 from '@carbon/icons/es/cloud--monitoring/16.js';\nimport Activity16 from '@carbon/icons/es/activity/16.js';\nimport Settings16 from '@carbon/icons/es/settings/16.js';\nimport '../../button';\n\n/**\n * Wrapper component for dismissable tabs story with state management\n */\n@customElement('tabs-story-wrapper')\nexport class DismissableTabsWrapper extends LitElement {\n /**\n * Whether to render tabs with icons\n */\n @property({ type: Boolean, attribute: 'with-icons' })\n withIcons = false;\n\n private _defaultTabs = [\n { id: 'all', label: 'Dashboard', value: 'all', icon: Dashboard16 },\n {\n id: 'cloudFoundry',\n label: 'Monitoring',\n value: 'cloudFoundry',\n icon: CloudMonitoring16,\n },\n { id: 'staging', label: 'Activity', value: 'staging', icon: Activity16 },\n {\n id: 'dea',\n label: 'Settings',\n value: 'dea',\n disabled: true,\n icon: Settings16,\n },\n ];\n /**\n * Array of tab configurations\n */\n @state()\n private _tabs = this._defaultTabs;\n\n /**\n * Whether tabs are disabled\n */\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * Whether tabs are contained\n */\n @property({ type: Boolean })\n contained = false;\n /**\n * Whether the rendered Tab children should be dismissable.\n */\n @property({ type: Boolean })\n dismissable = true;\n\n /**\n * Selection mode\n */\n @property({ attribute: 'selection-mode' })\n selectionMode = 'automatic';\n\n /**\n * Selected index for the initially selected content\n */\n @property({ attribute: 'selected-index' })\n selectedIndex = 0;\n\n /**\n * Size of the tabs\n */\n @property({ reflect: true })\n size?: TABS_SIZE;\n\n /**\n * Handle tab dismissed event\n */\n private _handleDismissed(event: CustomEvent) {\n const { index } = event.detail;\n this._tabs = this._tabs.filter((_, i) => i !== index);\n }\n\n /**\n * Handle before selected event\n */\n private _handleBeforeSelected(event: CustomEvent) {\n if (this.disabled) {\n event.preventDefault();\n }\n }\n\n private resetTabs() {\n this._tabs = [...this._defaultTabs];\n }\n\n render() {\n const { resetTabs } = this;\n return html`\n <cds-button style=\"margin-bottom: 3rem\" @click=\"${resetTabs}\">\n Reset\n </cds-button>\n <cds-tabs\n ?disabled=\"${this.disabled}\"\n selection-mode=\"${this.selectionMode}\"\n selected-index=\"${this.selectedIndex}\"\n type=\"${this.contained ? TABS_TYPE.CONTAINED : TABS_TYPE.REGULAR}\"\n ?dismissable=\"${this.dismissable}\"\n size=\"${this.size || TABS_SIZE.LARGE}\"\n value=\"all\"\n @cds-tab-closed=\"${this._handleDismissed}\"\n @cds-tabs-beingselected=\"${this._handleBeforeSelected}\">\n ${this._tabs.map(\n (tab) => html`\n <cds-tab\n id=\"tab-${tab.id}\"\n target=\"panel-${tab.id}\"\n value=\"${tab.value}\"\n ?disabled=\"${tab.disabled}\">\n ${this.withIcons ? iconLoader(tab.icon) : ''} ${tab.label}\n </cds-tab>\n `\n )}\n </cds-tabs>\n <div class=\"${prefix}-ce-demo-devenv--tab-panels\">\n ${this._tabs.map(\n (tab) => html`\n <div\n id=\"panel-${tab.id}\"\n role=\"tabpanel\"\n aria-labelledby=\"tab-${tab.id}\"\n hidden>\n ${tab.label}\n </div>\n `\n )}\n </div>\n `;\n }\n\n /**\n * Disable shadow DOM to inherit styles from parent\n */\n createRenderRoot() {\n return this;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBO,IAAA,yBAAA,MAAM,+BAA+B,WAAW;;;mBAKzC;sBAEW;GACrB;IAAE,IAAI;IAAO,OAAO;IAAa,OAAO;IAAO,MAAM;IAAa;GAClE;IACE,IAAI;IACJ,OAAO;IACP,OAAO;IACP,MAAM;IACP;GACD;IAAE,IAAI;IAAW,OAAO;IAAY,OAAO;IAAW,MAAM;IAAY;GACxE;IACE,IAAI;IACJ,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACP;GACF;eAKe,KAAK;kBAMV;mBAMC;qBAKE;uBAME;uBAMA;;;;;CAWhB,iBAAyB,OAAoB;EAC3C,MAAM,EAAE,UAAU,MAAM;AACxB,OAAK,QAAQ,KAAK,MAAM,QAAQ,GAAG,MAAM,MAAM,MAAM;;;;;CAMvD,sBAA8B,OAAoB;AAChD,MAAI,KAAK,SACP,OAAM,gBAAgB;;CAI1B,YAAoB;AAClB,OAAK,QAAQ,CAAC,GAAG,KAAK,aAAa;;CAGrC,SAAS;EACP,MAAM,EAAE,cAAc;AACtB,SAAO,IAAI;wDACyC,UAAU;;;;qBAI7C,KAAK,SAAS;0BACT,KAAK,cAAc;0BACnB,KAAK,cAAc;gBAC7B,KAAK,YAAA,cAAA,GAAoD;wBACjD,KAAK,YAAY;gBACzB,KAAK,QAAA,KAAwB;;2BAElB,KAAK,iBAAiB;mCACd,KAAK,sBAAsB;UACpD,KAAK,MAAM,KACV,QAAQ,IAAI;;wBAEC,IAAI,GAAG;8BACD,IAAI,GAAG;uBACd,IAAI,MAAM;2BACN,IAAI,SAAS;gBACxB,KAAK,YAAY,WAAW,IAAI,KAAK,GAAG,GAAG,GAAG,IAAI,MAAM;;YAG/D,CAAC;;0BAEiB;UACjB,KAAK,MAAM,KACV,QAAQ,IAAI;;0BAEG,IAAI,GAAG;;qCAEI,IAAI,GAAG;;gBAE5B,IAAI,MAAM;;YAGjB,CAAC;;;;;;;CAQR,mBAAmB;AACjB,SAAO;;;YAlIR,SAAS;CAAE,MAAM;CAAS,WAAW;CAAc,CAAC,CAAA,EAAA,uBAAA,WAAA,aAAA,KAAA,EAAA;YAuBpD,OAAO,CAAA,EAAA,uBAAA,WAAA,SAAA,KAAA,EAAA;YAMP,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,uBAAA,WAAA,YAAA,KAAA,EAAA;YAM3B,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,uBAAA,WAAA,aAAA,KAAA,EAAA;YAK3B,SAAS,EAAE,MAAM,SAAS,CAAC,CAAA,EAAA,uBAAA,WAAA,eAAA,KAAA,EAAA;YAM3B,SAAS,EAAE,WAAW,kBAAkB,CAAC,CAAA,EAAA,uBAAA,WAAA,iBAAA,KAAA,EAAA;YAMzC,SAAS,EAAE,WAAW,kBAAkB,CAAC,CAAA,EAAA,uBAAA,WAAA,iBAAA,KAAA,EAAA;YAMzC,SAAS,EAAE,SAAS,MAAM,CAAC,CAAA,EAAA,uBAAA,WAAA,QAAA,KAAA,EAAA;qCA/D7BA,cAAc,qBAAqB,CAAA,EAAA,uBAAA"}
@@ -42,6 +42,11 @@ export default class CDSTab extends CDSTab_base {
42
42
  * Tab type.
43
43
  */
44
44
  type: TABS_TYPE;
45
+ /**
46
+ * `true` if the tab is in vertical orientation.
47
+ * This is automatically set by the parent `<cds-tabs>` when it's in vertical mode.
48
+ */
49
+ vertical: boolean;
45
50
  /**
46
51
  * `true` if this tab is icon-only.
47
52
  */
@@ -63,6 +68,11 @@ export default class CDSTab extends CDSTab_base {
63
68
  * **Experimental**: Display an empty dot badge on the Tab.
64
69
  */
65
70
  badgeIndicator: boolean;
71
+ /**
72
+ * `true` if the tab text is truncated with ellipsis.
73
+ * This state is automatically updated when the component renders in vertical mode.
74
+ */
75
+ truncated: boolean;
66
76
  /**
67
77
  * Whether this tab should be dismissable.
68
78
  */
@@ -71,6 +81,22 @@ export default class CDSTab extends CDSTab_base {
71
81
  * The index of the tab component
72
82
  */
73
83
  _index: number;
84
+ /**
85
+ * Reference to the label span element (only present in vertical mode).
86
+ * @private
87
+ */
88
+ private _labelElement?;
89
+ /**
90
+ * Checks if the text overflow ellipsis is currently applied to the label.
91
+ * This is useful for determining if a tooltip should be shown.
92
+ *
93
+ * @returns `true` if text is truncated/clamped, `false` otherwise or if not in vertical mode
94
+ */
95
+ isTextTruncated(): boolean;
96
+ /**
97
+ * Updates the truncated state after the component has rendered.
98
+ */
99
+ updated(changedProperties: Map<PropertyKey, unknown>): void;
74
100
  /**
75
101
  * Handles `slotchange` event.
76
102
  */
@@ -1 +1 @@
1
- {"version":3,"file":"tab.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/tab.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,sBAAsB,MAAM,2CAA2C,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAKnD,OAAO,kBAAkB,CAAC;;;;;;;;;;uBAGzB,CAAC;;;;;AAEF;;;;;;;;GAQG;AAEH,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAyC;IAC3E;;;;;OAKG;IAEH,WAAW,UAAS;IAEpB;;OAEG;IAEH,IAAI,YAAqB;IAEzB;;OAEG;IAEH,QAAQ,UAAS;IAEjB;;OAEG;IAEH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B;;OAEG;IAEH,QAAQ,MAAC;IAET;;;OAGG;IAEH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IAEH,cAAc,UAAS;IAEvB;;OAEG;IAEH,YAAY,UAAS;IAErB;;OAEG;IAEH,MAAM,SAAM;IAEZ;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK;IAM7C;;;OAGG;IAEH,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,aAAa;IAY7C,iBAAiB;IAOjB,MAAM;IA6EN;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK;IAwBnC;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK;IAIzB;;;OAGG;IACH,MAAM,KAAK,gBAAgB,WAE1B;IAED;;OAEG;IACH,MAAM,KAAK,UAAU,WAEpB;IAED,MAAM,CAAC,MAAM,MAAU;CACxB"}
1
+ {"version":3,"file":"tab.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/tab.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,sBAAsB,MAAM,2CAA2C,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAKnD,OAAO,kBAAkB,CAAC;;;;;;;;;;uBAE6B,CAAC;;;;;AAGxD;;;;;;;;GAQG;AAEH,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAyC;IAC3E;;;;;OAKG;IAEH,WAAW,UAAS;IAEpB;;OAEG;IAEH,IAAI,YAAqB;IAEzB;;;OAGG;IAEH,QAAQ,UAAS;IAEjB;;OAEG;IAEH,QAAQ,UAAS;IAEjB;;OAEG;IAEH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B;;OAEG;IAEH,QAAQ,MAAC;IAET;;;OAGG;IAEH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IAEH,cAAc,UAAS;IAEvB;;;OAGG;IAEH,SAAS,UAAS;IAElB;;OAEG;IAEH,YAAY,UAAS;IAErB;;OAEG;IAEH,MAAM,SAAM;IAEZ;;;OAGG;IAEH,OAAO,CAAC,aAAa,CAAC,CAAc;IAEpC;;;;;OAKG;IACH,eAAe,IAAI,OAAO;IAU1B;;OAEG;IACH,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC;IAYpD;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK;IAQ7C;;;OAGG;IAEH,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,aAAa;IAY7C,iBAAiB;IAOjB,MAAM;IAuFN;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK;IAwBnC;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK;IAIzB;;;OAGG;IACH,MAAM,KAAK,gBAAgB,WAE1B;IAED;;OAEG;IACH,MAAM,KAAK,UAAU,WAEpB;IAED,MAAM,CAAC,MAAM,MAAU;CACxB"}
@@ -16,7 +16,7 @@ import content_switcher_item_default from "../content-switcher/content-switcher-
16
16
  import "./defs.js";
17
17
  import tabs_default from "./tabs.scss.js";
18
18
  import { html } from "lit";
19
- import { property, state } from "lit/decorators.js";
19
+ import { property, query, state } from "lit/decorators.js";
20
20
  import { classMap } from "lit/directives/class-map.js";
21
21
  import { ifDefined } from "lit/directives/if-defined.js";
22
22
  import Close16 from "@carbon/icons/es/close/16.js";
@@ -32,17 +32,39 @@ let CDSTab = class CDSTab extends HostListenerMixin(content_switcher_item_defaul
32
32
  super(..._args);
33
33
  this.highlighted = false;
34
34
  this.type = "";
35
+ this.vertical = false;
35
36
  this.iconOnly = false;
36
37
  this.badgeIndicator = false;
38
+ this.truncated = false;
37
39
  this._dismissable = false;
38
40
  this._index = -1;
39
41
  }
40
42
  /**
43
+ * Checks if the text overflow ellipsis is currently applied to the label.
44
+ * This is useful for determining if a tooltip should be shown.
45
+ *
46
+ * @returns `true` if text is truncated/clamped, `false` otherwise or if not in vertical mode
47
+ */
48
+ isTextTruncated() {
49
+ if (!this.vertical || !this._labelElement) return false;
50
+ return this._labelElement.scrollHeight > this._labelElement.clientHeight;
51
+ }
52
+ /**
53
+ * Updates the truncated state after the component has rendered.
54
+ */
55
+ updated(changedProperties) {
56
+ super.updated(changedProperties);
57
+ if (this.vertical && this._labelElement) {
58
+ const isTruncated = this.isTextTruncated();
59
+ if (this.truncated !== isTruncated) this.truncated = isTruncated;
60
+ }
61
+ }
62
+ /**
41
63
  * Handles `slotchange` event.
42
64
  */
43
65
  _handleSlotChange({ target }) {
44
- const content = target.assignedNodes();
45
- this.tabTitle = content[0]?.textContent?.trim() || void 0;
66
+ const textContent = target.assignedNodes()[0]?.textContent;
67
+ this.tabTitle = textContent?.trim().replace(/\s+/g, " ") || void 0;
46
68
  }
47
69
  /**
48
70
  * Handles `keydown` event on the tab.
@@ -68,7 +90,7 @@ let CDSTab = class CDSTab extends HostListenerMixin(content_switcher_item_defaul
68
90
  [`cds--tabs__nav-item--close`]: this._dismissable,
69
91
  [`cds--tabs__nav-item--close--hidden`]: !this._dismissable
70
92
  });
71
- const { badgeIndicator, disabled, secondaryLabel, selected, tabTitle, _handleSlotChange: handleSlotChange, _handleClick: handleClick } = this;
93
+ const { badgeIndicator, disabled, secondaryLabel, selected, tabTitle, vertical, truncated, _handleSlotChange: handleSlotChange, _handleClick: handleClick } = this;
72
94
  const iconButton = html`
73
95
  <cds-button
74
96
  title="${this.textContent?.trim() ? `Remove ${this.textContent.trim()} tab` : "Remove tab"}"
@@ -95,9 +117,15 @@ let CDSTab = class CDSTab extends HostListenerMixin(content_switcher_item_defaul
95
117
  tabindex="${selected ? 0 : -1}"
96
118
  ?disabled="${disabled}"
97
119
  aria-selected="${selected}">
98
- <span class="${"cds"}--tabs__nav-item-label-wrapper">
99
- <slot @slotchange="${handleSlotChange}"></slot>
100
- </span>
120
+ ${vertical ? html`<span
121
+ class="${"cds"}--tabs__nav-item-label"
122
+ title="${truncated ? tabTitle.trim() : ""}">
123
+ <slot @slotchange="${handleSlotChange}"></slot>
124
+ </span>` : html`
125
+ <span class="${"cds"}--tabs__nav-item-label-wrapper">
126
+ <slot @slotchange="${handleSlotChange}"></slot>
127
+ </span>
128
+ `}
101
129
  ${secondaryLabel ? html`<span
102
130
  class="${"cds"}--tabs__nav-item-secondary-label"
103
131
  title="${secondaryLabel}"
@@ -157,6 +185,10 @@ __decorate([property({
157
185
  reflect: true
158
186
  })], CDSTab.prototype, "highlighted", void 0);
159
187
  __decorate([property({ reflect: true })], CDSTab.prototype, "type", void 0);
188
+ __decorate([property({
189
+ type: Boolean,
190
+ reflect: true
191
+ })], CDSTab.prototype, "vertical", void 0);
160
192
  __decorate([property({
161
193
  type: Boolean,
162
194
  reflect: true,
@@ -176,8 +208,10 @@ __decorate([property({
176
208
  reflect: true,
177
209
  attribute: "badge-indicator"
178
210
  })], CDSTab.prototype, "badgeIndicator", void 0);
211
+ __decorate([state()], CDSTab.prototype, "truncated", void 0);
179
212
  __decorate([state()], CDSTab.prototype, "_dismissable", void 0);
180
213
  __decorate([state()], CDSTab.prototype, "_index", void 0);
214
+ __decorate([query(`.cds--tabs__nav-item-label`)], CDSTab.prototype, "_labelElement", void 0);
181
215
  __decorate([HostListener("keydown")], CDSTab.prototype, "_handleKeydown", null);
182
216
  CDSTab = __decorate([carbonElement(`cds-tab`)], CDSTab);
183
217
  var tab_default = CDSTab;
@@ -1 +1 @@
1
- {"version":3,"file":"tab.js","names":["CDSContentSwitcherItem","styles","customElement"],"sources":["../../../src/components/tabs/tab.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2019, 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { html } from 'lit';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { property, state } from 'lit/decorators.js';\nimport { prefix } from '../../globals/settings';\nimport CDSContentSwitcherItem from '../content-switcher/content-switcher-item';\nimport { TABS_ICON_SIZE, TABS_TYPE } from './defs';\nimport styles from './tabs.scss?lit';\nimport { carbonElement as customElement } from '../../globals/decorators/carbon-element';\nimport HostListenerMixin from '../../globals/mixins/host-listener';\nimport HostListener from '../../globals/decorators/host-listener';\nimport '../button/button';\nimport Close16 from '@carbon/icons/es/close/16.js';\nimport iconLoader from '../../globals/internal/icon-loader';\nimport { classMap } from 'lit/directives/class-map.js';\n\n/**\n * Basic tab.\n *\n * @element cds-tab\n * @fires cds-tab-beingclosed\n * The custom event fired before a tab is closed upon a user gesture.\n * Cancellation of this event stops changing the user-initiated action.\n * @fires cds-tab-closed - The custom event fired after a a tab is closed upon a user gesture.\n */\n@customElement(`${prefix}-tab`)\nexport default class CDSTab extends HostListenerMixin(CDSContentSwitcherItem) {\n /**\n * `true` if this tab should be highlighted.\n * If `true`, parent `<cds-tabs>` selects/deselects this tab upon keyboard interaction.\n *\n * @private\n */\n @property({ type: Boolean, reflect: true })\n highlighted = false;\n\n /**\n * Tab type.\n */\n @property({ reflect: true })\n type = TABS_TYPE.REGULAR;\n\n /**\n * `true` if this tab is icon-only.\n */\n @property({ type: Boolean, reflect: true, attribute: 'icon-only' })\n iconOnly = false;\n\n /**\n * Specify the icon size used by icon-only tabs.\n */\n @property({ attribute: 'icon-size', reflect: true })\n iconSize?: TABS_ICON_SIZE;\n\n /**\n * The tab text content.\n */\n @property()\n tabTitle;\n\n /**\n * An optional label to render under the primary tab label.\n * Only useful for contained tabs.\n */\n @property({ attribute: 'secondary-label', reflect: true })\n secondaryLabel?: string;\n\n /**\n * **Experimental**: Display an empty dot badge on the Tab.\n */\n @property({ type: Boolean, reflect: true, attribute: 'badge-indicator' })\n badgeIndicator = false;\n\n /**\n * Whether this tab should be dismissable.\n */\n @state()\n _dismissable = false;\n\n /**\n * The index of the tab component\n */\n @state()\n _index = -1;\n\n /**\n * Handles `slotchange` event.\n */\n protected _handleSlotChange({ target }: Event) {\n // Retrieve content of the slot to use for aria-label.\n const content = (target as HTMLSlotElement).assignedNodes();\n this.tabTitle = content[0]?.textContent?.trim() || undefined;\n }\n\n /**\n * Handles `keydown` event on the tab.\n * Triggers tab close when Delete key is pressed on a dismissable tab.\n */\n @HostListener('keydown')\n protected _handleKeydown(event: KeyboardEvent) {\n const { key } = event;\n if (\n this._dismissable &&\n !this.disabled &&\n (key === 'Delete' || key === 'Backspace')\n ) {\n event.preventDefault();\n this._handleClose(event);\n }\n }\n\n connectedCallback() {\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'listitem');\n }\n super.connectedCallback();\n }\n\n render() {\n const navLinkClasses = classMap({\n [`${prefix}--tabs__nav-link`]: true,\n [`${prefix}--tabs__nav-link--dismissable`]: this._dismissable,\n });\n const closeButtonClasses = classMap({\n [`${prefix}--tabs__nav-item--close`]: this._dismissable,\n [`${prefix}--tabs__nav-item--close--hidden`]: !this._dismissable,\n });\n const {\n badgeIndicator,\n disabled,\n secondaryLabel,\n selected,\n tabTitle,\n _handleSlotChange: handleSlotChange,\n _handleClick: handleClick,\n } = this;\n\n const iconButton = html`\n <cds-button\n title=\"${this.textContent?.trim()\n ? `Remove ${this.textContent.trim()} tab`\n : 'Remove tab'}\"\n class=\"${closeButtonClasses}\"\n kind=\"ghost\"\n size=\"xs\"\n @click=\"${handleClick}\"\n tab-index=\"${-1}\"\n aria-hidden=\"${this.selected && this._dismissable ? 'false' : 'true'}\"\n ?disabled=\"${disabled}\">\n ${iconLoader(Close16, { 'aria-label': 'close', slot: 'icon' })}\n </cds-button>\n `;\n\n const accessibleLabel = tabTitle || this.getAttribute('aria-label');\n const isIconOnly =\n this.iconOnly ||\n this.classList.contains(`${prefix}--tabs__nav-item--icon-only`);\n // No `href`/`tabindex` to not to make this `<a>` click-focusable\n const tabLink = html`\n <a\n class=\"${navLinkClasses}\"\n role=\"tab\"\n aria-label=\"${ifDefined(accessibleLabel || undefined)}\"\n tabindex=\"${selected ? 0 : -1}\"\n ?disabled=\"${disabled}\"\n aria-selected=\"${selected}\">\n <span class=\"${prefix}--tabs__nav-item-label-wrapper\">\n <slot @slotchange=\"${handleSlotChange}\"></slot>\n </span>\n ${secondaryLabel\n ? html`<span\n class=\"${prefix}--tabs__nav-item-secondary-label\"\n title=\"${secondaryLabel}\"\n >${secondaryLabel}</span\n >`\n : ''}\n ${!disabled && badgeIndicator\n ? html`<cds-badge-indicator></cds-badge-indicator>`\n : ''}\n </a>\n ${iconButton}\n `;\n\n if (isIconOnly && accessibleLabel && !disabled) {\n return html`\n <cds-tooltip align=\"bottom\" class=\"${prefix}--icon-tooltip\">\n ${tabLink}\n <cds-tooltip-content>${accessibleLabel}</cds-tooltip-content>\n </cds-tooltip>\n `;\n }\n\n return tabLink;\n }\n\n /**\n * Handles the close action for the tab.\n * Dispatches before-close and close events.\n */\n protected _handleClose(event: Event) {\n event.stopPropagation();\n const init = {\n bubbles: true,\n cancelable: true,\n composed: true,\n detail: {\n index: this._index,\n },\n };\n if (\n this.dispatchEvent(\n new CustomEvent(\n (this.constructor as typeof CDSTab).eventBeforeClose,\n init\n )\n )\n ) {\n this.dispatchEvent(\n new CustomEvent((this.constructor as typeof CDSTab).eventClose, init)\n );\n }\n }\n\n /**\n * Handles click event on the close button.\n */\n _handleClick(event: Event) {\n this._handleClose(event);\n }\n\n /**\n * The name of the custom event fired before a tab is closed upon a user gesture.\n * Cancellation of this event stops changing the user-initiated action.\n */\n static get eventBeforeClose() {\n return `${prefix}-tab-beingclosed`;\n }\n\n /**\n * The name of the custom event fired after a a tab is closed upon a user gesture.\n */\n static get eventClose() {\n return `${prefix}-tab-closed`;\n }\n\n static styles = styles;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tab.js","names":["CDSContentSwitcherItem","styles","customElement"],"sources":["../../../src/components/tabs/tab.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2019, 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { html } from 'lit';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { property, state, query } from 'lit/decorators.js';\nimport { prefix } from '../../globals/settings';\nimport CDSContentSwitcherItem from '../content-switcher/content-switcher-item';\nimport { TABS_ICON_SIZE, TABS_TYPE } from './defs';\nimport styles from './tabs.scss?lit';\nimport { carbonElement as customElement } from '../../globals/decorators/carbon-element';\nimport HostListenerMixin from '../../globals/mixins/host-listener';\nimport HostListener from '../../globals/decorators/host-listener';\nimport '../button/button';\nimport Close16 from '@carbon/icons/es/close/16.js';\nimport iconLoader from '../../globals/internal/icon-loader';\nimport { classMap } from 'lit/directives/class-map.js';\n\n/**\n * Basic tab.\n *\n * @element cds-tab\n * @fires cds-tab-beingclosed\n * The custom event fired before a tab is closed upon a user gesture.\n * Cancellation of this event stops changing the user-initiated action.\n * @fires cds-tab-closed - The custom event fired after a a tab is closed upon a user gesture.\n */\n@customElement(`${prefix}-tab`)\nexport default class CDSTab extends HostListenerMixin(CDSContentSwitcherItem) {\n /**\n * `true` if this tab should be highlighted.\n * If `true`, parent `<cds-tabs>` selects/deselects this tab upon keyboard interaction.\n *\n * @private\n */\n @property({ type: Boolean, reflect: true })\n highlighted = false;\n\n /**\n * Tab type.\n */\n @property({ reflect: true })\n type = TABS_TYPE.REGULAR;\n\n /**\n * `true` if the tab is in vertical orientation.\n * This is automatically set by the parent `<cds-tabs>` when it's in vertical mode.\n */\n @property({ type: Boolean, reflect: true })\n vertical = false;\n\n /**\n * `true` if this tab is icon-only.\n */\n @property({ type: Boolean, reflect: true, attribute: 'icon-only' })\n iconOnly = false;\n\n /**\n * Specify the icon size used by icon-only tabs.\n */\n @property({ attribute: 'icon-size', reflect: true })\n iconSize?: TABS_ICON_SIZE;\n\n /**\n * The tab text content.\n */\n @property()\n tabTitle;\n\n /**\n * An optional label to render under the primary tab label.\n * Only useful for contained tabs.\n */\n @property({ attribute: 'secondary-label', reflect: true })\n secondaryLabel?: string;\n\n /**\n * **Experimental**: Display an empty dot badge on the Tab.\n */\n @property({ type: Boolean, reflect: true, attribute: 'badge-indicator' })\n badgeIndicator = false;\n\n /**\n * `true` if the tab text is truncated with ellipsis.\n * This state is automatically updated when the component renders in vertical mode.\n */\n @state()\n truncated = false;\n\n /**\n * Whether this tab should be dismissable.\n */\n @state()\n _dismissable = false;\n\n /**\n * The index of the tab component\n */\n @state()\n _index = -1;\n\n /**\n * Reference to the label span element (only present in vertical mode).\n * @private\n */\n @query(`.${prefix}--tabs__nav-item-label`)\n private _labelElement?: HTMLElement;\n\n /**\n * Checks if the text overflow ellipsis is currently applied to the label.\n * This is useful for determining if a tooltip should be shown.\n *\n * @returns `true` if text is truncated/clamped, `false` otherwise or if not in vertical mode\n */\n isTextTruncated(): boolean {\n if (!this.vertical || !this._labelElement) {\n return false;\n }\n\n // Compare scrollHeight with clientHeight to detect if content is overflowing\n // When line-clamp is active and text exceeds 2 lines, scrollHeight > clientHeight\n return this._labelElement.scrollHeight > this._labelElement.clientHeight;\n }\n\n /**\n * Updates the truncated state after the component has rendered.\n */\n updated(changedProperties: Map<PropertyKey, unknown>) {\n super.updated(changedProperties);\n\n // Check if text is truncated and update state when in vertical mode\n if (this.vertical && this._labelElement) {\n const isTruncated = this.isTextTruncated();\n if (this.truncated !== isTruncated) {\n this.truncated = isTruncated;\n }\n }\n }\n\n /**\n * Handles `slotchange` event.\n */\n protected _handleSlotChange({ target }: Event) {\n // Retrieve content of the slot to use for aria-label.\n const content = (target as HTMLSlotElement).assignedNodes();\n const textContent = content[0]?.textContent;\n // Normalize whitespace: trim and replace multiple spaces with single space\n this.tabTitle = textContent?.trim().replace(/\\s+/g, ' ') || undefined;\n }\n\n /**\n * Handles `keydown` event on the tab.\n * Triggers tab close when Delete key is pressed on a dismissable tab.\n */\n @HostListener('keydown')\n protected _handleKeydown(event: KeyboardEvent) {\n const { key } = event;\n if (\n this._dismissable &&\n !this.disabled &&\n (key === 'Delete' || key === 'Backspace')\n ) {\n event.preventDefault();\n this._handleClose(event);\n }\n }\n\n connectedCallback() {\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'listitem');\n }\n super.connectedCallback();\n }\n\n render() {\n const navLinkClasses = classMap({\n [`${prefix}--tabs__nav-link`]: true,\n [`${prefix}--tabs__nav-link--dismissable`]: this._dismissable,\n });\n const closeButtonClasses = classMap({\n [`${prefix}--tabs__nav-item--close`]: this._dismissable,\n [`${prefix}--tabs__nav-item--close--hidden`]: !this._dismissable,\n });\n const {\n badgeIndicator,\n disabled,\n secondaryLabel,\n selected,\n tabTitle,\n vertical,\n truncated,\n _handleSlotChange: handleSlotChange,\n _handleClick: handleClick,\n } = this;\n\n const iconButton = html`\n <cds-button\n title=\"${this.textContent?.trim()\n ? `Remove ${this.textContent.trim()} tab`\n : 'Remove tab'}\"\n class=\"${closeButtonClasses}\"\n kind=\"ghost\"\n size=\"xs\"\n @click=\"${handleClick}\"\n tab-index=\"${-1}\"\n aria-hidden=\"${this.selected && this._dismissable ? 'false' : 'true'}\"\n ?disabled=\"${disabled}\">\n ${iconLoader(Close16, { 'aria-label': 'close', slot: 'icon' })}\n </cds-button>\n `;\n\n const accessibleLabel = tabTitle || this.getAttribute('aria-label');\n const isIconOnly =\n this.iconOnly ||\n this.classList.contains(`${prefix}--tabs__nav-item--icon-only`);\n // No `href`/`tabindex` to not to make this `<a>` click-focusable\n const tabLink = html`\n <a\n class=\"${navLinkClasses}\"\n role=\"tab\"\n aria-label=\"${ifDefined(accessibleLabel || undefined)}\"\n tabindex=\"${selected ? 0 : -1}\"\n ?disabled=\"${disabled}\"\n aria-selected=\"${selected}\">\n ${vertical\n ? html`<span\n class=\"${prefix}--tabs__nav-item-label\"\n title=\"${truncated ? tabTitle.trim() : ''}\">\n <slot @slotchange=\"${handleSlotChange}\"></slot>\n </span>`\n : html`\n <span class=\"${prefix}--tabs__nav-item-label-wrapper\">\n <slot @slotchange=\"${handleSlotChange}\"></slot>\n </span>\n `}\n ${secondaryLabel\n ? html`<span\n class=\"${prefix}--tabs__nav-item-secondary-label\"\n title=\"${secondaryLabel}\"\n >${secondaryLabel}</span\n >`\n : ''}\n ${!disabled && badgeIndicator\n ? html`<cds-badge-indicator></cds-badge-indicator>`\n : ''}\n </a>\n ${iconButton}\n `;\n\n if (isIconOnly && accessibleLabel && !disabled) {\n return html`\n <cds-tooltip align=\"bottom\" class=\"${prefix}--icon-tooltip\">\n ${tabLink}\n <cds-tooltip-content>${accessibleLabel}</cds-tooltip-content>\n </cds-tooltip>\n `;\n }\n\n return tabLink;\n }\n\n /**\n * Handles the close action for the tab.\n * Dispatches before-close and close events.\n */\n protected _handleClose(event: Event) {\n event.stopPropagation();\n const init = {\n bubbles: true,\n cancelable: true,\n composed: true,\n detail: {\n index: this._index,\n },\n };\n if (\n this.dispatchEvent(\n new CustomEvent(\n (this.constructor as typeof CDSTab).eventBeforeClose,\n init\n )\n )\n ) {\n this.dispatchEvent(\n new CustomEvent((this.constructor as typeof CDSTab).eventClose, init)\n );\n }\n }\n\n /**\n * Handles click event on the close button.\n */\n _handleClick(event: Event) {\n this._handleClose(event);\n }\n\n /**\n * The name of the custom event fired before a tab is closed upon a user gesture.\n * Cancellation of this event stops changing the user-initiated action.\n */\n static get eventBeforeClose() {\n return `${prefix}-tab-beingclosed`;\n }\n\n /**\n * The name of the custom event fired after a a tab is closed upon a user gesture.\n */\n static get eventClose() {\n return `${prefix}-tab-closed`;\n }\n\n static styles = styles;\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright IBM Corp. 2019, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { LitElement } from 'lit';
8
+ /**
9
+ * Vertical tabs container component.
10
+ *
11
+ * @element cds-tabs-vertical
12
+ * @slot tabs - The `<cds-tabs>` navigation element.
13
+ * @slot panel - One or more `<div role="tabpanel">` elements.
14
+ */
15
+ export default class CDSTabsVertical extends LitElement {
16
+ /**
17
+ * Option to set a height style only if using vertical variation.
18
+ */
19
+ customHeight?: string;
20
+ private _mediaQueryList;
21
+ private _handleViewportChange;
22
+ firstUpdated(): void;
23
+ updated(changedProperties: any): void;
24
+ disconnectedCallback(): void;
25
+ private _applyHeight;
26
+ render(): import("lit-html").TemplateResult<1>;
27
+ static styles: any;
28
+ }
29
+ //# sourceMappingURL=tabs-vertical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs-vertical.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/tabs-vertical.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAC;AAevC;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,UAAU;IACrD;;OAEG;IAEH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,eAAe,CAA+B;IAEtD,OAAO,CAAC,qBAAqB,CAe3B;IAEF,YAAY;IAeZ,OAAO,CAAC,iBAAiB,KAAA;IAOzB,oBAAoB;IASpB,OAAO,CAAC,YAAY;IA2CpB,MAAM;IASN,MAAM,CAAC,MAAM,MAAU;CACxB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Copyright IBM Corp. 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import "../../globals/settings.js";
9
+ import { carbonElement } from "../../globals/decorators/carbon-element.js";
10
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.js";
11
+ import tabs_default from "./tabs.scss.js";
12
+ import { LitElement, html } from "lit";
13
+ import { property } from "lit/decorators.js";
14
+ import { breakpoints } from "@carbon/layout";
15
+ //#region src/components/tabs/tabs-vertical.ts
16
+ /**
17
+ * Copyright IBM Corp. 2019, 2026
18
+ *
19
+ * This source code is licensed under the Apache-2.0 license found in the
20
+ * LICENSE file in the root directory of this source tree.
21
+ */
22
+ /**
23
+ * Breakpoint for switching between horizontal and vertical tab layouts.
24
+ * Uses Carbon's md breakpoint (42rem/672px) + 0.01rem offset to avoid overlap
25
+ * with max-width queries. This mirrors the Sass breakpoint behavior.
26
+ * Below this breakpoint, tabs display horizontally.
27
+ */
28
+ const VERTICAL_TABS_BREAKPOINT = `(min-width: calc(${breakpoints.md.width} + 0.01rem))`;
29
+ let CDSTabsVertical = class CDSTabsVertical extends LitElement {
30
+ constructor(..._args) {
31
+ super(..._args);
32
+ this._mediaQueryList = null;
33
+ this._handleViewportChange = (e) => {
34
+ const tabs = this.querySelector(`cds-tabs`);
35
+ if (e.matches) {
36
+ this.classList.add(`cds--css-grid`);
37
+ if (tabs) {
38
+ tabs.setAttribute("vertical", "");
39
+ tabs.removeAttribute("type");
40
+ }
41
+ } else {
42
+ this.classList.remove(`cds--css-grid`);
43
+ if (tabs) {
44
+ tabs.removeAttribute("vertical");
45
+ tabs.setAttribute("type", "contained");
46
+ }
47
+ }
48
+ };
49
+ }
50
+ firstUpdated() {
51
+ this._mediaQueryList = window.matchMedia(VERTICAL_TABS_BREAKPOINT);
52
+ this._handleViewportChange(this._mediaQueryList);
53
+ this._mediaQueryList.addEventListener("change", this._handleViewportChange);
54
+ requestAnimationFrame(() => {
55
+ this._applyHeight();
56
+ });
57
+ (this.shadowRoot?.querySelector("slot[name=\"panel\"]"))?.addEventListener("slotchange", () => {
58
+ this._applyHeight();
59
+ });
60
+ }
61
+ updated(changedProperties) {
62
+ super.updated?.(changedProperties);
63
+ if (changedProperties.has("customHeight")) this._applyHeight();
64
+ }
65
+ disconnectedCallback() {
66
+ super.disconnectedCallback();
67
+ this._mediaQueryList?.removeEventListener("change", this._handleViewportChange);
68
+ this._mediaQueryList = null;
69
+ }
70
+ _applyHeight() {
71
+ const isVertical = this.classList.contains(`cds--css-grid`);
72
+ if (this.customHeight) {
73
+ this.style.height = this.customHeight;
74
+ return;
75
+ }
76
+ if (!isVertical) {
77
+ this.style.removeProperty("height");
78
+ return;
79
+ }
80
+ const panels = Array.from(this.querySelectorAll("[slot=\"panel\"]"));
81
+ if (panels.length === 0) return;
82
+ const hiddenStates = panels.map((panel) => panel.hidden);
83
+ panels.forEach((panel) => {
84
+ panel.hidden = false;
85
+ });
86
+ const tallestPanel = Math.max(...panels.map((panel) => panel.offsetHeight));
87
+ panels.forEach((panel, index) => {
88
+ panel.hidden = hiddenStates[index];
89
+ });
90
+ const tabsHeight = this.querySelector(`cds-tabs`)?.offsetHeight ?? 0;
91
+ const height = Math.max(tallestPanel, tabsHeight);
92
+ if (height > 0) this.style.height = `${height}px`;
93
+ else this.style.removeProperty("height");
94
+ }
95
+ render() {
96
+ return html`
97
+ <slot name="tabs"></slot>
98
+ <div class="${"cds"}-panel-container">
99
+ <slot name="panel"></slot>
100
+ </div>
101
+ `;
102
+ }
103
+ static {
104
+ this.styles = tabs_default;
105
+ }
106
+ };
107
+ __decorate([property({ attribute: "custom-height" })], CDSTabsVertical.prototype, "customHeight", void 0);
108
+ CDSTabsVertical = __decorate([carbonElement(`cds-tabs-vertical`)], CDSTabsVertical);
109
+ var tabs_vertical_default = CDSTabsVertical;
110
+ //#endregion
111
+ export { tabs_vertical_default as default };
112
+
113
+ //# sourceMappingURL=tabs-vertical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs-vertical.js","names":["styles","customElement"],"sources":["../../../src/components/tabs/tabs-vertical.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2019, 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { LitElement, html } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { breakpoints } from '@carbon/layout';\nimport { prefix } from '../../globals/settings';\nimport styles from './tabs.scss?lit';\nimport { carbonElement as customElement } from '../../globals/decorators/carbon-element';\n\n/**\n * Breakpoint for switching between horizontal and vertical tab layouts.\n * Uses Carbon's md breakpoint (42rem/672px) + 0.01rem offset to avoid overlap\n * with max-width queries. This mirrors the Sass breakpoint behavior.\n * Below this breakpoint, tabs display horizontally.\n */\nconst VERTICAL_TABS_BREAKPOINT = `(min-width: calc(${breakpoints.md.width} + 0.01rem))`;\n\n/**\n * Vertical tabs container component.\n *\n * @element cds-tabs-vertical\n * @slot tabs - The `<cds-tabs>` navigation element.\n * @slot panel - One or more `<div role=\"tabpanel\">` elements.\n */\n@customElement(`${prefix}-tabs-vertical`)\nexport default class CDSTabsVertical extends LitElement {\n /**\n * Option to set a height style only if using vertical variation.\n */\n @property({ attribute: 'custom-height' })\n customHeight?: string;\n\n private _mediaQueryList: MediaQueryList | null = null;\n\n private _handleViewportChange = (e: MediaQueryListEvent | MediaQueryList) => {\n const tabs = this.querySelector(`${prefix}-tabs`);\n if (e.matches) {\n this.classList.add(`${prefix}--css-grid`);\n if (tabs) {\n tabs.setAttribute('vertical', '');\n tabs.removeAttribute('type');\n }\n } else {\n this.classList.remove(`${prefix}--css-grid`);\n if (tabs) {\n tabs.removeAttribute('vertical');\n tabs.setAttribute('type', 'contained');\n }\n }\n };\n\n firstUpdated() {\n this._mediaQueryList = window.matchMedia(VERTICAL_TABS_BREAKPOINT);\n this._handleViewportChange(this._mediaQueryList);\n this._mediaQueryList.addEventListener('change', this._handleViewportChange);\n\n requestAnimationFrame(() => {\n this._applyHeight();\n });\n\n const panelSlot = this.shadowRoot?.querySelector('slot[name=\"panel\"]');\n panelSlot?.addEventListener('slotchange', () => {\n this._applyHeight();\n });\n }\n\n updated(changedProperties) {\n super.updated?.(changedProperties);\n if (changedProperties.has('customHeight')) {\n this._applyHeight();\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this._mediaQueryList?.removeEventListener(\n 'change',\n this._handleViewportChange\n );\n this._mediaQueryList = null;\n }\n\n private _applyHeight() {\n const isVertical = this.classList.contains(`${prefix}--css-grid`);\n\n if (this.customHeight) {\n this.style.height = this.customHeight;\n return;\n }\n\n if (!isVertical) {\n this.style.removeProperty('height');\n return;\n }\n\n const panels = Array.from(\n this.querySelectorAll<HTMLElement>('[slot=\"panel\"]')\n );\n\n if (panels.length === 0) {\n return;\n }\n\n const hiddenStates = panels.map((panel) => panel.hidden);\n panels.forEach((panel) => {\n panel.hidden = false;\n });\n\n const tallestPanel = Math.max(...panels.map((panel) => panel.offsetHeight));\n\n panels.forEach((panel, index) => {\n panel.hidden = hiddenStates[index];\n });\n\n const tabsEl = this.querySelector<HTMLElement>(`${prefix}-tabs`);\n const tabsHeight = tabsEl?.offsetHeight ?? 0;\n\n const height = Math.max(tallestPanel, tabsHeight);\n if (height > 0) {\n this.style.height = `${height}px`;\n } else {\n this.style.removeProperty('height');\n }\n }\n\n render() {\n return html`\n <slot name=\"tabs\"></slot>\n <div class=\"${prefix}-panel-container\">\n <slot name=\"panel\"></slot>\n </div>\n `;\n }\n\n static styles = styles;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,2BAA2B,oBAAoB,YAAY,GAAG,MAAM;AAU3D,IAAA,kBAAA,MAAM,wBAAwB,WAAW;;;yBAOL;gCAEhB,MAA4C;GAC3E,MAAM,OAAO,KAAK,cAAc,WAAiB;AACjD,OAAI,EAAE,SAAS;AACb,SAAK,UAAU,IAAI,gBAAsB;AACzC,QAAI,MAAM;AACR,UAAK,aAAa,YAAY,GAAG;AACjC,UAAK,gBAAgB,OAAO;;UAEzB;AACL,SAAK,UAAU,OAAO,gBAAsB;AAC5C,QAAI,MAAM;AACR,UAAK,gBAAgB,WAAW;AAChC,UAAK,aAAa,QAAQ,YAAY;;;;;CAK5C,eAAe;AACb,OAAK,kBAAkB,OAAO,WAAW,yBAAyB;AAClE,OAAK,sBAAsB,KAAK,gBAAgB;AAChD,OAAK,gBAAgB,iBAAiB,UAAU,KAAK,sBAAsB;AAE3E,8BAA4B;AAC1B,QAAK,cAAc;IACnB;AAGF,GADkB,KAAK,YAAY,cAAc,uBAAqB,GAC3D,iBAAiB,oBAAoB;AAC9C,QAAK,cAAc;IACnB;;CAGJ,QAAQ,mBAAmB;AACzB,QAAM,UAAU,kBAAkB;AAClC,MAAI,kBAAkB,IAAI,eAAe,CACvC,MAAK,cAAc;;CAIvB,uBAAuB;AACrB,QAAM,sBAAsB;AAC5B,OAAK,iBAAiB,oBACpB,UACA,KAAK,sBACN;AACD,OAAK,kBAAkB;;CAGzB,eAAuB;EACrB,MAAM,aAAa,KAAK,UAAU,SAAS,gBAAsB;AAEjE,MAAI,KAAK,cAAc;AACrB,QAAK,MAAM,SAAS,KAAK;AACzB;;AAGF,MAAI,CAAC,YAAY;AACf,QAAK,MAAM,eAAe,SAAS;AACnC;;EAGF,MAAM,SAAS,MAAM,KACnB,KAAK,iBAA8B,mBAAiB,CACrD;AAED,MAAI,OAAO,WAAW,EACpB;EAGF,MAAM,eAAe,OAAO,KAAK,UAAU,MAAM,OAAO;AACxD,SAAO,SAAS,UAAU;AACxB,SAAM,SAAS;IACf;EAEF,MAAM,eAAe,KAAK,IAAI,GAAG,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE3E,SAAO,SAAS,OAAO,UAAU;AAC/B,SAAM,SAAS,aAAa;IAC5B;EAGF,MAAM,aADS,KAAK,cAA2B,WAAiB,EACrC,gBAAgB;EAE3C,MAAM,SAAS,KAAK,IAAI,cAAc,WAAW;AACjD,MAAI,SAAS,EACX,MAAK,MAAM,SAAS,GAAG,OAAO;MAE9B,MAAK,MAAM,eAAe,SAAS;;CAIvC,SAAS;AACP,SAAO,IAAI;;0BAEY;;;;;;gBAMTA;;;YAzGf,SAAS,EAAE,WAAW,iBAAiB,CAAC,CAAA,EAAA,gBAAA,WAAA,gBAAA,KAAA,EAAA;8BAL1CC,cAAc,oBAA0B,CAAA,EAAA,gBAAA"}
@@ -6,9 +6,9 @@
6
6
  */
7
7
  import { TemplateResult } from 'lit';
8
8
  import CDSContentSwitcher, { NAVIGATION_DIRECTION } from '../content-switcher/content-switcher';
9
- import { TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE } from './defs';
9
+ import { VERTICAL_NAVIGATION_DIRECTION, TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE, TABS_SIZE } from './defs';
10
10
  import CDSTab from './tab';
11
- export { NAVIGATION_DIRECTION, TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE, };
11
+ export { NAVIGATION_DIRECTION, VERTICAL_NAVIGATION_DIRECTION, TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE, TABS_SIZE, };
12
12
  declare const CDSTabs_base: {
13
13
  new (...args: any[]): {
14
14
  _handles: Set<import("../../globals/internal/handle").default>;
@@ -57,6 +57,10 @@ export default class CDSTabs extends CDSTabs_base {
57
57
  * The width of the overflow scroll buttons.
58
58
  */
59
59
  private BUTTON_WIDTH;
60
+ /**
61
+ * Propagates the layout size token to the host and all child tabs.
62
+ */
63
+ private _syncSizeToTabs;
60
64
  /**
61
65
  * Navigates through tabs.
62
66
  *
@@ -99,6 +103,10 @@ export default class CDSTabs extends CDSTabs_base {
99
103
  }): void;
100
104
  private _syncSecondaryLabels;
101
105
  _handleSlotchange(): void;
106
+ /**
107
+ * Updates the vertical attribute on all child tabs based on the vertical property.
108
+ */
109
+ private _updateTabsVerticalAttribute;
102
110
  protected _selectionDidChange(itemToSelect: CDSTab, interactionType?: 'mouse' | 'keyboard' | undefined): void;
103
111
  /**
104
112
  * The scrolling container.
@@ -138,10 +146,19 @@ export default class CDSTabs extends CDSTabs_base {
138
146
  * Tabs type.
139
147
  */
140
148
  type: TABS_TYPE;
149
+ /**
150
+ * `true` if the tabs are in vertical orientation.
151
+ * This is automatically set by `cds-tabs-vertical`.
152
+ */
153
+ vertical: boolean;
141
154
  /**
142
155
  * Whether the rendered Tab children should be dismissable.
143
156
  */
144
157
  dismissable: any;
158
+ /**
159
+ * Specify the size of contained tabs.
160
+ */
161
+ size?: TABS_SIZE;
145
162
  /**
146
163
  * Specify the icon size used by icon-only tabs.
147
164
  */
@@ -228,8 +245,9 @@ export default class CDSTabs extends CDSTabs_base {
228
245
  static styles: any;
229
246
  /**
230
247
  * @param key The key symbol.
231
- * @returns A action for dropdown for the given key symbol.
248
+ * @param isVertical Whether the tabs are in vertical orientation.
249
+ * @returns A action for tabs for the given key symbol.
232
250
  */
233
- static getAction(key: string): TABS_KEYBOARD_ACTION;
251
+ static getAction(key: string, isVertical?: boolean): TABS_KEYBOARD_ACTION;
234
252
  }
235
253
  //# sourceMappingURL=tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/tabs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/tabs.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ import HostListener from "../../globals/decorators/host-listener.js";
14
14
  import HostListenerMixin from "../../globals/mixins/host-listener.js";
15
15
  import { NAVIGATION_DIRECTION } from "../content-switcher/defs.js";
16
16
  import content_switcher_default from "../content-switcher/content-switcher.js";
17
- import { TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE } from "./defs.js";
17
+ import { TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_SIZE, TABS_TYPE, VERTICAL_NAVIGATION_DIRECTION } from "./defs.js";
18
18
  import tabs_default$1 from "./tabs.scss.js";
19
19
  import { html } from "lit";
20
20
  import { property, query, state } from "lit/decorators.js";
@@ -41,6 +41,7 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
41
41
  this.selectedItemAssistiveText = "Selected an item.";
42
42
  this.triggerContent = "";
43
43
  this.type = "";
44
+ this.vertical = false;
44
45
  this.fullWidth = false;
45
46
  this._isIntersectionLeftTrackerInContent = true;
46
47
  this._isIntersectionRightTrackerInContent = true;
@@ -54,6 +55,26 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
54
55
  };
55
56
  }
56
57
  /**
58
+ * Propagates the layout size token to the host and all child tabs.
59
+ */
60
+ _syncSizeToTabs() {
61
+ if (this.type === "contained") {
62
+ const size = this.getAttribute("size");
63
+ if (size) {
64
+ const value = `var(--cds-layout-size-height-${size})`;
65
+ this.style.setProperty(`--cds-layout-size-height`, value);
66
+ this.querySelectorAll(`cds-tab`).forEach((tab) => {
67
+ tab.style.setProperty(`--cds-layout-size-height`, value);
68
+ });
69
+ } else {
70
+ this.style.removeProperty(`--cds-layout-size-height`);
71
+ this.querySelectorAll(`cds-tab`).forEach((tab) => {
72
+ tab.style.removeProperty(`--cds-layout-size-height`);
73
+ });
74
+ }
75
+ }
76
+ }
77
+ /**
57
78
  * Navigates through tabs.
58
79
  *
59
80
  * @param direction `-1` to navigate backward, `1` to navigate forward.
@@ -112,8 +133,9 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
112
133
  }
113
134
  _handleKeydown(event) {
114
135
  const { key } = event;
115
- const action = this.constructor.getAction(key);
116
- const enabledTabs = this.querySelectorAll(`cds-tab:not([disabled])`);
136
+ const { selectorItemEnabled } = this.constructor;
137
+ const action = this.constructor.getAction(key, this.vertical);
138
+ const enabledTabs = this.querySelectorAll(selectorItemEnabled);
117
139
  switch (action) {
118
140
  case "home":
119
141
  {
@@ -141,7 +163,8 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
141
163
  break;
142
164
  case "navigating":
143
165
  {
144
- const direction = NAVIGATION_DIRECTION[key];
166
+ event.preventDefault();
167
+ const direction = this.vertical ? VERTICAL_NAVIGATION_DIRECTION[key] : NAVIGATION_DIRECTION[key];
145
168
  if (direction) this._navigate(direction);
146
169
  }
147
170
  break;
@@ -217,8 +240,20 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
217
240
  const selectedItem = this.querySelector(selectorItemSelected);
218
241
  const nextItem = this._getNextItem(selectedItem, 1);
219
242
  if (nextItem) nextItem.hideDivider = true;
243
+ this._updateTabsVerticalAttribute();
220
244
  this._syncSecondaryLabels();
221
245
  this._updateTabsState();
246
+ this._syncSizeToTabs();
247
+ }
248
+ /**
249
+ * Updates the vertical attribute on all child tabs based on the vertical property.
250
+ */
251
+ _updateTabsVerticalAttribute() {
252
+ const { selectorItem } = this.constructor;
253
+ forEach(this.querySelectorAll(selectorItem), (tab) => {
254
+ if (this.vertical) tab.setAttribute("vertical", "");
255
+ else tab.removeAttribute("vertical");
256
+ });
222
257
  }
223
258
  _selectionDidChange(itemToSelect, interactionType) {
224
259
  super._selectionDidChange(itemToSelect, interactionType);
@@ -256,7 +291,7 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
256
291
  this._isScrollable = scrollWidth > clientWidth;
257
292
  }
258
293
  const { selectorItem } = this.constructor;
259
- if (changedProperties.has("type") || changedProperties.has("iconSize")) {
294
+ if (changedProperties.has("type") || changedProperties.has("iconSize") || changedProperties.has("size")) {
260
295
  this._totalTabs = 0;
261
296
  forEach(this.querySelectorAll(selectorItem), (elem) => {
262
297
  this._totalTabs++;
@@ -271,9 +306,12 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
271
306
  this._tabInitialLoad();
272
307
  this._cleanAndCreateIntersectionObserverContainer({ create: true });
273
308
  this._syncSecondaryLabels();
309
+ this._syncSizeToTabs();
274
310
  }
275
311
  updated(changedProperties) {
276
312
  super.updated?.(changedProperties);
313
+ if (changedProperties.has("size") || changedProperties.has("type")) this._syncSizeToTabs();
314
+ if (changedProperties.has("vertical")) this._updateTabsVerticalAttribute();
277
315
  if (changedProperties.has("value")) {
278
316
  const tab = this.querySelector(`cds-tab[value="${this.value}"]`);
279
317
  if (tab) {
@@ -428,12 +466,13 @@ let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default)
428
466
  }
429
467
  /**
430
468
  * @param key The key symbol.
431
- * @returns A action for dropdown for the given key symbol.
469
+ * @param isVertical Whether the tabs are in vertical orientation.
470
+ * @returns A action for tabs for the given key symbol.
432
471
  */
433
- static getAction(key) {
472
+ static getAction(key, isVertical = false) {
434
473
  if (key === "Home") return "home";
435
474
  if (key === "End") return "end";
436
- if (key in NAVIGATION_DIRECTION) return "navigating";
475
+ if (key in (isVertical ? VERTICAL_NAVIGATION_DIRECTION : NAVIGATION_DIRECTION)) return "navigating";
437
476
  if (key === "Enter" || key === " ") return "activating";
438
477
  return "none";
439
478
  }
@@ -450,10 +489,12 @@ __decorate([property({ attribute: "selecting-items-assistive-text" })], CDSTabs.
450
489
  __decorate([property({ attribute: "selected-item-assistive-text" })], CDSTabs.prototype, "selectedItemAssistiveText", void 0);
451
490
  __decorate([property({ attribute: "trigger-content" })], CDSTabs.prototype, "triggerContent", void 0);
452
491
  __decorate([property({ reflect: true })], CDSTabs.prototype, "type", void 0);
492
+ __decorate([property({ type: Boolean })], CDSTabs.prototype, "vertical", void 0);
453
493
  __decorate([property({
454
494
  type: Boolean,
455
495
  reflect: true
456
496
  })], CDSTabs.prototype, "dismissable", void 0);
497
+ __decorate([property({ reflect: true })], CDSTabs.prototype, "size", void 0);
457
498
  __decorate([property({
458
499
  attribute: "icon-size",
459
500
  reflect: true
@@ -468,6 +509,6 @@ __decorate([state()], CDSTabs.prototype, "_isIntersectionRightTrackerInContent",
468
509
  CDSTabs = __decorate([carbonElement(`cds-tabs`)], CDSTabs);
469
510
  var tabs_default = CDSTabs;
470
511
  //#endregion
471
- export { NAVIGATION_DIRECTION, TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE, tabs_default as default };
512
+ export { NAVIGATION_DIRECTION, TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_SIZE, TABS_TYPE, VERTICAL_NAVIGATION_DIRECTION, tabs_default as default };
472
513
 
473
514
  //# sourceMappingURL=tabs.js.map