Skip to content

Commit

Permalink
Feat(web-react): UNSTABLE_Header is React #DS-1524
Browse files Browse the repository at this point in the history
  • Loading branch information
curdaj committed Dec 2, 2024
1 parent 0b0fa78 commit 0e2c9c5
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 0 deletions.
36 changes: 36 additions & 0 deletions packages/web-react/src/components/UNSTABLE_Header/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# UNSTABLE Truncate

> ⚠️ This component is UNSTABLE. It may significantly change at any point in the future.
> Please use it with caution.
Truncate is a component that truncates text based on defined number of rows.

```jsx
import { UNSTABLE_Truncate } from '@lmc-eu/spirit-web-react';

<UNSTABLE_Truncate>{/* Text go here */}</UNSTABLE_Truncate>;
```

## Lines

You can add the number of lines to which you want to truncate the text using `lines` props

```jsx
<UNSTABLE_Truncate lines={2}>{/* Text go here */}</UNSTABLE_Truncate>
```

## API

| Name | Type | Default | Required | Description |
| ------------- | ----------------------- | ------- | -------- | -------------------------------------------------- |
| `children` | `string` \| `ReactNode` | `null` || Content of the Truncate |
| `elementType` | `ElementType` | `span` || Type of element used |
| `lines` | `number` | 3 || The number of lines on which the text is truncated |

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].

