diff --git a/lerna.json b/lerna.json index ae61a12fb..0b5eb8916 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,5 @@ { - "packages": [ - "packages/*" - ], - "version": "1.16.4", + "packages": ["packages/*"], + "version": "1.16.5", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } diff --git a/package-lock.json b/package-lock.json index d1607f41b..82839c26d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26918,10 +26918,10 @@ } }, "packages/example-react": { - "version": "1.16.4", + "version": "1.16.5", "dependencies": { "@livechat/design-system-icons": "^1.16.3", - "@livechat/design-system-react-components": "^1.16.4", + "@livechat/design-system-react-components": "^1.16.5", "react": "^17.0.2", "react-dom": "^17.0.2" }, @@ -26945,7 +26945,7 @@ }, "packages/react-components": { "name": "@livechat/design-system-react-components", - "version": "1.16.4", + "version": "1.16.5", "license": "ISC", "dependencies": { "@emotion/css": "^11.9.0", @@ -37054,7 +37054,7 @@ "version": "file:packages/example-react", "requires": { "@livechat/design-system-icons": "^1.16.3", - "@livechat/design-system-react-components": "^1.16.4", + "@livechat/design-system-react-components": "^1.16.5", "@types/react": "^17.0.33", "@types/react-dom": "^17.0.10", "@vitejs/plugin-react": "^1.0.7", diff --git a/packages/example-react/package.json b/packages/example-react/package.json index aad513058..9963707b7 100644 --- a/packages/example-react/package.json +++ b/packages/example-react/package.json @@ -1,7 +1,7 @@ { "name": "example-react", "private": true, - "version": "1.16.4", + "version": "1.16.5", "scripts": { "start": "vite --open", "build": "tsc && vite build", @@ -9,7 +9,7 @@ }, "dependencies": { "@livechat/design-system-icons": "^1.16.3", - "@livechat/design-system-react-components": "^1.16.4", + "@livechat/design-system-react-components": "^1.16.5", "react": "^17.0.2", "react-dom": "^17.0.2" }, diff --git a/packages/react-components/.storybook/preview-head.html b/packages/react-components/.storybook/preview-head.html index f49a1bf88..a7be8ea9f 100644 --- a/packages/react-components/.storybook/preview-head.html +++ b/packages/react-components/.storybook/preview-head.html @@ -28,7 +28,8 @@ gap: 5px; } - .docs-story, .sb-show-main { + .docs-story, + .sb-show-main { transition: all 0.2s ease; } diff --git a/packages/react-components/package.json b/packages/react-components/package.json index 79638a10d..11a469cd6 100644 --- a/packages/react-components/package.json +++ b/packages/react-components/package.json @@ -1,6 +1,6 @@ { "name": "@livechat/design-system-react-components", - "version": "1.16.4", + "version": "1.16.5", "description": "", "publishConfig": { "access": "public" diff --git a/packages/react-components/src/components/DetailsCard/DetailsCard.module.scss b/packages/react-components/src/components/DetailsCard/DetailsCard.module.scss index 696c6042b..9dc15a07e 100644 --- a/packages/react-components/src/components/DetailsCard/DetailsCard.module.scss +++ b/packages/react-components/src/components/DetailsCard/DetailsCard.module.scss @@ -1,13 +1,15 @@ $base-class: 'details-card'; +$min-card-height: 72px; .#{$base-class} { position: relative; background-color: var(--surface-primary-default); width: 100%; + min-height: $min-card-height; color: var(--content-basic-primary); &:hover { - .#{$base-class}__float-button--open { + .#{$base-class}__button--fading { opacity: 1; } } @@ -16,38 +18,39 @@ $base-class: 'details-card'; border-bottom: 1px solid var(--border-basic-tertiary); } - &__button { + &__label-wrapper { display: flex; position: relative; align-items: center; justify-content: space-between; - transition: all 0.2s ease; + transition: + opacity var(--transition-duration-fast-1) ease-out + var(--transition-duration-moderate-1), + padding 0s ease-out var(--transition-duration-moderate-1), + max-height 0s ease-out; opacity: 1; border: 0; background-color: transparent; padding: 0; padding: var(--spacing-6); width: 100%; - max-height: 72px; + max-height: $min-card-height; overflow: hidden; color: var(--content-basic-primary); - &:hover { - cursor: pointer; - } - - &__icon { - transition: all 0.2s ease; - - &--open { - transform: rotate(90deg); - } - } - &--hide { + transition: + opacity var(--transition-duration-fast-1) ease-out, + padding var(--transition-duration-fast-1) ease-out + var(--transition-duration-fast-1), + max-height 0s ease-out var(--transition-duration-fast-1); opacity: 0; padding: 0 var(--spacing-6); - height: 0; + max-height: 0; + } + + &--fading { + position: absolute; } } @@ -82,21 +85,19 @@ $base-class: 'details-card'; } } - &__float-button { + &__button { position: absolute; top: 18px; right: 16px; transition: all 0.2s ease; - opacity: 0; z-index: 1; - &--closed { - opacity: 1; + &--fading { + opacity: 0; } - &--open { - top: var(--spacing-1); - right: var(--spacing-1); + &--closed { + opacity: 1; } &__icon { @@ -109,11 +110,18 @@ $base-class: 'details-card'; } &__content-wrapper { - transition: all 0.2s ease; + transition: + opacity var(--transition-duration-moderate-1) ease-out, + max-height var(--transition-duration-fast-1) ease-out + var(--transition-duration-moderate-1); opacity: 0; overflow: hidden; &--open { + transition: + max-height var(--transition-duration-fast-1) ease-out, + opacity var(--transition-duration-moderate-1) ease-out + var(--transition-duration-fast-1); opacity: 1; } } diff --git a/packages/react-components/src/components/DetailsCard/DetailsCard.spec.tsx b/packages/react-components/src/components/DetailsCard/DetailsCard.spec.tsx index 750f83fd1..d3df5b06b 100644 --- a/packages/react-components/src/components/DetailsCard/DetailsCard.spec.tsx +++ b/packages/react-components/src/components/DetailsCard/DetailsCard.spec.tsx @@ -20,48 +20,50 @@ const renderComponent = (props: IDetailsCardProps) => { describe(' component', () => { it('should render closed card with label by default', () => { - const { getByText, getByRole } = renderComponent(defaultProps); + const { getByText, getByTestId } = renderComponent(defaultProps); expect(getByText(label)).toBeVisible(); - expect(getByRole('button')).toHaveAttribute('aria-expanded', 'false'); + expect(getByTestId('details-card-label')).toHaveAttribute( + 'aria-expanded', + 'false' + ); }); it('should toggle the card on button click', () => { - const { getByRole } = renderComponent(defaultProps); + const { getByRole, getByTestId } = renderComponent(defaultProps); const button = getByRole('button'); + const label = getByTestId('details-card-label'); userEvent.click(button); - expect(button).toHaveAttribute('aria-expanded', 'true'); + expect(label).toHaveAttribute('aria-expanded', 'true'); userEvent.click(button); - expect(button).toHaveAttribute('aria-expanded', 'false'); + expect(label).toHaveAttribute('aria-expanded', 'false'); }); it('should hide the label if card is open when hideLabelOnOpen is set', () => { - const { queryByTestId, getByTestId } = renderComponent({ + const { getByRole, getByTestId } = renderComponent({ ...defaultProps, hideLabelOnOpen: true, }); - const button = getByTestId('details-card-button'); - const floatButton = queryByTestId('details-card-floating-button'); + const label = getByTestId('details-card-label'); + const button = getByRole('button'); - expect(button).toHaveAttribute('aria-hidden', 'false'); - expect(floatButton).toBeInTheDocument(); - expect(floatButton).toHaveAttribute('aria-expanded', 'false'); + expect(label).toHaveAttribute('aria-hidden', 'false'); + expect(label).toHaveAttribute('aria-expanded', 'false'); userEvent.click(button); - expect(button).toHaveAttribute('aria-expanded', 'true'); - expect(button).toHaveAttribute('aria-hidden', 'true'); - expect(floatButton).toHaveAttribute('aria-expanded', 'true'); + expect(label).toHaveAttribute('aria-expanded', 'true'); + expect(label).toHaveAttribute('aria-hidden', 'true'); }); it('should be open if openOnInit is set to true', () => { - const { getByRole } = renderComponent({ + const { getByTestId } = renderComponent({ ...defaultProps, openOnInit: true, }); - const button = getByRole('button'); + const label = getByTestId('details-card-label'); - expect(button).toHaveAttribute('aria-expanded', 'true'); + expect(label).toHaveAttribute('aria-expanded', 'true'); }); it('should call onClick handler on label click', () => { diff --git a/packages/react-components/src/components/DetailsCard/DetailsCard.tsx b/packages/react-components/src/components/DetailsCard/DetailsCard.tsx index 1c67fab6a..0a275ab97 100644 --- a/packages/react-components/src/components/DetailsCard/DetailsCard.tsx +++ b/packages/react-components/src/components/DetailsCard/DetailsCard.tsx @@ -70,11 +70,14 @@ export const DetailsCard: React.FC = ({ withDivider && styles[`${baseClass}--with-divider`], className ); - const isMainButtonHidden = hideLabelOnOpen && isOpen; + const isLabelHidden = hideLabelOnOpen && isOpen; const isTextContent = typeof label === 'string'; - const handleButtonClick = () => { + const handleButtonClick = ( + e: React.MouseEvent + ) => { setIsOpen((prevValue) => !prevValue); + e.currentTarget.blur(); onClick?.(); }; @@ -96,16 +99,16 @@ export const DetailsCard: React.FC = ({ return (
-
- {!hideLabelOnOpen && ( + + - {hideLabelOnOpen && ( -