Settings Option Card component (#8456)

fixes - #8195

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
nitin
2024-11-18 14:52:33 +05:30
committed by GitHub
parent ade1c57ff4
commit 2f5dc26545
56 changed files with 931 additions and 920 deletions

View File

@ -0,0 +1,37 @@
import styled from '@emotion/styled';
import { CardContent } from 'twenty-ui';
type StyledCardContentProps = {
disabled?: boolean;
divider?: boolean;
};
export const StyledSettingsOptionCardContent = styled(
CardContent,
)<StyledCardContentProps>`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
`;
export const StyledSettingsOptionCardIcon = styled.div`
align-items: center;
border: 2px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
background-color: ${({ theme }) => theme.background.primary};
display: flex;
height: ${({ theme }) => theme.spacing(8)};
justify-content: center;
width: ${({ theme }) => theme.spacing(8)};
min-width: ${({ theme }) => theme.icon.size.md};
`;
export const StyledSettingsOptionCardTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-weight: ${({ theme }) => theme.font.weight.medium};
margin-bottom: ${({ theme }) => theme.spacing(1)};
`;
export const StyledSettingsOptionCardDescription = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
`;

View File

@ -0,0 +1,57 @@
import { SettingsCounter } from '@/settings/components/SettingsCounter';
import {
StyledSettingsOptionCardContent,
StyledSettingsOptionCardDescription,
StyledSettingsOptionCardIcon,
StyledSettingsOptionCardTitle,
} from '@/settings/components/SettingsOptions/SettingsOptionCardContentBase';
import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer';
import { IconComponent } from 'twenty-ui';
type SettingsOptionCardContentCounterProps = {
Icon?: IconComponent;
title: React.ReactNode;
description?: string;
divider?: boolean;
disabled?: boolean;
value: number;
onChange: (value: number) => void;
minValue?: number;
maxValue?: number;
};
export const SettingsOptionCardContentCounter = ({
Icon,
title,
description,
divider,
disabled = false,
value,
onChange,
minValue,
maxValue,
}: SettingsOptionCardContentCounterProps) => {
return (
<StyledSettingsOptionCardContent divider={divider} disabled={disabled}>
{Icon && (
<StyledSettingsOptionCardIcon>
<SettingsOptionIconCustomizer Icon={Icon} />
</StyledSettingsOptionCardIcon>
)}
<div>
<StyledSettingsOptionCardTitle>{title}</StyledSettingsOptionCardTitle>
{description && (
<StyledSettingsOptionCardDescription>
{description}
</StyledSettingsOptionCardDescription>
)}
</div>
<SettingsCounter
value={value}
onChange={onChange}
minValue={minValue}
maxValue={maxValue}
/>
</StyledSettingsOptionCardContent>
);
};

View File

@ -0,0 +1,75 @@
import {
StyledSettingsOptionCardContent,
StyledSettingsOptionCardDescription,
StyledSettingsOptionCardIcon,
StyledSettingsOptionCardTitle,
} from '@/settings/components/SettingsOptions/SettingsOptionCardContentBase';
import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer';
import { Select } from '@/ui/input/components/Select';
import styled from '@emotion/styled';
import { IconComponent } from 'twenty-ui';
const StyledSettingsOptionCardSelect = styled(Select)`
margin-left: auto;
width: 120px;
`;
type SelectValue = string | number | boolean | null;
type SettingsOptionCardContentSelectProps<Value extends SelectValue> = {
Icon?: IconComponent;
title: React.ReactNode;
description?: string;
divider?: boolean;
disabled?: boolean;
value: Value;
onChange: (value: SelectValue) => void;
options: {
value: Value;
label: string;
Icon?: IconComponent;
}[];
selectClassName?: string;
dropdownId: string;
fullWidth?: boolean;
};
export const SettingsOptionCardContentSelect = <Value extends SelectValue>({
Icon,
title,
description,
divider,
disabled = false,
value,
onChange,
options,
selectClassName,
dropdownId,
fullWidth,
}: SettingsOptionCardContentSelectProps<Value>) => {
return (
<StyledSettingsOptionCardContent divider={divider} disabled={disabled}>
{Icon && (
<StyledSettingsOptionCardIcon>
<SettingsOptionIconCustomizer Icon={Icon} />
</StyledSettingsOptionCardIcon>
)}
<div>
<StyledSettingsOptionCardTitle>{title}</StyledSettingsOptionCardTitle>
<StyledSettingsOptionCardDescription>
{description}
</StyledSettingsOptionCardDescription>
</div>
<StyledSettingsOptionCardSelect
className={selectClassName}
dropdownWidth={fullWidth ? 'auto' : 120}
disabled={disabled}
dropdownId={dropdownId}
value={value}
onChange={onChange}
options={options}
selectSizeVariant="small"
/>
</StyledSettingsOptionCardContent>
);
};

View File

@ -0,0 +1,89 @@
import {
StyledSettingsOptionCardContent,
StyledSettingsOptionCardDescription,
StyledSettingsOptionCardIcon,
StyledSettingsOptionCardTitle,
} from '@/settings/components/SettingsOptions/SettingsOptionCardContentBase';
import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useId } from 'react';
import { IconComponent, Toggle } from 'twenty-ui';
const StyledSettingsOptionCardToggleContent = styled(
StyledSettingsOptionCardContent,
)`
cursor: ${({ disabled }) => (disabled ? 'default' : 'pointer')};
position: relative;
pointer-events: ${({ disabled }) => (disabled ? 'none' : 'auto')};
&:hover {
background: ${({ theme }) => theme.background.transparent.lighter};
}
`;
const StyledSettingsOptionCardToggleButton = styled(Toggle)`
margin-left: auto;
`;
const StyledSettingsOptionCardToggleCover = styled.span`
cursor: pointer;
inset: 0;
position: absolute;
`;
type SettingsOptionCardContentToggleProps = {
Icon?: IconComponent;
title: React.ReactNode;
description?: string;
divider?: boolean;
disabled?: boolean;
advancedMode?: boolean;
checked: boolean;
onChange: (checked: boolean) => void;
};
export const SettingsOptionCardContentToggle = ({
Icon,
title,
description,
divider,
disabled = false,
advancedMode = false,
checked,
onChange,
}: SettingsOptionCardContentToggleProps) => {
const theme = useTheme();
const toggleId = useId();
return (
<StyledSettingsOptionCardToggleContent
divider={divider}
disabled={disabled}
>
{Icon && (
<StyledSettingsOptionCardIcon>
<SettingsOptionIconCustomizer Icon={Icon} />
</StyledSettingsOptionCardIcon>
)}
<div>
<StyledSettingsOptionCardTitle>
<label htmlFor={toggleId}>
{title}
<StyledSettingsOptionCardToggleCover />
</label>
</StyledSettingsOptionCardTitle>
<StyledSettingsOptionCardDescription>
{description}
</StyledSettingsOptionCardDescription>
</div>
<StyledSettingsOptionCardToggleButton
id={toggleId}
value={checked}
onChange={onChange}
disabled={disabled}
color={advancedMode ? theme.color.yellow : theme.color.blue}
/>
</StyledSettingsOptionCardToggleContent>
);
};

View File

@ -0,0 +1,33 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconComponent } from 'twenty-ui';
type SettingsOptionIconCustomizerProps = {
Icon: IconComponent;
zoom?: number;
rotate?: number;
};
const StyledIconCustomizer = styled.div<{ zoom: number; rotate: number }>`
display: inline-flex;
align-items: center;
justify-content: center;
transform: scale(${({ zoom }) => zoom}) rotate(${({ rotate }) => rotate}deg);
`;
export const SettingsOptionIconCustomizer = ({
Icon,
zoom = 1,
rotate = -4,
}: SettingsOptionIconCustomizerProps) => {
const theme = useTheme();
return (
<StyledIconCustomizer zoom={zoom} rotate={rotate}>
<Icon
size={theme.icon.size.xl}
color={theme.IllustrationIcon.color.grey}
stroke={theme.icon.stroke.md}
/>
</StyledIconCustomizer>
);
};