diff --git a/packages/web-react/scripts/entryPoints.js b/packages/web-react/scripts/entryPoints.js index a16c5945c7..bc78d6a5e4 100644 --- a/packages/web-react/scripts/entryPoints.js +++ b/packages/web-react/scripts/entryPoints.js @@ -49,6 +49,7 @@ const entryPoints = [ { dirs: ['components', 'UNSTABLE_Avatar'] }, { dirs: ['components', 'UNSTABLE_Divider'] }, { dirs: ['components', 'UNSTABLE_EmptyState'] }, + { dirs: ['components', 'UNSTABLE_PartnerLogo'] }, { dirs: ['components', 'UNSTABLE_Slider'] }, { dirs: ['components', 'VisuallyHidden'] }, ]; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/README.md b/packages/web-react/src/components/UNSTABLE_PartnerLogo/README.md new file mode 100644 index 0000000000..f4bea048b3 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/README.md @@ -0,0 +1,85 @@ +# UNSTABLE PartnerLogo + +> ⚠️ This component is UNSTABLE. It may significantly change at any point in the future. +> Please use it with caution. + +PartnerLogo is a component designed to display the partner's logo (e.g. advertiser, business partner, etc.). + +```jsx +import { UNSTABLE_PartnerLogo } from '@lmc-eu/spirit-web-react'; + + + + +``` + +## Sizes + +The PartnerLogo component is available in [sizes][dictionary-size]. + +```jsx + + + + + + + + + +``` + +## Disabled safe area + +The PartnerLogo component can be displayed without the safe area (padding). Use `hasSafeAreaDisabled` prop to disable safe area around logo. + +```jsx + + + +``` + +## Content + +The content of the PartnerLogo component can be an image or svg. + +### Image + +```jsx + + + +``` + +ℹ️ Don't forget to add the `aria-label` attribute for accessible title. +The image should have an `alt` attribute set and can be aria-hidden, because the `aria-label` +attribute is set on the container. + +### SVG + +```jsx + + + + + +``` + +ℹ️ Don't forget to add the `aria-label` attribute for accessible title. + +## API + +| Name | Type | Default | Required | Description | +| --------------------- | ---------------------------------- | -------- | -------- | ------------------------------------------------------- | +| `children` | `ReactNode` | `null` | ✓ | Content of the PartnerLogo | +| `size` | [Size dictionary][dictionary-size] | `medium` | ✕ | Size of the PartnerLogo | +| `hasSafeAreaDisabled` | `boolean` | `false` | ✕ | If true, the PartnerLogo is displayed without safe area | + +The components accept [additional attributes][readme-additional-attributes]. +If you need more control over the styling of a component, you can use [style props][readme-style-props] +and [escape hatches][readme-escape-hatches]. + +[dictionary-size]: https://github.com/lmc-eu/spirit-design-system/tree/main/docs/DICTIONARIES.md#size +[readme-additional-attributes]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#additional-attributes +[readme-escape-hatches]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#escape-hatches +[readme-style-props]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#style-props diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/UNSTABLE_PartnerLogo.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/UNSTABLE_PartnerLogo.tsx new file mode 100644 index 0000000000..7d40f8ccc9 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/UNSTABLE_PartnerLogo.tsx @@ -0,0 +1,26 @@ +import classNames from 'classnames'; +import React from 'react'; +import { useStyleProps } from '../../hooks'; +import { SpiritPartnerLogoProps } from '../../types/partnerLogo'; +import { usePartnerLogoStyleProps } from './usePartnerLogoStyleProps'; + +const defaultProps: Partial = { + size: 'medium', + hasSafeAreaDisabled: false, +}; + +const UNSTABLE_PartnerLogo = (props: SpiritPartnerLogoProps) => { + const propsWithDefaults = { ...defaultProps, ...props }; + const { children, ...restProps } = propsWithDefaults; + + const { classProps, props: modifiedProps } = usePartnerLogoStyleProps(restProps); + const { styleProps, props: otherProps } = useStyleProps(modifiedProps); + + return ( +
+ {children} +
+ ); +}; + +export default UNSTABLE_PartnerLogo; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/__tests__/UNSTABLE_PartnerLogo.test.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/__tests__/UNSTABLE_PartnerLogo.test.tsx new file mode 100644 index 0000000000..0cc7144cb1 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/__tests__/UNSTABLE_PartnerLogo.test.tsx @@ -0,0 +1,40 @@ +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import { classNamePrefixProviderTest } from '../../../../tests/providerTests/classNamePrefixProviderTest'; +import { restPropsTest } from '../../../../tests/providerTests/restPropsTest'; +import { stylePropsTest } from '../../../../tests/providerTests/stylePropsTest'; +import { Sizes } from '../../../constants'; +import UNSTABLE_PartnerLogo from '../UNSTABLE_PartnerLogo'; + +describe('UNSTABLE_PartnerLogo', () => { + classNamePrefixProviderTest(UNSTABLE_PartnerLogo, 'UNSTABLE_PartnerLogo'); + + stylePropsTest(UNSTABLE_PartnerLogo); + + restPropsTest(UNSTABLE_PartnerLogo, 'div'); + + it('should render children', () => { + render(Content); + + expect(screen.getByText('Content')).toBeInTheDocument(); + }); + + it('should have correct className', () => { + render(Content); + + expect(screen.getByText('Content')).toHaveClass('UNSTABLE_PartnerLogo'); + }); + + it.each(Object.values(Sizes))('should return %s size', (size) => { + render(Content); + + expect(screen.getByText('Content')).toHaveClass(`UNSTABLE_PartnerLogo--${size}`); + }); + + it('should render without safe area', () => { + render(Content); + + expect(screen.getByText('Content')).toHaveClass('UNSTABLE_PartnerLogo--hasSafeAreaDisabled'); + }); +}); diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/__tests__/usePartnerLogoStyleProps.test.ts b/packages/web-react/src/components/UNSTABLE_PartnerLogo/__tests__/usePartnerLogoStyleProps.test.ts new file mode 100644 index 0000000000..45dcafb89e --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/__tests__/usePartnerLogoStyleProps.test.ts @@ -0,0 +1,26 @@ +import { renderHook } from '@testing-library/react'; +import { Sizes } from '../../../constants'; +import { usePartnerLogoStyleProps } from '../usePartnerLogoStyleProps'; + +describe('usePartnerLogoStyleProps', () => { + it('should return defaults', () => { + const props = {}; + const { result } = renderHook(() => usePartnerLogoStyleProps(props)); + + expect(result.current.classProps).toBe('UNSTABLE_PartnerLogo'); + }); + + it.each(Object.values(Sizes))('should return %s size PartnerLogo', (size) => { + const props = { size }; + const { result } = renderHook(() => usePartnerLogoStyleProps(props)); + + expect(result.current.classProps).toBe(`UNSTABLE_PartnerLogo UNSTABLE_PartnerLogo--${size}`); + }); + + it('should return without safe area', () => { + const props = { hasSafeAreaDisabled: true }; + const { result } = renderHook(() => usePartnerLogoStyleProps(props)); + + expect(result.current.classProps).toBe('UNSTABLE_PartnerLogo UNSTABLE_PartnerLogo--hasSafeAreaDisabled'); + }); +}); diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoDefault.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoDefault.tsx new file mode 100644 index 0000000000..32649c72fd --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoDefault.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import PartnerLogoDemoFactory from './PartnerLogoDemoFactory'; + +const PartnerLogoDefault = () => ( +
+ +
+); + +export default PartnerLogoDefault; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoDemoFactory.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoDemoFactory.tsx new file mode 100644 index 0000000000..53f6d0f0ce --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoDemoFactory.tsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { Sizes } from '../../../constants'; +import { SpiritPartnerLogoProps } from '../../../types/partnerLogo'; +import UNSTABLE_PartnerLogo from '../UNSTABLE_PartnerLogo'; + +const logo = ( + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const PartnerLogoDemoFactory = ({ ...props }: SpiritPartnerLogoProps) => { + const sizes = Object.values(Sizes); + + return ( + <> + {sizes.map((size) => ( +
+

{`Size ${size}`}

+
+ + {logo} + +
+
+ ))} + + ); +}; + +export default PartnerLogoDemoFactory; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoSafeAreaDisabled.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoSafeAreaDisabled.tsx new file mode 100644 index 0000000000..ce1a595ad2 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/PartnerLogoSafeAreaDisabled.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import PartnerLogoDemoFactory from './PartnerLogoDemoFactory'; + +const PartnerLogoSafeAreaDisabled = () => ( +
+ +
+); + +export default PartnerLogoSafeAreaDisabled; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/index.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/index.tsx new file mode 100644 index 0000000000..2ef4d58558 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/demo/index.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import DocsSection from '../../../../docs/DocsSections'; +import PartnerLogoDefault from './PartnerLogoDefault'; +import PartnerLogoSafeAreaDisabled from './PartnerLogoSafeAreaDisabled'; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + + + + + + , +); diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/index.html b/packages/web-react/src/components/UNSTABLE_PartnerLogo/index.html new file mode 100644 index 0000000000..8ddd1b2783 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/index.html @@ -0,0 +1 @@ +{{> web-react/demo }} diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/index.ts b/packages/web-react/src/components/UNSTABLE_PartnerLogo/index.ts new file mode 100644 index 0000000000..f6e9bef9ea --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/index.ts @@ -0,0 +1,3 @@ +export * from './UNSTABLE_PartnerLogo'; +export * from './usePartnerLogoStyleProps'; +export { default as UNSTABLE_PartnerLogo } from './UNSTABLE_PartnerLogo'; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/stories/UNSTABLE_PartnerLogo.stories.tsx b/packages/web-react/src/components/UNSTABLE_PartnerLogo/stories/UNSTABLE_PartnerLogo.stories.tsx new file mode 100644 index 0000000000..38205021d4 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/stories/UNSTABLE_PartnerLogo.stories.tsx @@ -0,0 +1,111 @@ +import { Markdown } from '@storybook/blocks'; +import type { Meta, StoryObj } from '@storybook/react'; +import React from 'react'; +import { Sizes } from '../../../constants'; +import ReadMe from '../README.md'; +import UNSTABLE_PartnerLogo from '../UNSTABLE_PartnerLogo'; + +const meta: Meta = { + title: 'Experimental/UNSTABLE_PartnerLogo', + component: UNSTABLE_PartnerLogo, + parameters: { + docs: { + page: () => {ReadMe}, + }, + backgrounds: { + default: 'light', + }, + }, + argTypes: { + size: { + control: 'select', + options: [...Object.values(Sizes)], + }, + }, + args: { + hasSafeAreaDisabled: false, + children: ( + + + + + + + + + + + + + + + + + + + + + + + + + + ), + size: 'medium', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + name: 'UNSTABLE_PartnerLogo', +}; diff --git a/packages/web-react/src/components/UNSTABLE_PartnerLogo/usePartnerLogoStyleProps.ts b/packages/web-react/src/components/UNSTABLE_PartnerLogo/usePartnerLogoStyleProps.ts new file mode 100644 index 0000000000..f8cea99fb6 --- /dev/null +++ b/packages/web-react/src/components/UNSTABLE_PartnerLogo/usePartnerLogoStyleProps.ts @@ -0,0 +1,25 @@ +import classNames from 'classnames'; +import { useClassNamePrefix } from '../../hooks'; +import { SpiritPartnerLogoProps } from '../../types/partnerLogo'; + +export interface PartnerLogoStyles { + classProps: string; + props: T; +} + +export function usePartnerLogoStyleProps(props: SpiritPartnerLogoProps): PartnerLogoStyles { + const { size, hasSafeAreaDisabled } = props; + + const partnerLogoClass = useClassNamePrefix('UNSTABLE_PartnerLogo'); + const partnerLogoSizeClass = `${partnerLogoClass}--${size}`; + const partnerLogoSafeAreaDisabledClass = `${partnerLogoClass}--hasSafeAreaDisabled`; + const classProps = classNames(partnerLogoClass, { + [partnerLogoSizeClass]: size, + [partnerLogoSafeAreaDisabledClass]: hasSafeAreaDisabled, + }); + + return { + classProps, + props, + }; +} diff --git a/packages/web-react/src/components/index.ts b/packages/web-react/src/components/index.ts index f62a29c8b7..9b9c74a332 100644 --- a/packages/web-react/src/components/index.ts +++ b/packages/web-react/src/components/index.ts @@ -35,4 +35,5 @@ export * from './Toast'; export * from './Tooltip'; export * from './UNSTABLE_Avatar'; export * from './UNSTABLE_Divider'; +export * from './UNSTABLE_PartnerLogo'; export * from './VisuallyHidden'; diff --git a/packages/web-react/src/types/partnerLogo.ts b/packages/web-react/src/types/partnerLogo.ts new file mode 100644 index 0000000000..d08c862ea8 --- /dev/null +++ b/packages/web-react/src/types/partnerLogo.ts @@ -0,0 +1,6 @@ +import { ChildrenProps, SizesDictionaryType, StyleProps } from './shared'; + +export interface SpiritPartnerLogoProps extends ChildrenProps, StyleProps { + size?: SizesDictionaryType | S; + hasSafeAreaDisabled?: boolean; +} diff --git a/packages/web/src/scss/components/UNSTABLE_PartnerLogo/index.scss b/packages/web/src/scss/components/UNSTABLE_PartnerLogo/index.scss new file mode 100644 index 0000000000..354a770b55 --- /dev/null +++ b/packages/web/src/scss/components/UNSTABLE_PartnerLogo/index.scss @@ -0,0 +1 @@ +@forward 'UNSTABLE_PartnerLogo';