diff --git a/lerna.json b/lerna.json
index b2c0e088d..877ae451b 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
"packages": ["packages/*"],
- "version": "2.6.2",
+ "version": "2.8.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
diff --git a/package-lock.json b/package-lock.json
index e75dc226c..61d6b37f2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25957,10 +25957,10 @@
}
},
"packages/example-react": {
- "version": "2.6.2",
+ "version": "2.8.0",
"dependencies": {
- "@livechat/design-system-icons": "^2.5.3",
- "@livechat/design-system-react-components": "^2.6.2",
+ "@livechat/design-system-icons": "^2.8.0",
+ "@livechat/design-system-react-components": "^2.8.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
@@ -25974,7 +25974,7 @@
},
"packages/icons": {
"name": "@livechat/design-system-icons",
- "version": "2.5.3",
+ "version": "2.8.0",
"devDependencies": {
"@svgr/cli": "^8.1.0",
"glob": "^10.3.10",
@@ -25996,12 +25996,12 @@
},
"packages/react-components": {
"name": "@livechat/design-system-react-components",
- "version": "2.6.2",
+ "version": "2.8.0",
"license": "ISC",
"dependencies": {
"@floating-ui/react": "^0.26.25",
"@livechat/data-utils": "^0.2.16",
- "@livechat/design-system-icons": "^2.5.3",
+ "@livechat/design-system-icons": "^2.8.0",
"clsx": "^1.1.1",
"date-fns": "^2.28.0",
"lodash.debounce": "^4.0.8",
diff --git a/packages/example-react/package.json b/packages/example-react/package.json
index 76e02bcc3..7941755f7 100644
--- a/packages/example-react/package.json
+++ b/packages/example-react/package.json
@@ -1,15 +1,15 @@
{
"name": "example-react",
"private": true,
- "version": "2.6.2",
+ "version": "2.8.0",
"scripts": {
"start": "vite --open",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
- "@livechat/design-system-icons": "^2.5.3",
- "@livechat/design-system-react-components": "^2.6.2",
+ "@livechat/design-system-icons": "^2.8.0",
+ "@livechat/design-system-react-components": "^2.8.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
diff --git a/packages/icons/package.json b/packages/icons/package.json
index 945db6892..250cd02bc 100644
--- a/packages/icons/package.json
+++ b/packages/icons/package.json
@@ -1,6 +1,6 @@
{
"name": "@livechat/design-system-icons",
- "version": "2.5.3",
+ "version": "2.8.0",
"description": "",
"publishConfig": {
"access": "public"
diff --git a/packages/icons/svg/arrows_diagonal.svg b/packages/icons/svg/arrows_diagonal.svg
new file mode 100644
index 000000000..94ae1979f
--- /dev/null
+++ b/packages/icons/svg/arrows_diagonal.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/icons/svg/arrows_diagonal_minimize.svg b/packages/icons/svg/arrows_diagonal_minimize.svg
new file mode 100644
index 000000000..7815a9c0c
--- /dev/null
+++ b/packages/icons/svg/arrows_diagonal_minimize.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/icons/svg/caret_down-filled.svg b/packages/icons/svg/caret_down-filled.svg
new file mode 100644
index 000000000..6b6d02a09
--- /dev/null
+++ b/packages/icons/svg/caret_down-filled.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/icons/svg/caret_down.svg b/packages/icons/svg/caret_down.svg
new file mode 100644
index 000000000..38f6607d5
--- /dev/null
+++ b/packages/icons/svg/caret_down.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/icons/svg/caret_up-filled.svg b/packages/icons/svg/caret_up-filled.svg
new file mode 100644
index 000000000..d60cd50b5
--- /dev/null
+++ b/packages/icons/svg/caret_up-filled.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/icons/svg/caret_up.svg b/packages/icons/svg/caret_up.svg
new file mode 100644
index 000000000..0812218ce
--- /dev/null
+++ b/packages/icons/svg/caret_up.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/icons/svg/multi_choice-filled.svg b/packages/icons/svg/multi_choice-filled.svg
new file mode 100644
index 000000000..3450c0aa2
--- /dev/null
+++ b/packages/icons/svg/multi_choice-filled.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/packages/icons/svg/multi_choice.svg b/packages/icons/svg/multi_choice.svg
new file mode 100644
index 000000000..11acebefc
--- /dev/null
+++ b/packages/icons/svg/multi_choice.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/react-components/package.json b/packages/react-components/package.json
index d090053a5..3053eeedc 100644
--- a/packages/react-components/package.json
+++ b/packages/react-components/package.json
@@ -1,6 +1,6 @@
{
"name": "@livechat/design-system-react-components",
- "version": "2.6.2",
+ "version": "2.8.0",
"description": "",
"publishConfig": {
"access": "public"
@@ -76,7 +76,7 @@
"dependencies": {
"@floating-ui/react": "^0.26.25",
"@livechat/data-utils": "^0.2.16",
- "@livechat/design-system-icons": "^2.5.3",
+ "@livechat/design-system-icons": "^2.8.0",
"clsx": "^1.1.1",
"date-fns": "^2.28.0",
"lodash.debounce": "^4.0.8",
diff --git a/packages/react-components/src/components/Accordion/Accordion.mdx b/packages/react-components/src/components/Accordion/Accordion.mdx
index a1349372e..8df5c122c 100644
--- a/packages/react-components/src/components/Accordion/Accordion.mdx
+++ b/packages/react-components/src/components/Accordion/Accordion.mdx
@@ -6,12 +6,14 @@ import * as AccordionStories from './Accordion.stories';
Accordion
-[Intro](#Intro) | [Component API](#ComponentAPI)
+[Intro](#Intro) | [Default Accordion](#Default) | [Promo Accordion](#Promo) | [Component API](#ComponentAPI)
## Intro
Accordion is a simple component for building expandable tiles that display provided content when opened.
+### Default Accordion
+
#### Example implementation
@@ -19,11 +21,39 @@ Accordion is a simple component for building expandable tiles that display provi
```jsx
import { Accordion } from '@livechat/design-system-react-components';
-
+ Label for closed accordion),
+ open: (Label for open accordion
),
+ }}
+ multilineElement={Multiline element
}
+ footer={Footer element
}
+ >
Default accordion content
```
+### Promo Accordion
+
+
+
+#### Example implementation
+
+```jsx
+import { AccordionPromo } from '@livechat/design-system-react-components';
+
+ Label for closed accordion),
+ open: (Label for open accordion
),
+ }}
+ multilineElement={Multiline element
}
+ footer={Footer element
}
+ >
+ Default accordion content
+
+```
+
## Component API
\ No newline at end of file
diff --git a/packages/react-components/src/components/Accordion/Accordion.module.scss b/packages/react-components/src/components/Accordion/Accordion.module.scss
index ff4d83cc2..598302138 100644
--- a/packages/react-components/src/components/Accordion/Accordion.module.scss
+++ b/packages/react-components/src/components/Accordion/Accordion.module.scss
@@ -39,6 +39,11 @@ $base-class: 'accordion';
}
}
+ &--promo {
+ border: 1px solid var(--border-basic-secondary);
+ background-color: var(--surface-primary-default);
+ }
+
&--open {
border: 1px solid var(--action-primary-default);
box-shadow: var(--shadow-float);
@@ -59,6 +64,10 @@ $base-class: 'accordion';
&--open {
transform: rotate(180deg);
}
+
+ &--promo {
+ top: 26px;
+ }
}
&__label {
@@ -69,6 +78,11 @@ $base-class: 'accordion';
&:hover {
cursor: pointer;
}
+
+ &--promo {
+ padding: var(--spacing-6) var(--spacing-12) var(--spacing-6)
+ var(--spacing-6);
+ }
}
&__content {
@@ -84,6 +98,19 @@ $base-class: 'accordion';
&--open {
opacity: 1;
}
+
+ &--promo {
+ padding: 0 var(--spacing-12) var(--spacing-6) var(--spacing-6);
+ }
+ }
+ }
+
+ &__footer {
+ border-top: 1px solid var(--border-basic-secondary);
+ padding: var(--spacing-5);
+
+ &--promo {
+ padding: var(--spacing-6);
}
}
}
diff --git a/packages/react-components/src/components/Accordion/Accordion.spec.tsx b/packages/react-components/src/components/Accordion/Accordion.spec.tsx
index 5f4573b86..36b9525b9 100644
--- a/packages/react-components/src/components/Accordion/Accordion.spec.tsx
+++ b/packages/react-components/src/components/Accordion/Accordion.spec.tsx
@@ -44,26 +44,26 @@ describe(' component', () => {
it('should call onClose and onOpen handlers on label click', async () => {
const onClose = vi.fn();
const onOpen = vi.fn();
- const { getByRole } = renderComponent({
+ const { getByText } = renderComponent({
...DEFAULT_PROPS,
onClose,
onOpen,
});
- expect(getByRole('button')).toHaveAttribute('aria-expanded', 'false');
- userEvent.click(getByRole('button'));
+ expect(getByText('Label')).toHaveAttribute('aria-expanded', 'false');
+ userEvent.click(getByText('Label'));
expect(onOpen).toHaveBeenCalledTimes(1);
await waitFor(() => {
- expect(getByRole('button')).toHaveAttribute('aria-expanded', 'false');
+ expect(getByText('Label')).toHaveAttribute('aria-expanded', 'false');
});
- userEvent.click(getByRole('button'));
+ userEvent.click(getByText('Label'));
expect(onClose).toHaveBeenCalledTimes(1);
});
it('should show different label content when open and closed', async () => {
- const { getByText, getByRole } = renderComponent({
+ const { getByText } = renderComponent({
...DEFAULT_PROPS,
label: {
open: Open label
,
@@ -72,7 +72,7 @@ describe(' component', () => {
});
expect(getByText('Closed label')).toBeInTheDocument();
- userEvent.click(getByRole('button'));
+ userEvent.click(getByText('Closed label'));
await waitFor(() => expect(getByText('Open label')).toBeInTheDocument());
});
@@ -84,4 +84,15 @@ describe(' component', () => {
expect(getByText('Multi')).toBeInTheDocument();
});
+
+ it('should show footer element if open', async () => {
+ const { queryByText, getByText } = renderComponent({
+ ...DEFAULT_PROPS,
+ footer: Footer
,
+ });
+
+ expect(queryByText('Footer')).not.toBeInTheDocument();
+ userEvent.click(getByText('Label'));
+ await waitFor(() => expect(queryByText('Footer')).toBeInTheDocument());
+ });
});
diff --git a/packages/react-components/src/components/Accordion/Accordion.stories.css b/packages/react-components/src/components/Accordion/Accordion.stories.css
index 312b64290..6926bc95b 100644
--- a/packages/react-components/src/components/Accordion/Accordion.stories.css
+++ b/packages/react-components/src/components/Accordion/Accordion.stories.css
@@ -29,3 +29,11 @@
}
}
}
+
+.accordion-promo-closed-heading {
+ margin-bottom: 4px;
+}
+
+.accordion-promo-closed-description {
+ color: var(--content-basic-secondary);
+}
diff --git a/packages/react-components/src/components/Accordion/Accordion.stories.tsx b/packages/react-components/src/components/Accordion/Accordion.stories.tsx
index 12b8383fe..96ba3272e 100644
--- a/packages/react-components/src/components/Accordion/Accordion.stories.tsx
+++ b/packages/react-components/src/components/Accordion/Accordion.stories.tsx
@@ -7,8 +7,12 @@ import { StoryDescriptor } from '../../stories/components/StoryDescriptor';
import { Icon } from '../Icon';
import { IPickerListItem, Picker } from '../Picker';
import { Tag } from '../Tag';
+import { Heading, Text } from '../Typography';
-import { Accordion } from './Accordion';
+import {
+ Accordion,
+ AccordionPromo as AccordionPromoComponent,
+} from './Accordion';
import { RULE_PICKER_OPTIONS, TAGS_PICKER_OPTIONS } from './stories-helpers';
import './Accordion.stories.css';
@@ -16,6 +20,9 @@ import './Accordion.stories.css';
export default {
title: 'Components/Accordion',
component: Accordion,
+ subcomponents: {
+ AccordionPromo: AccordionPromoComponent,
+ },
} as Meta;
export const Default = (): React.ReactElement => {
@@ -108,6 +115,83 @@ export const Examples = (): React.ReactElement => {
Default accordion content
+
+ Example footer element}>
+ Default accordion content
+
+
+
+ );
+};
+
+export const AccordionPromo = (): React.ReactElement => {
+ return (
+
+ Default accordion content
+
+ );
+};
+
+export const AccordionPromoExamples = (): React.ReactElement => {
+ return (
+
+
+
+
+ This example headline has 40 characters
+
+
+ A description with a maximum of 100 characters. That usually
+ means only one or two sentences
+
+
+ ),
+ open: (
+
+ Example headline for open state
+
+ ),
+ }}
+ >
+ Default accordion content
+
+
+
+
+ {`Hello {{ticket.requesterName}},`}
+
+ We haven't heard back from you for some time. If you need any
+ further help, please follow up on this email.
+
+ Thank you.
+
+ }
+ >
+ Default accordion content
+
+
+
+ Example footer element}
+ >
+ Default accordion content
+
+
);
};
diff --git a/packages/react-components/src/components/Accordion/Accordion.tsx b/packages/react-components/src/components/Accordion/Accordion.tsx
index ec1541860..a68b86a7d 100644
--- a/packages/react-components/src/components/Accordion/Accordion.tsx
+++ b/packages/react-components/src/components/Accordion/Accordion.tsx
@@ -5,24 +5,29 @@ import cx from 'clsx';
import { useAnimations, useHeightResizer } from '../../hooks';
import { Icon } from '../Icon';
-import { Text } from '../Typography';
+import { Heading, Text, TTextSize } from '../Typography';
import { AccordionMultilineElement } from './components/AccordionMultilineElement';
import { getLabel } from './helpers';
-import { IAccordionProps } from './types';
+import { useAccordion } from './hooks';
+import {
+ IAccordionProps,
+ IAccordionPromoProps,
+ IAccordionComponentProps,
+} from './types';
import styles from './Accordion.module.scss';
-const baseClass = 'accordion';
-
-export const Accordion: React.FC = ({
+const AccordionComponent: React.FC = ({
className,
+ mainClassName,
children,
label,
multilineElement,
- kind = 'default',
openOnInit = false,
isOpen,
+ isPromo,
+ footer,
onClose,
onOpen,
...props
@@ -38,34 +43,36 @@ export const Accordion: React.FC = ({
isVisible: currentlyOpen,
elementRef: contentRef,
});
+ const { size, handleResizeRef } = useHeightResizer();
+ const { handleExpandChange, handleKeyDown } = useAccordion({
+ isControlled,
+ isExpanded,
+ setShouldBeVisible,
+ onOpen,
+ onClose,
+ });
const mergedClassName = cx(
- styles[baseClass],
- styles[`${baseClass}--${kind}`],
+ mainClassName,
{
[styles[`${baseClass}--open`]]: isExpanded,
},
className
);
- const { size, handleResizeRef } = useHeightResizer();
-
- const handleExpandChange = (isExpanded: boolean) => {
- if (isExpanded) {
- onClose?.();
- !isControlled && setShouldBeVisible(false);
- } else {
- onOpen?.();
- !isControlled && setShouldBeVisible(true);
- }
- };
- const handleKeyDown = (event: React.KeyboardEvent) => {
- if (!isExpanded && (event.key === 'Enter' || event.key === ' ')) {
- handleExpandChange(isExpanded);
- }
+ const buildHeader = (isPromo?: boolean) => {
+ const Component = isPromo ? Heading : Text;
+ const props = {
+ 'aria-expanded': isExpanded,
+ as: 'div',
+ className: cx(styles[`${baseClass}__label`], {
+ [styles[`${baseClass}__label--promo`]]: isPromo,
+ }),
+ onClick: () => handleExpandChange(isExpanded),
+ bold: !isPromo ? true : undefined,
+ ...(isPromo ? { size: 'xs' as TTextSize } : {}),
+ };
- if (isExpanded && event.key === 'Escape') {
- handleExpandChange(isExpanded);
- }
+ return {getLabel(label, isExpanded)} ;
};
return (
@@ -80,18 +87,10 @@ export const Accordion: React.FC = ({
source={ChevronDown}
className={cx(styles[`${baseClass}__chevron`], {
[styles[`${baseClass}__chevron--open`]]: isExpanded,
+ [styles[`${baseClass}__chevron--promo`]]: isPromo,
})}
/>
- handleExpandChange(isExpanded)}
- >
- {getLabel(label, isExpanded)}
-
+ {buildHeader(isPromo)}
{multilineElement && (
{multilineElement}
@@ -104,17 +103,50 @@ export const Accordion: React.FC = ({
>
{isMounted && (
-
- {children}
-
+ <>
+
+ {children}
+
+ {footer && (
+
+ {footer}
+
+ )}
+ >
)}
);
};
+
+const baseClass = 'accordion';
+
+export const Accordion: React.FC = ({ kind, ...props }) => {
+ const mainClassName = cx(styles[baseClass], styles[`${baseClass}--${kind}`]);
+
+ return ;
+};
+
+const promoBaseClass = `${baseClass}--promo`;
+
+export const AccordionPromo: React.FC = (props) => {
+ const mainClassName = cx(styles[baseClass], styles[promoBaseClass]);
+
+ return (
+
+ );
+};
diff --git a/packages/react-components/src/components/Accordion/hooks.ts b/packages/react-components/src/components/Accordion/hooks.ts
new file mode 100644
index 000000000..79fea3690
--- /dev/null
+++ b/packages/react-components/src/components/Accordion/hooks.ts
@@ -0,0 +1,48 @@
+import * as React from 'react';
+
+interface UseAccordionProps {
+ isControlled: boolean;
+ isExpanded: boolean;
+ setShouldBeVisible: (isVisible: boolean) => void;
+ onOpen?: () => void;
+ onClose?: () => void;
+}
+
+interface IUseAccordion {
+ handleExpandChange: (isExpanded: boolean) => void;
+ handleKeyDown: (event: React.KeyboardEvent) => void;
+}
+
+export const useAccordion = ({
+ isControlled,
+ isExpanded,
+ setShouldBeVisible,
+ onOpen,
+ onClose,
+}: UseAccordionProps): IUseAccordion => {
+ const handleExpandChange = (isExpanded: boolean) => {
+ if (isExpanded) {
+ onClose?.();
+ } else {
+ onOpen?.();
+ }
+ !isControlled && setShouldBeVisible(!isExpanded);
+ };
+
+ const handleKeyDown = React.useCallback(
+ (event: React.KeyboardEvent) => {
+ if (
+ (!isExpanded && (event.key === 'Enter' || event.key === ' ')) ||
+ (isExpanded && event.key === 'Escape')
+ ) {
+ handleExpandChange(isExpanded);
+ }
+ },
+ [isExpanded, handleExpandChange]
+ );
+
+ return {
+ handleExpandChange,
+ handleKeyDown,
+ };
+};
diff --git a/packages/react-components/src/components/Accordion/index.ts b/packages/react-components/src/components/Accordion/index.ts
index feee0c4f0..bbca88aab 100644
--- a/packages/react-components/src/components/Accordion/index.ts
+++ b/packages/react-components/src/components/Accordion/index.ts
@@ -1 +1 @@
-export { Accordion } from './Accordion';
+export { Accordion, AccordionPromo } from './Accordion';
diff --git a/packages/react-components/src/components/Accordion/types.ts b/packages/react-components/src/components/Accordion/types.ts
index 3d57601a0..d87cff4d7 100644
--- a/packages/react-components/src/components/Accordion/types.ts
+++ b/packages/react-components/src/components/Accordion/types.ts
@@ -6,7 +6,7 @@ export type AccordionLabel =
| React.ReactNode
| { open: React.ReactNode; closed: React.ReactNode };
-export interface IAccordionProps extends ComponentCoreProps {
+export interface IAccordionGlobalProps extends ComponentCoreProps {
/**
* Specify the content of the accordion
*/
@@ -20,9 +20,9 @@ export interface IAccordionProps extends ComponentCoreProps {
*/
multilineElement?: React.ReactNode;
/**
- * Specify the kind of the accordion
+ * Specify the footer element, which will be displayed at the bottom
*/
- kind?: 'default' | 'warning' | 'error';
+ footer?: React.ReactNode;
/**
* Specify if the accordion should be open on init
*/
@@ -41,6 +41,26 @@ export interface IAccordionProps extends ComponentCoreProps {
onOpen?: () => void;
}
+export interface IAccordionProps extends IAccordionGlobalProps {
+ /**
+ * Specify the kind of the accordion
+ */
+ kind?: 'default' | 'warning' | 'error';
+}
+
+export interface IAccordionPromoProps extends IAccordionGlobalProps {}
+
+export interface IAccordionComponentProps extends IAccordionGlobalProps {
+ /**
+ * CSS class name for the main accordion wrapper
+ */
+ mainClassName: string;
+ /**
+ * Set to display promo accordion
+ */
+ isPromo?: boolean;
+}
+
export interface IAccordionAnimatedLabelProps {
open: React.ReactNode;
closed: React.ReactNode;
diff --git a/packages/react-components/src/components/AppFrame/AppFrame.module.scss b/packages/react-components/src/components/AppFrame/AppFrame.module.scss
index 2b1ca7bc5..fca4b4229 100644
--- a/packages/react-components/src/components/AppFrame/AppFrame.module.scss
+++ b/packages/react-components/src/components/AppFrame/AppFrame.module.scss
@@ -5,7 +5,7 @@ $base-class: 'app-frame';
flex-direction: row;
background-color: var(--navbar-background);
width: 100%;
- height: 100vh;
+ height: 100dvh;
color: var(--content-invert-default);
&__page-content-container {
diff --git a/packages/react-components/src/components/AppFrame/components/NavigationTopBar/NavigationTopBar.tsx b/packages/react-components/src/components/AppFrame/components/NavigationTopBar/NavigationTopBar.tsx
index 9918116e8..b2c188449 100644
--- a/packages/react-components/src/components/AppFrame/components/NavigationTopBar/NavigationTopBar.tsx
+++ b/packages/react-components/src/components/AppFrame/components/NavigationTopBar/NavigationTopBar.tsx
@@ -101,6 +101,7 @@ export const NavigationTopBarAlert: React.FC = ({
const { isMounted, isOpen } = useAnimations({
isVisible,
elementRef: alertRef,
+ includeSleepWakeScenario: true,
});
const handleResizeRef = React.useCallback(
(node: NODE) =>
@@ -110,8 +111,7 @@ export const NavigationTopBarAlert: React.FC = ({
[]
);
const mobileCtaKind = kind === 'warning' ? 'link-inverted' : 'text';
- const desktopCtaKind =
- kind === 'warning' ? 'plain-lock-black' : 'high-contrast';
+ const desktopCtaKind = kind === 'warning' ? 'secondary' : 'high-contrast';
const customPrimaryCtaKind = primaryCta?.kind;
const customSecondaryCtaKind = secondaryCta?.kind;
diff --git a/packages/react-components/src/components/Badge/Badge.module.scss b/packages/react-components/src/components/Badge/Badge.module.scss
index adb3032cf..c8d357587 100644
--- a/packages/react-components/src/components/Badge/Badge.module.scss
+++ b/packages/react-components/src/components/Badge/Badge.module.scss
@@ -69,8 +69,8 @@ $base-class: 'badge';
}
&--secondary {
- background-color: var(--surface-accent-emphasis-high-info);
- color: var(--content-locked-white);
+ background-color: var(--surface-invert-secondary);
+ color: var(--content-invert-primary);
.#{$base-class}__dot {
background-color: var(--content-locked-white);
diff --git a/packages/react-components/src/components/Badge/Badge.stories.tsx b/packages/react-components/src/components/Badge/Badge.stories.tsx
index 9b45b9450..39c9fb4f6 100644
--- a/packages/react-components/src/components/Badge/Badge.stories.tsx
+++ b/packages/react-components/src/components/Badge/Badge.stories.tsx
@@ -39,7 +39,7 @@ export const Kinds = (): React.ReactElement => (
-
+
diff --git a/packages/react-components/src/components/Badge/Badge.tsx b/packages/react-components/src/components/Badge/Badge.tsx
index 8489f6309..da28234f3 100644
--- a/packages/react-components/src/components/Badge/Badge.tsx
+++ b/packages/react-components/src/components/Badge/Badge.tsx
@@ -15,7 +15,6 @@ export interface BadgeProps extends React.HTMLAttributes {
count?: number;
/**
* Specify the badge kind
- * @param secondary - is deprecated, use "primary" or "tertiary" instead
*/
kind?: 'primary' | 'secondary' | 'tertiary';
/**
diff --git a/packages/react-components/src/components/Icon/IconsShowcase/constans.ts b/packages/react-components/src/components/Icon/IconsShowcase/constans.ts
index c8701cca1..198a3714f 100644
--- a/packages/react-components/src/components/Icon/IconsShowcase/constans.ts
+++ b/packages/react-components/src/components/Icon/IconsShowcase/constans.ts
@@ -38,6 +38,10 @@ export const IconsData: Record = {
ArrowsShuffle: IconGroup.Arrows,
ArrowsSort: IconGroup.Arrows,
ArrowsMerge: IconGroup.Arrows,
+ CaretDown: IconGroup.Arrows,
+ CaretDownFilled: IconGroup.Arrows,
+ CaretUp: IconGroup.Arrows,
+ CaretUpFilled: IconGroup.Arrows,
//FileType
FiletypeExe: IconGroup.FileType,
@@ -307,6 +311,8 @@ export const IconsData: Record = {
MoreHoriz: IconGroup.General,
MoveToFilled: IconGroup.General,
MoveTo: IconGroup.General,
+ MultiChoiceFilled: IconGroup.General,
+ MultiChoice: IconGroup.General,
NightModeFilled: IconGroup.General,
NightMode: IconGroup.General,
NoteAddFilled: IconGroup.General,
@@ -523,4 +529,6 @@ export const IconsData: Record = {
TextPlatform: IconGroup.Brands,
SquareRoundedPlusFilled: IconGroup.General,
SquareRoundedPlus: IconGroup.General,
+ ArrowsDiagonalMinimize: IconGroup.Arrows,
+ ArrowsDiagonal: IconGroup.Arrows,
};
diff --git a/packages/react-components/src/components/Typography/Text.tsx b/packages/react-components/src/components/Typography/Text.tsx
index f5740c68e..37982f254 100644
--- a/packages/react-components/src/components/Typography/Text.tsx
+++ b/packages/react-components/src/components/Typography/Text.tsx
@@ -22,6 +22,8 @@ interface IProps extends React.HTMLAttributes {
uppercase?: boolean;
/** Optional prop to set the bold */
bold?: boolean;
+ /** Optional prop to set the semi-bold */
+ semiBold?: boolean;
/** Optional prop to set the underline */
underline?: boolean;
/** Optional prop to set the strike */
@@ -40,6 +42,7 @@ export const Text: React.FC> = ({
caps = false,
uppercase = false,
bold = false,
+ semiBold = false,
underline = false,
strike = false,
children,
@@ -57,7 +60,8 @@ export const Text: React.FC> = ({
className: cx(
{
[styles[`${baseClassPrefix}-${size}`]]: true,
- [styles[`${baseClassPrefix}--bold`]]: bold,
+ [styles[`${baseClassPrefix}--semi-bold`]]: semiBold && !bold,
+ [styles[`${baseClassPrefix}--bold`]]: bold && !semiBold,
[styles[`${baseClassPrefix}--strike`]]: strike,
[styles[`${baseClassPrefix}--underline`]]: underline,
[styles[`${baseClassPrefix}--uppercase`]]: uppercase || caps,
diff --git a/packages/react-components/src/components/Typography/Typography.module.scss b/packages/react-components/src/components/Typography/Typography.module.scss
index f4a2d636d..dcf210815 100644
--- a/packages/react-components/src/components/Typography/Typography.module.scss
+++ b/packages/react-components/src/components/Typography/Typography.module.scss
@@ -162,6 +162,10 @@
}
.paragraph {
+ &--semi-bold {
+ font-weight: 500;
+ }
+
&--bold {
font-weight: 600;
}
diff --git a/packages/react-components/src/hooks/useAnimations.ts b/packages/react-components/src/hooks/useAnimations.ts
index 0104dae56..803518376 100644
--- a/packages/react-components/src/hooks/useAnimations.ts
+++ b/packages/react-components/src/hooks/useAnimations.ts
@@ -1,8 +1,11 @@
import * as React from 'react';
+import { useSleepWakeSync } from './useSleepWakeSync';
+
interface UseAnimationsProps {
isVisible: boolean;
elementRef: React.RefObject;
+ includeSleepWakeScenario?: boolean;
}
interface IUseAnimations {
@@ -14,6 +17,7 @@ interface IUseAnimations {
export const useAnimations = ({
isVisible,
elementRef,
+ includeSleepWakeScenario = false,
}: UseAnimationsProps): IUseAnimations => {
const [isMounted, setIsMounted] = React.useState(isVisible);
const [isOpen, setIsOpen] = React.useState(isVisible);
@@ -55,27 +59,17 @@ export const useAnimations = ({
}
}, [shouldBeVisible]);
- // Effect to listen for visibility changes (detecting sleep/wake scenarios)
- React.useEffect(() => {
- const handleVisibilityChange = () => {
- if (document.visibilityState === 'visible') {
- // Reset the animation state when returning to the visible state
- setShouldBeVisible(isVisible);
- }
- };
-
- document.addEventListener('visibilitychange', handleVisibilityChange);
-
- return () => {
- document.removeEventListener('visibilitychange', handleVisibilityChange);
- };
- }, [isVisible]);
-
// Synchronize shouldBeVisible with the isVisible prop
React.useEffect(() => {
setShouldBeVisible(isVisible);
}, [isVisible]);
+ // Effect to listen for visibility changes (detecting sleep/wake scenarios)
+ useSleepWakeSync(
+ () => setShouldBeVisible(isVisible),
+ includeSleepWakeScenario
+ );
+
return {
isOpen,
isMounted,
diff --git a/packages/react-components/src/hooks/useSleepWakeSync.ts b/packages/react-components/src/hooks/useSleepWakeSync.ts
new file mode 100644
index 000000000..d26c30641
--- /dev/null
+++ b/packages/react-components/src/hooks/useSleepWakeSync.ts
@@ -0,0 +1,29 @@
+import * as React from 'react';
+
+/**
+ * Syncs the wake event with the visibility change event.
+ * @param onWake The function to call when the wake event is triggered.
+ * @param enabled Whether the sync should be enabled.
+ */
+export const useSleepWakeSync = (onWake: () => void, enabled: boolean) => {
+ React.useEffect(() => {
+ const handleVisibilityChange = () => {
+ if (document.visibilityState === 'visible') {
+ onWake();
+ }
+ };
+
+ if (enabled) {
+ document.addEventListener('visibilitychange', handleVisibilityChange);
+ }
+
+ return () => {
+ if (enabled) {
+ document.removeEventListener(
+ 'visibilitychange',
+ handleVisibilityChange
+ );
+ }
+ };
+ }, [onWake, enabled]);
+};
diff --git a/packages/react-components/src/stories/foundations/Typography/components/TextExamples.tsx b/packages/react-components/src/stories/foundations/Typography/components/TextExamples.tsx
index 72e382b6f..51872e838 100644
--- a/packages/react-components/src/stories/foundations/Typography/components/TextExamples.tsx
+++ b/packages/react-components/src/stories/foundations/Typography/components/TextExamples.tsx
@@ -12,6 +12,9 @@ export const TextExamples: React.FC = () => {
Paragraph {size.toUpperCase()} with bold
+
+ Paragraph {size.toUpperCase()} with semi-bold
+
Paragraph {size.toUpperCase()} with underline