@coinbase/cds-web 9.0.0-rc.2 → 9.0.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 (81) hide show
  1. package/CHANGELOG.md +102 -4
  2. package/dts/buttons/Button.d.ts.map +1 -1
  3. package/dts/buttons/IconButton.d.ts +15 -1
  4. package/dts/buttons/IconButton.d.ts.map +1 -1
  5. package/dts/chips/TabbedChips.d.ts.map +1 -1
  6. package/dts/collapsible/Collapsible.d.ts.map +1 -1
  7. package/dts/controls/CheckboxGroup.d.ts +4 -0
  8. package/dts/controls/CheckboxGroup.d.ts.map +1 -1
  9. package/dts/controls/InputLabel.d.ts.map +1 -1
  10. package/dts/controls/NativeInput.d.ts +6 -0
  11. package/dts/controls/NativeInput.d.ts.map +1 -1
  12. package/dts/controls/SearchInput.d.ts +2 -0
  13. package/dts/controls/SearchInput.d.ts.map +1 -1
  14. package/dts/controls/TextInput.d.ts +2 -2
  15. package/dts/controls/TextInput.d.ts.map +1 -1
  16. package/dts/core/createThemeCssVars.d.ts.map +1 -1
  17. package/dts/core/theme.d.ts +15 -0
  18. package/dts/core/theme.d.ts.map +1 -1
  19. package/dts/illustrations/HeroSquare.d.ts.map +1 -1
  20. package/dts/illustrations/Pictogram.d.ts.map +1 -1
  21. package/dts/illustrations/SpotIcon.d.ts.map +1 -1
  22. package/dts/illustrations/SpotRectangle.d.ts.map +1 -1
  23. package/dts/illustrations/SpotSquare.d.ts.map +1 -1
  24. package/dts/illustrations/createIllustration.d.ts +19 -3
  25. package/dts/illustrations/createIllustration.d.ts.map +1 -1
  26. package/dts/navigation/NavigationBar.d.ts.map +1 -1
  27. package/dts/page/PageFooter.d.ts +4 -0
  28. package/dts/page/PageFooter.d.ts.map +1 -1
  29. package/dts/system/ThemeProvider.d.ts.map +1 -1
  30. package/dts/tabs/DefaultTab.d.ts +11 -2
  31. package/dts/tabs/DefaultTab.d.ts.map +1 -1
  32. package/dts/tabs/SegmentedTab.d.ts +13 -12
  33. package/dts/tabs/SegmentedTab.d.ts.map +1 -1
  34. package/dts/tabs/Tabs.d.ts +9 -3
  35. package/dts/tabs/Tabs.d.ts.map +1 -1
  36. package/dts/tag/Tag.d.ts +3 -2
  37. package/dts/tag/Tag.d.ts.map +1 -1
  38. package/dts/themes/coinbaseDenseTheme.d.ts +34 -2
  39. package/dts/themes/coinbaseDenseTheme.d.ts.map +1 -1
  40. package/dts/themes/coinbaseHighContrastTheme.d.ts +32 -0
  41. package/dts/themes/coinbaseHighContrastTheme.d.ts.map +1 -1
  42. package/dts/themes/coinbaseTheme.d.ts +34 -2
  43. package/dts/themes/coinbaseTheme.d.ts.map +1 -1
  44. package/dts/themes/defaultHighContrastTheme.d.ts +32 -0
  45. package/dts/themes/defaultHighContrastTheme.d.ts.map +1 -1
  46. package/dts/themes/defaultTheme.d.ts +34 -2
  47. package/dts/themes/defaultTheme.d.ts.map +1 -1
  48. package/dts/visualizations/chart/PeriodSelector.d.ts.map +1 -1
  49. package/esm/buttons/Button.css +1 -1
  50. package/esm/buttons/IconButton.js +27 -6
  51. package/esm/chips/TabbedChips.js +4 -2
  52. package/esm/collapsible/Collapsible.js +11 -15
  53. package/esm/controls/CheckboxGroup.js +5 -0
  54. package/esm/controls/InputLabel.js +4 -3
  55. package/esm/controls/InputStack.js +1 -3
  56. package/esm/controls/NativeInput.js +5 -3
  57. package/esm/controls/TextInput.js +10 -5
  58. package/esm/core/createThemeCssVars.js +23 -0
  59. package/esm/core/theme.js +3 -0
  60. package/esm/illustrations/HeroSquare.js +2 -1
  61. package/esm/illustrations/Pictogram.js +2 -1
  62. package/esm/illustrations/SpotIcon.js +2 -1
  63. package/esm/illustrations/SpotRectangle.js +2 -1
  64. package/esm/illustrations/SpotSquare.js +2 -1
  65. package/esm/illustrations/createIllustration.css +1 -0
  66. package/esm/illustrations/createIllustration.js +68 -20
  67. package/esm/navigation/NavigationBar.js +14 -10
  68. package/esm/overlays/tray/Tray.js +1 -1
  69. package/esm/page/PageFooter.js +20 -4
  70. package/esm/page/__figma__/PageFooter.figma.js +50 -6
  71. package/esm/system/ThemeProvider.js +3 -1
  72. package/esm/tabs/DefaultTab.css +1 -2
  73. package/esm/tabs/DefaultTab.js +6 -5
  74. package/esm/tabs/Tabs.js +8 -2
  75. package/esm/tag/Tag.js +13 -3
  76. package/esm/themes/coinbaseHighContrastTheme.js +32 -0
  77. package/esm/themes/coinbaseTheme.js +34 -2
  78. package/esm/themes/defaultHighContrastTheme.js +32 -0
  79. package/esm/themes/defaultTheme.js +34 -2
  80. package/esm/visualizations/chart/PeriodSelector.js +4 -3
  81. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- const _excluded = ["label", "accessibilityLabel", "helperText", "variant", "testID", "testIDMap", "start", "end", "width", "disabled", "align", "font", "compact", "suffix", "onFocus", "onBlur", "borderRadius", "height", "inputNode", "bordered", "focusedBorderWidth", "enableColorSurge", "helperTextErrorIconAccessibilityLabel", "labelVariant", "labelNode", "inputBackground"];
