@coinbase/cds-web 8.25.0 → 8.25.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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 8.25.1 (12/1/2025 PST)
12
+
13
+ #### 🐞 Fixes
14
+
15
+ - Improve keyboard navigation for Tabs components and upadate ARIA roles. [[#96](https://github.com/coinbase/cds/pull/96)]
16
+
11
17
  ## 8.25.0 (12/1/2025 PST)
12
18
 
13
19
  #### 🚀 Updates
@@ -1 +1 @@
1
- {"version":3,"file":"TabbedChips.d.ts","sourceRoot":"","sources":["../../../src/alpha/tabbed-chips/TabbedChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAChF,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE7F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIvD,OAAO,EAAU,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAyCpB,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,SAAS,CAAC,GAC9F,QAAQ,CAAC,CAAC,CAAC,GAAG;IACZ,SAAS,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;CACjE,CAAC;AAEJ,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAChE,aAAa,CAAC,CAAC,CAAC,EACd,cAAc,GACd,8BAA8B,GAC9B,MAAM,GACN,0BAA0B,GAC1B,kBAAkB,CACrB,GAAG;IACF,YAAY,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,4BAA4B,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC;IAC5E,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,oBAAoB,CAAC,CAAC,CAAC,GAC/E,WAAW,GACX,wBAAwB,GAAG;IACzB,UAAU,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IAC7B,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;OAGG;IACH,GAAG,CAAC,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,CAAC,EAAE;QACP;;WAEG;QACH,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAC3B;;WAEG;QACH,eAAe,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QACtC;;WAEG;QACH,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAC7B;;WAEG;QACH,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;KAC5B,CAAC;IACF,UAAU,CAAC,EAAE;QACX;;WAEG;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;QACd;;WAEG;QACH,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB;;WAEG;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAEJ,KAAK,aAAa,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC7C,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;CAAE,KACnE,KAAK,CAAC,YAAY,CAAC;AAuGxB,eAAO,MAAM,WAAW,EAA2B,aAAa,CAAC"}
1
+ {"version":3,"file":"TabbedChips.d.ts","sourceRoot":"","sources":["../../../src/alpha/tabbed-chips/TabbedChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AACnG,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE7F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIvD,OAAO,EAAU,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAmDpB,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,SAAS,CAAC,GAC9F,QAAQ,CAAC,CAAC,CAAC,GAAG;IACZ,SAAS,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;CACjE,CAAC;AAEJ,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAChE,aAAa,CAAC,CAAC,CAAC,EACd,cAAc,GACd,8BAA8B,GAC9B,MAAM,GACN,0BAA0B,GAC1B,kBAAkB,CACrB,GAAG;IACF,YAAY,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,4BAA4B,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC;IAC5E,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,oBAAoB,CAAC,CAAC,CAAC,GAC/E,WAAW,GACX,wBAAwB,GAAG;IACzB,UAAU,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IAC7B,+BAA+B,CAAC,EAAE,MAAM,CAAC;IACzC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;OAGG;IACH,GAAG,CAAC,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,CAAC,EAAE;QACP;;WAEG;QACH,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAC3B;;WAEG;QACH,eAAe,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QACtC;;WAEG;QACH,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAC7B;;WAEG;QACH,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;KAC5B,CAAC;IACF,UAAU,CAAC,EAAE;QACX;;WAEG;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;QACd;;WAEG;QACH,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB;;WAEG;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAEJ,KAAK,aAAa,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC7C,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;CAAE,KACnE,KAAK,CAAC,YAAY,CAAC;AAuGxB,eAAO,MAAM,WAAW,EAA2B,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabbedChips.d.ts","sourceRoot":"","sources":["../../src/chips/TabbedChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAMhF,OAAO,EAAE,KAAK,YAAY,EAAU,MAAM,WAAW,CAAC;AACtD,OAAO,EAAU,KAAK,sBAAsB,EAAQ,MAAM,SAAS,CAAC;AAiCpE,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,YAAY,GACxE,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAE7C,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAElF,KAAK,aAAa,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC7C,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;CAAE,KACnE,KAAK,CAAC,YAAY,CAAC;AA2FxB;;GAEG;AACH,eAAO,MAAM,WAAW,EAA2B,aAAa,CAAC"}
1
+ {"version":3,"file":"TabbedChips.d.ts","sourceRoot":"","sources":["../../src/chips/TabbedChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAMnG,OAAO,EAAE,KAAK,YAAY,EAAU,MAAM,WAAW,CAAC;AACtD,OAAO,EAAU,KAAK,sBAAsB,EAAQ,MAAM,SAAS,CAAC;AA2CpE,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,YAAY,GACxE,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAE7C,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAElF,KAAK,aAAa,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC7C,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;CAAE,KACnE,KAAK,CAAC,YAAY,CAAC;AA2FxB;;GAEG;AACH,eAAO,MAAM,WAAW,EAA2B,aAAa,CAAC"}
@@ -16,7 +16,16 @@ export type TabsActiveIndicatorProps = {
16
16
  activeTabRect: Rect;
17
17
  } & BoxProps<BoxDefaultElement> &
18
18
  MotionProps;
19
- export type TabComponent<T extends string = string> = React.FC<TabValue<T>>;
19
+ export type TabComponentProps<T extends string = string> = TabValue<T> & {
20
+ /** The tab index for the tab. Automatically set to manage focus behavior. */
21
+ tabIndex?: number;
22
+ /**
23
+ * The role for the tab.
24
+ * @default "tab"
25
+ */
26
+ role?: string;
27
+ };
28
+ export type TabComponent<T extends string = string> = React.FC<TabComponentProps<T>>;
20
29
  export type TabsActiveIndicatorComponent = React.FC<TabsActiveIndicatorProps>;
21
30
  export type TabsBaseProps<T extends string = string> = {
22
31
  /** The array of tabs data. Each tab may optionally define a custom Component to render. */
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAIjE,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,QAAQ,EAEd,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAe,KAAK,WAAW,EAAmB,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAO,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAU,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAkBvF,eAAO,MAAM,oBAAoB;;;;;;CAMF,CAAC;AAEhC,MAAM,MAAM,wBAAwB,GAAG;IACrC,aAAa,EAAE,IAAI,CAAC;CACrB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAC7B,WAAW,CAAC;AAEd,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5E,MAAM,MAAM,4BAA4B,GAAG,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC;AAE9E,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACrD,2FAA2F;IAC3F,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC,EAAE,CAAC;IACxD,gDAAgD;IAChD,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,iEAAiE;IACjE,4BAA4B,EAAE,4BAA4B,CAAC;IAC3D,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IACnC,2DAA2D;IAC3D,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CAClE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAEjC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,GACjE,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;AAE9D,KAAK,MAAM,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACtC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;CAAE,KAC5D,KAAK,CAAC,YAAY,CAAC;AA0FxB,eAAO,MAAM,IAAI,EAAoB,MAAM,CAAC;AAE5C,eAAO,MAAM,mBAAmB,GAAI,uCAIjC,wBAAwB,mDAgB1B,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAIjE,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,QAAQ,EAEd,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAe,KAAK,WAAW,EAAmB,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAO,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAU,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAkBvF,eAAO,MAAM,oBAAoB;;;;;;CAMF,CAAC;AAEhC,MAAM,MAAM,wBAAwB,GAAG;IACrC,aAAa,EAAE,IAAI,CAAC;CACrB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAC7B,WAAW,CAAC;AAEd,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IACvE,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAErF,MAAM,MAAM,4BAA4B,GAAG,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC;AAE9E,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACrD,2FAA2F;IAC3F,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC,EAAE,CAAC;IACxD,gDAAgD;IAChD,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,iEAAiE;IACjE,4BAA4B,EAAE,4BAA4B,CAAC;IAC3D,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;IACnC,2DAA2D;IAC3D,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CAClE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAEjC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,GACjE,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;AAE9D,KAAK,MAAM,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACtC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;CAAE,KAC5D,KAAK,CAAC,YAAY,CAAC;AAuJxB,eAAO,MAAM,IAAI,EAAoB,MAAM,CAAC;AAE5C,eAAO,MAAM,mBAAmB,GAAI,uCAIjC,wBAAwB,mDAgB1B,CAAC"}
@@ -7,7 +7,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
7
7
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
8
8
  function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
9
9
  function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
10
- import React, { forwardRef, memo, useCallback, useMemo, useState } from 'react';
10
+ import React, { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
11
11
  import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
12
12
  import { MediaChip } from '../../chips/MediaChip';
13
13
  import { cx } from '../../cx';
@@ -27,11 +27,20 @@ const DefaultTabComponent = _ref => {
27
27
  updateActiveTab
28
28
  } = useTabsContext();
29
29
  const isActive = useMemo(() => (activeTab === null || activeTab === void 0 ? void 0 : activeTab.id) === id, [activeTab, id]);
30
+ const chipRef = useRef(null);
30
31
  const handleClick = useCallback(event => {
31
32
  event.preventDefault();
32
33
  updateActiveTab(id);
33
34
  }, [id, updateActiveTab]);
35
+
36
+ // Keep focus on the newly active chip
37
+ useEffect(() => {
38
+ if (isActive && chipRef.current) {
39
+ chipRef.current.focus();
40
+ }
41
+ }, [isActive]);
34
42
  return /*#__PURE__*/_jsx(MediaChip, _objectSpread(_objectSpread({
43
+ ref: chipRef,
35
44
  "aria-selected": isActive,
36
45
  invertColorScheme: isActive,
37
46
  onClick: handleClick,
@@ -7,7 +7,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
7
7
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
8
8
  function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
9
9
  function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
10
- import React, { forwardRef, memo, useCallback, useMemo, useState } from 'react';
10
+ import React, { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
11
11
  import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
12
12
  import { useHorizontalScrollToTarget } from '../hooks/useHorizontalScrollToTarget';
13
13
  import { HStack } from '../layout';
@@ -26,8 +26,17 @@ const TabComponent = _ref => {
26
26
  updateActiveTab
27
27
  } = useTabsContext();
28
28
  const isActive = useMemo(() => (activeTab === null || activeTab === void 0 ? void 0 : activeTab.id) === id, [activeTab, id]);
29
+ const chipRef = useRef(null);
29
30
  const handleClick = useCallback(() => updateActiveTab(id), [id, updateActiveTab]);
31
+
32
+ // Keep focus on the newly active chip
33
+ useEffect(() => {
34
+ if (isActive && chipRef.current) {
35
+ chipRef.current.focus();
36
+ }
37
+ }, [isActive]);
30
38
  return /*#__PURE__*/_jsx(MediaChip, _objectSpread(_objectSpread({
39
+ ref: chipRef,
31
40
  "aria-selected": isActive,
32
41
  inverted: isActive,
33
42
  onClick: handleClick,
@@ -59,7 +59,7 @@ const SegmentedTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
59
59
  }), [activeColor, color, isActive]);
60
60
  return /*#__PURE__*/_jsx(Pressable, _objectSpread(_objectSpread({
61
61
  ref: ref,
62
- "aria-checked": isActive,
62
+ "aria-selected": isActive,
63
63
  className: cx(insetFocusRingCss, buttonCss, isDisabled && buttonDisabledCss, disabledProp && !allTabsDisabled && disabledCss, className),
64
64
  "data-testid": testID,
65
65
  disabled: isDisabled,
@@ -70,7 +70,7 @@ const SegmentedTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
70
70
  id: id,
71
71
  lineHeight: lineHeight,
72
72
  onClick: handlePress,
73
- role: "radio",
73
+ role: "tab",
74
74
  textAlign: textAlign,
75
75
  textTransform: textTransform,
76
76
  type: "button"
@@ -27,7 +27,7 @@ const SegmentedTabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref,
27
27
  activeBackground: activeBackground,
28
28
  background: background,
29
29
  borderRadius: borderRadius,
30
- role: "radiogroup"
30
+ role: "tablist"
31
31
  }, props));
32
32
  }));
33
33
  SegmentedTabsComponent.displayName = 'SegmentedTabs';
package/esm/tabs/Tabs.js CHANGED
@@ -77,6 +77,43 @@ const TabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) =>
77
77
  height: activeTabRef.offsetHeight
78
78
  };
79
79
  }, [activeTab, refMap, tabsContainerRect.width]);
80
+ const handleTabsContainerKeyDown = useCallback(event => {
81
+ const keyEventsToHandle = ['ArrowRight', 'ArrowLeft', 'Home', 'End'];
82
+ if (!keyEventsToHandle.includes(event.key)) return;
83
+ const focusedElement = document.activeElement;
84
+ if (!focusedElement) return;
85
+
86
+ // Find the focused tab's index
87
+ let focusedTabId = null;
88
+ for (const tab of tabs) {
89
+ const tabRef = refMap.getRef(tab.id);
90
+ if (tabRef && tabRef.contains(focusedElement)) {
91
+ focusedTabId = tab.id;
92
+ break;
93
+ }
94
+ }
95
+ if (!focusedTabId) return;
96
+ const focusedTabIndex = tabs.findIndex(tab => tab.id === focusedTabId);
97
+ if (focusedTabIndex === -1) return;
98
+ event.preventDefault();
99
+
100
+ // For ArrowLeft and End key events, we need to iterate backwards so a for loop is used
101
+ let targetTab;
102
+ if (event.key === 'ArrowRight') {
103
+ targetTab = tabs.slice(focusedTabIndex + 1).find(tab => !tab.disabled);
104
+ } else if (event.key === 'ArrowLeft') {
105
+ targetTab = tabs.slice(0, focusedTabIndex).reverse().find(tab => !tab.disabled);
106
+ } else if (event.key === 'Home') {
107
+ targetTab = tabs.find(tab => !tab.disabled);
108
+ } else if (event.key === 'End') {
109
+ targetTab = tabs.slice(0).reverse().find(tab => !tab.disabled);
110
+ }
111
+ if (targetTab) {
112
+ const targetRef = refMap.getRef(targetTab.id);
113
+ const focusableElement = targetRef === null || targetRef === void 0 ? void 0 : targetRef.querySelector('[data-rendered-tab], [tabindex]:not([tabindex="-1"])');
114
+ focusableElement === null || focusableElement === void 0 || focusableElement.focus();
115
+ }
116
+ }, [tabs, refMap]);
80
117
  const containerStyle = useMemo(() => _objectSpread({
81
118
  opacity: disabled ? accessibleOpacityDisabled : 1
82
119
  }, style), [disabled, style]);
@@ -88,6 +125,7 @@ const TabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) =>
88
125
  }, [activeTab, onActiveTabElementChange, refMap]);
89
126
  return /*#__PURE__*/_jsx(HStack, _objectSpread(_objectSpread({
90
127
  ref: mergedContainerRefs,
128
+ onKeyDown: handleTabsContainerKeyDown,
91
129
  position: position,
92
130
  role: role,
93
131
  style: containerStyle,
@@ -110,8 +148,11 @@ const TabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) =>
110
148
  id: id,
111
149
  registerRef: registerRef,
112
150
  children: /*#__PURE__*/_jsx(RenderedTab, _objectSpread({
151
+ "data-rendered-tab": true,
113
152
  disabled: tabDisabled,
114
- id: id
153
+ id: id,
154
+ role: "tab",
155
+ tabIndex: (activeTab === null || activeTab === void 0 ? void 0 : activeTab.id) === id || !activeTab ? 0 : -1
115
156
  }, props))
116
157
  }, id);
117
158
  })]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cds-web",
3
- "version": "8.25.0",
3
+ "version": "8.25.1",
4
4
  "description": "Coinbase Design System - Web",
5
5
  "repository": {
6
6
  "type": "git",
@@ -147,7 +147,7 @@
147
147
  "react-dom": "^18.3.1"
148
148
  },
149
149
  "dependencies": {
150
- "@coinbase/cds-common": "^8.25.0",
150
+ "@coinbase/cds-common": "^8.25.1",
151
151
  "@coinbase/cds-icons": "^5.7.0",
152
152
  "@coinbase/cds-illustrations": "^4.28.0",
153
153
  "@coinbase/cds-lottie-files": "^3.3.3",