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:
committed by
GitHub
parent
5ad8ff81f9
commit
67fb750ef6
@ -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>
|
||||
);
|
||||
};
|
||||
@ -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>
|
||||
);
|
||||
@ -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 },
|
||||
};
|
||||
Reference in New Issue
Block a user