@box/blueprint-web 6.17.0 → 6.19.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.
package/lib-esm/index.css CHANGED
@@ -791,7 +791,7 @@
791
791
  top:0;
792
792
  }
793
793
 
794
- .icon_button_module_iconButton--19afc{
794
+ .icon_button_module_iconButton--5ec37{
795
795
  align-items:center;
796
796
  background:var(--surface-cta-surface-icon);
797
797
  border:0;
@@ -802,44 +802,47 @@
802
802
  justify-content:center;
803
803
  padding:0;
804
804
  }
805
- .icon_button_module_iconButton--19afc .icon_button_module_iconColor--19afc *{
805
+ .icon_button_module_iconButton--5ec37 .icon_button_module_iconColor--5ec37 *{
806
806
  fill:var(--icon-cta-icon);
807
807
  }
808
- .icon_button_module_iconButton--19afc[aria-disabled=true]{
808
+ .icon_button_module_iconButton--5ec37[aria-disabled=true]{
809
809
  background:var(--surface-cta-surface-icon-disabled);
810
810
  opacity:.3;
811
811
  }
812
- .icon_button_module_iconButton--19afc[aria-disabled=true] .icon_button_module_iconColor--19afc *{
812
+ .icon_button_module_iconButton--5ec37[aria-disabled=true] .icon_button_module_iconColor--5ec37 *{
813
813
  fill:var(--gray-50);
814
814
  }
815
- .icon_button_module_iconButton--19afc:focus-visible,.icon_button_module_iconButton--19afc[data-focus-visible]{
815
+ .icon_button_module_iconButton--5ec37:focus-visible{
816
+ outline:none;
817
+ }
818
+ .icon_button_module_iconButton--5ec37[data-focus-visible]{
816
819
  background:var(--surface-cta-surface-icon-hover);
817
820
  outline:var(--border-2) solid var(--outline-focus-on-light);
818
821
  }
819
- .icon_button_module_iconButton--19afc:focus-visible .icon_button_module_iconColor--19afc *,.icon_button_module_iconButton--19afc[data-focus-visible] .icon_button_module_iconColor--19afc *{
822
+ .icon_button_module_iconButton--5ec37[data-focus-visible] .icon_button_module_iconColor--5ec37 *{
820
823
  fill:var(--icon-cta-icon-hover);
821
824
  }
822
- .icon_button_module_iconButton--19afc:hover{
825
+ .icon_button_module_iconButton--5ec37:hover{
823
826
  background:var(--surface-cta-surface-icon-hover);
824
827
  }
825
- .icon_button_module_iconButton--19afc:hover .icon_button_module_iconColor--19afc *{
828
+ .icon_button_module_iconButton--5ec37:hover .icon_button_module_iconColor--5ec37 *{
826
829
  fill:var(--icon-cta-icon-hover);
827
830
  }
828
- .icon_button_module_iconButton--19afc:active,.icon_button_module_iconButton--19afc[data-active]{
831
+ .icon_button_module_iconButton--5ec37:active,.icon_button_module_iconButton--5ec37[data-active]{
829
832
  background:var(--surface-cta-surface-icon-pressed);
830
833
  }
831
- .icon_button_module_iconButton--19afc:active .icon_button_module_iconColor--19afc *,.icon_button_module_iconButton--19afc[data-active] .icon_button_module_iconColor--19afc *{
834
+ .icon_button_module_iconButton--5ec37:active .icon_button_module_iconColor--5ec37 *,.icon_button_module_iconButton--5ec37[data-active] .icon_button_module_iconColor--5ec37 *{
832
835
  fill:var(--icon-cta-icon-pressed);
833
836
  }
834
- .icon_button_module_iconButton--19afc.icon_button_module_large--19afc{
837
+ .icon_button_module_iconButton--5ec37.icon_button_module_large--5ec37{
835
838
  height:var(--size-10);
836
839
  width:var(--size-10);
837
840
  }
838
- .icon_button_module_iconButton--19afc.icon_button_module_small--19afc{
841
+ .icon_button_module_iconButton--5ec37.icon_button_module_small--5ec37{
839
842
  height:var(--size-8);
840
843
  width:var(--size-8);
841
844
  }
842
- .icon_button_module_iconButton--19afc.icon_button_module_x-small--19afc{
845
+ .icon_button_module_iconButton--5ec37.icon_button_module_x-small--5ec37{
843
846
  height:var(--size-6);
844
847
  width:var(--size-6);
845
848
  }
@@ -4132,29 +4135,100 @@ table.inline_table_module_inlineTable--b023b tr:not(:last-child) td{
4132
4135
  opacity:.3;
4133
4136
  }
4134
4137
 
4135
- .tabs_module_tabsListContainer--23e09{
4138
+ .tabs_module_hiddenWidthSetter--6a56b{
4139
+ display:block;
4140
+ font-family:Lato, -apple-system, BlinkMacSystemFont, "San Francisco", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
4141
+ font-size:.875rem;
4142
+ font-weight:700;
4143
+ height:0;
4144
+ letter-spacing:.01875rem;
4145
+ line-height:1.25rem;
4146
+ overflow:hidden;
4147
+ text-decoration:none;
4148
+ text-transform:none;
4149
+ visibility:hidden;
4150
+ }
4151
+ .tabs_module_hiddenWidthSetter--6a56b > *{
4152
+ visibility:hidden;
4153
+ }
4154
+
4155
+ .tabs_module_contentSwitchTabList--6a56b{
4156
+ background:var(--surface-contentswitcher-surface);
4157
+ border-radius:var(--radius-3);
4158
+ display:grid;
4159
+ gap:var(--space-1);
4160
+ grid-auto-columns:1fr;
4161
+ grid-auto-flow:column;
4162
+ min-width:-moz-fit-content;
4163
+ min-width:fit-content;
4164
+ padding:var(--space-1);
4165
+ }
4166
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b{
4167
+ align-items:center;
4168
+ background:#0000;
4169
+ border:none;
4170
+ border-radius:var(--radius-2);
4171
+ display:flex;
4172
+ flex-direction:column;
4173
+ font-weight:400;
4174
+ height:var(--size-8);
4175
+ justify-content:center;
4176
+ outline:none;
4177
+ padding-inline:var(--space-4);
4178
+ white-space:nowrap;
4179
+ }
4180
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b,.tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b[aria-selected=true]{
4181
+ font-family:Lato, -apple-system, BlinkMacSystemFont, "San Francisco", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
4182
+ font-size:.875rem;
4183
+ letter-spacing:.01875rem;
4184
+ line-height:1.25rem;
4185
+ text-decoration:none;
4186
+ text-transform:none;
4187
+ }
4188
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b[aria-selected=true]{
4189
+ background:var(--surface-cta-surface-secondary);
4190
+ box-shadow:0 0 0 var(--border-1) var(--gray-50);
4191
+ color:var(--text-text-on-light);
4192
+ font-weight:700;
4193
+ }
4194
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b:not([aria-disabled=true])[data-focus-visible]{
4195
+ border-color:#0000;
4196
+ box-shadow:0 0 0 var(--border-2) var(--outline-focus-on-light);
4197
+ }
4198
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b:not([aria-disabled=true]):hover{
4199
+ background:var(--surface-surface-hover);
4200
+ }
4201
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b:not([aria-disabled=true]):active{
4202
+ background:var(--surface-cta-surface-secondary-pressed);
4203
+ }
4204
+ .tabs_module_contentSwitchTabList--6a56b .tabs_module_contentSwitchTab--6a56b[aria-disabled=true]{
4205
+ opacity:.3;
4206
+ pointer-events:none;
4207
+ }
4208
+
4209
+ .tabs_module_tabsListContainer--6a56b{
4136
4210
  height:calc(var(--size-10) + (var(--border-3) + 1px)*2);
4137
4211
  overflow-y:hidden;
4138
4212
  scroll-behavior:smooth;
4139
4213
  }
4140
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09{
4214
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b{
4141
4215
  display:flex;
4142
4216
  overflow-x:auto;
4143
4217
  padding:calc(var(--border-3) + 1px);
4144
4218
  }
4145
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tabSeparator--23e09{
4219
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tabSeparator--6a56b{
4146
4220
  border-bottom:var(--border-2) solid var(--border-tab-border);
4147
4221
  min-width:var(--space-4);
4148
4222
  }
4149
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tabSeparator--23e09:last-child{
4223
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tabSeparator--6a56b:last-child{
4150
4224
  display:none;
4151
4225
  }
4152
4226
  @media only screen and (max-width: 1023px){
4153
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tabSeparator--23e09{
4227
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tabSeparator--6a56b{
4154
4228
  min-width:calc(var(--border-3) + 1px);
4155
4229
  }
4156
4230
  }
4157
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09{
4231
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b{
4158
4232
  background:var(--background-background);
4159
4233
  border-style:none;
4160
4234
  border-bottom:var(--border-2) solid var(--border-tab-border);
@@ -4168,7 +4242,7 @@ table.inline_table_module_inlineTable--b023b tr:not(:last-child) td{
4168
4242
  scroll-margin:calc(var(--border-3) + 1px);
4169
4243
  z-index:2;
4170
4244
  }
4171
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09,.tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09 .tabs_module_hiddenWidthSetter--23e09{
4245
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b,.tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b[aria-selected=true]{
4172
4246
  font-family:Lato, -apple-system, BlinkMacSystemFont, "San Francisco", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
4173
4247
  font-size:.875rem;
4174
4248
  letter-spacing:.01875rem;
@@ -4176,42 +4250,26 @@ table.inline_table_module_inlineTable--b023b tr:not(:last-child) td{
4176
4250
  text-decoration:none;
4177
4251
  text-transform:none;
4178
4252
  }
4179
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09 .tabs_module_hiddenWidthSetter--23e09{
4180
- display:block;
4181
- font-weight:700;
4182
- height:0;
4183
- overflow:hidden;
4184
- visibility:hidden;
4185
- }
4186
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09 .tabs_module_hiddenWidthSetter--23e09 > *{
4187
- visibility:hidden;
4188
- }
4189
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09[aria-selected=true]{
4253
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b[aria-selected=true]{
4190
4254
  border-bottom:var(--border-2) solid var(--border-tab-border-selected);
4191
4255
  color:var(--text-cta-link);
4192
- font-family:Lato, -apple-system, BlinkMacSystemFont, "San Francisco", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
4193
- font-size:.875rem;
4194
4256
  font-weight:700;
4195
- letter-spacing:.01875rem;
4196
- line-height:1.25rem;
4197
- text-decoration:none;
4198
- text-transform:none;
4199
4257
  }
4200
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09:hover{
4258
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b:hover{
4201
4259
  background-color:var(--surface-tab-surface-hover);
4202
4260
  color:var(--text-text-on-light-secondary-hover);
4203
4261
  }
4204
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09:hover[aria-selected=true]{
4262
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b:hover[aria-selected=true]{
4205
4263
  color:var(--text-cta-link);
4206
4264
  }
4207
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09:active{
4265
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b:active{
4208
4266
  background-color:var(--surface-tab-surface-pressed);
4209
4267
  color:var(--text-text-on-light-secondary-hover);
4210
4268
  }
4211
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09:active[aria-selected=true]{
4269
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b:active[aria-selected=true]{
4212
4270
  color:var(--text-cta-link);
4213
4271
  }
4214
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09:focus-visible,.tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09[data-focus-visible]{
4272
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b:focus-visible,.tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b[data-focus-visible]{
4215
4273
  background-color:var(--surface-tab-surface-hover);
4216
4274
  border-radius:var(--radius-05);
4217
4275
  box-shadow:inset 0 0 0 1px #fff;
@@ -4219,10 +4277,10 @@ table.inline_table_module_inlineTable--b023b tr:not(:last-child) td{
4219
4277
  outline:var(--border-3) solid var(--outline-focus-on-light);
4220
4278
  outline-offset:1px;
4221
4279
  }
4222
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09:focus-visible[aria-selected=true],.tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09[data-focus-visible][aria-selected=true]{
4280
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b:focus-visible[aria-selected=true],.tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b[data-focus-visible][aria-selected=true]{
4223
4281
  color:var(--text-cta-link);
4224
4282
  }
4225
- .tabs_module_tabsListContainer--23e09 .tabs_module_tabList--23e09 .tabs_module_tab--23e09[aria-disabled=true]{
4283
+ .tabs_module_tabsListContainer--6a56b .tabs_module_tabList--6a56b .tabs_module_tab--6a56b[aria-disabled=true]{
4226
4284
  opacity:.5;
4227
4285
  }
4228
4286
 
@@ -1,4 +1,4 @@
1
1
  import '../../index.css';
2
- var styles = {"iconButton":"icon_button_module_iconButton--19afc","iconColor":"icon_button_module_iconColor--19afc","large":"icon_button_module_large--19afc","small":"icon_button_module_small--19afc","x-small":"icon_button_module_x-small--19afc"};
2
+ var styles = {"iconButton":"icon_button_module_iconButton--5ec37","iconColor":"icon_button_module_iconColor--5ec37","large":"icon_button_module_large--5ec37","small":"icon_button_module_small--5ec37","x-small":"icon_button_module_x-small--5ec37"};
3
3
 
4
4
  export { styles as default };
@@ -1,5 +1,6 @@
1
1
  import { SelectMenuGrid } from './select-menu-grid';
2
2
  import { SelectMenuGridColorCircle, SelectMenuGridOption, SelectMenuGridSquare } from './select-menu-grid-option';
3
+ export { type SelectMenuGridProps, type SelectMenuOptionProps } from './types';
3
4
  type SelectMenuOption = typeof SelectMenuGridOption & {
4
5
  Square: typeof SelectMenuGridSquare;
5
6
  ColorCircle: typeof SelectMenuGridColorCircle;
@@ -9,4 +10,3 @@ type SelectMenuType = {
9
10
  Grid: typeof SelectMenuGrid;
10
11
  };
11
12
  export declare const SelectMenu: SelectMenuType;
12
- export {};
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { Button } from '@ariakit/react';
2
+ import { CompositeItem, Button } from '@ariakit/react';
3
3
  import clsx from 'clsx';
4
4
  import Color from 'color';
5
5
  import { forwardRef } from 'react';
@@ -33,22 +33,24 @@ const SelectMenuGridOption = /*#__PURE__*/forwardRef((props, forwardedRef) => {
33
33
  const isButtonActive = !disabled && !loading && active;
34
34
  const shouldShowTooltip = !isButtonDisabled;
35
35
  // TODO: [DSYS-764] use IconButton instead of AriakitButton
36
- const button = jsxs(Button, {
37
- ...restProps,
38
- ref: forwardedRef,
39
- "aria-label": loading ? loadingAriaLabel : ariaLabel,
40
- className: clsx(styles.optionButton, className, {
41
- [styles.loading]: loading,
42
- [styles.active]: isButtonActive
43
- }),
44
- disabled: isButtonDisabled,
45
- children: [variant === 'colorCircle' && jsx(ColorSwatch, {
46
- color: color || '',
47
- loading: !!loading
48
- }), variant === 'square' && jsx(Icon, {
49
- loading: !!loading,
50
- children: children
51
- })]
36
+ const button = jsx(CompositeItem, {
37
+ render: jsxs(Button, {
38
+ ...restProps,
39
+ ref: forwardedRef,
40
+ "aria-label": loading ? loadingAriaLabel : ariaLabel,
41
+ className: clsx(styles.optionButton, className, {
42
+ [styles.loading]: loading,
43
+ [styles.active]: isButtonActive
44
+ }),
45
+ disabled: isButtonDisabled,
46
+ children: [variant === 'colorCircle' && jsx(ColorSwatch, {
47
+ color: color || '',
48
+ loading: !!loading
49
+ }), variant === 'square' && jsx(Icon, {
50
+ loading: !!loading,
51
+ children: children
52
+ })]
53
+ })
52
54
  });
53
55
  return jsxs("div", {
54
56
  className: styles.buttonWrapper,
@@ -2,4 +2,8 @@
2
2
  export declare const SelectMenuGrid: import("react").ForwardRefExoticComponent<Omit<{
3
3
  children: import("react").ReactNode;
4
4
  columns: number;
5
- } & import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
5
+ } & import("@ariakit/react").CompositeOptions<"div"> & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
6
+ ref?: ((instance: HTMLDivElement | null) => void) | import("react").RefObject<HTMLDivElement> | null | undefined;
7
+ }, keyof import("@ariakit/react").CompositeOptions<T>> & {
8
+ [index: `data-${string}`]: unknown;
9
+ }, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,10 +1,11 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
+ import { CompositeProvider, Composite, CompositeRow } from '@ariakit/react';
2
3
  import clsx from 'clsx';
3
4
  import chunk from 'lodash/chunk';
4
5
  import { forwardRef, Children } from 'react';
5
6
  import styles from './select-menu-grid.module.js';
6
7
 
7
- const Row = props => jsx("div", {
8
+ const Row = props => jsx(CompositeRow, {
8
9
  ...props,
9
10
  className: styles.row,
10
11
  role: "row"
@@ -17,14 +18,16 @@ const SelectMenuGrid = /*#__PURE__*/forwardRef((props, forwardedRef) => {
17
18
  ...rest
18
19
  } = props;
19
20
  const childrenByColumns = chunk(Children.toArray(children), columns);
20
- return jsx("div", {
21
- ...rest,
22
- ref: forwardedRef,
23
- className: clsx(styles.grid, className),
24
- role: "grid",
25
- children: childrenByColumns.map((row, i) => jsx(Row, {
26
- children: row
27
- }, row[0]?.key || i))
21
+ return jsx(CompositeProvider, {
22
+ children: jsx(Composite, {
23
+ ...rest,
24
+ ref: forwardedRef,
25
+ className: clsx(styles.grid, className),
26
+ role: "grid",
27
+ children: childrenByColumns.map((row, i) => jsx(Row, {
28
+ children: row
29
+ }, row[0]?.key || i))
30
+ })
28
31
  });
29
32
  });
30
33
 
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { type ButtonProps as AriakitButtonProps } from '@ariakit/react';
2
+ import { type ButtonProps as AriakitButtonProps, type CompositeProps, type CompositeRowProps } from '@ariakit/react';
3
3
  import { type RequireAllOrNone, type SetOptional } from 'type-fest';
4
4
  type Loading = {
5
5
  /** Loading state of the grid option. Ghost section is displaying as a placeholder. When this is true `loadingAriaLabel` must also be provided. */
@@ -23,13 +23,14 @@ export type SelectMenuGridColorCircleProps = CommonOptionProps & {
23
23
  /** The color of the swatch */
24
24
  color: string;
25
25
  };
26
- export type SelectMenuGridOptionProps = SetOptional<SelectMenuGridSquareProps, keyof SelectMenuGridSquareProps> & SetOptional<SelectMenuGridColorCircleProps, keyof SelectMenuGridColorCircleProps> & {
26
+ export type SelectMenuOptionProps = SetOptional<SelectMenuGridSquareProps, keyof SelectMenuGridSquareProps> & SetOptional<SelectMenuGridColorCircleProps, keyof SelectMenuGridColorCircleProps> & {
27
27
  variant: 'square' | 'colorCircle';
28
28
  };
29
+ export type SelectMenuGridRowProps = CompositeRowProps;
29
30
  export type SelectMenuGridProps = {
30
31
  /** The grid options to render */
31
32
  children: React.ReactNode;
32
33
  /** The number of columns to slice the grid options into */
33
34
  columns: number;
34
- } & React.ComponentProps<'div'>;
35
+ } & CompositeProps;
35
36
  export {};
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ export declare const ContentSwitchTab: import("react").ForwardRefExoticComponent<Omit<import("@ariakit/react").TabOptions<"button"> & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
3
+ ref?: ((instance: HTMLButtonElement | null) => void) | import("react").RefObject<HTMLButtonElement> | null | undefined;
4
+ }, keyof import("@ariakit/react").TabOptions<T>> & {
5
+ [index: `data-${string}`]: unknown;
6
+ } & {
7
+ variant?: import("./types").TabsVariant | undefined;
8
+ }, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,43 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Tab } from '@ariakit/react';
3
+ import clsx from 'clsx';
4
+ import { forwardRef, useRef, useEffect } from 'react';
5
+ import { useTabsWidthContext } from './tabs-width-context.js';
6
+ import styles from './tabs.module.js';
7
+
8
+ const ContentSwitchTab = /*#__PURE__*/forwardRef(function Tab$1(props, ref) {
9
+ const {
10
+ className,
11
+ children,
12
+ ...rest
13
+ } = props;
14
+ const widthSetterRef = useRef(null);
15
+ const {
16
+ minTabWidth,
17
+ addTabWidth
18
+ } = useTabsWidthContext();
19
+ useEffect(() => {
20
+ const tabElement = widthSetterRef.current;
21
+ if (!tabElement) {
22
+ return;
23
+ }
24
+ const tabWidth = tabElement.getBoundingClientRect().width;
25
+ addTabWidth(tabWidth);
26
+ }, [addTabWidth]);
27
+ return jsxs(Tab, {
28
+ ...rest,
29
+ ref: ref,
30
+ className: clsx(styles.contentSwitchTab, className),
31
+ children: [children, jsx("span", {
32
+ ref: widthSetterRef,
33
+ className: styles.hiddenWidthSetter,
34
+ style: {
35
+ minWidth: minTabWidth
36
+ },
37
+ children: children
38
+ })]
39
+ });
40
+ });
41
+ ContentSwitchTab.displayName = 'ContentSwitchTab';
42
+
43
+ export { ContentSwitchTab };
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ export declare const DefaultTab: import("react").ForwardRefExoticComponent<Omit<import("@ariakit/react").TabOptions<"button"> & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
3
+ ref?: import("react").RefObject<HTMLButtonElement> | ((instance: HTMLButtonElement | null) => void) | null | undefined;
4
+ }, keyof import("@ariakit/react").TabOptions<T>> & {
5
+ [index: `data-${string}`]: unknown;
6
+ } & {
7
+ variant?: import("./types").TabsVariant | undefined;
8
+ }, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,57 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { Tab } from '@ariakit/react';
3
+ import clsx from 'clsx';
4
+ import { forwardRef, useRef, useEffect } from 'react';
5
+ import { useForkRef } from '../../utils/useForkRef.js';
6
+ import styles from './tabs.module.js';
7
+ import { useTabs } from './use-tabs.js';
8
+
9
+ const outlineWidth = 3;
10
+ const outlineOffset = 1;
11
+ const padding = 12;
12
+ const scrollTabIntoViewIfSelected = (tabRef, isSelected) => {
13
+ const tabElement = tabRef.current;
14
+ const tabParentElement = tabRef.current?.parentElement;
15
+ const scrollOffset = outlineWidth + outlineOffset + padding;
16
+ if (!isSelected || !tabElement || !tabParentElement) {
17
+ return;
18
+ }
19
+ const scrollHorizontalPosition = tabElement.getBoundingClientRect().left - scrollOffset;
20
+ tabParentElement.scrollLeft = scrollHorizontalPosition;
21
+ };
22
+ const DefaultTab = /*#__PURE__*/forwardRef(function Tab$1(props, ref) {
23
+ const {
24
+ className,
25
+ children,
26
+ ...rest
27
+ } = props;
28
+ const tabRef = useRef(null);
29
+ const selectedTabId = useTabs()?.useState('selectedId');
30
+ const isTabSelected = selectedTabId === rest?.id;
31
+ const checkedScrollOnMount = useRef(false);
32
+ useEffect(() => {
33
+ if (checkedScrollOnMount.current) {
34
+ return;
35
+ }
36
+ scrollTabIntoViewIfSelected(tabRef, isTabSelected);
37
+ checkedScrollOnMount.current = true;
38
+ }, [isTabSelected]);
39
+ return jsxs(Fragment, {
40
+ children: [jsxs(Tab, {
41
+ ...rest,
42
+ ref: useForkRef(tabRef, ref),
43
+ className: clsx(styles.tab, className),
44
+ children: [children, jsx("span", {
45
+ className: styles.hiddenWidthSetter,
46
+ children: children
47
+ })]
48
+ }), jsx("div", {
49
+ "aria-hidden": "true",
50
+ className: styles.tabSeparator,
51
+ role: "presentation"
52
+ })]
53
+ });
54
+ });
55
+ DefaultTab.displayName = 'DefaultTab';
56
+
57
+ export { DefaultTab };
@@ -1,24 +1,19 @@
1
1
  /// <reference types="react" />
2
- export declare const Tabs: ((props: import("./tabs").TabsProps) => JSX.Element) & {
2
+ export declare const Tabs: ((props: import("./types").TabsProps) => JSX.Element) & {
3
3
  /**
4
4
  * The component that displays a Tab name and allows selection.
5
5
  */
6
- Tab: import("react").ForwardRefExoticComponent<Omit<import("@ariakit/react").TabOptions<"button"> & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
7
- ref?: ((instance: HTMLButtonElement | null) => void) | import("react").RefObject<HTMLButtonElement> | null | undefined;
8
- }, keyof import("@ariakit/react").TabOptions<T>> & {
9
- [index: `data-${string}`]: unknown;
10
- }, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
6
+ Tab: (props: import("./types").TabProps) => JSX.Element;
11
7
  /**
12
8
  * Wrapper for a list of Tabs.
13
9
  */
14
- TabList: import("react").ForwardRefExoticComponent<Omit<import("./tab-list").TabListProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
10
+ TabList: import("react").ForwardRefExoticComponent<Omit<Omit<import("@ariakit/react").TabListProps<"div">, "store"> & {
11
+ variant?: import("./types").TabsVariant | undefined;
12
+ }, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
15
13
  /**
16
14
  * The content for a single Tab.
17
15
  */
18
- TabPanel: import("react").ForwardRefExoticComponent<Omit<import("./tab-panel").TabPanelProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
16
+ TabPanel: import("react").ForwardRefExoticComponent<Omit<import("./types").TabPanelProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
19
17
  };
18
+ export { type TabListProps, type TabPanelProps, type TabProps, type TabsProps } from './types';
20
19
  export { useTabs } from './use-tabs';
21
- export { type TabProps } from './tab';
22
- export { type TabListProps } from './tab-list';
23
- export { type TabPanelProps } from './tab-panel';
24
- export { type TabsProps } from './tabs';
@@ -1,4 +1,4 @@
1
1
  /// <reference types="react" />
2
- import { type TabListProps as PrimitiveTabListProps } from '@ariakit/react';
3
- export type TabListProps = Omit<PrimitiveTabListProps, 'store'>;
4
- export declare const TabList: import("react").ForwardRefExoticComponent<Omit<TabListProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
2
+ export declare const TabList: import("react").ForwardRefExoticComponent<Omit<Omit<import("@ariakit/react").TabListProps<"div">, "store"> & {
3
+ variant?: import("./types").TabsVariant | undefined;
4
+ }, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -7,7 +7,8 @@ import { useTabs } from './use-tabs.js';
7
7
 
8
8
  const TabList = /*#__PURE__*/forwardRef(function TabList(props, ref) {
9
9
  const {
10
- className
10
+ className,
11
+ variant = 'default'
11
12
  } = props;
12
13
  const tab = useTabs();
13
14
  if (!tab) {
@@ -18,7 +19,7 @@ const TabList = /*#__PURE__*/forwardRef(function TabList(props, ref) {
18
19
  children: jsx(TabList$1, {
19
20
  ...props,
20
21
  ref: ref,
21
- className: clsx(styles.tabList, className),
22
+ className: clsx(variant === 'contentSwitcher' ? styles.contentSwitchTabList : styles.tabList, className),
22
23
  store: tab
23
24
  })
24
25
  });
@@ -1,4 +1,3 @@
1
1
  /// <reference types="react" />
2
- import { type TabPanelProps as PrimitiveTabPanelProps } from '@ariakit/react';
3
- export type TabPanelProps = Omit<PrimitiveTabPanelProps, 'store'>;
2
+ import { type TabPanelProps } from './types';
4
3
  export declare const TabPanel: import("react").ForwardRefExoticComponent<Omit<TabPanelProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,8 +1,3 @@
1
1
  /// <reference types="react" />
2
- import { type TabProps as PrimitiveTabProps } from '@ariakit/react';
3
- export type TabProps = PrimitiveTabProps;
4
- export declare const Tab: import("react").ForwardRefExoticComponent<Omit<import("@ariakit/react").TabOptions<"button"> & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
5
- ref?: ((instance: HTMLButtonElement | null) => void) | import("react").RefObject<HTMLButtonElement> | null | undefined;
6
- }, keyof import("@ariakit/react").TabOptions<T>> & {
7
- [index: `data-${string}`]: unknown;
8
- }, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
2
+ import { type TabProps } from './types';
3
+ export declare const Tab: (props: TabProps) => JSX.Element;
@@ -1,58 +1,17 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { Tab as Tab$1 } from '@ariakit/react';
3
- import clsx from 'clsx';
4
- import { forwardRef, useRef, useEffect } from 'react';
5
- import { useForkRef } from '../../utils/useForkRef.js';
6
- import styles from './tabs.module.js';
7
- import { useTabs } from './use-tabs.js';
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { ContentSwitchTab } from './content-switch-tab.js';
3
+ import { DefaultTab } from './default-tab.js';
8
4
 
9
- const scrollSelectedTabIntoView = (tabRef, isSelected) => {
10
- const tabElement = tabRef.current;
11
- const tabParentElement = tabRef.current?.parentElement;
12
- const outlineWidthAndOffset = 4;
13
- if (!isSelected || !tabElement || !tabParentElement) {
14
- return;
15
- }
16
- const scrollHorizontalPosition = tabElement.getBoundingClientRect().left + outlineWidthAndOffset;
17
- tabParentElement.scrollLeft = scrollHorizontalPosition;
18
- };
19
- const Tab = /*#__PURE__*/forwardRef(function Tab(props, ref) {
5
+ const Tab = props => {
20
6
  const {
21
- className,
22
- children,
23
- id,
7
+ variant = 'default',
24
8
  ...rest
25
9
  } = props;
26
- const tabRef = useRef(null);
27
- const selectedTabId = useTabs()?.useState('selectedId');
28
- const isTabSelected = selectedTabId === id;
29
- const tabId = id ? {
30
- id
31
- } : {};
32
- const scrolledOnMount = useRef(false);
33
- useEffect(() => {
34
- if (scrolledOnMount.current === true) {
35
- return;
36
- }
37
- scrollSelectedTabIntoView(tabRef, isTabSelected);
38
- scrolledOnMount.current = true;
39
- }, [isTabSelected]);
40
- return jsxs(Fragment, {
41
- children: [jsxs(Tab$1, {
42
- ...rest,
43
- ref: useForkRef(tabRef, ref),
44
- className: clsx(styles.tab, className),
45
- ...tabId,
46
- children: [children, jsx("span", {
47
- className: styles.hiddenWidthSetter,
48
- children: children
49
- })]
50
- }), jsx("div", {
51
- "aria-hidden": "true",
52
- className: styles.tabSeparator,
53
- role: "presentation"
54
- })]
10
+ return variant === 'contentSwitcher' ? jsx(ContentSwitchTab, {
11
+ ...rest
12
+ }) : jsx(DefaultTab, {
13
+ ...rest
55
14
  });
56
- });
15
+ };
57
16
 
58
17
  export { Tab };
@@ -0,0 +1,17 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface TabsWidthContextData {
3
+ /**
4
+ * Minimum width of each rendered tab, derived from a tab with the longest label with minimal paddings.
5
+ */
6
+ minTabWidth: number;
7
+ /**
8
+ * Register width of a tab in context.
9
+ */
10
+ addTabWidth: (width: number) => void;
11
+ }
12
+ export interface TabsWidthContextProps {
13
+ children: ReactNode;
14
+ }
15
+ export declare const TabsWidthContext: import("react").Context<TabsWidthContextData | undefined>;
16
+ export declare const useTabsWidthContext: () => TabsWidthContextData;
17
+ export declare const TabsWidthProvider: (props: TabsWidthContextProps) => JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useContext, useState, useCallback, useMemo, createContext } from 'react';
3
+
4
+ const TabsWidthContext = /*#__PURE__*/createContext(undefined);
5
+ const useTabsWidthContext = () => {
6
+ const tabsWidthContextData = useContext(TabsWidthContext);
7
+ if (!tabsWidthContextData) {
8
+ throw new Error('Tabs subcomponents must be wrapped in Tabs component.');
9
+ }
10
+ return tabsWidthContextData;
11
+ };
12
+ const TabsWidthProvider = props => {
13
+ const {
14
+ children
15
+ } = props;
16
+ const [tabWidths, setTabWidths] = useState([]);
17
+ const minTabWidth = Math.max(...tabWidths);
18
+ const addTabWidth = useCallback(width => {
19
+ setTabWidths(prev => [...prev, width]);
20
+ }, []);
21
+ const store = useMemo(() => ({
22
+ minTabWidth,
23
+ addTabWidth
24
+ }), [minTabWidth, addTabWidth]);
25
+ return jsx(TabsWidthContext.Provider, {
26
+ value: store,
27
+ children: children
28
+ });
29
+ };
30
+
31
+ export { TabsWidthContext, TabsWidthProvider, useTabsWidthContext };
@@ -1,6 +1,3 @@
1
- import { type TabStoreProps } from '@ariakit/react';
2
- import { type ReactNode } from 'react';
3
- export type TabsProps = TabStoreProps & {
4
- children: ReactNode;
5
- };
1
+ /// <reference types="react" />
2
+ import { type TabsProps } from './types';
6
3
  export declare const Tabs: (props: TabsProps) => JSX.Element;
@@ -1,14 +1,17 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { TabProvider } from '@ariakit/react';
3
+ import { TabsWidthProvider } from './tabs-width-context.js';
3
4
 
4
5
  const Tabs = props => {
5
6
  const {
6
7
  children
7
8
  } = props;
8
- return jsx(TabProvider, {
9
- selectOnMove: false,
10
- ...props,
11
- children: children
9
+ return jsx(TabsWidthProvider, {
10
+ children: jsx(TabProvider, {
11
+ selectOnMove: false,
12
+ ...props,
13
+ children: children
14
+ })
12
15
  });
13
16
  };
14
17
 
@@ -1,4 +1,4 @@
1
1
  import '../../index.css';
2
- var styles = {"tabsListContainer":"tabs_module_tabsListContainer--23e09","tabList":"tabs_module_tabList--23e09","tabSeparator":"tabs_module_tabSeparator--23e09","tab":"tabs_module_tab--23e09","hiddenWidthSetter":"tabs_module_hiddenWidthSetter--23e09"};
2
+ var styles = {"hiddenWidthSetter":"tabs_module_hiddenWidthSetter--6a56b","contentSwitchTabList":"tabs_module_contentSwitchTabList--6a56b","contentSwitchTab":"tabs_module_contentSwitchTab--6a56b","tabsListContainer":"tabs_module_tabsListContainer--6a56b","tabList":"tabs_module_tabList--6a56b","tabSeparator":"tabs_module_tabSeparator--6a56b","tab":"tabs_module_tab--6a56b"};
3
3
 
4
4
  export { styles as default };
@@ -0,0 +1,13 @@
1
+ import { type TabListProps as PrimitiveTabListProps, type TabPanelProps as PrimitiveTabPanelProps, type TabProps as PrimitiveTabProps, type TabStoreProps as PrimitiveTabStoreProps } from '@ariakit/react';
2
+ import { type ReactNode } from 'react';
3
+ export type TabsVariant = 'default' | 'contentSwitcher';
4
+ export type TabListProps = Omit<PrimitiveTabListProps, 'store'> & {
5
+ variant?: TabsVariant;
6
+ };
7
+ export type TabPanelProps = Omit<PrimitiveTabPanelProps, 'store'>;
8
+ export type TabProps = PrimitiveTabProps & {
9
+ variant?: TabsVariant;
10
+ };
11
+ export type TabsProps = PrimitiveTabStoreProps & {
12
+ children: ReactNode;
13
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@box/blueprint-web",
3
- "version": "6.17.0",
3
+ "version": "6.19.0",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -57,7 +57,7 @@
57
57
  "devDependencies": {
58
58
  "@box/storybook-utils": "^0.0.3"
59
59
  },
60
- "gitHead": "27a55b8816fa467409faedf10420e08d5f2004cf",
60
+ "gitHead": "05fe9fbc44f97b1e8b5df6062ded4ef9fc1d05ae",
61
61
  "module": "lib-esm/index.js",
62
62
  "main": "lib-esm/index.js",
63
63
  "exports": {