[UI] Extract our ColorSample and Tag components from twenty-front to twenty-ui. (#5543)
Two more components extracted out of twenty-front: `ColorSample` and `Tag`.
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconMail } from 'twenty-ui';
|
||||
import { IconMail, Tag } from 'twenty-ui';
|
||||
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
|
||||
|
||||
type EmailThreadHeaderProps = {
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconDotsVertical } from 'twenty-ui';
|
||||
import { IconDotsVertical, Tag } from 'twenty-ui';
|
||||
|
||||
import { RecordBoardColumnDropdownMenu } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnDropdownMenu';
|
||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Tag } from 'twenty-ui';
|
||||
|
||||
import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
|
||||
type MultiSelectFieldDisplayProps = {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { Tag } from 'twenty-ui';
|
||||
|
||||
import { useSelectField } from '../../hooks/useSelectField';
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
ColorSample,
|
||||
IconCheck,
|
||||
IconDotsVertical,
|
||||
IconGripVertical,
|
||||
@ -12,7 +13,6 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getOptionValueFromLabel } from '@/settings/data-model/fields/forms/utils/getOptionValueFromLabel';
|
||||
import { ColorSample } from '@/ui/display/color/components/ColorSample';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Tag } from 'twenty-ui';
|
||||
|
||||
import { ObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
|
||||
type SettingsDataModelObjectTypeTagProps = {
|
||||
objectTypeLabel: ObjectTypeLabel;
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ThemeColor } from '@/ui/theme/constants/MainColorNames';
|
||||
|
||||
export type ColorSampleVariant = 'default' | 'pipeline';
|
||||
|
||||
export type ColorSampleProps = {
|
||||
colorName: ThemeColor;
|
||||
variant?: ColorSampleVariant;
|
||||
};
|
||||
|
||||
const StyledColorSample = styled.div<ColorSampleProps>`
|
||||
background-color: ${({ theme, colorName }) =>
|
||||
theme.tag.background[colorName]};
|
||||
border: 1px solid ${({ theme, colorName }) => theme.tag.text[colorName]};
|
||||
border-radius: 60px;
|
||||
height: ${({ theme }) => theme.spacing(4)};
|
||||
width: ${({ theme }) => theme.spacing(3)};
|
||||
|
||||
${({ colorName, theme, variant }) => {
|
||||
if (variant === 'pipeline')
|
||||
return css`
|
||||
align-items: center;
|
||||
border: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&:after {
|
||||
background-color: ${theme.tag.text[colorName]};
|
||||
border-radius: ${theme.border.radius.rounded};
|
||||
content: '';
|
||||
display: block;
|
||||
height: ${theme.spacing(1)};
|
||||
width: ${theme.spacing(1)};
|
||||
}
|
||||
`;
|
||||
}}
|
||||
`;
|
||||
|
||||
export { StyledColorSample as ColorSample };
|
||||
@ -1,24 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import { ColorSample } from '../ColorSample';
|
||||
|
||||
const meta: Meta<typeof ColorSample> = {
|
||||
title: 'UI/Display/Color/ColorSample',
|
||||
component: ColorSample,
|
||||
decorators: [ComponentDecorator],
|
||||
args: { colorName: 'green' },
|
||||
argTypes: {
|
||||
as: { control: false },
|
||||
theme: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ColorSample>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Pipeline: Story = {
|
||||
args: { variant: 'pipeline' },
|
||||
};
|
||||
@ -1,77 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent, OverflowingTextWithTooltip } from 'twenty-ui';
|
||||
|
||||
import { ThemeColor } from '@/ui/theme/constants/MainColorNames';
|
||||
import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema';
|
||||
|
||||
const StyledTag = styled.h3<{
|
||||
color: ThemeColor;
|
||||
weight: TagWeight;
|
||||
}>`
|
||||
align-items: center;
|
||||
background: ${({ color, theme }) => theme.tag.background[color]};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
color: ${({ color, theme }) => theme.tag.text[color]};
|
||||
display: inline-flex;
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
font-style: normal;
|
||||
font-weight: ${({ theme, weight }) =>
|
||||
weight === 'regular'
|
||||
? theme.font.weight.regular
|
||||
: theme.font.weight.medium};
|
||||
height: ${({ theme }) => theme.spacing(5)};
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledContent = styled.span`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const StyledIconContainer = styled.div`
|
||||
display: flex;
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
type TagWeight = 'regular' | 'medium';
|
||||
|
||||
type TagProps = {
|
||||
className?: string;
|
||||
color: ThemeColor;
|
||||
text: string;
|
||||
Icon?: IconComponent;
|
||||
onClick?: () => void;
|
||||
weight?: TagWeight;
|
||||
};
|
||||
|
||||
export const Tag = ({
|
||||
className,
|
||||
color,
|
||||
text,
|
||||
Icon,
|
||||
onClick,
|
||||
weight = 'regular',
|
||||
}: TagProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledTag
|
||||
className={className}
|
||||
color={themeColorSchema.catch('gray').parse(color)}
|
||||
onClick={onClick}
|
||||
weight={weight}
|
||||
>
|
||||
{!!Icon && (
|
||||
<StyledIconContainer>
|
||||
<Icon size={theme.icon.size.sm} stroke={theme.icon.stroke.sm} />
|
||||
</StyledIconContainer>
|
||||
)}
|
||||
<StyledContent>
|
||||
<OverflowingTextWithTooltip text={text} />
|
||||
</StyledContent>
|
||||
</StyledTag>
|
||||
);
|
||||
};
|
||||
@ -1,66 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { CatalogDecorator, CatalogStory, ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
MAIN_COLOR_NAMES,
|
||||
ThemeColor,
|
||||
} from '@/ui/theme/constants/MainColorNames';
|
||||
|
||||
import { Tag } from '../Tag';
|
||||
|
||||
const meta: Meta<typeof Tag> = {
|
||||
title: 'UI/Display/Tag/Tag',
|
||||
component: Tag,
|
||||
args: {
|
||||
text: 'Urgent',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Tag>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
color: 'red',
|
||||
onClick: fn(),
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
play: async ({ canvasElement, args }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const tag = canvas.getByRole('heading', { level: 3 });
|
||||
|
||||
await userEvent.click(tag);
|
||||
await expect(args.onClick).toHaveBeenCalled();
|
||||
},
|
||||
};
|
||||
|
||||
export const WithLongText: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
args: {
|
||||
color: 'green',
|
||||
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
},
|
||||
parameters: {
|
||||
container: { width: 100 },
|
||||
},
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof Tag> = {
|
||||
argTypes: {
|
||||
color: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'colors',
|
||||
values: MAIN_COLOR_NAMES,
|
||||
props: (color: ThemeColor) => ({ color }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,10 +1,7 @@
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { ColorSample, ColorSampleProps } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
ColorSample,
|
||||
ColorSampleProps,
|
||||
} from '@/ui/display/color/components/ColorSample';
|
||||
import {
|
||||
LightIconButton,
|
||||
LightIconButtonProps,
|
||||
|
||||
@ -2,9 +2,8 @@ import styled from '@emotion/styled';
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/test';
|
||||
import { ComponentDecorator } from 'packages/twenty-ui';
|
||||
import { ComponentDecorator, Tag } from 'twenty-ui';
|
||||
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
import { MAIN_COLOR_NAMES } from '@/ui/theme/constants/MainColorNames';
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
import { IconComponent, Tag } from 'twenty-ui';
|
||||
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { Checkbox } from '@/ui/input/components/Checkbox';
|
||||
import { MenuItemLeftContent } from '@/ui/navigation/menu-item/internals/components/MenuItemLeftContent';
|
||||
import { ThemeColor } from '@/ui/theme/constants/MainColorNames';
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { Tag } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
Checkbox,
|
||||
CheckboxShape,
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { IconCheck } from 'twenty-ui';
|
||||
import { ColorSample, ColorSampleVariant, IconCheck } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
ColorSample,
|
||||
ColorSampleVariant,
|
||||
} from '@/ui/display/color/components/ColorSample';
|
||||
import { ThemeColor } from '@/ui/theme/constants/MainColorNames';
|
||||
|
||||
import {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { IconCheck } from 'twenty-ui';
|
||||
import { IconCheck, Tag } from 'twenty-ui';
|
||||
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { ThemeColor } from '@/ui/theme/constants/MainColorNames';
|
||||
|
||||
import { StyledMenuItemLeftContent } from '../internals/components/StyledMenuItemBase';
|
||||
|
||||
@ -4,10 +4,10 @@ import {
|
||||
CatalogDimension,
|
||||
CatalogOptions,
|
||||
CatalogStory,
|
||||
ColorSampleVariant,
|
||||
ComponentDecorator,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { ColorSampleVariant } from '@/ui/display/color/components/ColorSample';
|
||||
import {
|
||||
MAIN_COLOR_NAMES,
|
||||
ThemeColor,
|
||||
|
||||
Reference in New Issue
Block a user