1
+ const _excluded = ["label", "labelFont", "labelColor", "accessibilityLabel", "helperText", "variant", "testID", "testIDMap", "start", "end", "width", "disabled", "align", "font", "compact", "suffix", "onFocus", "onBlur", "borderRadius", "height", "inputNode", "bordered", "focusedBorderWidth", "enableColorSurge", "helperTextErrorIconAccessibilityLabel", "labelVariant", "labelNode", "inputBackground"];
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
@@ -7,6 +7,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7
7
  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; }
8
8
  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; }
9
9
  import React, { cloneElement, forwardRef, memo, useCallback, useMemo, useRef, useState } from 'react';
10
+ import { useInputVariant } from '@coinbase/cds-common/hooks/useInputVariant';
10
11
  import { usePrefixedId } from '@coinbase/cds-common/hooks/usePrefixedId';
11
12
  import { mergeReactElementRef, mergeRefs } from '@coinbase/cds-common/utils/mergeRefs';
12
13
  import { cx } from '../cx';
@@ -32,9 +33,6 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
32
33
  const nativeInputContainerCss = "nativeInputContainerCss-nvfk24";
33
34
  const insideLabelCss = "insideLabelCss-i1dqgbcz";
34
35
  const insideLabelCssStartCss = "insideLabelCssStartCss-i1scwjk";
35
- const useInputVariant = (focused, variant) => {
36
- return useMemo(() => focused && variant !== 'positive' && variant !== 'negative' ? 'primary' : variant, [focused, variant]);
37
- };
38
36
  const variantColorMap = {
39
37
  primary: 'fgPrimary',
40
38
  positive: 'fgPositive',
@@ -48,6 +46,8 @@ export const TextInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function Text
48
46
  const mergedProps = useComponentConfig('TextInput', _props);
49
47
  const {
50
48
  label,
49
+ labelFont = 'label1',
50
+ labelColor = 'fg',
51
51
  accessibilityLabel,
52
52
  helperText = '',
53
53
  variant = 'foregroundMuted',
@@ -139,6 +139,7 @@ export const TextInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function Text
139
139
  accessibilityLabel: accessibilityLabel !== null && accessibilityLabel !== void 0 ? accessibilityLabel : label,
140
140
  align: align,
141
141
  "aria-invalid": variant === 'negative',
142
+ caretColor: variantColorMap[focusedVariant],
142
143
  compact: compact,
143
144
  containerSpacing: nativeInputContainerCss,
144
145
  "data-compact": compact,
@@ -151,7 +152,7 @@ export const TextInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function Text
151
152
  onFocus: handleOnFocus,
152
153
  testID: testID
153
154
  }, nativeInputRestProps));
