Add styled component rule (#1261)
* Add StyledComponent rule * update doc * update doc * update doc
This commit is contained in:
@ -100,3 +100,36 @@ type MyType = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
### Use StyledComponents
|
||||||
|
|
||||||
|
Components should be styled with StyledComponents.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ❌ Bad
|
||||||
|
<div className="my-class">Hello World</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ Good
|
||||||
|
const StyledTitle = styled.div`
|
||||||
|
color: red;
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
||||||
|
Styled components should be prefixed with "Styled" to differentiate them from "real" components.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ❌ Bad
|
||||||
|
const Title = styled.div`
|
||||||
|
color: red;
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ Good
|
||||||
|
const StyledTitle = styled.div`
|
||||||
|
color: red;
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|||||||
@ -48,6 +48,7 @@ module.exports = {
|
|||||||
'simple-import-sort/exports': 'error',
|
'simple-import-sort/exports': 'error',
|
||||||
'twenty/sort-css-properties-alphabetically': 'error',
|
'twenty/sort-css-properties-alphabetically': 'error',
|
||||||
'twenty/no-hardcoded-colors': 'error',
|
'twenty/no-hardcoded-colors': 'error',
|
||||||
|
'twenty/styled-components-prefixed-with-styled': 'error',
|
||||||
'func-style':['error', 'declaration', { 'allowArrowFunctions': true }],
|
'func-style':['error', 'declaration', { 'allowArrowFunctions': true }],
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { Activity, useUpdateActivityMutation } from '~/generated/graphql';
|
|||||||
|
|
||||||
import { ACTIVITY_UPDATE_FRAGMENT } from '../graphql/fragments/activityUpdateFragment';
|
import { ACTIVITY_UPDATE_FRAGMENT } from '../graphql/fragments/activityUpdateFragment';
|
||||||
|
|
||||||
const BlockNoteStyledContainer = styled.div`
|
const StyledBlockNoteStyledContainer = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -70,8 +70,8 @@ export function ActivityBodyEditor({ activity, onChange }: OwnProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BlockNoteStyledContainer>
|
<StyledBlockNoteStyledContainer>
|
||||||
<BlockEditor editor={editor} />
|
<BlockEditor editor={editor} />
|
||||||
</BlockNoteStyledContainer>
|
</StyledBlockNoteStyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const meta: Meta<typeof CommentChip> = {
|
|||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof CommentChip>;
|
type Story = StoryObj<typeof CommentChip>;
|
||||||
|
|
||||||
const TestCellContainer = styled.div`
|
const StyledTestCellContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.primary};
|
background: ${({ theme }) => theme.background.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -51,10 +51,10 @@ export const InCellDefault: Story = {
|
|||||||
args: { count: 12 },
|
args: { count: 12 },
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<TestCellContainer>
|
<StyledTestCellContainer>
|
||||||
<StyledFakeCellText>Fake short text</StyledFakeCellText>
|
<StyledFakeCellText>Fake short text</StyledFakeCellText>
|
||||||
<Story />
|
<Story />
|
||||||
</TestCellContainer>
|
</StyledTestCellContainer>
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -63,12 +63,12 @@ export const InCellOverlappingBlur: Story = {
|
|||||||
...InCellDefault,
|
...InCellDefault,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<TestCellContainer>
|
<StyledTestCellContainer>
|
||||||
<StyledFakeCellText>
|
<StyledFakeCellText>
|
||||||
Fake long text to demonstrate ellipsis
|
Fake long text to demonstrate ellipsis
|
||||||
</StyledFakeCellText>
|
</StyledFakeCellText>
|
||||||
<Story />
|
<Story />
|
||||||
</TestCellContainer>
|
</StyledTestCellContainer>
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const Separator = styled.div`
|
const StyledSeparator = styled.div`
|
||||||
background-color: ${({ theme }) => theme.border.color.medium};
|
background-color: ${({ theme }) => theme.border.color.medium};
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(3)};
|
margin-bottom: ${({ theme }) => theme.spacing(3)};
|
||||||
@ -9,5 +9,5 @@ const Separator = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export function HorizontalSeparator(): JSX.Element {
|
export function HorizontalSeparator(): JSX.Element {
|
||||||
return <Separator />;
|
return <StyledSeparator />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,11 +11,11 @@ const meta: Meta<typeof CompanyChip> = {
|
|||||||
component: CompanyChip,
|
component: CompanyChip,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<TestCellContainer>
|
<StyledTestCellContainer>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Story />
|
<Story />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</TestCellContainer>
|
</StyledTestCellContainer>
|
||||||
),
|
),
|
||||||
ComponentDecorator,
|
ComponentDecorator,
|
||||||
],
|
],
|
||||||
@ -24,7 +24,7 @@ const meta: Meta<typeof CompanyChip> = {
|
|||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof CompanyChip>;
|
type Story = StoryObj<typeof CompanyChip>;
|
||||||
|
|
||||||
const TestCellContainer = styled.div`
|
const StyledTestCellContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.primary};
|
background: ${({ theme }) => theme.background.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
|||||||
|
|
||||||
import { PersonChip } from '../PersonChip';
|
import { PersonChip } from '../PersonChip';
|
||||||
|
|
||||||
const TestCellContainer = styled.div`
|
const StyledTestCellContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.primary};
|
background: ${({ theme }) => theme.background.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -22,11 +22,11 @@ const meta: Meta<typeof PersonChip> = {
|
|||||||
component: PersonChip,
|
component: PersonChip,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<TestCellContainer>
|
<StyledTestCellContainer>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Story />
|
<Story />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</TestCellContainer>
|
</StyledTestCellContainer>
|
||||||
),
|
),
|
||||||
ComponentDecorator,
|
ComponentDecorator,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { MainButton } from '@/ui/button/components/MainButton';
|
|||||||
import { Modal } from '@/ui/modal/components/Modal';
|
import { Modal } from '@/ui/modal/components/Modal';
|
||||||
import { CircularProgressBar } from '@/ui/progress-bar/components/CircularProgressBar';
|
import { CircularProgressBar } from '@/ui/progress-bar/components/CircularProgressBar';
|
||||||
|
|
||||||
const Footer = styled(Modal.Footer)`
|
const StyledFooter = styled(Modal.Footer)`
|
||||||
height: 60px;
|
height: 60px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
@ -12,7 +12,7 @@ const Footer = styled(Modal.Footer)`
|
|||||||
padding-right: ${({ theme }) => theme.spacing(30)};
|
padding-right: ${({ theme }) => theme.spacing(30)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Button = styled(MainButton)`
|
const StyledButton = styled(MainButton)`
|
||||||
width: 200px;
|
width: 200px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -27,11 +27,11 @@ export const ContinueButton = ({
|
|||||||
title,
|
title,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: ContinueButtonProps) => (
|
}: ContinueButtonProps) => (
|
||||||
<Footer>
|
<StyledFooter>
|
||||||
<Button
|
<StyledButton
|
||||||
icon={isLoading && <CircularProgressBar size={16} barWidth={2} />}
|
icon={isLoading && <CircularProgressBar size={16} barWidth={2} />}
|
||||||
title={title}
|
title={title}
|
||||||
onClick={!isLoading ? onContinue : undefined}
|
onClick={!isLoading ? onContinue : undefined}
|
||||||
/>
|
/>
|
||||||
</Footer>
|
</StyledFooter>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,20 +6,20 @@ export type Props = React.ComponentProps<'div'> & {
|
|||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Title = styled.span`
|
const StyledTitle = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.lg};
|
font-size: ${({ theme }) => theme.font.size.lg};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||||
text-align: center;
|
text-align: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Description = styled.span`
|
const StyledDescription = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
@ -29,9 +29,9 @@ const Description = styled.span`
|
|||||||
|
|
||||||
export function Heading({ title, description, ...props }: Props) {
|
export function Heading({ title, description, ...props }: Props) {
|
||||||
return (
|
return (
|
||||||
<Container {...props}>
|
<StyledContainer {...props}>
|
||||||
<Title>{title}</Title>
|
<StyledTitle>{title}</StyledTitle>
|
||||||
{description && <Description>{description}</Description>}
|
{description && <StyledDescription>{description}</StyledDescription>}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import { AppTooltip } from '@/ui/tooltip/AppTooltip';
|
|||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { useUpdateEffect } from '~/hooks/useUpdateEffect';
|
import { useUpdateEffect } from '~/hooks/useUpdateEffect';
|
||||||
|
|
||||||
const DropdownItem = styled.div`
|
const StyledDropdownItem = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: ${({ theme }) => theme.background.tertiary};
|
background-color: ${({ theme }) => theme.background.tertiary};
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
@ -42,7 +42,7 @@ const DropdownItem = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DropdownLabel = styled.span<{ isPlaceholder: boolean }>`
|
const StyledDropdownLabel = styled.span<{ isPlaceholder: boolean }>`
|
||||||
color: ${({ theme, isPlaceholder }) =>
|
color: ${({ theme, isPlaceholder }) =>
|
||||||
isPlaceholder ? theme.font.color.tertiary : theme.font.color.primary};
|
isPlaceholder ? theme.font.color.tertiary : theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -53,7 +53,7 @@ const DropdownLabel = styled.span<{ isPlaceholder: boolean }>`
|
|||||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const FloatingDropdown = styled.div`
|
const StyledFloatingDropdown = styled.div`
|
||||||
z-index: ${({ theme }) => theme.lastLayerZIndex};
|
z-index: ${({ theme }) => theme.lastLayerZIndex};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ export const MatchColumnSelect = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownItem
|
<StyledDropdownItem
|
||||||
id={name}
|
id={name}
|
||||||
ref={(node) => {
|
ref={(node) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
@ -158,14 +158,14 @@ export const MatchColumnSelect = ({
|
|||||||
onClick={handleDropdownItemClick}
|
onClick={handleDropdownItemClick}
|
||||||
>
|
>
|
||||||
{renderIcon(value?.icon)}
|
{renderIcon(value?.icon)}
|
||||||
<DropdownLabel isPlaceholder={!value?.label}>
|
<StyledDropdownLabel isPlaceholder={!value?.label}>
|
||||||
{value?.label ?? placeholder}
|
{value?.label ?? placeholder}
|
||||||
</DropdownLabel>
|
</StyledDropdownLabel>
|
||||||
<IconChevronDown size={16} color={theme.font.color.tertiary} />
|
<IconChevronDown size={16} color={theme.font.color.tertiary} />
|
||||||
</DropdownItem>
|
</StyledDropdownItem>
|
||||||
{isOpen &&
|
{isOpen &&
|
||||||
createPortal(
|
createPortal(
|
||||||
<FloatingDropdown ref={refs.setFloating} style={floatingStyles}>
|
<StyledFloatingDropdown ref={refs.setFloating} style={floatingStyles}>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
ref={dropdownContainerRef}
|
ref={dropdownContainerRef}
|
||||||
width={dropdownItemRef.current?.clientWidth}
|
width={dropdownItemRef.current?.clientWidth}
|
||||||
@ -210,7 +210,7 @@ export const MatchColumnSelect = ({
|
|||||||
)}
|
)}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</FloatingDropdown>,
|
</StyledFloatingDropdown>,
|
||||||
document.body,
|
document.body,
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { IconButton } from '@/ui/button/components/IconButton';
|
|||||||
import { useDialog } from '@/ui/dialog/hooks/useDialog';
|
import { useDialog } from '@/ui/dialog/hooks/useDialog';
|
||||||
import { IconX } from '@/ui/icon/index';
|
import { IconX } from '@/ui/icon/index';
|
||||||
|
|
||||||
const CloseButtonContainer = styled.div`
|
const StyledCloseButtonContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -39,12 +39,12 @@ export const ModalCloseButton = ({ onClose }: ModalCloseButtonProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CloseButtonContainer>
|
<StyledCloseButtonContainer>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<IconX size={16} color={theme.font.color.tertiary} />}
|
icon={<IconX size={16} color={theme.font.color.tertiary} />}
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
/>
|
/>
|
||||||
</CloseButtonContainer>
|
</StyledCloseButtonContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import type { Columns } from '../MatchColumnsStep';
|
import type { Columns } from '../MatchColumnsStep';
|
||||||
|
|
||||||
const GridContainer = styled.div`
|
const StyledGridContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -12,7 +12,7 @@ const GridContainer = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Grid = styled.div`
|
const StyledGrid = styled.div`
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -26,7 +26,7 @@ type HeightProps = {
|
|||||||
height?: `${number}px`;
|
height?: `${number}px`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GridRow = styled.div<HeightProps>`
|
const StyledGridRow = styled.div<HeightProps>`
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -37,7 +37,7 @@ type PositionProps = {
|
|||||||
position: 'left' | 'right';
|
position: 'left' | 'right';
|
||||||
};
|
};
|
||||||
|
|
||||||
const GridCell = styled.div<PositionProps>`
|
const StyledGridCell = styled.div<PositionProps>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -59,7 +59,7 @@ const GridCell = styled.div<PositionProps>`
|
|||||||
}};
|
}};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const GridHeader = styled.div<PositionProps>`
|
const StyledGridHeader = styled.div<PositionProps>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: ${({ theme }) => theme.background.tertiary};
|
background-color: ${({ theme }) => theme.background.tertiary};
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -98,29 +98,31 @@ export const ColumnGrid = <T extends string>({
|
|||||||
}: ColumnGridProps<T>) => {
|
}: ColumnGridProps<T>) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GridContainer>
|
<StyledGridContainer>
|
||||||
<Grid>
|
<StyledGrid>
|
||||||
<GridRow height="29px">
|
<StyledGridRow height="29px">
|
||||||
<GridHeader position="left">Imported data</GridHeader>
|
<StyledGridHeader position="left">Imported data</StyledGridHeader>
|
||||||
<GridHeader position="right">Twenty fields</GridHeader>
|
<StyledGridHeader position="right">Twenty fields</StyledGridHeader>
|
||||||
</GridRow>
|
</StyledGridRow>
|
||||||
{columns.map((column, index) => {
|
{columns.map((column, index) => {
|
||||||
const userColumn = renderUserColumn(columns, index);
|
const userColumn = renderUserColumn(columns, index);
|
||||||
const templateColumn = renderTemplateColumn(columns, index);
|
const templateColumn = renderTemplateColumn(columns, index);
|
||||||
|
|
||||||
if (React.isValidElement(userColumn)) {
|
if (React.isValidElement(userColumn)) {
|
||||||
return (
|
return (
|
||||||
<GridRow key={index}>
|
<StyledGridRow key={index}>
|
||||||
<GridCell position="left">{userColumn}</GridCell>
|
<StyledGridCell position="left">{userColumn}</StyledGridCell>
|
||||||
<GridCell position="right">{templateColumn}</GridCell>
|
<StyledGridCell position="right">
|
||||||
</GridRow>
|
{templateColumn}
|
||||||
|
</StyledGridCell>
|
||||||
|
</StyledGridRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
})}
|
})}
|
||||||
</Grid>
|
</StyledGrid>
|
||||||
</GridContainer>
|
</StyledGridContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,12 +11,12 @@ import type {
|
|||||||
MatchedSelectOptionsColumn,
|
MatchedSelectOptionsColumn,
|
||||||
} from '../MatchColumnsStep';
|
} from '../MatchColumnsStep';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
padding-bottom: ${({ theme }) => theme.spacing(1)};
|
padding-bottom: ${({ theme }) => theme.spacing(1)};
|
||||||
padding-left: ${({ theme }) => theme.spacing(2)};
|
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const SelectLabel = styled.span`
|
const StyledSelectLabel = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
@ -40,8 +40,8 @@ export const SubMatchingSelect = <T extends string>({
|
|||||||
const value = options.find((opt) => opt.value === option.value);
|
const value = options.find((opt) => opt.value === option.value);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<StyledContainer>
|
||||||
<SelectLabel>{option.entry}</SelectLabel>
|
<StyledSelectLabel>{option.entry}</StyledSelectLabel>
|
||||||
<MatchColumnSelect
|
<MatchColumnSelect
|
||||||
value={value}
|
value={value}
|
||||||
placeholder="Select..."
|
placeholder="Select..."
|
||||||
@ -51,6 +51,6 @@ export const SubMatchingSelect = <T extends string>({
|
|||||||
options={options}
|
options={options}
|
||||||
name={option.entry}
|
name={option.entry}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,14 +18,14 @@ import { ColumnType } from '../MatchColumnsStep';
|
|||||||
|
|
||||||
import { SubMatchingSelect } from './SubMatchingSelect';
|
import { SubMatchingSelect } from './SubMatchingSelect';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 10px;
|
min-height: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const AccordionButton = styled(ChakraAccordionButton)`
|
const StyledAccordionButton = styled(ChakraAccordionButton)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: ${({ theme }) => theme.accent.secondary};
|
background-color: ${({ theme }) => theme.accent.secondary};
|
||||||
border: none;
|
border: none;
|
||||||
@ -46,12 +46,12 @@ const AccordionButton = styled(ChakraAccordionButton)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const AccordionContainer = styled.div`
|
const StyledAccordionContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const AccordionLabel = styled.span`
|
const StyledAccordionLabel = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -123,7 +123,7 @@ export const TemplateColumn = <T extends string>({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<StyledContainer>
|
||||||
<MatchColumnSelect
|
<MatchColumnSelect
|
||||||
placeholder="Select column..."
|
placeholder="Select column..."
|
||||||
value={isIgnored ? ignoreValue : selectValue}
|
value={isIgnored ? ignoreValue : selectValue}
|
||||||
@ -132,15 +132,15 @@ export const TemplateColumn = <T extends string>({
|
|||||||
name={column.header}
|
name={column.header}
|
||||||
/>
|
/>
|
||||||
{isSelect && (
|
{isSelect && (
|
||||||
<AccordionContainer>
|
<StyledAccordionContainer>
|
||||||
<Accordion allowMultiple width="100%">
|
<Accordion allowMultiple width="100%">
|
||||||
<AccordionItem border="none" py={1}>
|
<AccordionItem border="none" py={1}>
|
||||||
<AccordionButton data-testid="accordion-button">
|
<StyledAccordionButton data-testid="accordion-button">
|
||||||
<AccordionLabel>
|
<StyledAccordionLabel>
|
||||||
{getAccordionTitle<T>(fields, column)}
|
{getAccordionTitle<T>(fields, column)}
|
||||||
</AccordionLabel>
|
</StyledAccordionLabel>
|
||||||
<AccordionIcon as={IconChevronDown} />
|
<AccordionIcon as={IconChevronDown} />
|
||||||
</AccordionButton>
|
</StyledAccordionButton>
|
||||||
<AccordionPanel pb={4} pr={3} display="flex" flexDir="column">
|
<AccordionPanel pb={4} pr={3} display="flex" flexDir="column">
|
||||||
{column.matchedOptions.map((option) => (
|
{column.matchedOptions.map((option) => (
|
||||||
<SubMatchingSelect
|
<SubMatchingSelect
|
||||||
@ -153,8 +153,8 @@ export const TemplateColumn = <T extends string>({
|
|||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</AccordionContainer>
|
</StyledAccordionContainer>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,13 +5,13 @@ import { assertNotNull } from '~/utils/assert';
|
|||||||
|
|
||||||
import type { Column } from '../MatchColumnsStep';
|
import type { Column } from '../MatchColumnsStep';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Value = styled.span`
|
const StyledValue = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
@ -20,7 +20,7 @@ const Value = styled.span`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Example = styled.span`
|
const StyledExample = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
@ -42,9 +42,9 @@ export const UserTableColumn = <T extends string>({
|
|||||||
const entry = entries.find(assertNotNull);
|
const entry = entries.find(assertNotNull);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<StyledContainer>
|
||||||
<Value>{header}</Value>
|
<StyledValue>{header}</StyledValue>
|
||||||
{entry && <Example>{`ex: ${entry}`}</Example>}
|
{entry && <StyledExample>{`ex: ${entry}`}</StyledExample>}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,7 +12,7 @@ const StyledHeading = styled(Heading)`
|
|||||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TableContainer = styled.div`
|
const StyledTableContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 0px;
|
height: 0px;
|
||||||
@ -42,13 +42,13 @@ export const SelectHeaderStep = ({ data, onContinue }: SelectHeaderProps) => {
|
|||||||
<>
|
<>
|
||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<StyledHeading title="Select header row" />
|
<StyledHeading title="Select header row" />
|
||||||
<TableContainer>
|
<StyledTableContainer>
|
||||||
<SelectHeaderTable
|
<SelectHeaderTable
|
||||||
data={data}
|
data={data}
|
||||||
selectedRows={selectedRows}
|
selectedRows={selectedRows}
|
||||||
setSelectedRows={setSelectedRows}
|
setSelectedRows={setSelectedRows}
|
||||||
/>
|
/>
|
||||||
</TableContainer>
|
</StyledTableContainer>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
<ContinueButton
|
<ContinueButton
|
||||||
onContinue={handleContinue}
|
onContinue={handleContinue}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { Radio } from '@/ui/input/radio/components/Radio';
|
|||||||
import { RadioGroup } from '@/ui/input/radio/components/RadioGroup';
|
import { RadioGroup } from '@/ui/input/radio/components/RadioGroup';
|
||||||
import { Modal } from '@/ui/modal/components/Modal';
|
import { Modal } from '@/ui/modal/components/Modal';
|
||||||
|
|
||||||
const Content = styled(Modal.Content)`
|
const StyledContent = styled(Modal.Content)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ const StyledHeading = styled(Heading)`
|
|||||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const RadioContainer = styled.div`
|
const StyledRadioContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@ -46,16 +46,16 @@ export const SelectSheetStep = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Content>
|
<StyledContent>
|
||||||
<StyledHeading title="Select the sheet to use" />
|
<StyledHeading title="Select the sheet to use" />
|
||||||
<RadioContainer>
|
<StyledRadioContainer>
|
||||||
<RadioGroup onValueChange={(value) => setValue(value)} value={value}>
|
<RadioGroup onValueChange={(value) => setValue(value)} value={value}>
|
||||||
{sheetNames.map((sheetName) => (
|
{sheetNames.map((sheetName) => (
|
||||||
<Radio value={sheetName} key={sheetName} />
|
<Radio value={sheetName} key={sheetName} />
|
||||||
))}
|
))}
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</RadioContainer>
|
</StyledRadioContainer>
|
||||||
</Content>
|
</StyledContent>
|
||||||
<ContinueButton
|
<ContinueButton
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
onContinue={() => handleOnContinue(value)}
|
onContinue={() => handleOnContinue(value)}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { useStepBar } from '@/ui/step-bar/hooks/useStepBar';
|
|||||||
|
|
||||||
import { UploadFlow } from './UploadFlow';
|
import { UploadFlow } from './UploadFlow';
|
||||||
|
|
||||||
const Header = styled(Modal.Header)`
|
const StyledHeader = styled(Modal.Header)`
|
||||||
background-color: ${({ theme }) => theme.background.secondary};
|
background-color: ${({ theme }) => theme.background.secondary};
|
||||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
|
border-bottom: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
height: 60px;
|
height: 60px;
|
||||||
@ -36,13 +36,13 @@ export const Steps = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header>
|
<StyledHeader>
|
||||||
<StepBar activeStep={activeStep}>
|
<StepBar activeStep={activeStep}>
|
||||||
{steps.map((key) => (
|
{steps.map((key) => (
|
||||||
<StepBar.Step label={stepTitles[key]} key={key} />
|
<StepBar.Step label={stepTitles[key]} key={key} />
|
||||||
))}
|
))}
|
||||||
</StepBar>
|
</StepBar>
|
||||||
</Header>
|
</StyledHeader>
|
||||||
<UploadFlow nextStep={nextStep} />
|
<UploadFlow nextStep={nextStep} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { SelectSheetStep } from './SelectSheetStep/SelectSheetStep';
|
|||||||
import { UploadStep } from './UploadStep/UploadStep';
|
import { UploadStep } from './UploadStep/UploadStep';
|
||||||
import { ValidationStep } from './ValidationStep/ValidationStep';
|
import { ValidationStep } from './ValidationStep/ValidationStep';
|
||||||
|
|
||||||
const ProgressBarContainer = styled(Modal.Content)`
|
const StyledProgressBarContainer = styled(Modal.Content)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -209,13 +209,13 @@ export const UploadFlow = ({ nextStep }: Props) => {
|
|||||||
case StepType.loading:
|
case StepType.loading:
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<ProgressBarContainer>
|
<StyledProgressBarContainer>
|
||||||
<CircularProgressBar
|
<CircularProgressBar
|
||||||
size={80}
|
size={80}
|
||||||
barWidth={8}
|
barWidth={8}
|
||||||
barColor={theme.font.color.primary}
|
barColor={theme.font.color.primary}
|
||||||
/>
|
/>
|
||||||
</ProgressBarContainer>
|
</StyledProgressBarContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { Modal } from '@/ui/modal/components/Modal';
|
|||||||
|
|
||||||
import { DropZone } from './components/DropZone';
|
import { DropZone } from './components/DropZone';
|
||||||
|
|
||||||
const Content = styled(Modal.Content)`
|
const StyledContent = styled(Modal.Content)`
|
||||||
padding: ${({ theme }) => theme.spacing(6)};
|
padding: ${({ theme }) => theme.spacing(6)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -27,8 +27,8 @@ export const UploadStep = ({ onContinue }: UploadProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Content>
|
<StyledContent>
|
||||||
<DropZone onContinue={handleOnContinue} isLoading={isLoading} />
|
<DropZone onContinue={handleOnContinue} isLoading={isLoading} />
|
||||||
</Content>
|
</StyledContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { readFileAsync } from '@/spreadsheet-import/utils/readFilesAsync';
|
|||||||
import { MainButton } from '@/ui/button/components/MainButton';
|
import { MainButton } from '@/ui/button/components/MainButton';
|
||||||
import { useSnackBar } from '@/ui/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/snack-bar/hooks/useSnackBar';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => `
|
background: ${({ theme }) => `
|
||||||
repeating-linear-gradient(
|
repeating-linear-gradient(
|
||||||
@ -55,7 +55,7 @@ const Container = styled.div`
|
|||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Overlay = styled.div`
|
const StyledOverlay = styled.div`
|
||||||
background: ${({ theme }) => theme.background.transparent.medium};
|
background: ${({ theme }) => theme.background.transparent.medium};
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
@ -65,14 +65,14 @@ const Overlay = styled.div`
|
|||||||
top: 0px;
|
top: 0px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Text = styled.span`
|
const StyledText = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
text-align: center;
|
text-align: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Button = styled(MainButton)`
|
const StyledButton = styled(MainButton)`
|
||||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
margin-top: ${({ theme }) => theme.spacing(2)};
|
||||||
width: 200px;
|
width: 200px;
|
||||||
`;
|
`;
|
||||||
@ -125,19 +125,19 @@ export const DropZone = ({ onContinue, isLoading }: DropZoneProps) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container {...getRootProps()}>
|
<StyledContainer {...getRootProps()}>
|
||||||
{isDragActive && <Overlay />}
|
{isDragActive && <StyledOverlay />}
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
{isDragActive ? (
|
{isDragActive ? (
|
||||||
<Text>Drop file here...</Text>
|
<StyledText>Drop file here...</StyledText>
|
||||||
) : loading || isLoading ? (
|
) : loading || isLoading ? (
|
||||||
<Text>Processing...</Text>
|
<StyledText>Processing...</StyledText>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Text>Upload .xlsx, .xls or .csv file</Text>
|
<StyledText>Upload .xlsx, .xls or .csv file</StyledText>
|
||||||
<Button onClick={open} title="Select file" />
|
<StyledButton onClick={open} title="Select file" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,21 +5,21 @@ import styled from '@emotion/styled';
|
|||||||
import type { Fields } from '@/spreadsheet-import/types';
|
import type { Fields } from '@/spreadsheet-import/types';
|
||||||
import { AppTooltip } from '@/ui/tooltip/AppTooltip';
|
import { AppTooltip } from '@/ui/tooltip/AppTooltip';
|
||||||
|
|
||||||
const HeaderContainer = styled.div`
|
const StyledHeaderContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const HeaderLabel = styled.span`
|
const StyledHeaderLabel = styled.span`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DefaultContainer = styled.div`
|
const StyledDefaultContainer = styled.div`
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -33,8 +33,10 @@ export const generateColumns = <T extends string>(fields: Fields<T>) =>
|
|||||||
name: column.label,
|
name: column.label,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
headerRenderer: () => (
|
headerRenderer: () => (
|
||||||
<HeaderContainer>
|
<StyledHeaderContainer>
|
||||||
<HeaderLabel id={`${column.key}`}>{column.label}</HeaderLabel>
|
<StyledHeaderLabel id={`${column.key}`}>
|
||||||
|
{column.label}
|
||||||
|
</StyledHeaderLabel>
|
||||||
{column.description &&
|
{column.description &&
|
||||||
createPortal(
|
createPortal(
|
||||||
<AppTooltip
|
<AppTooltip
|
||||||
@ -44,10 +46,10 @@ export const generateColumns = <T extends string>(fields: Fields<T>) =>
|
|||||||
/>,
|
/>,
|
||||||
document.body,
|
document.body,
|
||||||
)}
|
)}
|
||||||
</HeaderContainer>
|
</StyledHeaderContainer>
|
||||||
),
|
),
|
||||||
formatter: ({ row }) => (
|
formatter: ({ row }) => (
|
||||||
<DefaultContainer>{row[column.key]}</DefaultContainer>
|
<StyledDefaultContainer>{row[column.key]}</StyledDefaultContainer>
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { Modal } from '@/ui/modal/components/Modal';
|
|||||||
import { generateColumns } from './components/columns';
|
import { generateColumns } from './components/columns';
|
||||||
import type { Meta } from './types';
|
import type { Meta } from './types';
|
||||||
|
|
||||||
const Toolbar = styled.div`
|
const StyledToolbar = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -25,20 +25,20 @@ const Toolbar = styled.div`
|
|||||||
margin-top: ${({ theme }) => theme.spacing(8)};
|
margin-top: ${({ theme }) => theme.spacing(8)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ErrorToggle = styled.div`
|
const StyledErrorToggle = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ErrorToggleDescription = styled.span`
|
const StyledErrorToggleDescription = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ScrollContainer = styled.div`
|
const StyledScrollContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@ -46,7 +46,7 @@ const ScrollContainer = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const NoRowsContainer = styled.div`
|
const StyledNoRowsContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
grid-column: 1/-1;
|
grid-column: 1/-1;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -188,16 +188,16 @@ export const ValidationStep = <T extends string>({
|
|||||||
title="Review your import"
|
title="Review your import"
|
||||||
description="Correct the issues and fill the missing data."
|
description="Correct the issues and fill the missing data."
|
||||||
/>
|
/>
|
||||||
<Toolbar>
|
<StyledToolbar>
|
||||||
<ErrorToggle>
|
<StyledErrorToggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
value={filterByErrors}
|
value={filterByErrors}
|
||||||
onChange={() => setFilterByErrors(!filterByErrors)}
|
onChange={() => setFilterByErrors(!filterByErrors)}
|
||||||
/>
|
/>
|
||||||
<ErrorToggleDescription>
|
<StyledErrorToggleDescription>
|
||||||
Show only rows with errors
|
Show only rows with errors
|
||||||
</ErrorToggleDescription>
|
</StyledErrorToggleDescription>
|
||||||
</ErrorToggle>
|
</StyledErrorToggle>
|
||||||
<Button
|
<Button
|
||||||
icon={<IconTrash />}
|
icon={<IconTrash />}
|
||||||
title="Remove"
|
title="Remove"
|
||||||
@ -205,8 +205,8 @@ export const ValidationStep = <T extends string>({
|
|||||||
onClick={deleteSelectedRows}
|
onClick={deleteSelectedRows}
|
||||||
disabled={selectedRows.size === 0}
|
disabled={selectedRows.size === 0}
|
||||||
/>
|
/>
|
||||||
</Toolbar>
|
</StyledToolbar>
|
||||||
<ScrollContainer>
|
<StyledScrollContainer>
|
||||||
<Table
|
<Table
|
||||||
rowKeyGetter={rowKeyGetter}
|
rowKeyGetter={rowKeyGetter}
|
||||||
rows={tableData}
|
rows={tableData}
|
||||||
@ -216,15 +216,15 @@ export const ValidationStep = <T extends string>({
|
|||||||
onSelectedRowsChange={setSelectedRows}
|
onSelectedRowsChange={setSelectedRows}
|
||||||
components={{
|
components={{
|
||||||
noRowsFallback: (
|
noRowsFallback: (
|
||||||
<NoRowsContainer>
|
<StyledNoRowsContainer>
|
||||||
{filterByErrors
|
{filterByErrors
|
||||||
? 'No data containing errors'
|
? 'No data containing errors'
|
||||||
: 'No data found'}
|
: 'No data found'}
|
||||||
</NoRowsContainer>
|
</StyledNoRowsContainer>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ScrollContainer>
|
</StyledScrollContainer>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
<ContinueButton onContinue={onContinue} title="Confirm" />
|
<ContinueButton onContinue={onContinue} title="Confirm" />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -14,21 +14,21 @@ import { AppTooltip } from '@/ui/tooltip/AppTooltip';
|
|||||||
|
|
||||||
import type { Meta } from '../types';
|
import type { Meta } from '../types';
|
||||||
|
|
||||||
const HeaderContainer = styled.div`
|
const StyledHeaderContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const HeaderLabel = styled.span`
|
const StyledHeaderLabel = styled.span`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const CheckboxContainer = styled.div`
|
const StyledCheckboxContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -39,13 +39,13 @@ const CheckboxContainer = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ToggleContainer = styled.div`
|
const StyledToggleContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const InputContainer = styled.div`
|
const StyledInputContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
@ -53,7 +53,7 @@ const InputContainer = styled.div`
|
|||||||
padding-right: ${({ theme }) => theme.spacing(2)};
|
padding-right: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DefaultContainer = styled.div`
|
const StyledDefaultContainer = styled.div`
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -79,7 +79,7 @@ export const generateColumns = <T extends string>(
|
|||||||
const [isRowSelected, onRowSelectionChange] = useRowSelection();
|
const [isRowSelected, onRowSelectionChange] = useRowSelection();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxContainer>
|
<StyledCheckboxContainer>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
aria-label="Select"
|
aria-label="Select"
|
||||||
checked={isRowSelected}
|
checked={isRowSelected}
|
||||||
@ -92,7 +92,7 @@ export const generateColumns = <T extends string>(
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</CheckboxContainer>
|
</StyledCheckboxContainer>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -103,8 +103,10 @@ export const generateColumns = <T extends string>(
|
|||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
headerRenderer: () => (
|
headerRenderer: () => (
|
||||||
<HeaderContainer>
|
<StyledHeaderContainer>
|
||||||
<HeaderLabel id={`${column.key}`}>{column.label}</HeaderLabel>
|
<StyledHeaderLabel id={`${column.key}`}>
|
||||||
|
{column.label}
|
||||||
|
</StyledHeaderLabel>
|
||||||
{column.description &&
|
{column.description &&
|
||||||
createPortal(
|
createPortal(
|
||||||
<AppTooltip
|
<AppTooltip
|
||||||
@ -114,7 +116,7 @@ export const generateColumns = <T extends string>(
|
|||||||
/>,
|
/>,
|
||||||
document.body,
|
document.body,
|
||||||
)}
|
)}
|
||||||
</HeaderContainer>
|
</StyledHeaderContainer>
|
||||||
),
|
),
|
||||||
editable: column.fieldType.type !== 'checkbox',
|
editable: column.fieldType.type !== 'checkbox',
|
||||||
editor: ({ row, onRowChange, onClose }) => {
|
editor: ({ row, onRowChange, onClose }) => {
|
||||||
@ -158,7 +160,7 @@ export const generateColumns = <T extends string>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <InputContainer>{component}</InputContainer>;
|
return <StyledInputContainer>{component}</StyledInputContainer>;
|
||||||
},
|
},
|
||||||
editorOptions: {
|
editorOptions: {
|
||||||
editOnClick: true,
|
editOnClick: true,
|
||||||
@ -170,7 +172,7 @@ export const generateColumns = <T extends string>(
|
|||||||
switch (column.fieldType.type) {
|
switch (column.fieldType.type) {
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
component = (
|
component = (
|
||||||
<ToggleContainer
|
<StyledToggleContainer
|
||||||
id={`${columnKey}-${row.__index}`}
|
id={`${columnKey}-${row.__index}`}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -185,23 +187,23 @@ export const generateColumns = <T extends string>(
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ToggleContainer>
|
</StyledToggleContainer>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'select':
|
case 'select':
|
||||||
component = (
|
component = (
|
||||||
<DefaultContainer id={`${columnKey}-${row.__index}`}>
|
<StyledDefaultContainer id={`${columnKey}-${row.__index}`}>
|
||||||
{column.fieldType.options.find(
|
{column.fieldType.options.find(
|
||||||
(option) => option.value === row[columnKey as T],
|
(option) => option.value === row[columnKey as T],
|
||||||
)?.label || null}
|
)?.label || null}
|
||||||
</DefaultContainer>
|
</StyledDefaultContainer>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
component = (
|
component = (
|
||||||
<DefaultContainer id={`${columnKey}-${row.__index}`}>
|
<StyledDefaultContainer id={`${columnKey}-${row.__index}`}>
|
||||||
{row[columnKey]}
|
{row[columnKey]}
|
||||||
</DefaultContainer>
|
</StyledDefaultContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -65,11 +65,11 @@ const StyledDropdownItem = styled.button<ButtonProps>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DropdownContainer = styled.div`
|
const StyledDropdownContainer = styled.div`
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DropdownMenu = styled.div`
|
const StyledDropdownMenu = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -112,7 +112,7 @@ export function DropdownButton({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{selectedOption && (
|
{selectedOption && (
|
||||||
<DropdownContainer>
|
<StyledDropdownContainer>
|
||||||
<StyledButton
|
<StyledButton
|
||||||
onClick={() => setIsOpen(!isOpen)}
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
@ -123,7 +123,7 @@ export function DropdownButton({
|
|||||||
{options.length > 1 && <IconChevronDown />}
|
{options.length > 1 && <IconChevronDown />}
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<DropdownMenu>
|
<StyledDropdownMenu>
|
||||||
{options
|
{options
|
||||||
.filter((option) => option.label !== selectedOption.label)
|
.filter((option) => option.label !== selectedOption.label)
|
||||||
.map((option, index) => (
|
.map((option, index) => (
|
||||||
@ -135,9 +135,9 @@ export function DropdownButton({
|
|||||||
{option.label}
|
{option.label}
|
||||||
</StyledDropdownItem>
|
</StyledDropdownItem>
|
||||||
))}
|
))}
|
||||||
</DropdownMenu>
|
</StyledDropdownMenu>
|
||||||
)}
|
)}
|
||||||
</DropdownContainer>
|
</StyledDropdownContainer>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -13,12 +13,12 @@ const StyledContainer = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const CardContainer = styled.div`
|
const StyledCardContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Label = styled.span`
|
const StyledLabel = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.secondary};
|
color: ${({ theme }) => theme.font.color.secondary};
|
||||||
font-size: ${({ theme }) => theme.font.size.xs};
|
font-size: ${({ theme }) => theme.font.size.xs};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
@ -33,30 +33,30 @@ export type ColorSchemePickerProps = {
|
|||||||
export function ColorSchemePicker({ value, onChange }: ColorSchemePickerProps) {
|
export function ColorSchemePicker({ value, onChange }: ColorSchemePickerProps) {
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<CardContainer>
|
<StyledCardContainer>
|
||||||
<ColorSchemeCard
|
<ColorSchemeCard
|
||||||
onClick={() => onChange(ColorScheme.Light)}
|
onClick={() => onChange(ColorScheme.Light)}
|
||||||
variant="light"
|
variant="light"
|
||||||
selected={value === ColorScheme.Light}
|
selected={value === ColorScheme.Light}
|
||||||
/>
|
/>
|
||||||
<Label>Light</Label>
|
<StyledLabel>Light</StyledLabel>
|
||||||
</CardContainer>
|
</StyledCardContainer>
|
||||||
<CardContainer>
|
<StyledCardContainer>
|
||||||
<ColorSchemeCard
|
<ColorSchemeCard
|
||||||
onClick={() => onChange(ColorScheme.Dark)}
|
onClick={() => onChange(ColorScheme.Dark)}
|
||||||
variant="dark"
|
variant="dark"
|
||||||
selected={value === ColorScheme.Dark}
|
selected={value === ColorScheme.Dark}
|
||||||
/>
|
/>
|
||||||
<Label>Dark</Label>
|
<StyledLabel>Dark</StyledLabel>
|
||||||
</CardContainer>
|
</StyledCardContainer>
|
||||||
<CardContainer>
|
<StyledCardContainer>
|
||||||
<ColorSchemeCard
|
<ColorSchemeCard
|
||||||
onClick={() => onChange(ColorScheme.System)}
|
onClick={() => onChange(ColorScheme.System)}
|
||||||
variant="system"
|
variant="system"
|
||||||
selected={value === ColorScheme.System}
|
selected={value === ColorScheme.System}
|
||||||
/>
|
/>
|
||||||
<Label>System settings</Label>
|
<StyledLabel>System settings</StyledLabel>
|
||||||
</CardContainer>
|
</StyledCardContainer>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
|||||||
|
|
||||||
import { ColorSchemeCard } from '../ColorSchemeCard';
|
import { ColorSchemeCard } from '../ColorSchemeCard';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
> * + * {
|
> * + * {
|
||||||
@ -18,9 +18,9 @@ const meta: Meta<typeof ColorSchemeCard> = {
|
|||||||
component: ColorSchemeCard,
|
component: ColorSchemeCard,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<Container>
|
<StyledContainer>
|
||||||
<Story />
|
<Story />
|
||||||
</Container>
|
</StyledContainer>
|
||||||
),
|
),
|
||||||
ComponentDecorator,
|
ComponentDecorator,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { motion } from 'framer-motion';
|
|||||||
|
|
||||||
import { Button, ButtonVariant } from '@/ui/button/components/Button';
|
import { Button, ButtonVariant } from '@/ui/button/components/Button';
|
||||||
|
|
||||||
const DialogOverlay = styled(motion.div)`
|
const StyledDialogOverlay = styled(motion.div)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.overlay};
|
background: ${({ theme }) => theme.background.overlay};
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -17,7 +17,7 @@ const DialogOverlay = styled(motion.div)`
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DialogContainer = styled(motion.div)`
|
const StyledDialogContainer = styled(motion.div)`
|
||||||
background: ${({ theme }) => theme.background.primary};
|
background: ${({ theme }) => theme.background.primary};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -28,7 +28,7 @@ const DialogContainer = styled(motion.div)`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DialogTitle = styled.span`
|
const StyledDialogTitle = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.md};
|
font-size: ${({ theme }) => theme.font.size.md};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||||
@ -36,7 +36,7 @@ const DialogTitle = styled.span`
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DialogMessage = styled.span`
|
const StyledDialogMessage = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
@ -44,7 +44,7 @@ const DialogMessage = styled.span`
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DialogButton = styled(Button)`
|
const StyledDialogButton = styled(Button)`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
@ -87,7 +87,7 @@ export function Dialog({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DialogOverlay
|
<StyledDialogOverlay
|
||||||
variants={dialogVariants}
|
variants={dialogVariants}
|
||||||
initial="closed"
|
initial="closed"
|
||||||
animate="open"
|
animate="open"
|
||||||
@ -99,16 +99,16 @@ export function Dialog({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DialogContainer
|
<StyledDialogContainer
|
||||||
variants={containerVariants}
|
variants={containerVariants}
|
||||||
transition={{ damping: 15, stiffness: 100 }}
|
transition={{ damping: 15, stiffness: 100 }}
|
||||||
{...rootProps}
|
{...rootProps}
|
||||||
>
|
>
|
||||||
{title && <DialogTitle>{title}</DialogTitle>}
|
{title && <StyledDialogTitle>{title}</StyledDialogTitle>}
|
||||||
{message && <DialogMessage>{message}</DialogMessage>}
|
{message && <StyledDialogMessage>{message}</StyledDialogMessage>}
|
||||||
{children}
|
{children}
|
||||||
{buttons.map((button) => (
|
{buttons.map((button) => (
|
||||||
<DialogButton
|
<StyledDialogButton
|
||||||
key={button.title}
|
key={button.title}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
button?.onClick?.(e);
|
button?.onClick?.(e);
|
||||||
@ -119,7 +119,7 @@ export function Dialog({
|
|||||||
{...button}
|
{...button}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</DialogContainer>
|
</StyledDialogContainer>
|
||||||
</DialogOverlay>
|
</StyledDialogOverlay>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const DropdownMenu = styled.div<{
|
export const DropdownMenu = styled.div<{
|
||||||
|
|||||||
@ -11,7 +11,7 @@ type Props = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DropdownMenuCheckableItemContainer = styled(DropdownMenuItem)`
|
const StyledDropdownMenuCheckableItemContainer = styled(DropdownMenuItem)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -42,11 +42,11 @@ export function DropdownMenuCheckableItem({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenuCheckableItemContainer onClick={handleClick}>
|
<StyledDropdownMenuCheckableItemContainer onClick={handleClick}>
|
||||||
<StyledLeftContainer>
|
<StyledLeftContainer>
|
||||||
<Checkbox checked={checked} />
|
<Checkbox checked={checked} />
|
||||||
<StyledChildrenContainer>{children}</StyledChildrenContainer>
|
<StyledChildrenContainer>{children}</StyledChildrenContainer>
|
||||||
</StyledLeftContainer>
|
</StyledLeftContainer>
|
||||||
</DropdownMenuCheckableItemContainer>
|
</StyledDropdownMenuCheckableItemContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import { textInputStyle } from '@/ui/theme/constants/effects';
|
import { textInputStyle } from '@/ui/theme/constants/effects';
|
||||||
|
|
||||||
export const DropdownMenuInputContainer = styled.div`
|
const StyledDropdownMenuInputContainer = styled.div`
|
||||||
--vertical-padding: ${({ theme }) => theme.spacing(1)};
|
--vertical-padding: ${({ theme }) => theme.spacing(1)};
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -28,7 +28,7 @@ export const DropdownMenuInput = forwardRef<
|
|||||||
HTMLInputElement,
|
HTMLInputElement,
|
||||||
InputHTMLAttributes<HTMLInputElement>
|
InputHTMLAttributes<HTMLInputElement>
|
||||||
>((props, ref) => (
|
>((props, ref) => (
|
||||||
<DropdownMenuInputContainer>
|
<StyledDropdownMenuInputContainer>
|
||||||
<StyledInput autoComplete="off" placeholder="Search" {...props} ref={ref} />
|
<StyledInput autoComplete="off" placeholder="Search" {...props} ref={ref} />
|
||||||
</DropdownMenuInputContainer>
|
</StyledDropdownMenuInputContainer>
|
||||||
));
|
));
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const DropdownMenuItemsContainer = styled.div<{
|
export const DropdownMenuItemsContainer = styled.div<{
|
||||||
|
|||||||
@ -13,7 +13,7 @@ type Props = React.ComponentProps<'li'> & {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DropdownMenuSelectableItemContainer = styled(DropdownMenuItem)<
|
const StyledDropdownMenuSelectableItemContainer = styled(DropdownMenuItem)<
|
||||||
Pick<Props, 'hovered'>
|
Pick<Props, 'hovered'>
|
||||||
>`
|
>`
|
||||||
${hoverBackground};
|
${hoverBackground};
|
||||||
@ -72,7 +72,7 @@ export function DropdownMenuSelectableItem({
|
|||||||
}, [hovered]);
|
}, [hovered]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenuSelectableItemContainer
|
<StyledDropdownMenuSelectableItemContainer
|
||||||
{...restProps}
|
{...restProps}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
hovered={hovered}
|
hovered={hovered}
|
||||||
@ -82,6 +82,6 @@ export function DropdownMenuSelectableItem({
|
|||||||
<StyledRightIcon>
|
<StyledRightIcon>
|
||||||
{selected && <IconCheck size={theme.icon.size.md} />}
|
{selected && <IconCheck size={theme.icon.size.md} />}
|
||||||
</StyledRightIcon>
|
</StyledRightIcon>
|
||||||
</DropdownMenuSelectableItemContainer>
|
</StyledDropdownMenuSelectableItemContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const DropdownMenuSeparator = styled.div`
|
export const DropdownMenuSeparator = styled.div`
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const DropdownMenuSubheader = styled.div`
|
export const DropdownMenuSubheader = styled.div`
|
||||||
|
|||||||
@ -43,19 +43,19 @@ const FakeContentBelow = () => (
|
|||||||
const avatarUrl =
|
const avatarUrl =
|
||||||
'https://s3-alpha-sig.figma.com/img/bbb5/4905/f0a52cc2b9aaeb0a82a360d478dae8bf?Expires=1687132800&Signature=iVBr0BADa3LHoFVGbwqO-wxC51n1o~ZyFD-w7nyTyFP4yB-Y6zFawL-igewaFf6PrlumCyMJThDLAAc-s-Cu35SBL8BjzLQ6HymzCXbrblUADMB208PnMAvc1EEUDq8TyryFjRO~GggLBk5yR0EXzZ3zenqnDEGEoQZR~TRqS~uDF-GwQB3eX~VdnuiU2iittWJkajIDmZtpN3yWtl4H630A3opQvBnVHZjXAL5YPkdh87-a-H~6FusWvvfJxfNC2ZzbrARzXofo8dUFtH7zUXGCC~eUk~hIuLbLuz024lFQOjiWq2VKyB7dQQuGFpM-OZQEV8tSfkViP8uzDLTaCg__&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4';
|
'https://s3-alpha-sig.figma.com/img/bbb5/4905/f0a52cc2b9aaeb0a82a360d478dae8bf?Expires=1687132800&Signature=iVBr0BADa3LHoFVGbwqO-wxC51n1o~ZyFD-w7nyTyFP4yB-Y6zFawL-igewaFf6PrlumCyMJThDLAAc-s-Cu35SBL8BjzLQ6HymzCXbrblUADMB208PnMAvc1EEUDq8TyryFjRO~GggLBk5yR0EXzZ3zenqnDEGEoQZR~TRqS~uDF-GwQB3eX~VdnuiU2iittWJkajIDmZtpN3yWtl4H630A3opQvBnVHZjXAL5YPkdh87-a-H~6FusWvvfJxfNC2ZzbrARzXofo8dUFtH7zUXGCC~eUk~hIuLbLuz024lFQOjiWq2VKyB7dQQuGFpM-OZQEV8tSfkViP8uzDLTaCg__&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4';
|
||||||
|
|
||||||
const FakeMenuContent = styled.div`
|
const StyledFakeMenuContent = styled.div`
|
||||||
height: 400px;
|
height: 400px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const FakeBelowContainer = styled.div`
|
const StyledFakeBelowContainer = styled.div`
|
||||||
height: 600px;
|
height: 600px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
width: 300px;
|
width: 300px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const MenuAbsolutePositionWrapper = styled.div`
|
const StyledMenuAbsolutePositionWrapper = styled.div`
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ const FakeCheckableMenuItemList = ({ hasAvatar }: { hasAvatar?: boolean }) => {
|
|||||||
export const Empty: Story = {
|
export const Empty: Story = {
|
||||||
render: (args) => (
|
render: (args) => (
|
||||||
<DropdownMenu {...args}>
|
<DropdownMenu {...args}>
|
||||||
<FakeMenuContent />
|
<StyledFakeMenuContent />
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@ -166,12 +166,12 @@ export const WithContentBelow: Story = {
|
|||||||
...Empty,
|
...Empty,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<FakeBelowContainer>
|
<StyledFakeBelowContainer>
|
||||||
<FakeContentBelow />
|
<FakeContentBelow />
|
||||||
<MenuAbsolutePositionWrapper>
|
<StyledMenuAbsolutePositionWrapper>
|
||||||
<Story />
|
<Story />
|
||||||
</MenuAbsolutePositionWrapper>
|
</StyledMenuAbsolutePositionWrapper>
|
||||||
</FakeBelowContainer>
|
</StyledFakeBelowContainer>
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -50,7 +50,7 @@ const StyledEditButtonContainer = styled(motion.div)`
|
|||||||
right: 0;
|
right: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const EditableFieldBaseContainer = styled.div`
|
export const StyledEditableFieldBaseContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ export function EditableField({
|
|||||||
const showEditButton = !isFieldInEditMode && isHovered && useEditButton;
|
const showEditButton = !isFieldInEditMode && isHovered && useEditButton;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableFieldBaseContainer
|
<StyledEditableFieldBaseContainer
|
||||||
onMouseEnter={handleContainerMouseEnter}
|
onMouseEnter={handleContainerMouseEnter}
|
||||||
onMouseLeave={handleContainerMouseLeave}
|
onMouseLeave={handleContainerMouseLeave}
|
||||||
>
|
>
|
||||||
@ -151,6 +151,6 @@ export function EditableField({
|
|||||||
<EditableFieldEditButton />
|
<EditableFieldEditButton />
|
||||||
</StyledEditButtonContainer>
|
</StyledEditButtonContainer>
|
||||||
)}
|
)}
|
||||||
</EditableFieldBaseContainer>
|
</StyledEditableFieldBaseContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const EditableFieldNormalModeOuterContainer = styled.div<
|
const StyledEditableFieldNormalModeOuterContainer = styled.div<
|
||||||
Pick<
|
Pick<
|
||||||
OwnProps,
|
OwnProps,
|
||||||
| 'disableClick'
|
| 'disableClick'
|
||||||
@ -51,7 +51,7 @@ export const EditableFieldNormalModeOuterContainer = styled.div<
|
|||||||
}}
|
}}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const EditableFieldNormalModeInnerContainer = styled.div`
|
const StyledEditableFieldNormalModeInnerContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
font-size: 'inherit';
|
font-size: 'inherit';
|
||||||
@ -82,16 +82,16 @@ export function EditableFieldDisplayMode({
|
|||||||
isDisplayModeFixHeight,
|
isDisplayModeFixHeight,
|
||||||
}: React.PropsWithChildren<OwnProps>) {
|
}: React.PropsWithChildren<OwnProps>) {
|
||||||
return (
|
return (
|
||||||
<EditableFieldNormalModeOuterContainer
|
<StyledEditableFieldNormalModeOuterContainer
|
||||||
onClick={disableClick ? undefined : onClick}
|
onClick={disableClick ? undefined : onClick}
|
||||||
disableClick={disableClick}
|
disableClick={disableClick}
|
||||||
isDisplayModeContentEmpty={isDisplayModeContentEmpty}
|
isDisplayModeContentEmpty={isDisplayModeContentEmpty}
|
||||||
disableHoverEffect={disableHoverEffect}
|
disableHoverEffect={disableHoverEffect}
|
||||||
isDisplayModeFixHeight={isDisplayModeFixHeight}
|
isDisplayModeFixHeight={isDisplayModeFixHeight}
|
||||||
>
|
>
|
||||||
<EditableFieldNormalModeInnerContainer>
|
<StyledEditableFieldNormalModeInnerContainer>
|
||||||
{children}
|
{children}
|
||||||
</EditableFieldNormalModeInnerContainer>
|
</StyledEditableFieldNormalModeInnerContainer>
|
||||||
</EditableFieldNormalModeOuterContainer>
|
</StyledEditableFieldNormalModeOuterContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers';
|
import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers';
|
||||||
|
|
||||||
export const EditableFieldEditModeContainer = styled.div<OwnProps>`
|
const StyledEditableFieldEditModeContainer = styled.div<OwnProps>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -33,11 +33,11 @@ export function EditableFieldEditMode({
|
|||||||
useRegisterCloseFieldHandlers(wrapperRef, onSubmit, onCancel);
|
useRegisterCloseFieldHandlers(wrapperRef, onSubmit, onCancel);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableFieldEditModeContainer
|
<StyledEditableFieldEditModeContainer
|
||||||
data-testid="editable-field-edit-mode-container"
|
data-testid="editable-field-edit-mode-container"
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</EditableFieldEditModeContainer>
|
</StyledEditableFieldEditModeContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import {
|
|||||||
FieldRelationValue,
|
FieldRelationValue,
|
||||||
} from '../types/FieldMetadata';
|
} from '../types/FieldMetadata';
|
||||||
|
|
||||||
const RelationPickerContainer = styled.div`
|
const StyledRelationPickerContainer = styled.div`
|
||||||
left: 0px;
|
left: 0px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -8px;
|
top: -8px;
|
||||||
@ -116,13 +116,13 @@ export function GenericEditableRelationFieldEditMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RelationPickerContainer>
|
<StyledRelationPickerContainer>
|
||||||
<RelationPicker
|
<RelationPicker
|
||||||
fieldDefinition={currentEditableFieldDefinition}
|
fieldDefinition={currentEditableFieldDefinition}
|
||||||
fieldValue={fieldValue}
|
fieldValue={fieldValue}
|
||||||
handleEntitySubmit={handleSubmit}
|
handleEntitySubmit={handleSubmit}
|
||||||
handleCancel={handleCancel}
|
handleCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
</RelationPickerContainer>
|
</StyledRelationPickerContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,12 @@ import styled from '@emotion/styled';
|
|||||||
import { Button, ButtonVariant } from '@/ui/button/components/Button';
|
import { Button, ButtonVariant } from '@/ui/button/components/Button';
|
||||||
import { IconFileUpload, IconTrash, IconUpload } from '@/ui/icon';
|
import { IconFileUpload, IconTrash, IconUpload } from '@/ui/icon';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Picture = styled.button<{ withPicture: boolean }>`
|
const StyledPicture = styled.button<{ withPicture: boolean }>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme, disabled }) =>
|
background: ${({ theme, disabled }) =>
|
||||||
disabled ? theme.background.secondary : theme.background.tertiary};
|
disabled ? theme.background.secondary : theme.background.tertiary};
|
||||||
@ -46,7 +46,7 @@ const Picture = styled.button<{ withPicture: boolean }>`
|
|||||||
}};
|
}};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Content = styled.div`
|
const StyledContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -54,7 +54,7 @@ const Content = styled.div`
|
|||||||
margin-left: ${({ theme }) => theme.spacing(4)};
|
margin-left: ${({ theme }) => theme.spacing(4)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ButtonContainer = styled.div`
|
const StyledButtonContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
> * + * {
|
> * + * {
|
||||||
@ -62,7 +62,7 @@ const ButtonContainer = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Text = styled.span`
|
const StyledText = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.light};
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
font-size: ${({ theme }) => theme.font.size.xs};
|
font-size: ${({ theme }) => theme.font.size.xs};
|
||||||
`;
|
`;
|
||||||
@ -92,8 +92,8 @@ export function ImageInput({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container {...restProps}>
|
<StyledContainer {...restProps}>
|
||||||
<Picture
|
<StyledPicture
|
||||||
withPicture={!!picture}
|
withPicture={!!picture}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={onUploadButtonClick}
|
onClick={onUploadButtonClick}
|
||||||
@ -106,9 +106,9 @@ export function ImageInput({
|
|||||||
) : (
|
) : (
|
||||||
<IconFileUpload size={theme.icon.size.md} />
|
<IconFileUpload size={theme.icon.size.md} />
|
||||||
)}
|
)}
|
||||||
</Picture>
|
</StyledPicture>
|
||||||
<Content>
|
<StyledContent>
|
||||||
<ButtonContainer>
|
<StyledButtonContainer>
|
||||||
<StyledHiddenFileInput
|
<StyledHiddenFileInput
|
||||||
type="file"
|
type="file"
|
||||||
ref={hiddenFileInput}
|
ref={hiddenFileInput}
|
||||||
@ -136,11 +136,11 @@ export function ImageInput({
|
|||||||
disabled={!picture || disabled}
|
disabled={!picture || disabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</ButtonContainer>
|
</StyledButtonContainer>
|
||||||
<Text>
|
<StyledText>
|
||||||
We support your best PNGs, JPEGs and GIFs portraits under 10MB
|
We support your best PNGs, JPEGs and GIFs portraits under 10MB
|
||||||
</Text>
|
</StyledText>
|
||||||
</Content>
|
</StyledContent>
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export enum LabelPosition {
|
|||||||
Right = 'right',
|
Right = 'right',
|
||||||
}
|
}
|
||||||
|
|
||||||
const Container = styled.div<{ labelPosition?: LabelPosition }>`
|
const StyledContainer = styled.div<{ labelPosition?: LabelPosition }>`
|
||||||
${({ labelPosition }) =>
|
${({ labelPosition }) =>
|
||||||
labelPosition === LabelPosition.Left
|
labelPosition === LabelPosition.Left
|
||||||
? `
|
? `
|
||||||
@ -33,7 +33,7 @@ type RadioInputProps = {
|
|||||||
'radio-size'?: RadioSize;
|
'radio-size'?: RadioSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
const RadioInput = styled(motion.input)<RadioInputProps>`
|
const StyledRadioInput = styled(motion.input)<RadioInputProps>`
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@ -86,7 +86,7 @@ type LabelProps = {
|
|||||||
labelPosition?: LabelPosition;
|
labelPosition?: LabelPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Label = styled.label<LabelProps>`
|
const StyledLabel = styled.label<LabelProps>`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
@ -126,8 +126,8 @@ export function Radio({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container {...restProps} labelPosition={labelPosition}>
|
<StyledContainer {...restProps} labelPosition={labelPosition}>
|
||||||
<RadioInput
|
<StyledRadioInput
|
||||||
type="radio"
|
type="radio"
|
||||||
id="input-radio"
|
id="input-radio"
|
||||||
name="input-radio"
|
name="input-radio"
|
||||||
@ -142,15 +142,15 @@ export function Radio({
|
|||||||
transition={{ type: 'spring', stiffness: 300, damping: 20 }}
|
transition={{ type: 'spring', stiffness: 300, damping: 20 }}
|
||||||
/>
|
/>
|
||||||
{value && (
|
{value && (
|
||||||
<Label
|
<StyledLabel
|
||||||
htmlFor="input-radio"
|
htmlFor="input-radio"
|
||||||
labelPosition={labelPosition}
|
labelPosition={labelPosition}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
</Label>
|
</StyledLabel>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { overlayBackground } from '@/ui/theme/constants/effects';
|
|
||||||
|
|
||||||
export const TextInputContainer = styled.div`
|
|
||||||
align-items: center;
|
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
|
||||||
display: flex;
|
|
||||||
margin-left: -1px;
|
|
||||||
min-height: 32px;
|
|
||||||
width: inherit;
|
|
||||||
|
|
||||||
${overlayBackground}
|
|
||||||
|
|
||||||
z-index: 10;
|
|
||||||
`;
|
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const TextInputDisplay = styled.div`
|
export const TextInputDisplay = styled.div`
|
||||||
|
|||||||
@ -1,15 +1,28 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { textInputStyle } from '@/ui/theme/constants/effects';
|
import { textInputStyle } from '@/ui/theme/constants/effects';
|
||||||
|
import { overlayBackground } from '@/ui/theme/constants/effects';
|
||||||
|
|
||||||
import { TextInputContainer } from './TextInputContainer';
|
const StyledInplaceInputTextInput = styled.input`
|
||||||
|
|
||||||
const InplaceInputTextInput = styled.input`
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
${textInputStyle}
|
${textInputStyle}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledTextInputContainer = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
|
display: flex;
|
||||||
|
margin-left: -1px;
|
||||||
|
min-height: 32px;
|
||||||
|
width: inherit;
|
||||||
|
|
||||||
|
${overlayBackground}
|
||||||
|
|
||||||
|
z-index: 10;
|
||||||
|
`;
|
||||||
|
|
||||||
export type TextInputEditProps = {
|
export type TextInputEditProps = {
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
@ -24,14 +37,14 @@ export function TextInputEdit({
|
|||||||
autoFocus,
|
autoFocus,
|
||||||
}: TextInputEditProps) {
|
}: TextInputEditProps) {
|
||||||
return (
|
return (
|
||||||
<TextInputContainer>
|
<StyledTextInputContainer>
|
||||||
<InplaceInputTextInput
|
<StyledInplaceInputTextInput
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange?.(e.target.value)}
|
onChange={(e) => onChange?.(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</TextInputContainer>
|
</StyledTextInputContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ type ContainerProps = {
|
|||||||
color?: string;
|
color?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Container = styled.div<ContainerProps>`
|
const StyledContainer = styled.div<ContainerProps>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: ${({ theme, isOn, color }) =>
|
background-color: ${({ theme, isOn, color }) =>
|
||||||
isOn ? color ?? theme.color.blue : theme.background.quaternary};
|
isOn ? color ?? theme.color.blue : theme.background.quaternary};
|
||||||
@ -19,7 +19,7 @@ const Container = styled.div<ContainerProps>`
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Circle = styled(motion.div)`
|
const StyledCircle = styled(motion.div)`
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@ -56,8 +56,8 @@ export function Toggle({ value, onChange, color }: ToggleProps) {
|
|||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container onClick={handleChange} isOn={isOn} color={color}>
|
<StyledContainer onClick={handleChange} isOn={isOn} color={color}>
|
||||||
<Circle animate={isOn ? 'on' : 'off'} variants={circleVariants} />
|
<StyledCircle animate={isOn ? 'on' : 'off'} variants={circleVariants} />
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ const StyledLayout = styled.div`
|
|||||||
|
|
||||||
const NAVBAR_WIDTH = '236px';
|
const NAVBAR_WIDTH = '236px';
|
||||||
|
|
||||||
const MainContainer = styled.div`
|
const StyledMainContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -63,7 +63,7 @@ export function DefaultLayout({ children }: OwnProps) {
|
|||||||
<NavbarAnimatedContainer>
|
<NavbarAnimatedContainer>
|
||||||
<AppNavbar />
|
<AppNavbar />
|
||||||
</NavbarAnimatedContainer>
|
</NavbarAnimatedContainer>
|
||||||
<MainContainer>
|
<StyledMainContainer>
|
||||||
{onboardingStatus && onboardingStatus !== OnboardingStatus.Completed ? (
|
{onboardingStatus && onboardingStatus !== OnboardingStatus.Completed ? (
|
||||||
<>
|
<>
|
||||||
<CompaniesMockMode />
|
<CompaniesMockMode />
|
||||||
@ -76,7 +76,7 @@ export function DefaultLayout({ children }: OwnProps) {
|
|||||||
) : (
|
) : (
|
||||||
<>{children}</>
|
<>{children}</>
|
||||||
)}
|
)}
|
||||||
</MainContainer>
|
</StyledMainContainer>
|
||||||
</StyledLayout>
|
</StyledLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { isNavbarOpenedState } from '../../states/isNavbarOpenedState';
|
|||||||
|
|
||||||
export const PAGE_BAR_MIN_HEIGHT = 40;
|
export const PAGE_BAR_MIN_HEIGHT = 40;
|
||||||
|
|
||||||
const TopBarContainer = styled.div`
|
const StyledTopBarContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.noisy};
|
background: ${({ theme }) => theme.background.noisy};
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
@ -35,18 +35,18 @@ const StyledLeftContainer = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TitleContainer = styled.div`
|
const StyledTitleContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: ${({ theme }) => theme.font.size.md};
|
font-size: ${({ theme }) => theme.font.size.md};
|
||||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TopBarButtonContainer = styled.div`
|
const StyledTopBarButtonContainer = styled.div`
|
||||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const BackIconButton = styled(IconButton)`
|
const StyledBackIconButton = styled(IconButton)`
|
||||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ const StyledTopBarIconTitleContainer = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ActionButtonsContainer = styled.div`
|
const StyledActionButtonsContainer = styled.div`
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: ${({ theme }) => theme.spacing(2)};
|
gap: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
@ -91,29 +91,29 @@ export function PageBar({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TopBarContainer>
|
<StyledTopBarContainer>
|
||||||
<StyledLeftContainer>
|
<StyledLeftContainer>
|
||||||
{!isNavbarOpened && (
|
{!isNavbarOpened && (
|
||||||
<TopBarButtonContainer>
|
<StyledTopBarButtonContainer>
|
||||||
<NavCollapseButton direction="right" />
|
<NavCollapseButton direction="right" />
|
||||||
</TopBarButtonContainer>
|
</StyledTopBarButtonContainer>
|
||||||
)}
|
)}
|
||||||
{hasBackButton && (
|
{hasBackButton && (
|
||||||
<TopBarButtonContainer>
|
<StyledTopBarButtonContainer>
|
||||||
<BackIconButton
|
<StyledBackIconButton
|
||||||
icon={<IconChevronLeft size={iconSize} />}
|
icon={<IconChevronLeft size={iconSize} />}
|
||||||
onClick={navigateBack}
|
onClick={navigateBack}
|
||||||
/>
|
/>
|
||||||
</TopBarButtonContainer>
|
</StyledTopBarButtonContainer>
|
||||||
)}
|
)}
|
||||||
<StyledTopBarIconTitleContainer>
|
<StyledTopBarIconTitleContainer>
|
||||||
{icon}
|
{icon}
|
||||||
<TitleContainer data-testid="top-bar-title">
|
<StyledTitleContainer data-testid="top-bar-title">
|
||||||
<OverflowingTextWithTooltip text={title} />
|
<OverflowingTextWithTooltip text={title} />
|
||||||
</TitleContainer>
|
</StyledTitleContainer>
|
||||||
</StyledTopBarIconTitleContainer>
|
</StyledTopBarIconTitleContainer>
|
||||||
</StyledLeftContainer>
|
</StyledLeftContainer>
|
||||||
<ActionButtonsContainer>
|
<StyledActionButtonsContainer>
|
||||||
{onFavoriteButtonClick && (
|
{onFavoriteButtonClick && (
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<IconHeart size={16} />}
|
icon={<IconHeart size={16} />}
|
||||||
@ -134,8 +134,8 @@ export function PageBar({
|
|||||||
variant="border"
|
variant="border"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ActionButtonsContainer>
|
</StyledActionButtonsContainer>
|
||||||
</TopBarContainer>
|
</StyledTopBarContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
useListenClickOutside,
|
useListenClickOutside,
|
||||||
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
|
|
||||||
const ModalDiv = styled(motion.div)`
|
const StyledModalDiv = styled(motion.div)`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: ${({ theme }) => theme.background.primary};
|
background: ${({ theme }) => theme.background.primary};
|
||||||
@ -43,7 +43,7 @@ const StyledFooter = styled.div`
|
|||||||
padding: ${({ theme }) => theme.spacing(5)};
|
padding: ${({ theme }) => theme.spacing(5)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const BackDrop = styled(motion.div)`
|
const StyledBackDrop = styled(motion.div)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.overlay};
|
background: ${({ theme }) => theme.background.overlay};
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -111,8 +111,8 @@ export function Modal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BackDrop>
|
<StyledBackDrop>
|
||||||
<ModalDiv
|
<StyledModalDiv
|
||||||
// framer-motion seems to have typing problems with refs
|
// framer-motion seems to have typing problems with refs
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -125,8 +125,8 @@ export function Modal({
|
|||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</ModalDiv>
|
</StyledModalDiv>
|
||||||
</BackDrop>
|
</StyledBackDrop>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ type OwnProps = {
|
|||||||
title: string;
|
title: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const IconAndButtonContainer = styled.button`
|
const StyledIconAndButtonContainer = styled.button`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: inherit;
|
background: inherit;
|
||||||
border: none;
|
border: none;
|
||||||
@ -39,7 +39,7 @@ export default function NavBackButton({ title }: OwnProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<IconAndButtonContainer
|
<StyledIconAndButtonContainer
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsNavbarSwitchingSize(true);
|
setIsNavbarSwitchingSize(true);
|
||||||
navigate('/', { replace: true });
|
navigate('/', { replace: true });
|
||||||
@ -47,7 +47,7 @@ export default function NavBackButton({ title }: OwnProps) {
|
|||||||
>
|
>
|
||||||
<IconChevronLeft />
|
<IconChevronLeft />
|
||||||
<span>{title}</span>
|
<span>{title}</span>
|
||||||
</IconAndButtonContainer>
|
</StyledIconAndButtonContainer>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
|||||||
|
|
||||||
import { navbarIconSize } from '../constants';
|
import { navbarIconSize } from '../constants';
|
||||||
|
|
||||||
const CollapseButton = styled.button`
|
const StyledCollapseButton = styled.button`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: inherit;
|
background: inherit;
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -48,13 +48,13 @@ export default function NavCollapseButton({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{direction === 'left' ? (
|
{direction === 'left' ? (
|
||||||
<CollapseButton onClick={() => setIsNavOpen(!isNavOpen)}>
|
<StyledCollapseButton onClick={() => setIsNavOpen(!isNavOpen)}>
|
||||||
<IconLayoutSidebarLeftCollapse size={iconSize} />
|
<IconLayoutSidebarLeftCollapse size={iconSize} />
|
||||||
</CollapseButton>
|
</StyledCollapseButton>
|
||||||
) : (
|
) : (
|
||||||
<CollapseButton onClick={() => setIsNavOpen(!isNavOpen)}>
|
<StyledCollapseButton onClick={() => setIsNavOpen(!isNavOpen)}>
|
||||||
<IconLayoutSidebarRightCollapse size={iconSize} />
|
<IconLayoutSidebarRightCollapse size={iconSize} />
|
||||||
</CollapseButton>
|
</StyledCollapseButton>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const StyledContainer = styled.div`
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LogoAndNameContainer = styled.div`
|
const StyledLogoAndNameContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
`;
|
`;
|
||||||
@ -56,7 +56,7 @@ function NavWorkspaceButton() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<LogoAndNameContainer>
|
<StyledLogoAndNameContainer>
|
||||||
<StyledLogo
|
<StyledLogo
|
||||||
logo={
|
logo={
|
||||||
currentWorkspace?.logo
|
currentWorkspace?.logo
|
||||||
@ -65,7 +65,7 @@ function NavWorkspaceButton() {
|
|||||||
}
|
}
|
||||||
></StyledLogo>
|
></StyledLogo>
|
||||||
<StyledName>{currentWorkspace?.displayName ?? 'Twenty'}</StyledName>
|
<StyledName>{currentWorkspace?.displayName ?? 'Twenty'}</StyledName>
|
||||||
</LogoAndNameContainer>
|
</StyledLogoAndNameContainer>
|
||||||
<NavCollapseButton direction="left" />
|
<NavCollapseButton direction="left" />
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -10,14 +10,14 @@ import { RightDrawerPages } from '../types/RightDrawerPages';
|
|||||||
|
|
||||||
import { RightDrawerTopBar } from './RightDrawerTopBar';
|
import { RightDrawerTopBar } from './RightDrawerTopBar';
|
||||||
|
|
||||||
const RightDrawerPage = styled.div`
|
const StyledRightDrawerPage = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const RightDrawerBody = styled.div`
|
const StyledRightDrawerBody = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: calc(
|
height: calc(
|
||||||
@ -47,9 +47,9 @@ export function RightDrawerRouter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RightDrawerPage>
|
<StyledRightDrawerPage>
|
||||||
<RightDrawerTopBar />
|
<RightDrawerTopBar />
|
||||||
<RightDrawerBody>{page}</RightDrawerBody>
|
<StyledRightDrawerBody>{page}</StyledRightDrawerBody>
|
||||||
</RightDrawerPage>
|
</StyledRightDrawerPage>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const StyledRightDrawerTopBar = styled.div`
|
|||||||
padding-right: ${({ theme }) => theme.spacing(2)};
|
padding-right: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TopBarWrapper = styled.div`
|
const StyledTopBarWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -34,10 +34,10 @@ export function RightDrawerTopBar() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledRightDrawerTopBar>
|
<StyledRightDrawerTopBar>
|
||||||
<TopBarWrapper>
|
<StyledTopBarWrapper>
|
||||||
<RightDrawerTopBarCloseButton />
|
<RightDrawerTopBarCloseButton />
|
||||||
{!isMobile && <RightDrawerTopBarExpandButton />}
|
{!isMobile && <RightDrawerTopBarExpandButton />}
|
||||||
</TopBarWrapper>
|
</StyledTopBarWrapper>
|
||||||
<ActivityActionBar activityId={activityId ?? ''} />
|
<ActivityActionBar activityId={activityId ?? ''} />
|
||||||
</StyledRightDrawerTopBar>
|
</StyledRightDrawerTopBar>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -51,7 +51,7 @@ const StyledIconContainer = styled.div`
|
|||||||
margin-right: ${({ theme }) => theme.spacing(2)};
|
margin-right: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProgressBarContainer = styled.div`
|
const StyledProgressBarContainer = styled.div`
|
||||||
height: 5px;
|
height: 5px;
|
||||||
left: 0;
|
left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -59,7 +59,7 @@ const ProgressBarContainer = styled.div`
|
|||||||
top: 0;
|
top: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const CloseButton = styled.button<Pick<SnackbarProps, 'variant'>>`
|
const StyledCloseButton = styled.button<Pick<SnackbarProps, 'variant'>>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
@ -162,20 +162,20 @@ export function SnackBar({
|
|||||||
variant={variant}
|
variant={variant}
|
||||||
{...rootProps}
|
{...rootProps}
|
||||||
>
|
>
|
||||||
<ProgressBarContainer>
|
<StyledProgressBarContainer>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
ref={progressBarRef}
|
ref={progressBarRef}
|
||||||
barHeight={5}
|
barHeight={5}
|
||||||
barColor={rgba(theme.grayScale.gray0, 0.3)}
|
barColor={rgba(theme.grayScale.gray0, 0.3)}
|
||||||
duration={duration}
|
duration={duration}
|
||||||
/>
|
/>
|
||||||
</ProgressBarContainer>
|
</StyledProgressBarContainer>
|
||||||
{icon && <StyledIconContainer>{icon}</StyledIconContainer>}
|
{icon && <StyledIconContainer>{icon}</StyledIconContainer>}
|
||||||
{children ? children : message}
|
{children ? children : message}
|
||||||
{allowDismiss && (
|
{allowDismiss && (
|
||||||
<CloseButton variant={variant} onClick={closeSnackbar}>
|
<StyledCloseButton variant={variant} onClick={closeSnackbar}>
|
||||||
<IconX aria-label="Close" size={theme.icon.size.md} />
|
<IconX aria-label="Close" size={theme.icon.size.md} />
|
||||||
</CloseButton>
|
</StyledCloseButton>
|
||||||
)}
|
)}
|
||||||
</StyledMotionContainer>
|
</StyledMotionContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { snackBarInternalState } from '../states/snackBarState';
|
|||||||
|
|
||||||
import { SnackBar } from './SnackBar';
|
import { SnackBar } from './SnackBar';
|
||||||
|
|
||||||
const SnackBarContainer = styled.div`
|
const StyledSnackBarContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -15,7 +15,7 @@ const SnackBarContainer = styled.div`
|
|||||||
z-index: 99999999;
|
z-index: 99999999;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const SnackBarMotionContainer = styled(motion.div)`
|
const StyledSnackBarMotionContainer = styled(motion.div)`
|
||||||
margin-right: ${({ theme }) => theme.spacing(3)};
|
margin-right: ${({ theme }) => theme.spacing(3)};
|
||||||
margin-top: ${({ theme }) => theme.spacing(3)};
|
margin-top: ${({ theme }) => theme.spacing(3)};
|
||||||
`;
|
`;
|
||||||
@ -68,9 +68,9 @@ export function SnackBarProvider({ children }: React.PropsWithChildren) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{children}
|
{children}
|
||||||
<SnackBarContainer>
|
<StyledSnackBarContainer>
|
||||||
{snackBarState.queue.map((snackBar) => (
|
{snackBarState.queue.map((snackBar) => (
|
||||||
<SnackBarMotionContainer
|
<StyledSnackBarMotionContainer
|
||||||
key={snackBar.id}
|
key={snackBar.id}
|
||||||
variants={reducedMotion ? reducedVariants : variants}
|
variants={reducedMotion ? reducedVariants : variants}
|
||||||
initial="initial"
|
initial="initial"
|
||||||
@ -83,9 +83,9 @@ export function SnackBarProvider({ children }: React.PropsWithChildren) {
|
|||||||
{...snackBar}
|
{...snackBar}
|
||||||
onClose={() => handleSnackBarClose(snackBar.id)}
|
onClose={() => handleSnackBarClose(snackBar.id)}
|
||||||
/>
|
/>
|
||||||
</SnackBarMotionContainer>
|
</StyledSnackBarMotionContainer>
|
||||||
))}
|
))}
|
||||||
</SnackBarContainer>
|
</StyledSnackBarContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,13 +4,13 @@ import { motion } from 'framer-motion';
|
|||||||
|
|
||||||
import { AnimatedCheckmark } from '@/ui/checkmark/components/AnimatedCheckmark';
|
import { AnimatedCheckmark } from '@/ui/checkmark/components/AnimatedCheckmark';
|
||||||
|
|
||||||
const Container = styled.div<{ isLast: boolean }>`
|
const StyledContainer = styled.div<{ isLast: boolean }>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: ${({ isLast }) => (isLast ? '0' : '1')};
|
flex-grow: ${({ isLast }) => (isLast ? '0' : '1')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StepCircle = styled(motion.div)`
|
const StyledStepCircle = styled(motion.div)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
@ -25,13 +25,13 @@ const StepCircle = styled(motion.div)`
|
|||||||
width: 20px;
|
width: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StepIndex = styled.span`
|
const StyledStepIndex = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
font-size: ${({ theme }) => theme.font.size.md};
|
font-size: ${({ theme }) => theme.font.size.md};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StepLabel = styled.span<{ isActive: boolean }>`
|
const StyledStepLabel = styled.span<{ isActive: boolean }>`
|
||||||
color: ${({ theme, isActive }) =>
|
color: ${({ theme, isActive }) =>
|
||||||
isActive ? theme.font.color.primary : theme.font.color.tertiary};
|
isActive ? theme.font.color.primary : theme.font.color.tertiary};
|
||||||
font-size: ${({ theme }) => theme.font.size.md};
|
font-size: ${({ theme }) => theme.font.size.md};
|
||||||
@ -40,7 +40,7 @@ const StepLabel = styled.span<{ isActive: boolean }>`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StepLine = styled(motion.div)`
|
const StyledStepLine = styled(motion.div)`
|
||||||
height: 2px;
|
height: 2px;
|
||||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||||
margin-right: ${({ theme }) => theme.spacing(2)};
|
margin-right: ${({ theme }) => theme.spacing(2)};
|
||||||
@ -90,8 +90,8 @@ export const Step = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container isLast={isLast}>
|
<StyledContainer isLast={isLast}>
|
||||||
<StepCircle
|
<StyledStepCircle
|
||||||
variants={variantsCircle}
|
variants={variantsCircle}
|
||||||
animate={isActive ? 'active' : 'inactive'}
|
animate={isActive ? 'active' : 'inactive'}
|
||||||
>
|
>
|
||||||
@ -101,17 +101,17 @@ export const Step = ({
|
|||||||
color={theme.grayScale.gray0}
|
color={theme.grayScale.gray0}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isActive && <StepIndex>{index + 1}</StepIndex>}
|
{!isActive && <StyledStepIndex>{index + 1}</StyledStepIndex>}
|
||||||
</StepCircle>
|
</StyledStepCircle>
|
||||||
<StepLabel isActive={isActive}>{label}</StepLabel>
|
<StyledStepLabel isActive={isActive}>{label}</StyledStepLabel>
|
||||||
{!isLast && (
|
{!isLast && (
|
||||||
<StepLine
|
<StyledStepLine
|
||||||
variants={variantsLine}
|
variants={variantsLine}
|
||||||
animate={isActive ? 'active' : 'inactive'}
|
animate={isActive ? 'active' : 'inactive'}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isActive && children}
|
{isActive && children}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import { Step, StepProps } from './Step';
|
import { Step, StepProps } from './Step';
|
||||||
|
|
||||||
const Container = styled.div`
|
const StyledContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -16,7 +16,7 @@ export type StepsProps = React.PropsWithChildren &
|
|||||||
|
|
||||||
export const StepBar = ({ children, activeStep, ...restProps }: StepsProps) => {
|
export const StepBar = ({ children, activeStep, ...restProps }: StepsProps) => {
|
||||||
return (
|
return (
|
||||||
<Container {...restProps}>
|
<StyledContainer {...restProps}>
|
||||||
{React.Children.map(children, (child, index) => {
|
{React.Children.map(children, (child, index) => {
|
||||||
if (!React.isValidElement(child)) {
|
if (!React.isValidElement(child)) {
|
||||||
return null;
|
return null;
|
||||||
@ -35,7 +35,7 @@ export const StepBar = ({ children, activeStep, ...restProps }: StepsProps) => {
|
|||||||
isLast: index === React.Children.count(children) - 1,
|
isLast: index === React.Children.count(children) - 1,
|
||||||
});
|
});
|
||||||
})}
|
})}
|
||||||
</Container>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const StyledEditableCellDisplayModeOuterContainer = styled.div<
|
|||||||
: ''}
|
: ''}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EditableCellDisplayModeInnerContainer = styled.div`
|
const StyledEditableCellDisplayModeInnerContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -52,9 +52,9 @@ export function EditableCellDisplayContainer({
|
|||||||
softFocus={softFocus}
|
softFocus={softFocus}
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
>
|
>
|
||||||
<EditableCellDisplayModeInnerContainer>
|
<StyledEditableCellDisplayModeInnerContainer>
|
||||||
{children}
|
{children}
|
||||||
</EditableCellDisplayModeInnerContainer>
|
</StyledEditableCellDisplayModeInnerContainer>
|
||||||
</StyledEditableCellDisplayModeOuterContainer>
|
</StyledEditableCellDisplayModeOuterContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable twenty/styled-components-prefixed-with-styled */
|
||||||
import { Tooltip } from 'react-tooltip';
|
import { Tooltip } from 'react-tooltip';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const StyledContainer = styled(motion.div)`
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Word = styled(motion.span)`
|
const StyledWord = styled(motion.span)`
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -61,9 +61,9 @@ export function AnimatedTextWord({ text = '', ...restProps }: Props) {
|
|||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{words.map((word, index) => (
|
{words.map((word, index) => (
|
||||||
<Word variants={childAnimation} key={index}>
|
<StyledWord variants={childAnimation} key={index}>
|
||||||
{word}
|
{word}
|
||||||
</Word>
|
</StyledWord>
|
||||||
))}
|
))}
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const StyledContainer = styled.div`
|
|||||||
padding: ${({ theme }) => theme.spacing(3)};
|
padding: ${({ theme }) => theme.spacing(3)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Content = styled.div`
|
const StyledContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -22,11 +22,11 @@ const Content = styled.div`
|
|||||||
margin-left: ${({ theme }) => theme.spacing(3)};
|
margin-left: ${({ theme }) => theme.spacing(3)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const NameText = styled.span`
|
const StyledNameText = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EmailText = styled.span`
|
const StyledEmailText = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -50,10 +50,10 @@ export function WorkspaceMemberCard({ workspaceMember, accessory }: OwnProps) {
|
|||||||
type="squared"
|
type="squared"
|
||||||
size="xl"
|
size="xl"
|
||||||
/>
|
/>
|
||||||
<Content>
|
<StyledContent>
|
||||||
<NameText>{workspaceMember.user.displayName}</NameText>
|
<StyledNameText>{workspaceMember.user.displayName}</StyledNameText>
|
||||||
<EmailText>{workspaceMember.user.email}</EmailText>
|
<StyledEmailText>{workspaceMember.user.email}</StyledEmailText>
|
||||||
</Content>
|
</StyledContent>
|
||||||
|
|
||||||
{accessory}
|
{accessory}
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
|
|||||||
@ -30,7 +30,7 @@ const StyledContainer = styled.div`
|
|||||||
width: 350px;
|
width: 350px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ButtonContainer = styled.div`
|
const StyledButtonContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -109,7 +109,7 @@ export function SettingsWorkspaceMembers() {
|
|||||||
workspaceMember={{ user: member.user }}
|
workspaceMember={{ user: member.user }}
|
||||||
accessory={
|
accessory={
|
||||||
currentUser?.id !== member.user.id && (
|
currentUser?.id !== member.user.id && (
|
||||||
<ButtonContainer>
|
<StyledButtonContainer>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsConfirmationModalOpen(true);
|
setIsConfirmationModalOpen(true);
|
||||||
@ -119,7 +119,7 @@ export function SettingsWorkspaceMembers() {
|
|||||||
size={ButtonSize.Small}
|
size={ButtonSize.Small}
|
||||||
icon={<IconTrash size={theme.icon.size.md} />}
|
icon={<IconTrash size={theme.icon.size.md} />}
|
||||||
/>
|
/>
|
||||||
</ButtonContainer>
|
</StyledButtonContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9722,7 +9722,7 @@ eslint-plugin-testing-library@^5.0.1:
|
|||||||
"@typescript-eslint/utils" "^5.58.0"
|
"@typescript-eslint/utils" "^5.58.0"
|
||||||
|
|
||||||
"eslint-plugin-twenty@file:../packages/eslint-plugin-twenty":
|
"eslint-plugin-twenty@file:../packages/eslint-plugin-twenty":
|
||||||
version "0.0.1"
|
version "0.0.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
postcss "^8.4.24"
|
postcss "^8.4.24"
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const noHardcodedColors = require('./rules/no-hardcoded-colors');
|
const noHardcodedColors = require('./rules/no-hardcoded-colors');
|
||||||
const cssAlphabetically = require('./rules/sort-css-properties-alphabetically');
|
const cssAlphabetically = require('./rules/sort-css-properties-alphabetically');
|
||||||
|
const styledComponentsPrefixedWithStyled = require('./rules/styled-components-prefixed-with-styled');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rules: {
|
rules: {
|
||||||
'no-hardcoded-colors': noHardcodedColors,
|
'no-hardcoded-colors': noHardcodedColors,
|
||||||
'sort-css-properties-alphabetically': cssAlphabetically,
|
'sort-css-properties-alphabetically': cssAlphabetically,
|
||||||
|
'styled-components-prefixed-with-styled': styledComponentsPrefixedWithStyled,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eslint-plugin-twenty",
|
"name": "eslint-plugin-twenty",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"postcss": "^8.4.24"
|
"postcss": "^8.4.24"
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
module.exports = {
|
||||||
|
meta: {
|
||||||
|
type: 'suggestion',
|
||||||
|
docs: {
|
||||||
|
description: 'Warn when StyledComponents are not prefixed with Styled',
|
||||||
|
},
|
||||||
|
recommended: true,
|
||||||
|
fixable: 'code',
|
||||||
|
schema: [],
|
||||||
|
},
|
||||||
|
create: function(context) {
|
||||||
|
return {
|
||||||
|
VariableDeclarator: node => {
|
||||||
|
const templateExpr = node.init
|
||||||
|
if (templateExpr?.type !== 'TaggedTemplateExpression') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tag = templateExpr.tag
|
||||||
|
const tagged = tag.type === 'MemberExpression' ? tag.object
|
||||||
|
: tag.type === 'CallExpression' ? tag.callee
|
||||||
|
: null
|
||||||
|
if (tagged?.name === 'styled') {
|
||||||
|
const variable = node.id;
|
||||||
|
if (variable?.name.startsWith('Styled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.report({ node, message: `'${variable.name}' is a StyledComponent and is not prefixed with Styled.` });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user