refactor: move Checkmark, Avatar, Chip and Tooltip to twenty-ui (#4946)
Split from https://github.com/twentyhq/twenty/pull/4518 Part of #4766
This commit is contained in:
160
packages/twenty-ui/src/testing/decorators/CatalogDecorator.tsx
Normal file
160
packages/twenty-ui/src/testing/decorators/CatalogDecorator.tsx
Normal file
@ -0,0 +1,160 @@
|
||||
import { ComponentProps, JSX } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNumber, isString } from '@sniptt/guards';
|
||||
import { Decorator } from '@storybook/react';
|
||||
|
||||
const StyledColumnTitle = styled.h1`
|
||||
font-size: ${({ theme }) => theme.font.size.lg};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledRowsTitle = styled.h2`
|
||||
color: ${({ theme }) => theme.font.color.secondary};
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin: ${({ theme }) => theme.spacing(2)};
|
||||
width: 100px;
|
||||
`;
|
||||
|
||||
const StyledRowTitle = styled.h3`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin: ${({ theme }) => theme.spacing(2)};
|
||||
width: 100px;
|
||||
`;
|
||||
|
||||
const StyledElementTitle = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
const StyledColumnContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledRowsContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledRowContainer = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledElementContainer = styled.div<{ width: number }>`
|
||||
display: flex;
|
||||
${({ width }) => width && `min-width: ${width}px;`}
|
||||
`;
|
||||
|
||||
const StyledCellContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const emptyDimension = {
|
||||
name: '',
|
||||
values: [undefined],
|
||||
props: () => ({}),
|
||||
} as CatalogDimension;
|
||||
|
||||
const isStringOrNumber = (term: unknown): term is string | number =>
|
||||
isString(term) || isNumber(term);
|
||||
|
||||
export type CatalogDimension<
|
||||
ComponentType extends React.ElementType = () => JSX.Element,
|
||||
> = {
|
||||
name: string;
|
||||
values: any[];
|
||||
props: (value: any) => Partial<ComponentProps<ComponentType>>;
|
||||
labels?: (value: any) => string;
|
||||
};
|
||||
|
||||
export type CatalogOptions = {
|
||||
elementContainer?: {
|
||||
width?: number;
|
||||
};
|
||||
};
|
||||
|
||||
export const CatalogDecorator: Decorator = (Story, context) => {
|
||||
const {
|
||||
catalog: { dimensions, options },
|
||||
} = context.parameters;
|
||||
|
||||
const [
|
||||
dimension1,
|
||||
dimension2 = emptyDimension,
|
||||
dimension3 = emptyDimension,
|
||||
dimension4 = emptyDimension,
|
||||
] = dimensions as CatalogDimension[];
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
{dimension4.values.map((value4: any) => (
|
||||
<StyledColumnContainer key={value4}>
|
||||
<StyledColumnTitle>
|
||||
{dimension4.labels?.(value4) ??
|
||||
(isStringOrNumber(value4) ? value4 : '')}
|
||||
</StyledColumnTitle>
|
||||
{dimension3.values.map((value3: any) => (
|
||||
<StyledRowsContainer key={value3}>
|
||||
<StyledRowsTitle>
|
||||
{dimension3.labels?.(value3) ??
|
||||
(isStringOrNumber(value3) ? value3 : '')}
|
||||
</StyledRowsTitle>
|
||||
{dimension2.values.map((value2: any) => (
|
||||
<StyledRowContainer key={value2}>
|
||||
<StyledRowTitle>
|
||||
{dimension2.labels?.(value2) ??
|
||||
(isStringOrNumber(value2) ? value2 : '')}
|
||||
</StyledRowTitle>
|
||||
{dimension1.values.map((value1: any) => {
|
||||
return (
|
||||
<StyledCellContainer key={value1} id={value1}>
|
||||
<StyledElementTitle>
|
||||
{dimension1.labels?.(value1) ??
|
||||
(isStringOrNumber(value1) ? value1 : '')}
|
||||
</StyledElementTitle>
|
||||
<StyledElementContainer
|
||||
width={options?.elementContainer?.width}
|
||||
>
|
||||
<Story
|
||||
args={{
|
||||
...context.args,
|
||||
...dimension1.props(value1),
|
||||
...dimension2.props(value2),
|
||||
...dimension3.props(value3),
|
||||
...dimension4.props(value4),
|
||||
}}
|
||||
/>
|
||||
</StyledElementContainer>
|
||||
</StyledCellContainer>
|
||||
);
|
||||
})}
|
||||
</StyledRowContainer>
|
||||
))}
|
||||
</StyledRowsContainer>
|
||||
))}
|
||||
</StyledColumnContainer>
|
||||
))}
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Decorator } from '@storybook/react';
|
||||
|
||||
export const RouterDecorator: Decorator = (Story) => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
);
|
||||
@ -1,2 +1,6 @@
|
||||
export * from './ComponentStorybookLayout';
|
||||
export * from './decorators/CatalogDecorator';
|
||||
export * from './decorators/ComponentDecorator';
|
||||
export * from './decorators/RouterDecorator';
|
||||
export * from './mocks/avatarUrlMock';
|
||||
export * from './types/CatalogStory';
|
||||
|
||||
2
packages/twenty-ui/src/testing/mocks/avatarUrlMock.ts
Normal file
2
packages/twenty-ui/src/testing/mocks/avatarUrlMock.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const AVATAR_URL_MOCK =
|
||||
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAYABgAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABgAAAAAQAAAGAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAABSgAwAEAAAAAQAAABQAAAAA/8AAEQgAFAAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMACwgICggHCwoJCg0MCw0RHBIRDw8RIhkaFBwpJCsqKCQnJy0yQDctMD0wJyc4TDk9Q0VISUgrNk9VTkZUQEdIRf/bAEMBDA0NEQ8RIRISIUUuJy5FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRf/dAAQAAv/aAAwDAQACEQMRAD8Ava1q728otYY98joSCTgZrnbXWdTtrhrfVZXWLafmcAEkdgR/hVltQku9Q8+OIEBcGOT+ID0PY1ka1KH2u8ToqnPLbmIqG7u6LtbQ7RXBRec4Uck9eKXcPWsKDWVnhWSL5kYcFelSf2m3901POh8jP//QoyIAnTuKpXsY82NsksUyWPU5q/L9z8RVK++/F/uCsVsaEURwgA4HtT9x9TUcf3KfUGh//9k=';
|
||||
24
packages/twenty-ui/src/testing/types/CatalogStory.ts
Normal file
24
packages/twenty-ui/src/testing/types/CatalogStory.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { ElementType } from 'react';
|
||||
import { StoryObj } from '@storybook/react';
|
||||
|
||||
import {
|
||||
CatalogDimension,
|
||||
CatalogOptions,
|
||||
} from '../decorators/CatalogDecorator';
|
||||
|
||||
export type CatalogStory<
|
||||
StoryType extends StoryObj<ComponentType>,
|
||||
ComponentType extends ElementType,
|
||||
> = {
|
||||
args?: StoryType['args'];
|
||||
argTypes?: StoryType['argTypes'];
|
||||
play?: StoryType['play'];
|
||||
render?: StoryType['render'];
|
||||
parameters: StoryType['parameters'] & {
|
||||
catalog: {
|
||||
dimensions: CatalogDimension<ComponentType>[];
|
||||
options?: CatalogOptions;
|
||||
};
|
||||
};
|
||||
decorators: StoryType['decorators'];
|
||||
};
|
||||
Reference in New Issue
Block a user