Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UNSTABLE_EmptyState Integration #1515

Merged
merged 14 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/demo/scss/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@
white-space: normal;
}

.docs-Placeholder {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
padding: 3rem 1.5rem;
text-align: center;
gap: 2rem;
border: 1px dashed #3eac98;
background: #fff;
}

.docs-Placeholder__text {
display: flex;
flex-direction: column;
color: #3eac98;
gap: 0.5rem;
}

@media (min-width: 768px) {
.docs-TileLink {
padding: 1.5rem;
Expand Down
2 changes: 2 additions & 0 deletions packages/web-react/scripts/entryPoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ const entryPoints = [
{ dirs: ['components', 'TextFieldBase'] },
{ dirs: ['components', 'Toast'] },
{ dirs: ['components', 'Tooltip'] },
{ dirs: ['components', 'UNSTABLE_ActionLayout'] },
{ dirs: ['components', 'UNSTABLE_Avatar'] },
{ dirs: ['components', 'UNSTABLE_Divider'] },
{ dirs: ['components', 'UNSTABLE_EmptyState'] },
{ dirs: ['components', 'UNSTABLE_Slider'] },
{ dirs: ['components', 'VisuallyHidden'] },
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# UNSTABLE ActionLayout

⚠️ This component is UNSTABLE. It may significantly change at any point in the future.
Please use it with caution.

ActionLayout component is a container component that is used to position action components in a predefined layout.

- For desktop and tablet views, actions are positioned in a horizontal direction with reverse order.
- For mobile view, actions are positioned in a vertical layout and are stretched to the full width of the container.

```jsx
<UNSTABLE_ActionLayout>
<!-- Actions components goes here -->
</UNSTABLE_ActionLayout>
```

## Full Example

```jsx
<UNSTABLE_ActionLayout>
<ButtonLink href="#" color="primary">
Primary Action
</ButtonLink>
<ButtonLink href="#" color="secondary">
Secondary Action
</ButtonLink>
</UNSTABLE_ActionLayout>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import classNames from 'classnames';
import React, { ReactElement } from 'react';
import { useStyleProps } from '../../hooks';
import { SpiritActionLayoutProps } from '../../types/actionLayout';
import { useActionLayoutStyleProps } from './useActionLayoutStyleProps';

export const UNSTABLE_ActionLayout = (props: SpiritActionLayoutProps): ReactElement => {
const { children, ...restProps } = props;
const { classProps, props: modifiedProps } = useActionLayoutStyleProps(restProps);
const { styleProps, props: otherProps } = useStyleProps(modifiedProps);

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

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

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

stylePropsTest(UNSTABLE_ActionLayout);

restPropsTest(UNSTABLE_ActionLayout, 'div');

beforeEach(() => {
render(<UNSTABLE_ActionLayout>Content</UNSTABLE_ActionLayout>);
});

it('should render content', () => {
expect(screen.getByText('Content')).toBeInTheDocument();
});

it('should render children', () => {
expect(screen.getByText('Content')).toHaveClass('UNSTABLE_ActionLayout');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { renderHook } from '@testing-library/react';
import { useActionLayoutStyleProps } from '../useActionLayoutStyleProps';

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

expect(result.current.classProps.root).toBe('UNSTABLE_ActionLayout');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { ButtonLink } from '../../Button';
import { UNSTABLE_ActionLayout } from '../index';

const ActionLayoutDefault = () => (
<UNSTABLE_ActionLayout>
<ButtonLink color="primary" href="#">
Primary Action
</ButtonLink>
<ButtonLink color="secondary" href="#">
Secondary Action
</ButtonLink>
</UNSTABLE_ActionLayout>
);

export default ActionLayoutDefault;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import DocsSection from '../../../../docs/DocsSections';
import ActionLayoutDefault from './ActionLayoutDefault';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<DocsSection title="Default" stackAlignment="stretch">
<ActionLayoutDefault />
</DocsSection>
</React.StrictMode>,
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{> web-react/demo}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as UNSTABLE_ActionLayout } from './UNSTABLE_ActionLayout';
export * from './UNSTABLE_ActionLayout';
export * from './useActionLayoutStyleProps';
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Markdown } from '@storybook/blocks';
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { ButtonLink } from '../../Button';
import ReadMe from '../README.md';
import { UNSTABLE_ActionLayout } from '..';

const meta: Meta<typeof UNSTABLE_ActionLayout> = {
title: 'Experimental/UNSTABLE_ActionLayout',
component: UNSTABLE_ActionLayout,
parameters: {
docs: {
page: () => <Markdown>{ReadMe}</Markdown>,
},
},
argTypes: {},
args: {
children: (
<>
<ButtonLink color="primary" href="/">
Primary Action
</ButtonLink>
<ButtonLink color="secondary" href="/">
Secondary Action
</ButtonLink>
</>
),
},
};

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

export const Playground: Story = {
name: 'UNSTABLE_ActionLayout',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useClassNamePrefix } from '../../hooks';
import { SpiritActionLayoutProps } from '../../types/actionLayout';

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

export function useActionLayoutStyleProps(props: SpiritActionLayoutProps): ActionLayoutStyles<SpiritActionLayoutProps> {
const actionLayoutClass = useClassNamePrefix('UNSTABLE_ActionLayout');

return {
classProps: {
root: actionLayoutClass,
},
props,
};
}
69 changes: 69 additions & 0 deletions packages/web-react/src/components/UNSTABLE_EmptyState/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# UNSTABLE EmptyState

⚠️ This component is UNSTABLE. It may significantly change at any point in the future.
Please use it with caution.

EmptyState component should be included in the error pages or empty state pages as the carrier of information and links to elsewhere.

EmptyState component is a composition of the following components:

- [UNSTABLE_EmptyState](#unstable-emptystate)
- [UNSTABLE_EmptyStateSection](#unstable-emptystatesection)

## UNSTABLE EmptyState

The `UNSTABLE_EmptyState` component is a main container responsible for positioning the [UNSTABLE_EmptyStateSection](#unstable-emptystatesection) components or content.

```jsx
<UNSTABLE_EmptyState>
<!-- UNSTABLE_EmptyStateSection components or content go here -->
</UNSTABLE_EmptyState>
```

### API

The component is based on the [Stack][stack] component and accepts all its properties. For more information, see the [Stack component API][stack-api].

## UNSTABLE EmptyStateSection

The `UNSTABLE_EmptyStateSection` component is a container for the content of each section.

```jsx
<UNSTABLE_EmptyStateSection>
<!-- Content goes here -->
</UNSTABLE_EmptyStateSection>
```

### API

The component is based on the [Stack][stack] component and accepts all its properties. For more information, see the [Stack component API][stack-api].

[stack]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Stack/README.md
[stack-api]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Stack/README.md#api

## Full Example

```jsx
<UNSTABLE_EmptyState spacing="space-700">
<UNSTABLE_EmptyStateSection>
<Icon name="search" isSymbol />
</UNSTABLE_EmptyStateSection>
<UNSTABLE_EmptyStateSection>
<Heading>Heading</Heading>
<Text>Description</Text>
</UNSTABLE_EmptyStateSection>
<UNSTABLE_EmptyStateSection>
<UNSTABLE_ActionLayout>
<ButtonLink href="#" color="primary">
Primary Action
</ButtonLink>
<ButtonLink href="#" color="secondary">
Secondary Action
</ButtonLink>
</UNSTABLE_ActionLayout>
</UNSTABLE_EmptyStateSection>
<UNSTABLE_EmptyStateSection>
<Link href="#">Link to something</Link>
</UNSTABLE_EmptyStateSection>
</UNSTABLE_EmptyState>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import classNames from 'classnames';
import React, { ReactElement } from 'react';
import { useStyleProps } from '../../hooks';
import { SpiritEmptyStateProps } from '../../types/emptyState';
import { Stack } from '../Stack';
import { useEmptyStateStyleProps } from './useEmptyStateStyleProps';

export const UNSTABLE_EmptyState = (props: SpiritEmptyStateProps): ReactElement => {
const { children, ...restProps } = props;
const { classProps, props: modifiedProps } = useEmptyStateStyleProps(restProps);
const { styleProps, props: otherProps } = useStyleProps(modifiedProps);

return (
<Stack
{...otherProps}
UNSAFE_className={classNames(classProps.root, styleProps.className)}
UNSAFE_style={styleProps.style}
>
{children}
</Stack>
);
};

export default UNSTABLE_EmptyState;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import classNames from 'classnames';
import React, { ReactElement } from 'react';
import { useStyleProps } from '../../hooks';
import { SpiritEmptyStateProps } from '../../types/emptyState';
import { Stack } from '../Stack';
import { useEmptyStateStyleProps } from './useEmptyStateStyleProps';

export const UNSTABLE_EmptyStateSection = (props: SpiritEmptyStateProps): ReactElement => {
const { children, ...restProps } = props;
const { classProps, props: modifiedProps } = useEmptyStateStyleProps(restProps);
const { styleProps, props: otherProps } = useStyleProps(modifiedProps);

return (
<Stack
{...otherProps}
UNSAFE_className={classNames(classProps.section, styleProps.className)}
UNSAFE_style={styleProps.style}
>
{children}
</Stack>
);
};

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

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

stylePropsTest(UNSTABLE_EmptyState);

restPropsTest(UNSTABLE_EmptyState, 'div');

beforeEach(() => {
render(<UNSTABLE_EmptyState>Content</UNSTABLE_EmptyState>);
});

it('should have default classname', () => {
expect(screen.getByText('Content')).toHaveClass('UNSTABLE_EmptyState');
});

it('should render children', () => {
expect(screen.getByText('Content')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
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_EmptyStateSection } from '..';

describe('UNSTABLE_EmptyStateSection', () => {
classNamePrefixProviderTest(UNSTABLE_EmptyStateSection, 'UNSTABLE_EmptyState__section');

stylePropsTest(UNSTABLE_EmptyStateSection);

restPropsTest(UNSTABLE_EmptyStateSection, 'div');

beforeEach(() => {
render(<UNSTABLE_EmptyStateSection>Content</UNSTABLE_EmptyStateSection>);
});

it('should have default classname', () => {
expect(screen.getByText('Content')).toHaveClass('UNSTABLE_EmptyState__section');
});

it('should render children', () => {
expect(screen.getByText('Content')).toBeInTheDocument();
});
});
Loading
Loading