ML: Add FolderCard component

This commit is contained in:
Gustav Hansen 2022-04-28 13:39:19 +02:00
parent a9abafccb0
commit 0d0a24f29d
7 changed files with 200 additions and 0 deletions

View File

@ -0,0 +1,92 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { pxToRem } from '@strapi/helper-plugin';
import { Box } from '@strapi/design-system/Box';
import { Stack } from '@strapi/design-system/Stack';
import Folder from '@strapi/icons/Folder';
import { FolderCardContext } from './FolderCardContext';
import useId from './utils/useId';
const FauxClickWrapper = styled.button`
height: 100%;
left: 0;
position: absolute;
opacity: 0;
top: 0;
width: 100%;
&:hover,
&:focus {
text-decoration: none;
}
`;
const StyledFolder = styled(Folder)`
path {
fill: currentColor;
}
`;
export const FolderCard = ({ children, id, startAction, ariaLabel, onDoubleClick, ...props }) => {
const generatedId = useId(id);
return (
<FolderCardContext.Provider value={{ id: generatedId }}>
<Box position="relative" {...props}>
<FauxClickWrapper
type="button"
onClick={event => event.preventDefault()}
onDoubleClick={onDoubleClick}
zIndex={1}
tabIndex={-1}
aria-label={ariaLabel}
aria-hidden
/>
<Stack
hasRadius
background="neutral0"
shadow="tableShadow"
paddingBottom={3}
paddingLeft={4}
paddingRight={4}
paddingTop={3}
spacing={3}
horizontal
cursor="pointer"
>
{startAction}
<Box
hasRadius
background="secondary100"
color="secondary500"
paddingBottom={2}
paddingLeft={3}
paddingRight={3}
paddingTop={2}
>
<StyledFolder width={pxToRem(20)} height={pxToRem(18)} />
</Box>
{children}
</Stack>
</Box>
</FolderCardContext.Provider>
);
};
FolderCard.defaultProps = {
id: undefined,
};
FolderCard.propTypes = {
ariaLabel: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
id: PropTypes.string,
onDoubleClick: PropTypes.func.isRequired,
startAction: PropTypes.element.isRequired,
};

View File

@ -0,0 +1,25 @@
import React from 'react';
import styled from 'styled-components';
import { Flex } from '@strapi/design-system/Flex';
import { useFolderCard } from './FolderCardContext';
const StyledBox = styled(Flex)`
user-select: none;
`;
export const FolderCardBody = props => {
const { id } = useFolderCard();
return (
<StyledBox
{...props}
id={`${id}-title`}
alignItems="flex-start"
direction="column"
position="relative"
zIndex={3}
/>
);
};

View File

@ -0,0 +1,14 @@
import React from 'react';
import { Box } from '@strapi/design-system/Box';
import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
import { useFolderCard } from './FolderCardContext';
export const FolderCardCheckbox = props => {
const { id } = useFolderCard();
return (
<Box position="relative" zIndex={2}>
<BaseCheckbox aria-labelledby={`${id}-title`} {...props} />
</Box>
);
};

View File

@ -0,0 +1,7 @@
import { createContext, useContext } from 'react';
export const FolderCardContext = createContext();
export function useFolderCard() {
return useContext(FolderCardContext);
}

View File

@ -0,0 +1,7 @@
import styled from 'styled-components';
import { BaseLink } from '@strapi/design-system/BaseLink';
export const FolderCardLink = styled(BaseLink)`
text-decoration: none;
`;

View File

@ -0,0 +1,42 @@
import React from 'react';
import { render, act } from '@testing-library/react';
import useId from '../useId';
function setup(...args) {
let returnVal;
function TestComponent() {
returnVal = useId(...args);
return null;
}
render(<TestComponent />);
return returnVal;
}
describe('useId', () => {
let id;
test('increments', () => {
id = setup('one');
expect(id).toBe('one-1');
act(() => {
id = setup('one');
});
expect(id).toBe('one-2');
});
test('works with namespaces', () => {
act(() => {
id = setup('two');
});
expect(id).toBe('two-3');
});
});

View File

@ -0,0 +1,13 @@
import { useRef } from 'react';
let id = 0;
const genId = () => ++id;
const useId = (prefix, initialId) => {
const idRef = useRef(initialId || `${prefix}-${genId()}`);
return idRef.current;
};
export default useId;