diff --git a/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap b/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap index 927975b6f8..2efb42a232 100644 --- a/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap +++ b/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap @@ -9,14 +9,12 @@ exports[`AttentionBox Tests Snapshot Tests renders correctly 1`] = ` className="monday-style-attention-box-component__title-container monday-style-attention-box-component--type-primary__title-container" > - - + /> `; @@ -98,7 +91,6 @@ exports[`Checkbox Tests Snapshot Tests renders correctly when disabled 1`] = ` onMouseUp={[Function]} > @@ -132,9 +122,7 @@ exports[`Checkbox Tests Snapshot Tests renders correctly when disabled 1`] = ` - - + /> `; @@ -144,7 +132,6 @@ exports[`Checkbox Tests Snapshot Tests renders correctly with empty props 1`] = onMouseUp={[Function]} > @@ -178,8 +163,6 @@ exports[`Checkbox Tests Snapshot Tests renders correctly with empty props 1`] = - - + /> `; diff --git a/src/components/Combobox/__tests__/__snapshots__/combobox.jest.js.snap b/src/components/Combobox/__tests__/__snapshots__/combobox.jest.js.snap index ff08a94105..30efe67897 100644 --- a/src/components/Combobox/__tests__/__snapshots__/combobox.jest.js.snap +++ b/src/components/Combobox/__tests__/__snapshots__/combobox.jest.js.snap @@ -55,11 +55,11 @@ exports[` renders correctly with empty props 1`] = ` tabIndex="-1" >
renders correctly with empty props 1`] = ` tabIndex="-1" >
@@ -157,11 +157,11 @@ exports[` renders correctly with one option 1`] = ` tabIndex="-1" >
renders correctly with one option 1`] = ` tabIndex="-1" >
@@ -279,11 +279,11 @@ exports[` renders correctly with options and categories 1`] = ` tabIndex="-1" >
renders correctly with options and categories 1`] = ` tabIndex="-1" >
diff --git a/src/components/Dropdown/__tests__/__snapshots__/dropdown.jest.js.snap b/src/components/Dropdown/__tests__/__snapshots__/dropdown.jest.js.snap index 91c38f2c7a..69cda20b52 100644 --- a/src/components/Dropdown/__tests__/__snapshots__/dropdown.jest.js.snap +++ b/src/components/Dropdown/__tests__/__snapshots__/dropdown.jest.js.snap @@ -69,7 +69,6 @@ exports[`Dropdown should open menu on click if set 1`] = ` > { - const tabIndex = clickable ? 0 : -1; +const CustomSvgIcon = ({ className, src, onClick, clickable, ariaLabel, ariaHidden, ...props }) => { + const screenReaderAccessProps = useIconScreenReaderAccessProps({ + isClickable: clickable, + label: ariaLabel, + isDecorationOnly: ariaHidden + }); return ( { CustomSvgIcon.defaultProps = { className: PropTypes.string, - src: PropTypes.string + src: PropTypes.string, + ariaLabel: PropTypes.string, + ariaHidden: PropTypes.bool }; CustomSvgIcon.propTypes = { className: "", - src: "" + src: "", + ariaLabel: undefined, + ariaHidden: false }; export default CustomSvgIcon; diff --git a/src/components/Icon/FontIcon/FontIcon.jsx b/src/components/Icon/FontIcon/FontIcon.jsx index 1c6595328f..f92e9e1786 100644 --- a/src/components/Icon/FontIcon/FontIcon.jsx +++ b/src/components/Icon/FontIcon/FontIcon.jsx @@ -2,20 +2,25 @@ import React, { forwardRef } from "react"; import "./FontIcon.scss"; import classNames from "classnames"; -const FontIcon = forwardRef(({ className, onClick, iconLabel, tabIndex, icon, role = "img", ariaHidden }, iconRef) => { - const iconClassName = typeof icon === "function" ? "" : icon; - return ( - - {typeof icon === "function" && icon()} - - ); -}); +const FontIcon = forwardRef( + ( + { className, onClick, "aria-label": iconLabel, tabIndex, icon, role = "img", "aria-hidden": ariaHidden }, + iconRef + ) => { + const iconClassName = typeof icon === "function" ? "" : icon; + return ( + + {typeof icon === "function" && icon()} + + ); + } +); export default FontIcon; diff --git a/src/components/Icon/Icon.jsx b/src/components/Icon/Icon.jsx index 23bcaf057c..9fd7c91a4d 100644 --- a/src/components/Icon/Icon.jsx +++ b/src/components/Icon/Icon.jsx @@ -25,11 +25,14 @@ const Icon = forwardRef( }, ref ) => { - const { tabindex, onClickCallback, computedClassName, iconRef, role } = useIconProps({ + const { screenReaderAccessProps, onClickCallback, computedClassName, iconRef } = useIconProps({ onClick, + iconLabel, clickable, className, - ignoreFocusStyle + isDecorationOnly: ariaHidden, + ignoreFocusStyle, + externalTabIndex }); const mergedRef = useMergeRefs({ refs: [ref, iconRef] }); @@ -42,28 +45,22 @@ const Icon = forwardRef( const IconComponent = icon; return ( ); } return ( ); } diff --git a/src/components/Icon/hooks/useIconProps.js b/src/components/Icon/hooks/useIconProps.js index cbf3fe8fa9..a39f83a3b8 100644 --- a/src/components/Icon/hooks/useIconProps.js +++ b/src/components/Icon/hooks/useIconProps.js @@ -4,10 +4,19 @@ import NOOP from "lodash/noop"; import useEventListener from "../../../hooks/useEventListener"; import useKeyEvent from "../../../hooks/useKeyEvent"; import { keyCodes } from "../../../constants/KeyCodes"; +import useIconScreenReaderAccessProps from "../../../hooks/useIconScreenReaderAccessProps"; const KEYS = [keyCodes.ENTER, keyCodes.SPACE]; -export default function useIconProps({ onClick, className, clickable, ignoreFocusStyle }) { +export default function useIconProps({ + onClick, + className, + clickable, + ignoreFocusStyle, + isDecorationOnly, + iconLabel, + externalTabIndex +}) { const iconRef = useRef(null); const onEnterCallback = useCallback( event => { @@ -54,15 +63,20 @@ export default function useIconProps({ onClick, className, clickable, ignoreFocu }, [onClick] ); - const tabindex = clickable ? 0 : -1; - const role = clickable ? "button" : undefined; + + const screenReaderAccessProps = useIconScreenReaderAccessProps({ + isClickable: clickable, + label: iconLabel, + isDecorationOnly + }); + + screenReaderAccessProps.tabIndex = externalTabIndex ?? screenReaderAccessProps.tabIndex; return { - tabindex, + screenReaderAccessProps, onClickCallback, computedClassName, onEnterCallback, - iconRef, - role + iconRef }; } diff --git a/src/components/MultiStepIndicator/__tests__/__snapshots__/multiStepIndicator.jest.js.snap b/src/components/MultiStepIndicator/__tests__/__snapshots__/multiStepIndicator.jest.js.snap index 7c983e5f0e..d321902165 100644 --- a/src/components/MultiStepIndicator/__tests__/__snapshots__/multiStepIndicator.jest.js.snap +++ b/src/components/MultiStepIndicator/__tests__/__snapshots__/multiStepIndicator.jest.js.snap @@ -21,14 +21,12 @@ exports[`MultiStepIndicator Render tests Renders correctly with non-default prop className="monday-style-step-indicator-component__number-container__text monday-style-step-indicator-component--type-success__number-container__text monday-style-step-indicator-component--status-fulfilled__number-container__text" >
- {directChildren} - {!!menuChildren.length && ( +
+ {index !== null && ( +
+ {directChildren} + {!!menuChildren.length && ( + +
{menuChildren}
+
+ )} +
+ )} +
+ {children} -
{menuChildren}
+
- )} +
); } @@ -75,6 +101,8 @@ ResponsiveList.propTypes = { These attributes will be passed to the MenuButton */ menuButtonProps: PropTypes.object, + menuButtonAriaLabel: "More Actions", + rootClassName: PropTypes.string, dialogClassName: PropTypes.string, menuButtonSize: PropTypes.oneOf(Object.keys(ResponsiveList.menuButtonSizes)), /** @@ -92,6 +120,8 @@ ResponsiveList.defaultProps = { className: "", dialogClassName: "", menuButtonClassName: "", + rootClassName: "", + menuButtonAriaLabel: "More Actions", menuButtonProps: {}, menuButtonSize: ResponsiveList.menuButtonSizes.SMALL, paddingSize: DEFAULT_MINIMAL_MARGIN, diff --git a/src/components/ResponsiveList/ResponsiveList.scss b/src/components/ResponsiveList/ResponsiveList.scss index a3701d27a2..f47c77ee5b 100644 --- a/src/components/ResponsiveList/ResponsiveList.scss +++ b/src/components/ResponsiveList/ResponsiveList.scss @@ -1,6 +1,9 @@ @import "../../styles/themes.scss"; @import "../../styles/typography.scss"; +.responsive-list--root { + position: relative; +} .responsive-list--wrapper { display: flex; justify-content: flex-end; @@ -8,6 +11,11 @@ flex-shrink: 0; } } +.responsive-list--dummy { + width: 100%; + position: absolute; + visibility: hidden; +} .responsive-list--menu-button-dialog { display: flex; } diff --git a/src/components/ResponsiveList/__stories__/responsiveList.stories.js b/src/components/ResponsiveList/__stories__/responsiveList.stories.js index 34886d8f3a..2e2d20f26e 100644 --- a/src/components/ResponsiveList/__stories__/responsiveList.stories.js +++ b/src/components/ResponsiveList/__stories__/responsiveList.stories.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { withPerformance } from "storybook-addon-performance"; import ResponsiveList from "../ResponsiveList"; import "./responsiveListStory.scss"; @@ -16,11 +16,13 @@ import { Alert, Broom, Search as SearchIcon, - CloseSmall + CloseSmall, + MoreActions } from "../../Icon/Icons"; import { MenuItem } from "../../index"; import Menu from "../../Menu/Menu/Menu"; import DescriptionLabel from "../../storybook-helpers/description-label/description-label"; +import { boolean, number } from "@storybook/addon-knobs"; function SecondaryContentComponent() { return ( @@ -32,6 +34,7 @@ function SecondaryContentComponent() { } const DefaultExampleTemplate = (responseListProps) => { + const { lessItems } = responseListProps; return }> Add Item @@ -44,19 +47,19 @@ const DefaultExampleTemplate = (responseListProps) => { secondaryIconName={() => } />
- - } + {!lessItems && - } + {!lessItems && - } + {!lessItems && + } @@ -66,8 +69,10 @@ const DefaultExampleTemplate = (responseListProps) => { } -export const Sandbox = () => ( -
+export const Sandbox = () => { + const lessItems = boolean("Less iitems", false); + + return
Use this component when you want to collapse elements into a menu button which appends to the end of the row. The list wraps the element with display: flex; property in order to @@ -75,19 +80,40 @@ export const Sandbox = () => (
- +
-); +}; export const SandboxWithDifferentIcon = () => { return
- You can also override the MenuButton props. Here's an example of how to use it with Bolt icon + You can also override the MenuButton props. Here's an example of how to use it with MoreActions icon
- + +
+
+} + + +export const ChangeChildrenCheck = () => { + const width = number("width", 300) + const knobLessItems = boolean("less items", false); + const [lessItems, setLessItems] = useState(true); + setTimeout(() => { + setLessItems(false); + }, 100); + return
+ + This is a story to reproduce a case where the items in the list are changed, + it should still be able to recalculate their size. + It adds some items at the beginning of the story, and it should be able to calculate the new items size although they weren't drawn yet. + +
+
+
} diff --git a/src/components/Search/Search.jsx b/src/components/Search/Search.jsx index e352c1b336..16f5f446dc 100644 --- a/src/components/Search/Search.jsx +++ b/src/components/Search/Search.jsx @@ -146,7 +146,7 @@ Search.defaultProps = { className: "", id: "search", validation: null, - inputAriaLabel: "", + inputAriaLabel: undefined, searchResultsContainerId: "", activeDescendant: "", iconNames: ICON_NAMES diff --git a/src/components/Tabs/Tab/Tab.jsx b/src/components/Tabs/Tab/Tab.jsx index f9ad51dfd6..29a50b5129 100644 --- a/src/components/Tabs/Tab/Tab.jsx +++ b/src/components/Tabs/Tab/Tab.jsx @@ -5,59 +5,49 @@ import useMergeRefs from "../../../hooks/useMergeRefs"; import Icon from "../../Icon/Icon"; import "./Tab.scss"; -const Tab = forwardRef(({ - className, - id, - value, - disabled, - active, - focus, - onClick, - icon, - iconType, - iconSide, - children -}, ref) => { - const componentRef = useRef(null); - const mergedRef = useMergeRefs({ refs: [ref, componentRef] }); +const Tab = forwardRef( + ({ className, id, value, disabled, active, focus, onClick, icon, iconType, iconSide, children }, ref) => { + const componentRef = useRef(null); + const mergedRef = useMergeRefs({ refs: [ref, componentRef] }); - function renderIconAndChildren() { - if (!icon) return children; + function renderIconAndChildren() { + if (!icon) return children; - const iconElement = ( - - ); + const iconElement = ( + + ); - if (iconSide === "left") { - return [iconElement, ...children]; - } + if (iconSide === "left") { + return [iconElement, ...children]; + } - return [...children, iconElement]; - } + return [...children, iconElement]; + } - return ( - - ); -}); + + ); + } +); Tab.propTypes = { className: PropTypes.string, diff --git a/src/components/Tabs/Tab/__tests__/__snapshots__/tab.jest.js.snap b/src/components/Tabs/Tab/__tests__/__snapshots__/tab.jest.js.snap index 79ba718917..d0c66ea385 100644 --- a/src/components/Tabs/Tab/__tests__/__snapshots__/tab.jest.js.snap +++ b/src/components/Tabs/Tab/__tests__/__snapshots__/tab.jest.js.snap @@ -73,14 +73,12 @@ exports[` Snapshot tests renders correctly tab with icon on left 1`] = ` onClick={[Function]} >
- {action &&
{action}
} + {(toastButtons || deprecatedAction) && ( +
{toastButtons || deprecatedAction}
+ )} {closeable && ( - closeToast()} - action={ - - } - type={knobs.type} - icon={icon} - closeable={knobs.closeable} - autoHideDuration={knobs.autoHideDuration} - hideIcon={knobs.hideIcon} - > - Something Happened - - - + + + closeToast()} + type={knobs.type} + icon={icon} + closeable={knobs.closeable} + autoHideDuration={knobs.autoHideDuration} + hideIcon={knobs.hideIcon} + > + Something Happened + + + + + closeToastButton()} + type={knobs.type} + actions={[{ type: Toast.actionTypes.BUTTON, content: "Undo 5" }]} + icon={icon} + closeable={knobs.closeable} + autoHideDuration={knobs.autoHideDuration} + hideIcon={knobs.hideIcon} + > + Something Happened + + + + + closeToastLink()} + type={knobs.type} + icon={icon} + closeable={knobs.closeable} + autoHideDuration={knobs.autoHideDuration} + hideIcon={knobs.hideIcon} + actions={[{ type: Toast.actionTypes.LINK, text: "Lorem ipsum", href: "https://monday.com" }]} + > + Something Happened + + + + + closeToastLinkButton()} + type={knobs.type} + icon={icon} + closeable={knobs.closeable} + autoHideDuration={knobs.autoHideDuration} + hideIcon={knobs.hideIcon} + actions={[ + { type: Toast.actionTypes.LINK, text: "Lorem ipsum", href: "https://monday.com" }, + { type: Toast.actionTypes.BUTTON, content: "Undo 5" } + ]} + > + Something Happened + + ); }; - export default { title: "Components|Toast", component: Toast diff --git a/src/components/Toast/__tests__/__snapshots__/toast.jest.js.snap b/src/components/Toast/__tests__/__snapshots__/toast.jest.js.snap new file mode 100644 index 0000000000..f446a72e0a --- /dev/null +++ b/src/components/Toast/__tests__/__snapshots__/toast.jest.js.snap @@ -0,0 +1,367 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Toast tests Snapshot Tests don't renders close button if closeable=false 1`] = ` +
+
+ +
+
+ Something Happened +
+
+`; + +exports[`Toast tests Snapshot Tests renders correctly (renders nothing) with empty props 1`] = `null`; + +exports[`Toast tests Snapshot Tests renders correctly with button 1`] = ` +
+
+ +
+
+ Something Happened +
+
+ +
+ +
+`; + +exports[`Toast tests Snapshot Tests renders correctly with button and link 1`] = ` +
+
+ +
+
+ Something Happened + + + Lorem ipsum + + +
+
+ +
+ +
+`; + +exports[`Toast tests Snapshot Tests renders correctly with link 1`] = ` +
+
+ +
+
+ Something Happened + + + Lorem ipsum + + +
+
+ +
+`; + +exports[`Toast tests Snapshot Tests renders nothing when open is false 1`] = `null`; + +exports[`Toast tests Snapshot Tests renders toast when open is true 1`] = ` +
+
+ +
+
+ Something Happened +
+ +
+`; diff --git a/src/components/Toast/__tests__/toast.jest.js b/src/components/Toast/__tests__/toast.jest.js index 932d972d26..891729ef99 100644 --- a/src/components/Toast/__tests__/toast.jest.js +++ b/src/components/Toast/__tests__/toast.jest.js @@ -2,62 +2,113 @@ import React from "react"; import { fireEvent, render, cleanup } from "@testing-library/react"; import { act } from "@testing-library/react-hooks"; import Toast from "../Toast"; +import renderer from "react-test-renderer"; +import { Checkbox } from "../../Checkbox/Checkbox"; jest.useFakeTimers(); const renderComponent = ({ ...props } = {}, contenct = "") => { return render({contenct}); }; +describe("Toast tests", () => { + describe("Snapshot Tests", () => { + it("renders correctly (renders nothing) with empty props", () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); + }); -describe("", () => { - afterEach(() => { - cleanup(); - }); - - it("renders nothing when open=false", () => { - const toast = renderComponent({}, "text"); - expect(toast.queryByText("text")).toBeNull(); - }); - - it("renders toast when open=true", () => { - const toast = renderComponent({ open: true }, "text"); - expect(toast.queryByText("text")).not.toBeNull(); - }); + it("renders nothing when open is false", () => { + const tree = renderer.create(Something Happened).toJSON(); + expect(tree).toMatchSnapshot(); + }); - it("rendres action", () => { - const action =
my action
; - const toast = renderComponent({ open: true, action }, "text"); - expect(toast.queryByText("my action")).not.toBeNull(); - }); + it("renders toast when open is true", () => { + const tree = renderer.create(Something Happened).toJSON(); + expect(tree).toMatchSnapshot(); + }); - it("don't renders close button if closeable=false", () => { - const toast = renderComponent({ open: true, closeable: false }, "text"); - expect(toast.queryByLabelText("close-toast")).toBeNull(); - }); + it("don't renders close button if closeable=false", () => { + const tree = renderer + .create( + + Something Happened + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); - it("calls onClose when click on close button", () => { - const onCloseMock = jest.fn(); - const toast = renderComponent({ - open: true, - onClose: onCloseMock + it("renders correctly with button", () => { + const tree = renderer + .create( + + Something Happened + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); }); - const closeButton = toast.getByLabelText("close-toast"); - act(() => { - fireEvent.click(closeButton); + it("renders correctly with link", () => { + const tree = renderer + .create( + + Something Happened + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); }); - expect(onCloseMock.mock.calls.length).toBe(1); + it("renders correctly with button and link", () => { + const tree = renderer + .create( + + Something Happened + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); }); + describe("Integration Tests", () => { + afterEach(() => { + cleanup(); + }); + + it("calls onClose when click on close button", () => { + const onCloseMock = jest.fn(); + const toast = renderComponent({ + open: true, + onClose: onCloseMock + }); + const closeButton = toast.getByLabelText("close-toast"); + + act(() => { + fireEvent.click(closeButton); + }); + + expect(onCloseMock.mock.calls.length).toBe(1); + }); - it("calls onClose after 1S when autoHideDuration=1000", () => { - const onCloseMock = jest.fn(); - renderComponent({ - onClose: onCloseMock, - autoHideDuration: 1000, - open: true + it("calls onClose after 1S when autoHideDuration=1000", () => { + const onCloseMock = jest.fn(); + renderComponent({ + onClose: onCloseMock, + autoHideDuration: 1000, + open: true + }); + jest.advanceTimersByTime(1000); + expect(onCloseMock.mock.calls.length).toBe(1); }); - jest.advanceTimersByTime(1000); - expect(onCloseMock.mock.calls.length).toBe(1); }); }); diff --git a/src/components/Toggle/Toggle.scss b/src/components/Toggle/Toggle.scss index f278e56513..a9bb152203 100644 --- a/src/components/Toggle/Toggle.scss +++ b/src/components/Toggle/Toggle.scss @@ -7,6 +7,9 @@ align-items: center; &--disabled { opacity: 0.4; + & .monday-style-toggle_toggle { + cursor: not-allowed; + } & .monday-style-toggle_text { color: rgba(var(--primary-text-color), 0.4); } diff --git a/src/components/index.js b/src/components/index.js index cc3416d7f3..ff0918fafa 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -30,6 +30,8 @@ export { default as Checkbox } from "./Checkbox/Checkbox"; export { default as DialogContentContainer } from "./DialogContentContainer/DialogContentContainer"; export { default as Dropdown } from "./Dropdown/Dropdown"; export { default as Toast } from "./Toast/Toast"; +export { default as ToastButton } from "./Toast/ToastButton/ToastButton"; +export { default as ToastLink } from "./Toast/ToastLink/ToastLink"; export { default as Banner } from "./Banner/Banner"; export { default as ButtonGroup } from "./ButtonGroup/ButtonGroup"; diff --git a/src/helpers/screenReaderAccessHelper.js b/src/helpers/screenReaderAccessHelper.js new file mode 100644 index 0000000000..0e0e9d1fa4 --- /dev/null +++ b/src/helpers/screenReaderAccessHelper.js @@ -0,0 +1,28 @@ +export function getIconScreenReaderAccessProps({ isClickable, isDecorationOnly, isKeyboardAccessible, label }) { + if (isClickable) return getClickableIconScreenReaderAccessProps({ label, isDecorationOnly, isKeyboardAccessible }); + return { + role: "img", + "aria-hidden": isDecorationOnly, + tabIndex: undefined, + "aria-label": isDecorationOnly ? undefined : label + }; +} + +export function getClickableScreenReaderAccessProps({ isKeyboardAccessible = true, isDecorationOnly = false }) { + return { + role: "button", + tabIndex: isKeyboardAccessible ? 0 : -1, + "aria-hidden": isDecorationOnly + }; +} + +export function getClickableIconScreenReaderAccessProps({ + label, + isDecorationOnly = false, + isKeyboardAccessible = true +}) { + return { + ...getClickableScreenReaderAccessProps({ isDecorationOnly, isKeyboardAccessible }), + "aria-label": label + }; +} diff --git a/src/hooks/useElementsOverflowingIndex.js b/src/hooks/useElementsOverflowingIndex.js index 786e2fa0fb..500665bf7d 100644 --- a/src/hooks/useElementsOverflowingIndex.js +++ b/src/hooks/useElementsOverflowingIndex.js @@ -1,14 +1,15 @@ import { useCallback, useEffect, useState } from "react"; +import last from "lodash/last"; import useResizeObserver from "./useResizeObserver"; // Use this hook when you want to get the index of the child which should be hidden from -function useElementsOverflowingIndex({ ref, children, paddingSize, resizeDebounceTime }) { +function useElementsOverflowingIndex({ ref, children, paddingSize, resizeDebounceTime, ignoreLast }) { const [size, setSize] = useState(null); const onResize = useCallback( - () => { - setSize(ref.current.scrollWidth); + ({ borderBoxSize }) => { + setSize(borderBoxSize.inlineSize); }, [setSize] ); @@ -19,10 +20,21 @@ function useElementsOverflowingIndex({ ref, children, paddingSize, resizeDebounc }); const [aggregatedChildLengths, setAggregatedChildLengths] = useState([]); - const [indexToSplit, setIndexToSplit] = useState(-1); + const [indexToSplit, setIndexToSplit] = useState(null); useEffect(() => { - setIndexToSplit(aggregatedChildLengths.findIndex(({ totalLength }) => totalLength > size - paddingSize)); + if(ignoreLast) { + const withoutLast = aggregatedChildLengths.slice(0, -1); + const allInWithoutLast = !withoutLast.find(({ totalLength }) => totalLength > size - paddingSize); + if(allInWithoutLast) { + setIndexToSplit(-1); + } else { + const lastSize = aggregatedChildLengths.length > 0 ? last(aggregatedChildLengths).childLength : 0; + setIndexToSplit(aggregatedChildLengths.findIndex(({ totalLength }) => totalLength > size - paddingSize - lastSize)); + } + } else { + setIndexToSplit(aggregatedChildLengths.findIndex(({ totalLength }) => totalLength > size - paddingSize)); + } }, [aggregatedChildLengths, size, setIndexToSplit, paddingSize]); useEffect(() => { diff --git a/src/hooks/useIconScreenReaderAccessProps.js b/src/hooks/useIconScreenReaderAccessProps.js new file mode 100644 index 0000000000..290a4a7389 --- /dev/null +++ b/src/hooks/useIconScreenReaderAccessProps.js @@ -0,0 +1,15 @@ +import { useMemo } from "react"; +import { getIconScreenReaderAccessProps } from "../helpers/screenReaderAccessHelper"; + +export default function useIconScreenReaderAccessProps({ isClickable, label, isDecorationOnly }) { + const screenReaderAccessProps = useMemo( + () => + getIconScreenReaderAccessProps({ + isClickable, + label, + isDecorationOnly + }), + [isClickable, label, isDecorationOnly] + ); + return screenReaderAccessProps; +} diff --git a/src/published-components.js b/src/published-components.js index 4828b48eaf..e10a9dc909 100644 --- a/src/published-components.js +++ b/src/published-components.js @@ -41,6 +41,8 @@ const publishedComponents = { Search: "/src/components/Search/Search.jsx", TextField: "/src/components/TextField/TextField.jsx", Toast: "/src/components/Toast/Toast.jsx", + ToastButton: "/src/components/Toast/ToastButton/ToastButton.jsx", + ToastLink: "/src/components/Toast/ToastLink/ToastLink.jsx", Tooltip: "/src/components/Tooltip/Tooltip.jsx", Button: "/src/components/Button/Button.jsx", Loader: "/src/components/Loader/Loader.jsx",