154
- }, [inputNode, refs, shouldSetHelperTextId, helperTextId, accessibilityLabel, label, hasLabel, align, font, variant, compact, labelVariant, start, disabled, shouldSetLabelId, labelId, handleOnBlur, handleOnFocus, testID, nativeInputRestProps]);
155
+ }, [inputNode, refs, shouldSetHelperTextId, helperTextId, accessibilityLabel, label, align, variant, focusedVariant, compact, hasLabel, labelVariant, start, disabled, font, shouldSetLabelId, labelId, handleOnBlur, handleOnFocus, testID, nativeInputRestProps]);
155
156
  return /*#__PURE__*/_jsx(TextInputFocusVariantContext.Provider, {
156
157
  value: focused ? focusedVariant : undefined,
157
158
  children: /*#__PURE__*/_jsx(InputStack, {
@@ -202,6 +203,8 @@ export const TextInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function Text
202
203
  }) : labelNode : !!label && /*#__PURE__*/_jsx(InputLabel, {
203
204
  background: labelVariant === 'inside' ? readOnlyInputBackground : undefined,
204
205
  className: cx(labelVariant === 'inside' && insideLabelCss, labelVariant === 'inside' && !!start && insideLabelCssStartCss),
206
+ color: labelColor,
207
+ font: labelFont,
205
208
  htmlFor: shouldSetLabelId ? labelId : undefined,
206
209
  testID: (_testIDMap$label = testIDMap === null || testIDMap === void 0 ? void 0 : testIDMap.label) !== null && _testIDMap$label !== void 0 ? _testIDMap$label : '',
207
210
  children: label
@@ -216,6 +219,8 @@ export const TextInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function Text
216
219
  paddingStart: compact && hasLabel ? 2 : undefined,
217
220
  testID: (_testIDMap$start = testIDMap === null || testIDMap === void 0 ? void 0 : testIDMap.start) !== null && _testIDMap$start !== void 0 ? _testIDMap$start : '',
218
221
  children: [compact && (labelNode ? labelNode : !!label && /*#__PURE__*/_jsx(InputLabel, {
222
+ color: labelColor,
223
+ font: labelFont,
219
224
  htmlFor: shouldSetLabelId ? labelId : undefined,
220
225
  children: label
221
226
  })), !!start && /*#__PURE__*/_jsx(_Fragment, {
@@ -1,6 +1,10 @@
1
1
  import { styleVarPrefixes } from './theme';
2
2
  const periodsRegex = /\./g;
3
3
 
4
+ // Converts a camelCase illustration theme key to the kebab-case CSS var suffix that
5
+ // the generated themeable SVGs expect: accent1 → accent-1, gray2 → gray-2.
6
+ const toIllustrationVarSuffix = key => key.replace(/([a-z])(\d+)$/i, '$1-$2');
7
+
4
8
  /** Takes a theme object and formats its keys as CSS variables to be used in inline styles. */
5
9
  export const createThemeCssVars = theme => {
6
10
  const themeCss = {};
@@ -14,6 +18,25 @@ export const createThemeCssVars = theme => {
14
18
  themeCss['--activeColorScheme'] = theme.activeColorScheme;
15
19
  continue;
16
20
  }
21
+
22
+ // lightIllustrationColor/darkIllustrationColor are resolved into theme.illustrationColor by ThemeProvider.
23
+ // Skip them here to avoid emitting --lightIllustrationColor-* / --darkIllustrationColor-* vars.
24
+ if (key === 'lightIllustrationColor' || key === 'darkIllustrationColor') {
25
+ continue;
26
+ }
27
+
28
+ // Illustration colors use a kebab-converted key format to match the var(--illustration-accent-1)
29
+ // tokens in the generated themeable SVGs, so they need special handling rather than the default
30
+ // period-to-underscore substitution.
31
+ if (key === 'illustrationColor') {
32
+ for (const varName of Object.keys(themeVars)) {
33
+ const value = themeVars[varName];
34
+ if (value !== undefined) {
35
+ themeCss["--illustration-".concat(toIllustrationVarSuffix(varName))] = value;
36
+ }
37
+ }
38
+ continue;
39
+ }
17
40
  const prefix = styleVarPrefixes[key];
18
41
  const cssVarPrefix = prefix ? "--".concat(prefix, "-") : '--';
19
42
  const varNames = Object.keys(themeVars);
package/esm/core/theme.js CHANGED
@@ -4,6 +4,9 @@ export const styleVarPrefixes = {
4
4
  darkSpectrum: 'dark',
5
5
  lightColor: 'lightColor',
6
6
  darkColor: 'darkColor',
7
+ lightIllustrationColor: 'lightIllustrationColor',
8
+ darkIllustrationColor: 'darkIllustrationColor',
9
+ illustrationColor: 'illustration',
7
10
  spectrum: '',
8
11
  color: 'color',
9
12
  space: 'space',
@@ -1,3 +1,4 @@
1
+ import heroSquareSvgEsmMap from '@coinbase/cds-illustrations/__generated__/heroSquare/data/svgEsmMap';
1
2
  import heroSquareVersionMap from '@coinbase/cds-illustrations/__generated__/heroSquare/data/versionMap';
2
3
  import { createIllustration } from './createIllustration';
3
- export const HeroSquare = createIllustration('heroSquare', heroSquareVersionMap);
4
+ export const HeroSquare = createIllustration('heroSquare', heroSquareVersionMap, heroSquareSvgEsmMap);
@@ -1,3 +1,4 @@
1
+ import pictogramSvgEsmMap from '@coinbase/cds-illustrations/__generated__/pictogram/data/svgEsmMap';
1
2
  import pictogramVersionMap from '@coinbase/cds-illustrations/__generated__/pictogram/data/versionMap';
2
3
  import { createIllustration } from './createIllustration';
3
- export const Pictogram = createIllustration('pictogram', pictogramVersionMap);
4
+ export const Pictogram = createIllustration('pictogram', pictogramVersionMap, pictogramSvgEsmMap);
@@ -1,3 +1,4 @@
1
+ import spotIconSvgEsmMap from '@coinbase/cds-illustrations/__generated__/spotIcon/data/svgEsmMap';
1
2
  import spotIconVersionMap from '@coinbase/cds-illustrations/__generated__/spotIcon/data/versionMap';
2
3
  import { createIllustration } from './createIllustration';
3
- export const SpotIcon = createIllustration('spotIcon', spotIconVersionMap);
4
+ export const SpotIcon = createIllustration('spotIcon', spotIconVersionMap, spotIconSvgEsmMap);
@@ -1,3 +1,4 @@
1
+ import spotRectangleSvgEsmMap from '@coinbase/cds-illustrations/__generated__/spotRectangle/data/svgEsmMap';
1
2
  import spotRectangleVersionMap from '@coinbase/cds-illustrations/__generated__/spotRectangle/data/versionMap';
2
3
  import { createIllustration } from './createIllustration';
3
- export const SpotRectangle = createIllustration('spotRectangle', spotRectangleVersionMap);
4
+ export const SpotRectangle = createIllustration('spotRectangle', spotRectangleVersionMap, spotRectangleSvgEsmMap);
@@ -1,3 +1,4 @@
1
+ import spotSquareSvgEsmMap from '@coinbase/cds-illustrations/__generated__/spotSquare/data/svgEsmMap';
1
2
  import spotSquareVersionMap from '@coinbase/cds-illustrations/__generated__/spotSquare/data/versionMap';
2
3
  import { createIllustration } from './createIllustration';
3
- export const SpotSquare = createIllustration('spotSquare', spotSquareVersionMap);
4
+ export const SpotSquare = createIllustration('spotSquare', spotSquareVersionMap, spotSquareSvgEsmMap);
@@ -0,0 +1 @@
1
+ @layer cds{.inlineSvgCss-ip1tc09{display:inline-block;-webkit-flex:none;-ms-flex:none;flex:none;}}
@@ -1,11 +1,19 @@
1
- import React, { memo, useMemo } from 'react';
1
+ import React, { memo, useEffect, useMemo, useState } from 'react';
2
2
  import { convertDimensionToSize } from '@coinbase/cds-common/utils/convertDimensionToSize';
3
3
  import { convertSizeWithMultiplier } from '@coinbase/cds-common/utils/convertSizeWithMultiplier';
4
4
  import { getDefaultSizeObjectForIllustration } from '@coinbase/cds-common/utils/getDefaultSizeObjectForIllustration';
5
5
  import { isDevelopment } from '@coinbase/cds-utils';
6
6
  import { useTheme } from '../hooks/useTheme';
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
- export function createIllustration(variant, config) {
8
+ const inlineSvgCss = "inlineSvgCss-ip1tc09";
9
+ const STATIC_ASSETS_CDN = 'https://static-assets.coinbase.com/ui-infra/illustration/v1';
10
+
11
+ /**
12
+ * ESM-compatible lazy loader map. Each entry uses a relative dynamic import so
13
+ * any bundler (Vite, webpack, esbuild) can code-split without CORS or bare-specifier issues.
14
+ */
15
+
16
+ export function createIllustration(variant, versionMap, svgEsmConfig) {
9
17
  const defaultSize = getDefaultSizeObjectForIllustration(variant);
10
18
  const Illustration = /*#__PURE__*/memo(function Illustration(_ref) {
11
19
  let {
@@ -14,40 +22,80 @@ export function createIllustration(variant, config) {
14
22
  scaleMultiplier,
15
23
  testID,
16
24
  alt = '',
17
- fallback = null
25
+ fallback,
26
+ applyTheme
18
27
  } = _ref;
19
28
  const {
20
- activeColorScheme
29
+ activeColorScheme,
30
+ illustrationColor
21
31
  } = useTheme();
22
- const version = config[name];
23
- const src = "https://static-assets.coinbase.com/ui-infra/illustration/v1/".concat(variant, "/svg/").concat(activeColorScheme, "/").concat(name, "-").concat(version, ".svg");
32
+ const version = versionMap[name];
33
+
34
+ // null = not yet loaded (or load failed), string = loaded inline SVG
35
+ const [svgMarkup, setSvgMarkup] = useState(null);
36
+ useEffect(() => {
37
+ var _svgEsmConfig$name;
38
+ let cancelled = false;
39
+ const themeableLoader = svgEsmConfig === null || svgEsmConfig === void 0 || (_svgEsmConfig$name = svgEsmConfig[name]) === null || _svgEsmConfig$name === void 0 ? void 0 : _svgEsmConfig$name.themeable;
40
+ if (applyTheme && themeableLoader) {
41
+ themeableLoader().then(svg => {
42
+ if (!cancelled) setSvgMarkup(svg);
43
+ }).catch(err => {
44
+ if (isDevelopment()) {
45
+ console.error("Failed to load themeable illustration ".concat(name, ":"), err);
46
+ }
47
+ // Clear stale markup on failure so we don't display the wrong illustration.
48
+ if (!cancelled) setSvgMarkup(null);
49
+ });
50
+ }
51
+ return () => {
52
+ cancelled = true;
53
+ };
54
+ // The SVG source is the same regardless of the active palette — illustrationColor
55
+ // only affects the CSS variables emitted by ThemeProvider, not the file to load.
56
+ }, [name, version, applyTheme]);
24
57
  const {
25
58
  width,
26
59
  height
27
60
  } = useMemo(() => {
28
61
  let size = defaultSize;
29
- if (dimension) {
30
- size = convertDimensionToSize(dimension);
31
- }
32
- if (scaleMultiplier) {
33
- size = convertSizeWithMultiplier(size, scaleMultiplier);
34
- }
62
+ if (dimension) size = convertDimensionToSize(dimension);
63
+ if (scaleMultiplier) size = convertSizeWithMultiplier(size, scaleMultiplier);
35
64
  return size;
36
65
  }, [dimension, scaleMultiplier]);
37
- if (version === undefined) {
38
- if (isDevelopment()) {
39
- console.error("Unable to find illustration with name: ".concat(name));
66
+ if (applyTheme && illustrationColor) {
67
+ if (svgMarkup) {
68
+ // The SVG retains its var(--illustration-*) tokens. ThemeProvider emits the resolved
69
+ // --illustration-* CSS vars so the browser applies them through normal cascade.
70
+ return /*#__PURE__*/_jsx("div", {
71
+ dangerouslySetInnerHTML: {
72
+ __html: svgMarkup
73
+ },
74
+ "aria-label": alt || undefined,
75
+ className: inlineSvgCss,
76
+ "data-testid": testID,
77
+ role: alt ? 'img' : 'presentation',
78
+ style: {
79
+ width,
80
+ height
81
+ }
82
+ });
40
83
  }
41
- return fallback;
84
+
85
+ // Still loading or failed — return fallback (defaults to null).
86
+ return fallback !== null && fallback !== void 0 ? fallback : null;
42
87
  }
43
- return /*#__PURE__*/_jsx("img", {
88
+
89
+ // Default CDN path — used when applyTheme is false.
90
+ return version !== undefined ? /*#__PURE__*/_jsx("img", {
44
91
  alt: alt,
45
92
  "data-testid": testID,
46
93
  height: height,
47
- src: src,
94
+ src: "".concat(STATIC_ASSETS_CDN, "/").concat(variant, "/svg/").concat(activeColorScheme, "/").concat(name, "-").concat(version, ".svg"),
48
95
  width: width
49
- });
96
+ }) : fallback !== null && fallback !== void 0 ? fallback : null;
50
97
  });
51
98
  Illustration.displayName = 'Illustration';
52
99
  return Illustration;
53
- }
100
+ }
101
+ import "./createIllustration.css";
@@ -77,10 +77,6 @@ export const NavigationBar = /*#__PURE__*/memo(_props => {
77
77
  }, props), {}, {
78
78
  children: [/*#__PURE__*/_jsxs(HStack, {
79
79
  alignItems: "center",
80
- gap: columnGap !== null && columnGap !== void 0 ? columnGap : {
81
- base: 2,
82
- phone: 1
83
- },
84
80
  overflow: "auto",
85
81
  children: [/*#__PURE__*/_jsx(Collapsible, {
86
82
  collapsed: !start,
@@ -96,14 +92,22 @@ export const NavigationBar = /*#__PURE__*/memo(_props => {
96
92
  style: styles === null || styles === void 0 ? void 0 : styles.start,
97
93
  children: startNode
98
94
  })
99
- }), /*#__PURE__*/_jsx(HStack, {
95
+ }), /*#__PURE__*/_jsxs(HStack, {
100
96
  alignItems: "center",
101
- className: cx(navigationBarClassNames.content, classNames === null || classNames === void 0 ? void 0 : classNames.content),
102
97
  flexGrow: 1,
103
- gap: 1,
104
- style: styles === null || styles === void 0 ? void 0 : styles.content,
105
- children: children
106
- }), end]
98
+ gap: columnGap !== null && columnGap !== void 0 ? columnGap : {
99
+ base: 2,
100
+ phone: 1
101
+ },
102
+ children: [/*#__PURE__*/_jsx(HStack, {
103
+ alignItems: "center",
104
+ className: cx(navigationBarClassNames.content, classNames === null || classNames === void 0 ? void 0 : classNames.content),
105
+ flexGrow: 1,
106
+ gap: 1,
107
+ style: styles === null || styles === void 0 ? void 0 : styles.content,
108
+ children: children
109
+ }), end]
110
+ })]
107
111
  }), bottom]
108
112
  }));
109
113
  });
@@ -285,7 +285,7 @@ export const Tray = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function Tray(_pro
285
285
  children: /*#__PURE__*/_jsxs(Box, {
286
286
  ref: trayRef,
287
287
  className: cx(trayClassNames.root, classNames === null || classNames === void 0 ? void 0 : classNames.root),
288
- height: "100vh",
288
+ height: "100dvh",
289
289
  pin: "all",
290
290
  position: "fixed",
291
291
  style: styles === null || styles === void 0 ? void 0 : styles.root,
@@ -1,4 +1,4 @@
1
- const _excluded = ["action", "height", "justifyContent", "paddingX", "paddingY", "role"];
1
+ const _excluded = ["action", "legalText", "height", "justifyContent", "paddingX", "paddingY", "role"];
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
@@ -10,7 +10,9 @@ import React, { forwardRef, memo } from 'react';
10
10
  import { pageFooterHeight } from '@coinbase/cds-common/tokens/page';
11
11
  import { useComponentConfig } from '../hooks/useComponentConfig';
12
12
  import { Box } from '../layout/Box';
13
- import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { VStack } from '../layout/VStack';
14
+ import { Text } from '../typography/Text';
15
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
16
  export const pageFooterPaddingX = {
15
17
  phone: 3,
16
18
  tablet: 4,
@@ -21,11 +23,17 @@ export const pageFooterJustifyContent = {
21
23
  tablet: 'flex-end',
22
24
  desktop: 'flex-end'
23
25
  };
26
+ const legalTextAlignItems = {
27
+ phone: 'center',
28
+ tablet: 'flex-end',
29
+ desktop: 'flex-end'
30
+ };
24
31
  export const PageFooter = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, ref) => {
25
32
  const mergedProps = useComponentConfig('PageFooter', _props);
26
33
  const {
27
34
  action,
28
- height = pageFooterHeight,
35
+ legalText,
36
+ height = legalText ? undefined : pageFooterHeight,
29
37
  justifyContent = pageFooterJustifyContent,
30
38
  paddingX = pageFooterPaddingX,
31
39
  paddingY = 1.5,
@@ -40,6 +48,14 @@ export const PageFooter = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, ref
40
48
  paddingY: paddingY,
41
49
  role: role
42
50
  }, props), {}, {
43
- children: action
51
+ children: legalText ? /*#__PURE__*/_jsxs(VStack, {
52
+ alignItems: legalTextAlignItems,
53
+ gap: 2,
54
+ children: [action, /*#__PURE__*/_jsx(Text, {
55
+ color: "fgMuted",
56
+ font: "legal",
57
+ children: legalText
58
+ })]
59
+ }) : action
44
60
  }));
45
61
  }));
@@ -1,17 +1,61 @@
1
+ import React from 'react';
1
2
  import { figma } from '@figma/code-connect';
3
+ import { Button } from '../../buttons/Button';
4
+ import { ButtonGroup } from '../../buttons/ButtonGroup';
2
5
  import { PageFooter } from '../PageFooter';
3
- import { jsx as _jsx } from "react/jsx-runtime";
4
- figma.connect(PageFooter, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=17685%3A3266', {
5
- imports: ["import { PageFooter } from '@coinbase/cds-web/page/PageFooter'"],
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ const url = 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=17685%3A3266';
8
+ figma.connect(PageFooter, url, {
9
+ imports: ["import { PageFooter } from '@coinbase/cds-web/page/PageFooter'", "import { Button } from '@coinbase/cds-web/buttons/Button'"],
10
+ variant: {
11
+ '# of actions': '1'
12
+ },
6
13
  props: {
7
- action: figma.children('ButtonGroup')
14
+ action: figma.children('Button'),
15
+ legalText: figma.boolean('show legal text', {
16
+ true: 'Your legal text here.',
17
+ false: undefined
18
+ })
8
19
  },
9
20
  example: _ref => {
10
21
  let {
11
- action
22
+ legalText
12
23
  } = _ref;
13
24
  return /*#__PURE__*/_jsx(PageFooter, {
14
- action: action
25
+ action: /*#__PURE__*/_jsx(Button, {
26
+ variant: "primary",
27
+ children: "Next"
28
+ }),
29
+ legalText: legalText
30
+ });
31
+ }
32
+ });
33
+ figma.connect(PageFooter, url, {
34
+ imports: ["import { PageFooter } from '@coinbase/cds-web/page/PageFooter'", "import { Button } from '@coinbase/cds-web/buttons/Button'", "import { ButtonGroup } from '@coinbase/cds-web/buttons/ButtonGroup'"],
35
+ variant: {
36
+ '# of actions': '2'
37
+ },
38
+ props: {
39
+ legalText: figma.boolean('show legal text', {
40
+ true: 'Your legal text here.',
41
+ false: undefined
42
+ })
43
+ },
44
+ example: _ref2 => {
45
+ let {
46
+ legalText
47
+ } = _ref2;
48
+ return /*#__PURE__*/_jsx(PageFooter, {
49
+ action: /*#__PURE__*/_jsxs(ButtonGroup, {
50
+ children: [/*#__PURE__*/_jsx(Button, {
51
+ variant: "secondary",
52
+ children: "Back"
53
+ }), /*#__PURE__*/_jsx(Button, {
54
+ variant: "primary",
55
+ children: "Next"
56
+ })]
57
+ }),
58
+ legalText: legalText
15
59
  });
16
60
  }
17
61
  });
@@ -73,6 +73,7 @@ export const ThemeProvider = /*#__PURE__*/memo(_ref2 => {
73
73
  const themeApi = useMemo(() => {
74
74
  const activeSpectrumKey = activeColorScheme === 'dark' ? 'darkSpectrum' : 'lightSpectrum';
75
75
  const activeColorKey = activeColorScheme === 'dark' ? 'darkColor' : 'lightColor';
76
+ const activeIllustrationKey = activeColorScheme === 'dark' ? 'darkIllustrationColor' : 'lightIllustrationColor';
76
77
  const inverseSpectrumKey = activeColorScheme === 'dark' ? 'lightSpectrum' : 'darkSpectrum';
77
78
  const inverseColorKey = activeColorScheme === 'dark' ? 'lightColor' : 'darkColor';
78
79
  if (!theme[activeColorKey]) throw Error("ThemeProvider activeColorScheme is ".concat(activeColorScheme, " but no ").concat(activeColorScheme, " colors are defined for the theme. See the docs https://cds.coinbase.com/getting-started/theming"));
@@ -82,7 +83,8 @@ export const ThemeProvider = /*#__PURE__*/memo(_ref2 => {
82
83
  return _objectSpread(_objectSpread({}, theme), {}, {
83
84
  activeColorScheme: activeColorScheme,
84
85
  spectrum: theme[activeSpectrumKey],
85
- color: theme[activeColorKey]
86
+ color: theme[activeColorKey],
87
+ illustrationColor: theme[activeIllustrationKey]
86
88
  });
87
89
  }, [theme, activeColorScheme]);
88
90
  const parentTheme = useContext(ThemeContext);
@@ -1,3 +1,2 @@
1
1
  @layer cds{.pressableCss-p1gyavxu{margin:0;padding:0;white-space:nowrap;}
2
- .insetFocusRingCss-i14sq9yf{position:relative;}.insetFocusRingCss-i14sq9yf:focus{outline:none;}.insetFocusRingCss-i14sq9yf:focus-visible{outline-style:solid;outline-width:2px;outline-color:var(--color-bgPrimary);outline-offset:-3px;border-radius:4px;}
3
- .labelPaddingCss-lu2xm1d{padding-top:var(--space-2);padding-bottom:calc(var(--space-2) - 2px);}}
2
+ .insetFocusRingCss-i14sq9yf{position:relative;}.insetFocusRingCss-i14sq9yf:focus{outline:none;}.insetFocusRingCss-i14sq9yf:focus-visible{outline-style:solid;outline-width:2px;outline-color:var(--color-bgPrimary);outline-offset:-3px;border-radius:4px;}}
@@ -1,4 +1,4 @@
1
- const _excluded = ["id", "label", "disabled", "onClick", "count", "max", "accessibilityLabel", "className"];
1
+ const _excluded = ["id", "label", "disabled", "onClick", "count", "max", "accessibilityLabel", "className", "color", "activeColor"];
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
@@ -18,7 +18,6 @@ import { Text } from '../typography/Text';
18
18
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
19
  const pressableCss = "pressableCss-p1gyavxu";
20
20
  const insetFocusRingCss = "insetFocusRingCss-i14sq9yf";
21
- const labelPaddingCss = "labelPaddingCss-lu2xm1d";
22
21
  const DefaultTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
23
22
  let {
24
23
  id,
@@ -28,7 +27,9 @@ const DefaultTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref
28
27
  count,
29
28
  max,
30
29
  accessibilityLabel,
31
- className
30
+ className,
31
+ color = 'fg',
32
+ activeColor = 'fgPrimary'
32
33
  } = _ref,
33
34
  props = _objectWithoutProperties(_ref, _excluded);
34
35
  const {
@@ -59,10 +60,10 @@ const DefaultTabComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref
59
60
  gap: 0.5,
60
61
  children: [/*#__PURE__*/_jsx(Text, {
61
62
  as: "h2",
62
- className: labelPaddingCss,
63
- color: isActive ? 'fgPrimary' : 'fg',
63
+ color: isActive ? activeColor : color,
64
64
  display: "block",
65
65
  font: "headline",
66
+ paddingY: 2,
66
67
  children: label
67
68
  }), !!count && /*#__PURE__*/_jsx(DotCount, {
68
69
  accessibilityLabel: "".concat(accessibilityLabel !== null && accessibilityLabel !== void 0 ? accessibilityLabel : typeof label === 'string' ? label : '', " count: ").concat(count),
package/esm/tabs/Tabs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const _excluded = ["id", "registerRef"],
2
- _excluded2 = ["tabs", "TabComponent", "TabsActiveIndicatorComponent", "activeBackground", "activeTab", "onActiveTabElementChange", "disabled", "onChange", "className", "classNames", "styles", "role", "position", "width", "borderRadius", "borderTopLeftRadius", "borderTopRightRadius", "borderBottomLeftRadius", "borderBottomRightRadius", "style", "testID"],
2
+ _excluded2 = ["tabs", "TabComponent", "TabsActiveIndicatorComponent", "activeBackground", "activeColor", "activeTab", "color", "onActiveTabElementChange", "disabled", "onChange", "className", "classNames", "styles", "role", "position", "width", "borderRadius", "borderTopLeftRadius", "borderTopRightRadius", "borderBottomLeftRadius", "borderBottomRightRadius", "style", "testID"],
3
3
  _excluded3 = ["activeTabRect", "position", "testID"];
4
4
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
5
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -52,7 +52,9 @@ const TabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, ref) =>
52
52
  TabComponent = DefaultTab,
53
53
  TabsActiveIndicatorComponent = DefaultTabsActiveIndicator,
54
54
  activeBackground,
55
+ activeColor,
55
56
  activeTab,
57
+ color,
56
58
  onActiveTabElementChange,
57
59
  disabled,
58
60
  onChange,
@@ -144,6 +146,7 @@ const TabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, ref) =>
144
146
  borderTopLeftRadius: borderTopLeftRadius,
145
147
  borderTopRightRadius: borderTopRightRadius,
146
148
  className: cx(className, classNames === null || classNames === void 0 ? void 0 : classNames.root),
149
+ color: color,
147
150
  onKeyDown: handleTabsContainerKeyDown,
148
151
  opacity: disabled ? accessibleOpacityDisabled : 1,
149
152
  position: position,
@@ -168,7 +171,10 @@ const TabsComponent = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, ref) =>
168
171
  }), tabs.map(props => {
169
172
  var _props$Component;
170
173
  const RenderedTab = (_props$Component = props.Component) !== null && _props$Component !== void 0 ? _props$Component : TabComponent;
171
- const renderedTabProps = _objectSpread(_objectSpread({}, props), {}, {
174
+ const renderedTabProps = _objectSpread(_objectSpread({
175
+ activeColor,
176
+ color
177
+ }, props), {}, {
172
178
  'data-rendered-tab': true,
173
179
  className: classNames === null || classNames === void 0 ? void 0 : classNames.tab,
174
180
  role: 'tab',
package/esm/tag/Tag.js CHANGED
@@ -1,4 +1,4 @@
1
- const _excluded = ["children", "intent", "emphasis", "colorScheme", "background", "color", "start", "startIcon", "startIconActive", "end", "endIcon", "endIconActive", "display", "alignItems", "gap", "justifyContent", "paddingY", "testID"];
1
+ const _excluded = ["children", "intent", "emphasis", "colorScheme", "background", "color", "start", "startIcon", "startIconActive", "end", "endIcon", "endIconActive", "display", "alignItems", "gap", "justifyContent", "paddingX", "paddingY", "font", "fontFamily", "fontSize", "fontWeight", "lineHeight", "testID"];
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
@@ -35,7 +35,13 @@ export const Tag = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, forwardedR
35
35
  alignItems = 'center',
36
36
  gap = 0.5,
37
37
  justifyContent = 'center',
38
+ paddingX,
38
39
  paddingY = 0.25,
40
+ font,
41
+ fontFamily,
42
+ fontSize,
43
+ fontWeight,
44
+ lineHeight,
39
45
  testID = tagStaticClassName
40
46
  } = mergedProps,
41
47
  props = _objectWithoutProperties(mergedProps, _excluded);
@@ -58,7 +64,7 @@ export const Tag = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, forwardedR
58
64
  display: display,
59
65
  gap: gap,
60
66
  justifyContent: justifyContent,
61
- paddingX: tagHorizontalSpacing[intent],
67
+ paddingX: paddingX !== null && paddingX !== void 0 ? paddingX : tagHorizontalSpacing[intent],
62
68
  paddingY: paddingY,
63
69
  style: boxStyles,
64
70
  testID: testID
@@ -77,7 +83,11 @@ export const Tag = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, forwardedR
77
83
  }) : null, /*#__PURE__*/_jsx(Text, {
78
84
  color: "currentColor",
79
85
  display: "inline",
80
- font: tagFontMap[intent],
86
+ font: font !== null && font !== void 0 ? font : tagFontMap[intent],
87
+ fontFamily: fontFamily,
88
+ fontSize: fontSize,
89
+ fontWeight: fontWeight,
90
+ lineHeight: lineHeight,
81
91
  overflow: "truncate",
82
92
  testID: "".concat(testID, "--text"),
83
93
  children: children
@@ -569,6 +569,38 @@ export const coinbaseHighContrastTheme = {
569
569
  caption: 'uppercase',
570
570
  legal: 'none'
571
571
  },
572
+ lightIllustrationColor: {
573
+ primary: "rgb(".concat(lightSpectrum.blue60, ")"),
574
+ black: "rgb(".concat(lightSpectrum.gray100, ")"),
575
+ white: "rgb(".concat(lightSpectrum.gray0, ")"),
576
+ gray: "rgb(".concat(lightSpectrum.gray20, ")"),
577
+ gray2: "rgb(10, 11, 15)",
578
+ gray3: "rgb(206, 210, 220)",
579
+ positive: "rgb(".concat(lightSpectrum.green30, ")"),
580
+ negative: "rgb(".concat(lightSpectrum.red50, ")"),
581
+ accent1: "rgb(255, 210, 0)",
582
+ accent2: "rgb(".concat(lightSpectrum.teal15, ")"),
583
+ accent3: "rgb(".concat(lightSpectrum.orange40, ")"),
584
+ accent4: "rgb(".concat(lightSpectrum.blue20, ")"),
585
+ invert: "rgb(10, 11, 14)",
586
+ invert2: "rgb(255, 255, 254)"
587
+ },
588
+ darkIllustrationColor: {
589
+ primary: "rgb(".concat(darkSpectrum.blue70, ")"),
590
+ black: "rgb(".concat(darkSpectrum.gray0, ")"),
591
+ white: "rgb(".concat(darkSpectrum.gray100, ")"),
592
+ gray: "rgb(".concat(darkSpectrum.gray30, ")"),
593
+ gray2: "rgb(".concat(darkSpectrum.gray30, ")"),
594
+ gray3: "rgb(".concat(darkSpectrum.gray100, ")"),
595
+ positive: "rgb(".concat(darkSpectrum.green70, ")"),
596
+ negative: "rgb(".concat(darkSpectrum.red60, ")"),
597
+ accent1: "rgb(236, 208, 105)",
598
+ accent2: "rgb(".concat(darkSpectrum.teal80, ")"),
599
+ accent3: "rgb(".concat(darkSpectrum.orange60, ")"),
600
+ accent4: "rgb(".concat(darkSpectrum.blue80, ")"),
601
+ invert: "rgb(".concat(darkSpectrum.gray100, ")"),
602
+ invert2: "rgb(".concat(darkSpectrum.gray50, ")")
603
+ },
572
604
  shadow: {
573
605
  elevation1: '0px 8px 12px rgba(0, 0, 0, 0.12)',
574
606
  elevation2: '0px 8px 24px rgba(0, 0, 0, 0.12)'