Merge pull request #10878 from strapi/content-box

ContentBox helper-plugin
This commit is contained in:
cyril lopez 2021-09-06 07:32:40 +02:00 committed by GitHub
commit b9c5a0b762
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 255 additions and 0 deletions

View File

@ -0,0 +1,77 @@
<!--- ContentBox.stories.mdx --->
import { useState } from 'react';
import { ArgsTable, Meta, Canvas, Story } from '@storybook/addon-docs';
import ContentBox from './index';
import { Stack } from '@strapi/parts/Stack';
import { IconButton } from '@strapi/parts/IconButton';
import ReadDoc from '@strapi/icons/ReadDoc';
import CodeExample from '@strapi/icons/CodeExample';
import Tutorial from '@strapi/icons/Tutorial';
import Blog from '@strapi/icons/Blog';
import Duplicate from '@strapi/icons/Duplicate';
<Meta title="components/ContentBox" />
# ContentBox
TODO
## Usage
<Canvas>
<Story name="base">
<Stack size={4}>
<ContentBox
title="Read the documentation"
subtitle="Discover the concepts, reference, guides and tutorials"
icon={<ReadDoc />}
iconBackground="primary100"
/>
<ContentBox
title="Code example"
subtitle="Learn by testing real project developed by the community"
icon={<CodeExample />}
iconBackground="warning100"
/>
<ContentBox
title="Tutorial"
subtitle="Discover the concepts, reference, guides and tutorials"
icon={<Tutorial />}
iconBackground="secondary100"
/>
<ContentBox
title="Blog"
subtitle="Discover the concepts, reference, guides and tutorials"
icon={<Blog />}
iconBackground="alternative100"
/>
<ContentBox
endAction={<IconButton label="Duplicate" noBorder icon={<Duplicate />} />}
title="https://cs.testing.Token=9e9de97839dewihl832ekjdw903w8j"
subtitle="Send this link to the user for them to connect"
icon={
//to replace with real envelope icon
<svg xmlns="http://www.w3.org/2000/svg">
<text
transform="translate(-23 -9)"
fill="#4B515A"
fillRule="evenodd"
fontSize="32"
fontFamily="AppleColorEmoji, Apple Color Emoji"
>
<tspan x="23" y="36">
✉️
</tspan>
</text>
</svg>
}
iconBackground="neutral100"
/>
</Stack>
</Story>
</Canvas>
### Props
<ArgsTable of={ContentBox} />

View File

@ -0,0 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { Row } from '@strapi/parts/Row';
import { Stack } from '@strapi/parts/Stack';
import { Text, TextButton } from '@strapi/parts/Text';
const IconWrapper = styled(Row)`
margin-right: ${({ theme }) => theme.spaces[6]};
svg {
width: ${32 / 16}rem;
height: ${32 / 16}rem;
}
`;
const ContentBox = ({ title, subtitle, icon, iconBackground, endAction }) => {
return (
<Row shadow="tableShadow" hasRadius padding={6}>
<IconWrapper background={iconBackground} hasRadius padding={3}>
{icon}
</IconWrapper>
<Stack size={endAction ? '' : 1}>
<Row>
<TextButton>{title}</TextButton>
{endAction}
</Row>
<Text textColor="neutral600">{subtitle}</Text>
</Stack>
</Row>
);
};
ContentBox.defaultProps = {
title: undefined,
subtitle: undefined,
icon: undefined,
iconBackground: undefined,
endAction: undefined,
};
ContentBox.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string,
icon: PropTypes.node,
iconBackground: PropTypes.string,
endAction: PropTypes.node,
};
export default ContentBox;

View File

@ -0,0 +1,128 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import ContentBox from '../index';
const App = (
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={{ en: {} }} textComponent="span">
<ContentBox
title="Code example"
subtitle="Learn by testing real project developed by the community"
/>
</IntlProvider>
</ThemeProvider>
);
describe('ContentBox', () => {
it('renders and matches the snapshot', async () => {
const {
container: { firstChild },
} = render(App);
expect(firstChild).toMatchInlineSnapshot(`
.c0 {
padding: 24px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c2 {
padding: 12px;
border-radius: 4px;
}
.c1 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c4 > * {
margin-top: 0;
margin-bottom: 0;
}
.c4 > * + * {
margin-top: 4px;
}
.c5 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c7 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #666687;
}
.c6 {
font-weight: 600;
line-height: 1.14;
}
.c3 {
margin-right: 24px;
}
.c3 svg {
width: 2rem;
height: 2rem;
}
<div
class="c0 c1"
>
<div
class="c2 c1 c3"
/>
<div
class="c4"
>
<div
class="c1"
>
<span
class="c5 c6"
>
Code example
</span>
</div>
<span
class="c7"
>
Learn by testing real project developed by the community
</span>
</div>
</div>
`);
expect(
screen.getByText('Learn by testing real project developed by the community')
).toBeInTheDocument();
});
});

View File

@ -173,6 +173,7 @@ export { default as SearchIcon } from './old/svgs/Search';
export { default as CheckPagePermissions } from './components/CheckPagePermissions';
export { default as CheckPermissions } from './components/CheckPermissions';
export { default as ConfirmDialog } from './components/ConfirmDialog';
export { default as ContentBox } from './components/ContentBox';
export { default as CustomContentLayout } from './components/CustomContentLayout';
export { default as EmptyStateLayout } from './components/EmptyStateLayout';
export { default as EmptyBodyTable } from './components/EmptyBodyTable';