Migrate to twenty-ui - input/color-scheme (#7995)

This PR was created by [GitStart](https://gitstart.com/) to address the
requirements from this ticket:
[TWNTY-7063](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7063).

 --- 

### Description

- Move color-scheme components to `twenty-ui`

Fixes  twentyhq/private-issues#93

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
gitstart-app[bot]
2024-10-24 13:39:25 +02:00
committed by GitHub
parent 5ad8ff81f9
commit 67fb750ef6
8 changed files with 13 additions and 15 deletions

View File

@ -1,239 +0,0 @@
import React from 'react';
import styled from '@emotion/styled';
import {
AnimatePresence,
AnimationControls,
motion,
useAnimation,
} from 'framer-motion';
import { Checkmark } from 'twenty-ui';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
const StyledColorSchemeBackground = styled.div<
Pick<ColorSchemeCardProps, 'variant'>
>`
align-items: flex-end;
background: ${({ variant, theme }) => {
switch (variant) {
case 'Dark':
return theme.grayScale.gray75;
case 'Light':
default:
return theme.grayScale.gray15;
}
}};
border: ${({ variant, theme }) => {
switch (variant) {
case 'Dark':
return `1px solid ${theme.grayScale.gray70};`;
case 'Light':
default:
return `1px solid ${theme.grayScale.gray20};`;
}
}};
border-radius: ${({ theme }) => theme.border.radius.md};
box-sizing: border-box;
cursor: pointer;
display: flex;
height: 80px;
justify-content: flex-end;
overflow: hidden;
padding-left: ${({ theme }) => theme.spacing(6)};
padding-top: ${({ theme }) => theme.spacing(6)};
width: 160px;
`;
const StyledColorSchemeContent = styled(motion.div)<
Pick<ColorSchemeCardProps, 'variant'>
>`
background: ${({ theme, variant }) => {
switch (variant) {
case 'Dark':
return theme.grayScale.gray75;
case 'Light':
return theme.grayScale.gray0;
}
}};
border-left: ${({ variant, theme }) => {
switch (variant) {
case 'Dark':
return `1px solid ${theme.grayScale.gray60};`;
case 'Light':
default:
return `1px solid ${theme.grayScale.gray20};`;
}
}};
border-radius: ${({ theme }) => theme.border.radius.md} 0px 0px 0px;
border-top: ${({ variant, theme }) => {
switch (variant) {
case 'Dark':
return `1px solid ${theme.grayScale.gray60};`;
case 'Light':
default:
return `1px solid ${theme.grayScale.gray20};`;
}
}};
box-sizing: border-box;
color: ${({ variant, theme }) => {
switch (variant) {
case 'Dark':
return theme.grayScale.gray30;
case 'Light':
default:
return theme.grayScale.gray60;
}
}};
display: flex;
flex: 1;
font-size: 20px;
height: 56px;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(2)};
`;
export type ColorSchemeSegmentProps = {
variant: ColorScheme;
controls: AnimationControls;
className?: string;
} & React.ComponentPropsWithoutRef<'div'>;
const ColorSchemeSegment = ({
variant,
controls,
style,
className,
onClick,
onMouseEnter,
onMouseLeave,
}: ColorSchemeSegmentProps) => (
<StyledColorSchemeBackground
className={className}
{...{ variant, style, onClick, onMouseEnter, onMouseLeave }}
>
<StyledColorSchemeContent animate={controls} variant={variant}>
Aa
</StyledColorSchemeContent>
</StyledColorSchemeBackground>
);
const StyledContainer = styled.div`
position: relative;
width: 160px;
`;
const StyledMixedColorSchemeSegment = styled.div`
border-radius: ${({ theme }) => theme.border.radius.md};
cursor: pointer;
display: flex;
height: 80px;
overflow: hidden;
position: relative;
width: 160px;
`;
const StyledCheckmarkContainer = styled(motion.div)`
bottom: 0px;
padding: ${({ theme }) => theme.spacing(2)};
position: absolute;
right: 0px;
`;
export type ColorSchemeCardProps = {
variant: ColorScheme;
selected?: boolean;
} & React.ComponentPropsWithoutRef<'div'>;
const checkmarkAnimationVariants = {
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
};
export const ColorSchemeCard = ({
variant,
selected,
onClick,
}: ColorSchemeCardProps) => {
const controls = useAnimation();
const handleMouseEnter = () => {
controls.start({
height: 61,
fontSize: '22px',
transition: { duration: 0.1 },
});
};
const handleMouseLeave = () => {
controls.start({
height: 56,
fontSize: '20px',
transition: { duration: 0.1 },
});
};
if (variant === 'System') {
return (
<StyledContainer>
<StyledMixedColorSchemeSegment
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={onClick}
>
<ColorSchemeSegment
style={{ borderTopRightRadius: 0, borderBottomRightRadius: 0 }}
controls={controls}
variant="Light"
/>
<ColorSchemeSegment
style={{ borderTopLeftRadius: 0, borderBottomLeftRadius: 0 }}
controls={controls}
variant="Dark"
/>
</StyledMixedColorSchemeSegment>
<AnimatePresence>
{selected && (
<StyledCheckmarkContainer
key="system"
variants={checkmarkAnimationVariants}
initial="initial"
animate="animate"
exit="exit"
transition={{ duration: 0.3 }}
>
<Checkmark />
</StyledCheckmarkContainer>
)}
</AnimatePresence>
</StyledContainer>
);
}
return (
<StyledContainer>
<ColorSchemeSegment
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
controls={controls}
variant={variant}
onClick={onClick}
/>
<AnimatePresence>
{selected && (
<StyledCheckmarkContainer
key={variant}
variants={checkmarkAnimationVariants}
initial="initial"
animate="animate"
exit="exit"
transition={{ duration: 0.3 }}
>
<Checkmark />
</StyledCheckmarkContainer>
)}
</AnimatePresence>
</StyledContainer>
);
};

View File

@ -1,69 +0,0 @@
import React from 'react';
import styled from '@emotion/styled';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { ColorSchemeCard } from './ColorSchemeCard';
import { MOBILE_VIEWPORT } from 'twenty-ui';
const StyledContainer = styled.div`
display: flex;
flex-direction: row;
> * + * {
margin-left: ${({ theme }) => theme.spacing(4)};
}
@media (max-width: ${MOBILE_VIEWPORT}px) {
overflow: scroll;
}
`;
const StyledCardContainer = styled.div`
display: flex;
flex-direction: column;
`;
const StyledLabel = styled.span`
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.medium};
margin-top: ${({ theme }) => theme.spacing(2)};
`;
export type ColorSchemePickerProps = {
value: ColorScheme;
className?: string;
onChange: (value: ColorScheme) => void;
};
export const ColorSchemePicker = ({
value,
onChange,
className,
}: ColorSchemePickerProps) => (
<StyledContainer className={className}>
<StyledCardContainer>
<ColorSchemeCard
onClick={() => onChange('Light')}
variant="Light"
selected={value === 'Light'}
/>
<StyledLabel>Light</StyledLabel>
</StyledCardContainer>
<StyledCardContainer>
<ColorSchemeCard
onClick={() => onChange('Dark')}
variant="Dark"
selected={value === 'Dark'}
/>
<StyledLabel>Dark</StyledLabel>
</StyledCardContainer>
<StyledCardContainer>
<ColorSchemeCard
onClick={() => onChange('System')}
variant="System"
selected={value === 'System'}
/>
<StyledLabel>System settings</StyledLabel>
</StyledCardContainer>
</StyledContainer>
);

View File

@ -1,48 +0,0 @@
import styled from '@emotion/styled';
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
import { ColorSchemeCard } from '../ColorSchemeCard';
const StyledContainer = styled.div`
display: flex;
flex-direction: row;
> * + * {
margin-left: ${({ theme }) => theme.spacing(4)};
}
`;
const meta: Meta<typeof ColorSchemeCard> = {
title: 'UI/Input/ColorScheme/ColorSchemeCard',
component: ColorSchemeCard,
decorators: [
(Story) => (
<StyledContainer>
<Story />
</StyledContainer>
),
ComponentDecorator,
],
argTypes: {
variant: { control: false },
},
args: { selected: false },
};
export default meta;
type Story = StoryObj<typeof ColorSchemeCard>;
export const Default: Story = {
render: (args) => (
<>
<ColorSchemeCard variant="Light" selected={args.selected} />
<ColorSchemeCard variant="Dark" selected={args.selected} />
<ColorSchemeCard variant="System" selected={args.selected} />
</>
),
};
export const Selected: Story = {
...Default,
args: { selected: true },
};