onboarding compo redone

This commit is contained in:
ronronscelestes 2021-09-07 16:21:33 +02:00
parent d3e85fad13
commit 2bed9f51d6
4 changed files with 153 additions and 232 deletions

View File

@ -1,82 +0,0 @@
/**
*
* StaticLinks
*
*/
import React from 'react';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Text } from '@strapi/parts/Text';
import { InjectionZone } from '../../../../shared/components';
const StyledLink = styled.a`
display: flex;
width: 100%;
height: 27px;
padding: 0 20px;
color: ${({ theme }) => theme.colors.neutral400};
text-decoration: none;
span,
svg {
margin: auto 0;
}
svg {
margin-right: 10px;
}
${[Text]} {
color: ${({ theme }) => theme.colors.neutral400};
margin: auto 0;
}
&:hover {
background: ${({ theme }) => theme.colors.neutral100};
color: ${({ theme }) => theme.colors.neutral500};
${[Text]} {
color: ${({ theme }) => theme.colors.neutral700};
}
}
${[Text]} {
color: ${({ theme }) => theme.colors.neutral600};
}
`;
const StaticLinks = () => {
const { formatMessage } = useIntl();
const staticLinks = [
{
icon: 'book',
label: formatMessage({ id: 'app.components.LeftMenuFooter.documentation' }),
destination: 'https://strapi.io/documentation',
},
{
icon: 'file',
label: formatMessage({ id: 'app.static.links.cheatsheet' }),
destination: 'https://strapi-showcase.s3-us-west-2.amazonaws.com/CheatSheet.pdf',
},
];
return (
<ul className="list">
{staticLinks.map(link => {
const { icon, label, destination } = link;
return (
<li key={label}>
<StyledLink href={destination} target="_blank" rel="noopener noreferrer">
<FontAwesomeIcon icon={icon} />
<Text>{label}</Text>
</StyledLink>
</li>
);
})}
<InjectionZone area="admin.tutorials.links" />
</ul>
);
};
export default StaticLinks;

View File

@ -1,131 +0,0 @@
import styled, { keyframes } from 'styled-components';
const fadeIn = keyframes`
0% {
width: auto;
height: auto;
opacity: 0;
}
5% {
opacity: 0;
}
100% {
opacity: 1;
}
`;
const fadeOut = keyframes`
0% {
opacity: 1;
}
60% {
opacity: 0;
}
100% {
opacity: 0;
width: 0;
height: 0;
}
`;
const Wrapper = styled.div`
max-width: ${({ isOpen }) => (isOpen ? 'initial' : '0px')};
position: fixed;
right: 15px;
bottom: 15px;
button,
button:focus,
a {
cursor: pointer;
outline: 0;
}
p {
margin-bottom: 0;
}
.videosHeader {
padding: 25px 15px 18px 15px;
p {
display: inline-block;
vertical-align: top;
width: 50%;
font-family: Lato;
font-weight: bold;
font-size: 11px;
color: #5c5f66;
letter-spacing: 0.5px;
text-transform: uppercase;
&:last-of-type {
color: #5a9e06;
text-align: right;
}
}
}
&.visible {
opacity: 1;
z-index: 10;
}
&.hidden {
opacity: 0;
}
.videosContent {
min-width: 320px;
margin-bottom: 10px;
margin-right: 15px;
background-color: white;
box-shadow: 0 2px 4px 0 #e3e9f3;
border-radius: ${({ theme }) => theme.spaces[2]};
overflow: hidden;
&.shown {
animation: ${fadeIn} 0.5s forwards;
}
&.hide {
min-width: 0;
animation: ${fadeOut} 0.5s forwards;
}
ul {
padding: 0 0 8px 0;
margin-bottom: 0;
list-style: none;
&:last-of-type {
padding: 8px 0 10px 0;
border-top: 1px solid #f6f6f6;
}
}
}
.openBtn {
float: right;
width: 38px;
height: 38px;
button {
width: 100%;
height: 100%;
border-radius: 50%;
color: white;
background: ${({ theme }) => theme.colors.primary600};
box-shadow: ${({ theme }) => theme.shadows.tableShadow};
i,
svg {
margin: auto;
}
i:last-of-type,
svg:last-of-type {
display: none;
}
&.active {
i:first-of-type,
svg:first-of-type {
display: none;
}
i:last-of-type,
svg:last-of-type {
display: block;
}
}
}
}
`;
export default Wrapper;

View File

