diff --git a/.all-contributorsrc b/.all-contributorsrc index 444d90530529..438d1bb8bd25 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -801,6 +801,15 @@ "contributions": [ "code" ] + }, + { + "login": "ColbyJohnIBM", + "name": "ColbyJohnIBM", + "avatar_url": "https://avatars.githubusercontent.com/u/19613692?v=4", + "profile": "https://github.com/ColbyJohnIBM", + "contributions": [ + "code" + ] } ], "commitConvention": "none" diff --git a/README.md b/README.md index 1cd859141ab4..935208018c02 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ check out our [Contributing Guide](/.github/CONTRIBUTING.md) and our
Adam Alston

📖
Krithika S Udupa

📖
Eshin Griffith

💻 +
ColbyJohnIBM

💻 diff --git a/packages/components/src/globals/scss/_helper-mixins.scss b/packages/components/src/globals/scss/_helper-mixins.scss index 8bbb63d3a663..9d928cb6e322 100644 --- a/packages/components/src/globals/scss/_helper-mixins.scss +++ b/packages/components/src/globals/scss/_helper-mixins.scss @@ -55,7 +55,7 @@ /// @example @include box-shadow; /// @group global-helpers @mixin box-shadow { - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 6px $shadow; } /// Adds outline styles depending on specific type diff --git a/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap index 8d62e1a6b1db..875bace53a77 100644 --- a/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -318,6 +318,7 @@ Array [ "scale", "selectedLightUI", "selectedUI", + "shadow", "size2XLarge", "sizeLarge", "sizeMedium", diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index 248de768906b..7390b283f019 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -1212,21 +1212,46 @@ Map { }, "TableExpandHeader": Object { "propTypes": Object { - "ariaLabel": [Function], + "ariaLabel": Object { + "args": Array [ + Array [ + [Function], + [Function], + ], + ], + "type": "oneOfType", + }, "children": Object { "type": "node", }, "className": Object { "type": "string", }, - "enableExpando": Object { + "enableExpando": [Function], + "enableToggle": Object { "type": "bool", }, "expandIconDescription": Object { "type": "string", }, - "isExpanded": [Function], - "onExpand": [Function], + "isExpanded": Object { + "args": Array [ + Array [ + [Function], + [Function], + ], + ], + "type": "oneOfType", + }, + "onExpand": Object { + "args": Array [ + Array [ + [Function], + [Function], + ], + ], + "type": "oneOfType", + }, }, }, "TableExpandRow": Object { @@ -1852,21 +1877,46 @@ Map { }, "TableExpandHeader" => Object { "propTypes": Object { - "ariaLabel": [Function], + "ariaLabel": Object { + "args": Array [ + Array [ + [Function], + [Function], + ], + ], + "type": "oneOfType", + }, "children": Object { "type": "node", }, "className": Object { "type": "string", }, - "enableExpando": Object { + "enableExpando": [Function], + "enableToggle": Object { "type": "bool", }, "expandIconDescription": Object { "type": "string", }, - "isExpanded": [Function], - "onExpand": [Function], + "isExpanded": Object { + "args": Array [ + Array [ + [Function], + [Function], + ], + ], + "type": "oneOfType", + }, + "onExpand": Object { + "args": Array [ + Array [ + [Function], + [Function], + ], + ], + "type": "oneOfType", + }, }, }, "TableExpandRow" => Object { diff --git a/packages/react/src/components/Accordion/AccordionItem.js b/packages/react/src/components/Accordion/AccordionItem.js index 79aa438a913d..c2c8a472f8cf 100644 --- a/packages/react/src/components/Accordion/AccordionItem.js +++ b/packages/react/src/components/Accordion/AccordionItem.js @@ -13,7 +13,7 @@ import React, { useState } from 'react'; import { Text } from '../Text'; import { match, keys } from '../../internal/keyboard'; import { useId } from '../../internal/useId'; -import deprecate from '../../prop-types/deprecate.js'; +import deprecate from '../../prop-types/deprecate'; const { prefix } = settings; const defaultRenderExpando = (props) => - )} + ) : null} {children} ); @@ -56,15 +58,27 @@ TableExpandHeader.propTypes = { * Specify the string read by a voice reader when the expand trigger is * focused */ - ariaLabel: requiredIfGivenPropIsTruthy('enableExpando', PropTypes.string), + ariaLabel: PropTypes.oneOfType([ + requiredIfGivenPropIsTruthy('enableExpando', PropTypes.string), + requiredIfGivenPropIsTruthy('enableToggle', PropTypes.string), + ]), + children: PropTypes.node, className: PropTypes.string, + /** + * The enableExpando prop is being replaced by enableToggle + */ + enableExpando: deprecate( + PropTypes.bool, + 'The `enableExpando` prop has been deprecated in favor of `enableToggle`. This prop will be removed in the next major release.' + ), + /** * Specify whether an expand all button should be displayed */ - enableExpando: PropTypes.bool, + enableToggle: PropTypes.bool, /** * The description of the chevron right icon, to be put in its SVG `` element. @@ -75,12 +89,18 @@ TableExpandHeader.propTypes = { * Specify whether this row is expanded or not. This helps coordinate data * attributes so that `TableExpandRow` and `TableExpandedRow` work together */ - isExpanded: requiredIfGivenPropIsTruthy('enableExpando', PropTypes.bool), + isExpanded: PropTypes.oneOfType([ + requiredIfGivenPropIsTruthy('enableExpando', PropTypes.bool), + requiredIfGivenPropIsTruthy('enableToggle', PropTypes.bool), + ]), /** * Hook for when a listener initiates a request to expand the given row */ - onExpand: requiredIfGivenPropIsTruthy('enableExpando', PropTypes.func), + onExpand: PropTypes.oneOfType([ + requiredIfGivenPropIsTruthy('enableExpando', PropTypes.func), + requiredIfGivenPropIsTruthy('enableToggle', PropTypes.func), + ]), }; export default TableExpandHeader; diff --git a/packages/react/src/components/Modal/Modal.js b/packages/react/src/components/Modal/Modal.js index 1b14c8e5ac80..012baa8e1216 100644 --- a/packages/react/src/components/Modal/Modal.js +++ b/packages/react/src/components/Modal/Modal.js @@ -451,32 +451,6 @@ export default class Modal extends Component { alertDialogProps['aria-describedby'] = this.modalBodyId; } - const SecondaryButtonSet = () => { - if (Array.isArray(secondaryButtons) && secondaryButtons.length <= 2) { - return secondaryButtons.map( - ({ buttonText, onClick: onButtonClick }, i) => ( - <Button - key={`${buttonText}-${i}`} - kind="secondary" - onClick={onButtonClick}> - {buttonText} - </Button> - ) - ); - } - if (secondaryButtonText) { - return ( - <Button - kind="secondary" - onClick={onSecondaryButtonClick} - ref={this.secondaryButton}> - {secondaryButtonText} - </Button> - ); - } - return null; - }; - const modalBody = ( <div ref={this.innerModal} @@ -514,7 +488,25 @@ export default class Modal extends Component { )} {!passiveModal && ( <ButtonSet className={footerClasses}> - <SecondaryButtonSet /> + {Array.isArray(secondaryButtons) && secondaryButtons.length <= 2 + ? secondaryButtons.map( + ({ buttonText, onClick: onButtonClick }, i) => ( + <Button + key={`${buttonText}-${i}`} + kind="secondary" + onClick={onButtonClick}> + {buttonText} + </Button> + ) + ) + : secondaryButtonText && ( + <Button + kind="secondary" + onClick={onSecondaryButtonClick} + ref={this.secondaryButton}> + {secondaryButtonText} + </Button> + )} <Button kind={danger ? 'danger' : 'primary'} disabled={primaryButtonDisabled} diff --git a/packages/react/src/components/ModalWrapper/__snapshots__/ModalWrapper-test.js.snap b/packages/react/src/components/ModalWrapper/__snapshots__/ModalWrapper-test.js.snap index 4d504e9133ad..deffd66f96e6 100644 --- a/packages/react/src/components/ModalWrapper/__snapshots__/ModalWrapper-test.js.snap +++ b/packages/react/src/components/ModalWrapper/__snapshots__/ModalWrapper-test.js.snap @@ -167,36 +167,34 @@ exports[`ModalWrapper should render 1`] = ` <div className="bx--modal-footer bx--btn-set" > - <SecondaryButtonSet> - <Button - dangerDescription="danger" + <Button + dangerDescription="danger" + disabled={false} + isExpressive={false} + kind="secondary" + onClick={[Function]} + size="default" + tabIndex={0} + tooltipAlignment="center" + tooltipPosition="top" + type="button" + > + <button + aria-describedby={null} + aria-pressed={null} + className="bx--btn bx--btn--secondary" disabled={false} - isExpressive={false} - kind="secondary" + onBlur={[Function]} onClick={[Function]} - size="default" + onFocus={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} tabIndex={0} - tooltipAlignment="center" - tooltipPosition="top" type="button" > - <button - aria-describedby={null} - aria-pressed={null} - className="bx--btn bx--btn--secondary" - disabled={false} - onBlur={[Function]} - onClick={[Function]} - onFocus={[Function]} - onMouseEnter={[Function]} - onMouseLeave={[Function]} - tabIndex={0} - type="button" - > - Cancel - </button> - </Button> - </SecondaryButtonSet> + Cancel + </button> + </Button> <Button dangerDescription="danger" disabled={false} diff --git a/packages/react/src/components/MultiSelect/MultiSelect.js b/packages/react/src/components/MultiSelect/MultiSelect.js index 392bc95476c3..aa148aa2cb46 100644 --- a/packages/react/src/components/MultiSelect/MultiSelect.js +++ b/packages/react/src/components/MultiSelect/MultiSelect.js @@ -190,6 +190,9 @@ const MultiSelect = React.forwardRef(function MultiSelect( case ItemClick: case MenuKeyDownSpaceButton: case MenuKeyDownEnter: + if (changes.selectedItem === undefined) { + break; + } onItemChange(changes.selectedItem); break; case MenuKeyDownArrowDown: diff --git a/packages/react/src/components/OverflowMenu/OverflowMenu-test.js b/packages/react/src/components/OverflowMenu/OverflowMenu-test.js index 7235879fad81..d670e58b5a99 100644 --- a/packages/react/src/components/OverflowMenu/OverflowMenu-test.js +++ b/packages/react/src/components/OverflowMenu/OverflowMenu-test.js @@ -160,6 +160,15 @@ describe('OverflowMenu', () => { ); }); + it('fires onClick only once per button click', () => { + const mockOnClick = jest.fn(); + const rootWrapper = mount(<OverflowMenu onClick={mockOnClick} />); + + rootWrapper.find('button').simulate('click'); + + expect(mockOnClick).toHaveBeenCalledTimes(1); + }); + it('should NOT toggle state in response to Enter or Space when the menu is open', () => { const enterKey = 13; const spaceKey = 32; diff --git a/packages/react/src/components/OverflowMenu/OverflowMenu.js b/packages/react/src/components/OverflowMenu/OverflowMenu.js index 596c68c3ea05..fa39310e553a 100644 --- a/packages/react/src/components/OverflowMenu/OverflowMenu.js +++ b/packages/react/src/components/OverflowMenu/OverflowMenu.js @@ -278,6 +278,7 @@ class OverflowMenu extends Component { } handleClick = (evt) => { + evt.stopPropagation(); if (!this._menuBody || !this._menuBody.contains(evt.target)) { this.setState({ open: !this.state.open }); this.props.onClick(evt); diff --git a/packages/react/src/internal/FloatingMenu.js b/packages/react/src/internal/FloatingMenu.js index cd8f53c9867e..a64b952533fc 100644 --- a/packages/react/src/internal/FloatingMenu.js +++ b/packages/react/src/internal/FloatingMenu.js @@ -261,7 +261,7 @@ class FloatingMenu extends React.Component { * * @private */ - _updateMenuSize = (prevProps = {}) => { + _updateMenuSize = (prevProps = {}, isAdjustment = false) => { const menuBody = this._menuBody; warning( menuBody, @@ -279,7 +279,8 @@ class FloatingMenu extends React.Component { if ( hasChangeInOffset(oldMenuOffset, menuOffset) || - oldMenuDirection !== menuDirection + oldMenuDirection !== menuDirection || + isAdjustment ) { const { flipped, triggerRef } = this.props; const { current: triggerEl } = triggerRef; @@ -293,20 +294,30 @@ class FloatingMenu extends React.Component { // a) Menu body has `display:none` // b) `menuOffset` as a callback returns `undefined` (The callback saw that it couldn't calculate the value) if ((menuSize.width > 0 && menuSize.height > 0) || !offset) { - this.setState({ - floatingPosition: getFloatingPosition({ - menuSize, - refPosition, - direction: menuDirection, - offset, - scrollX: window.pageXOffset, - scrollY: window.pageYOffset, - container: { - rect: this.props.target().getBoundingClientRect(), - position: getComputedStyle(this.props.target()).position, - }, - }), - }); + this.setState( + { + floatingPosition: getFloatingPosition({ + menuSize, + refPosition, + direction: menuDirection, + offset, + scrollX: window.pageXOffset, + scrollY: window.pageYOffset, + container: { + rect: this.props.target().getBoundingClientRect(), + position: getComputedStyle(this.props.target()).position, + }, + }), + }, + () => { + if (!isAdjustment) { + const newMenuSize = menuBody.getBoundingClientRect(); + if (newMenuSize !== menuSize) { + this._updateMenuSize(this.props, true); + } + } + } + ); } } }; diff --git a/packages/styles/scss/__tests__/theme-test.js b/packages/styles/scss/__tests__/theme-test.js index 244b21093666..c31873150bcd 100644 --- a/packages/styles/scss/__tests__/theme-test.js +++ b/packages/styles/scss/__tests__/theme-test.js @@ -126,6 +126,7 @@ Array [ "highlight", "overlay", "toggle-off", + "shadow", "focus", "focus-inset", "focus-inverse", diff --git a/packages/styles/scss/utilities/_box-shadow.scss b/packages/styles/scss/utilities/_box-shadow.scss index cd309cb4016f..273f6bc12c3a 100644 --- a/packages/styles/scss/utilities/_box-shadow.scss +++ b/packages/styles/scss/utilities/_box-shadow.scss @@ -5,10 +5,12 @@ // LICENSE file in the root directory of this source tree. // +@use '../theme'; + /// Adds box shadow /// @access public /// @example @include box-shadow; /// @group utilities @mixin box-shadow { - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 6px theme.$shadow; } diff --git a/packages/themes/src/g10.js b/packages/themes/src/g10.js index 93631086aa35..4ab4b3ec91f9 100644 --- a/packages/themes/src/g10.js +++ b/packages/themes/src/g10.js @@ -37,6 +37,7 @@ import { // Constants white, + black, // Tools rgba, @@ -182,6 +183,7 @@ export const supportInfoInverse = inverseSupport04; export const overlay = overlay01; export const toggleOff = ui04; +export const shadow = rgba(black, 0.3); export const buttonPrimary = interactive01; export const buttonSecondary = interactive02; diff --git a/packages/themes/src/g100.js b/packages/themes/src/g100.js index 75aeba2352a1..e26fa82520a2 100644 --- a/packages/themes/src/g100.js +++ b/packages/themes/src/g100.js @@ -36,6 +36,7 @@ import { // Constants white, + black, // Tools rgba, @@ -86,7 +87,7 @@ export const inverseSupport02 = green50; export const inverseSupport03 = yellow; export const inverseSupport04 = blue60; -export const overlay01 = rgba(gray100, 0.7); +export const overlay01 = rgba(black, 0.65); export const danger01 = red60; export const danger02 = red50; @@ -181,6 +182,7 @@ export const supportInfoInverse = inverseSupport04; export const overlay = overlay01; export const toggleOff = ui04; +export const shadow = rgba(black, 0.8); export const buttonPrimary = interactive01; export const buttonSecondary = interactive02; diff --git a/packages/themes/src/g80.js b/packages/themes/src/g80.js index a3fd1c306bcb..48a407ebf097 100644 --- a/packages/themes/src/g80.js +++ b/packages/themes/src/g80.js @@ -37,6 +37,7 @@ import { // Constants white, + black, // Tools rgba, @@ -86,8 +87,9 @@ export const supportSuccessInverse = green50; export const supportWarningInverse = yellow30; export const supportInfoInverse = blue60; -export const overlay = rgba(gray100, 0.7); +export const overlay = rgba(black, 0.65); export const toggleOff = gray50; +export const shadow = rgba(black, 0.8); export const buttonPrimary = blue60; export const buttonSecondary = gray60; diff --git a/packages/themes/src/g90.js b/packages/themes/src/g90.js index 8a402752d663..1c82f1ee96bd 100644 --- a/packages/themes/src/g90.js +++ b/packages/themes/src/g90.js @@ -38,6 +38,7 @@ import { // Constants white, + black, // Tools rgba, @@ -88,7 +89,7 @@ export const inverseSupport02 = green50; export const inverseSupport03 = yellow; export const inverseSupport04 = blue60; -export const overlay01 = rgba(gray100, 0.7); +export const overlay01 = rgba(black, 0.65); export const danger01 = red60; export const danger02 = red40; @@ -183,6 +184,7 @@ export const supportInfoInverse = inverseSupport04; export const overlay = overlay01; export const toggleOff = ui04; +export const shadow = rgba(black, 0.8); export const buttonPrimary = interactive01; export const buttonSecondary = interactive02; diff --git a/packages/themes/src/next/g10.js b/packages/themes/src/next/g10.js index 036f585d0f92..9f56a2c37369 100644 --- a/packages/themes/src/next/g10.js +++ b/packages/themes/src/next/g10.js @@ -192,6 +192,7 @@ export const interactive = blue60; export const highlight = blue20; export const overlay = 'rgba(22, 22, 22, 0.5)'; export const toggleOff = gray50; +export const shadow = 'rgba(0, 0, 0, 0.3)'; export { // Type diff --git a/packages/themes/src/next/g100.js b/packages/themes/src/next/g100.js index 9f94922376f0..e4025736c52f 100644 --- a/packages/themes/src/next/g100.js +++ b/packages/themes/src/next/g100.js @@ -41,6 +41,10 @@ import { // Constants white, + black, + + // Tools + rgba, } from '@carbon/colors'; import { adjustLightness } from '../tools'; @@ -193,8 +197,9 @@ export const skeletonElement = gray80; // Misc export const interactive = blue50; export const highlight = blue20; -export const overlay = 'rgba(22, 22, 22, 0.5)'; +export const overlay = rgba(black, 0.65); export const toggleOff = gray50; +export const shadow = rgba(black, 0.8); export { // Type diff --git a/packages/themes/src/next/g90.js b/packages/themes/src/next/g90.js index 6ca00c2bee2f..8606bdb7930a 100644 --- a/packages/themes/src/next/g90.js +++ b/packages/themes/src/next/g90.js @@ -40,6 +40,10 @@ import { // Constants white, + black, + + // Tools + rgba, } from '@carbon/colors'; import { adjustLightness } from '../tools'; @@ -192,8 +196,9 @@ export const skeletonElement = gray70; // Misc export const interactive = blue50; export const highlight = blue70; -export const overlay = 'rgba(22, 22, 22, 0.7)'; +export const overlay = rgba(black, 0.65); export const toggleOff = gray50; +export const shadow = rgba(black, 0.8); export { // Type diff --git a/packages/themes/src/next/tokens/__tests__/__snapshots__/v11-test.js.snap b/packages/themes/src/next/tokens/__tests__/__snapshots__/v11-test.js.snap index 181d9068e21e..ff737aea4135 100644 --- a/packages/themes/src/next/tokens/__tests__/__snapshots__/v11-test.js.snap +++ b/packages/themes/src/next/tokens/__tests__/__snapshots__/v11-test.js.snap @@ -233,6 +233,7 @@ Array [ "highlight", "overlay", "toggle-off", + "shadow", "focus", "focus-inset", "focus-inverse", diff --git a/packages/themes/src/next/tokens/v11TokenGroup.js b/packages/themes/src/next/tokens/v11TokenGroup.js index 937a633dac75..d70bab34dff2 100644 --- a/packages/themes/src/next/tokens/v11TokenGroup.js +++ b/packages/themes/src/next/tokens/v11TokenGroup.js @@ -350,6 +350,9 @@ export const group = TokenGroup.create({ { name: 'toggle-off', }, + { + name: 'shadow', + }, focus, skeleton, diff --git a/packages/themes/src/next/white.js b/packages/themes/src/next/white.js index 6bbddd37bb67..d930c5f9cda1 100644 --- a/packages/themes/src/next/white.js +++ b/packages/themes/src/next/white.js @@ -191,6 +191,7 @@ export const interactive = blue60; export const highlight = blue20; export const overlay = 'rgba(22, 22, 22, 0.5)'; export const toggleOff = gray50; +export const shadow = 'rgba(0, 0, 0, 0.3)'; // Type export { diff --git a/packages/themes/src/tokens.js b/packages/themes/src/tokens.js index 2140cdaf82d0..9a65ea2f0852 100644 --- a/packages/themes/src/tokens.js +++ b/packages/themes/src/tokens.js @@ -150,6 +150,7 @@ const colors = [ 'overlay', 'toggleOff', + 'shadow', 'buttonPrimary', 'buttonSecondary', @@ -346,6 +347,7 @@ export const unstable__meta = { 'overlay', 'toggleOff', + 'shadow', 'buttonPrimary', 'buttonSecondary', diff --git a/packages/themes/src/v9.js b/packages/themes/src/v9.js index 3b18d198b9f0..09009202ec20 100644 --- a/packages/themes/src/v9.js +++ b/packages/themes/src/v9.js @@ -6,7 +6,7 @@ */ import { adjustLightness } from './tools'; -import { white, red60, gray40 } from '@carbon/colors'; +import { white, red60, gray40, black, rgba } from '@carbon/colors'; export const interactive01 = '#3d70b2'; export const interactive02 = '#4d5358'; @@ -147,6 +147,7 @@ export const supportInfoInverse = inverseSupport04; export const overlay = overlay01; export const toggleOff = ui04; +export const shadow = rgba(black, 0.3); export const buttonPrimary = interactive01; export const buttonSecondary = interactive02; diff --git a/packages/themes/src/white.js b/packages/themes/src/white.js index c928676bf532..19fe02f00ae5 100644 --- a/packages/themes/src/white.js +++ b/packages/themes/src/white.js @@ -37,6 +37,7 @@ import { // Constants white, + black, // Tools rgba, @@ -182,6 +183,7 @@ export const supportInfoInverse = inverseSupport04; export const overlay = overlay01; export const toggleOff = ui04; +export const shadow = rgba(black, 0.3); export const buttonPrimary = interactive01; export const buttonSecondary = interactive02;