[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
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client';

import classNames from 'classnames';
import React from 'react';
import { useStyleProps } from '../../hooks';
import { ChildrenProps, StyleProps } from '../../types';
import { useHeaderStyleProps } from './useHeaderStyleProps';

export type SpiritHeaderProps = {
isFluid?: boolean;
isSimple?: boolean;
} & StyleProps &
ChildrenProps;

const defaultProps: Partial<SpiritHeaderProps> = {
isFluid: false,
isSimple: false,
};

const UNSTABLE_Header = (props: SpiritHeaderProps): JSX.Element => {
const propsWithDefaults = { ...defaultProps, ...props };
const { children, ...restProps } = propsWithDefaults;

const { classProps, props: modifiedProps } = useHeaderStyleProps(restProps);
const { styleProps, props: otherProps } = useStyleProps(modifiedProps);

return (
<header {...otherProps} className={classNames(classProps.root, styleProps.className)} style={styleProps.style}>
<div className={classProps.container}>{children}</div>
</header>
);
};

export default UNSTABLE_Header;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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 UNSTABLE_Header from '../UNSTABLE_Header';

describe('UNSTABLE_Header', () => {
classNamePrefixProviderTest(UNSTABLE_Header, 'UNSTABLE_Header');

stylePropsTest(UNSTABLE_Header);

restPropsTest(UNSTABLE_Header, 'header');

it('should have default classname', () => {
render(<UNSTABLE_Header>Content</UNSTABLE_Header>);

const header = screen.getByRole('banner');

expect(header).toHaveClass('UNSTABLE_Header');
expect(header.firstChild).toHaveClass('UNSTABLE_Header__container');
});

it('should have fluid classname', () => {
render(<UNSTABLE_Header isFluid>Content</UNSTABLE_Header>);

expect(screen.getByRole('banner')).toHaveClass('UNSTABLE_Header--fluid');
});

it('should have simple classname', () => {
render(<UNSTABLE_Header isSimple>Content</UNSTABLE_Header>);

expect(screen.getByRole('banner')).toHaveClass('UNSTABLE_Header--simple');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { renderHook } from '@testing-library/react';
import { useHeaderStyleProps } from '../useHeaderStyleProps';

describe('useHeaderStyleProps', () => {
it('should return defaults', () => {
const props = {};
const { result } = renderHook(() => useHeaderStyleProps(props));

expect(result.current.classProps.root).toBe('UNSTABLE_Header');
expect(result.current.classProps.container).toBe('UNSTABLE_Header__container');
});

it('should return isFluid', () => {
const props = { isFluid: true };
const { result } = renderHook(() => useHeaderStyleProps(props));

expect(result.current.classProps.root).toBe('UNSTABLE_Header UNSTABLE_Header--fluid');
});

it('should return isSimple', () => {
const props = { isSimple: true };
const { result } = renderHook(() => useHeaderStyleProps(props));

expect(result.current.classProps.root).toBe('UNSTABLE_Header UNSTABLE_Header--simple');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { Link } from '../../Link';
import { ProductLogo } from '../../ProductLogo';
import { defaultSvgLogo } from '../../ProductLogo/demo/ProductLogoDefault';
import { UNSTABLE_Header } from '../index';

const HeaderDefault = () => {
return (
<UNSTABLE_Header>
<Link href="/">
<ProductLogo>{defaultSvgLogo}</ProductLogo>
</Link>
</UNSTABLE_Header>
);
};
export default HeaderDefault;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import { Link } from '../../Link';
import { ProductLogo } from '../../ProductLogo';
import { defaultSvgLogo } from '../../ProductLogo/demo/ProductLogoDefault';
import { UNSTABLE_Header } from '..';

const HeaderFluid = () => {
return (
<UNSTABLE_Header isFluid>
<Link href="/">
<ProductLogo>{defaultSvgLogo}</ProductLogo>
</Link>
</UNSTABLE_Header>
);
};

export default HeaderFluid;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import { Link } from '../../Link';
import { ProductLogo } from '../../ProductLogo';
import { defaultSvgLogo } from '../../ProductLogo/demo/ProductLogoDefault';
import { UNSTABLE_Header } from '..';

const HeaderSimple = () => {
return (
<UNSTABLE_Header isSimple>
<Link href="/">
<ProductLogo>{defaultSvgLogo}</ProductLogo>
</Link>
</UNSTABLE_Header>
);
};

export default HeaderSimple;
20 changes: 20 additions & 0 deletions packages/web-react/src/components/UNSTABLE_Header/demo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import DocsSection from '../../../../docs/DocsSections';
import HeaderDefault from './HeaderDefault';
import HeaderFluid from './HeaderFluid';
import HeaderSimple from './HeaderSimple';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<DocsSection title="Minimal Header" stackAlignment="stretch">
<HeaderSimple />
</DocsSection>
<DocsSection title="Minimal Header" stackAlignment="stretch">
<HeaderDefault />
</DocsSection>
<DocsSection title="Header Fluid" stackAlignment="stretch">
<HeaderFluid />
</DocsSection>
</React.StrictMode>,
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{> web-react/demo title="Header" parentPageName="Components" isUnstable=true }}
4 changes: 4 additions & 0 deletions packages/web-react/src/components/UNSTABLE_Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use client';

export { default as UNSTABLE_Header } from './UNSTABLE_Header';
export * from './useHeaderStyleProps';
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Markdown } from '@storybook/blocks';
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { Link } from '../../Link';
import { ProductLogo } from '../../ProductLogo';
import { defaultSvgLogo } from '../../ProductLogo/demo/ProductLogoDefault';
import ReadMe from '../README.md';
import { UNSTABLE_Header } from '..';

const meta: Meta<typeof UNSTABLE_Header> = {
title: 'Experimental/UNSTABLE_Header',
component: UNSTABLE_Header,
parameters: {
docs: {
page: () => <Markdown>{ReadMe}</Markdown>,
},
},
argTypes: {
isSimple: {
control: 'boolean',
table: {
defaultValue: { summary: 'false' },
},
},
isFluid: {
control: 'boolean',
table: {
defaultValue: { summary: 'false' },
},
},
},
args: {
children: (
<Link href="/">
<ProductLogo>{defaultSvgLogo}</ProductLogo>
</Link>
),
isFluid: false,
isSimple: false,
},
};

export default meta;
type Story = StoryObj<typeof UNSTABLE_Header>;

export const Playground: Story = {
name: 'UNSTABLE_Header',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import classNames from 'classnames';
import { useClassNamePrefix } from '../../hooks';
import { SpiritHeaderProps } from './UNSTABLE_Header';

export interface HeaderStyles<T> {
classProps: {
root: string;
container: string;
};
props: T;
}

export const useHeaderStyleProps = (props: SpiritHeaderProps): HeaderStyles<SpiritHeaderProps> => {
const { isFluid, isSimple, ...restProps } = props;

const headerClass = useClassNamePrefix('UNSTABLE_Header');
const headerSimpleClass = `${headerClass}--simple`;
const headerFluidClass = `${headerClass}--fluid`;
const rootClassProps = classNames(headerClass, {
[headerSimpleClass]: isSimple,
[headerFluidClass]: isFluid,
});
const containerClassProps = `${headerClass}__container`;

return {
classProps: {
root: rootClassProps,
container: containerClassProps,
},
props: restProps,
};
};

0 comments on commit 0e2c9c5

Please sign in to comment.