@ -1,40 +1,119 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { useIntl } from 'react-intl';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faQuestion, faTimes } from '@fortawesome/free-solid-svg-icons';
import cn from 'classnames';
import { Box } from '@strapi/parts/Box';
import { Text } from '@strapi/parts/Text';
import { useConfigurations } from '../../../hooks';
import StaticLinks from './StaticLinks';
import Wrapper from './Wrapper';
const Wrapper = styled.button`
position: fixed;
bottom: ${({ theme }) => theme.spaces[2]};
right: ${({ theme }) => theme.spaces[2]};
width: ${({ theme }) => theme.spaces[8]};
height: ${({ theme }) => theme.spaces[8]};
background: ${({ theme }) => theme.colors.primary600};
box-shadow: ${({ theme }) => theme.shadows.tableShadow};
border-radius: 50%;
svg {
color: white;
}
`;
const LinksWrapper = styled(Box)`
position: absolute;
bottom: ${({ theme }) => `${theme.spaces[9]}`};
right: 0;
width: ${200 / 16}rem;
`;
const StyledLink = styled.a`
display: flex;
align-items: center;
width: 100%;
text-decoration: none;
padding: ${({ theme }) => theme.spaces[2]};
padding-left: ${({ theme }) => theme.spaces[5]};
svg {
color: ${({ theme }) => theme.colors.neutral600};
margin-right: ${({ theme }) => theme.spaces[2]};
}
&:hover {
background: ${({ theme }) => theme.colors.neutral100};
color: ${({ theme }) => theme.colors.neutral500};
svg {
color: ${({ theme }) => theme.colors.neutral700};
}
${[Text]} {
color: ${({ theme }) => theme.colors.neutral700};
}
}
${[Text]} {
color: ${({ theme }) => theme.colors.neutral600};
}
`;
const Onboarding = () => {
const [isOpen, setIsOpen] = useState(false);
const { formatMessage } = useIntl();
const { showTutorials } = useConfigurations();
if (!showTutorials) {
return null;
}
return <OnboardingVideos />;
};
const OnboardingVideos = () => {
const [isOpen, setIsOpen] = useState(false);
const staticLinks = [
{
icon: 'book',
label: formatMessage({
id: 'app.components.LeftMenuFooter.documentation',
defaultMessage: 'Documentation',
}),
destination: 'https://strapi.io/documentation',
},
{
icon: 'file',
label: formatMessage({ id: 'app.static.links.cheatsheet', defaultMessage: 'CheatSheet' }),
destination: 'https://strapi-showcase.s3-us-west-2.amazonaws.com/CheatSheet.pdf',
},
];
const handleClick = () => {
setIsOpen(prev => !prev);
};
return (
<Wrapper className="visible" isOpen={isOpen}>
<div className={cn('videosContent', isOpen ? 'shown' : 'hide')}>
<StaticLinks />
</div>
<div className="openBtn">
<button onClick={handleClick} className={isOpen ? 'active' : ''} type="button">
<FontAwesomeIcon icon={faQuestion} />
<FontAwesomeIcon icon={faTimes} />
<span />
</button>
</div>
<Wrapper onClick={handleClick}>
{!isOpen && <FontAwesomeIcon icon={faQuestion} />}
{isOpen && <FontAwesomeIcon icon={faTimes} />}
{isOpen && (
<LinksWrapper
background="neutral0"
hasRadius
shadow="tableShadow"
paddingBottom={2}
paddingTop={2}
>
{staticLinks.map(link => (
<StyledLink
key={link.label}
rel="nofollow noreferrer noopener"
target="_blank"
href={link.destination}
>
<FontAwesomeIcon icon={link.icon} />
<Text>{link.label}</Text>
</StyledLink>
))}
</LinksWrapper>
)}
</Wrapper>
);
};

View File

@ -0,0 +1,55 @@
import React from 'react';
import { render } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import Onboarding from '../index';
const App = (
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={{ en: {} }} textComponent="span">
<Onboarding />
</IntlProvider>
</ThemeProvider>
);
describe('Onboarding', () => {
it('renders and matches the snapshot', () => {
const {
container: { firstChild },
} = render(App);
expect(firstChild).toMatchInlineSnapshot(`
.c0 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
<div
class="c0"
>
<p
aria-live="polite"
id="live-region-log"
role="log"
/>
<p
aria-live="polite"
id="live-region-status"
role="status"
/>
<p
aria-live="assertive"
id="live-region-alert"
role="alert"
/>
</div>
`);
});
});