Skip to content

Commit

Permalink
dropdown improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
ehconitin committed Aug 29, 2024
1 parent be22eb9 commit 3b7c2e7
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -1,59 +1,103 @@
import { Button } from '@/ui/input/button/components/Button';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconChevronDown } from 'twenty-ui';

type SettingsDataModelNewFieldBreadcrumbDropDownProps = {
isConfigureStep: boolean;
onBreadcrumbClick: (isConfigureStep: boolean) => void;
};

const StyledSpan = styled.span`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
const StyledContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
cursor: pointer;
display: flex;
font-size: ${({ theme }) => theme.font.size.md};
`;
const StyledButtonContainer = styled.div`
position: relative;
width: 100%;
`;

const StyledDownChevron = styled(IconChevronDown)`
color: ${({ theme }) => theme.font.color.primary};
position: absolute;
right: ${({ theme }) => theme.spacing(1.5)};
top: 50%;
transform: translateY(-50%);
`;

const StyledMenuItem = styled(MenuItem)`
const StyledMenuItem = styled(MenuItem)<{ selected?: boolean }>`
background: ${({ theme, selected }) =>
selected ? theme.background.quaternary : 'transparent'};
cursor: pointer;
`;

const StyledSpan = styled.span`
margin-left: ${({ theme }) => theme.spacing(2)};
`;

const StyledButton = styled(Button)`
color: ${({ theme }) => theme.font.color.primary};
padding-right: ${({ theme }) => theme.spacing(6)};
`;

export const SettingsDataModelNewFieldBreadcrumbDropDown = ({
isConfigureStep,
onBreadcrumbClick,
}: SettingsDataModelNewFieldBreadcrumbDropDownProps) => {
const dropdownId = `settings-object-new-field-breadcrumb-dropdown`;

const { closeDropdown } = useDropdown(dropdownId);

const handleClick = (step: boolean) => {
onBreadcrumbClick(step);
closeDropdown();
};
const theme = useTheme();

return (
<Dropdown
dropdownPlacement="bottom"
dropdownId={dropdownId}
clickableComponent={
isConfigureStep ? (
<StyledSpan>New Field - 2. Configure</StyledSpan>
) : (
<StyledSpan>New Field - 1. Type</StyledSpan>
)
}
dropdownComponents={
<DropdownMenu>
<DropdownMenuItemsContainer>
<StyledMenuItem text="1. Type" onClick={() => handleClick(false)} />

<StyledMenuItem
text="2. Configure"
onClick={() => handleClick(true)}
/>
</DropdownMenuItemsContainer>
</DropdownMenu>
}
dropdownHotkeyScope={{
scope: dropdownId,
}}
/>
<StyledContainer>
New Field <StyledSpan>-</StyledSpan>
<Dropdown
dropdownPlacement="bottom-start"
dropdownId={dropdownId}
clickableComponent={
<StyledButtonContainer>
<StyledDownChevron size={theme.icon.size.md} />
{isConfigureStep ? (
<StyledButton variant="tertiary" title="2. Configure" />
) : (
<StyledButton variant="tertiary" title="1. Type" />
)}
</StyledButtonContainer>
}
dropdownComponents={
<DropdownMenu>
<DropdownMenuItemsContainer>
<StyledMenuItem
text="1. Type"
onClick={() => handleClick(false)}
selected={!isConfigureStep}
/>
<StyledMenuItem
text="2. Configure"
onClick={() => handleClick(true)}
selected={isConfigureStep}
/>
</DropdownMenuItemsContainer>
</DropdownMenu>
}
dropdownHotkeyScope={{
scope: dropdownId,
}}
/>
</StyledContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import { useCurrencySettingsFormInitialValues } from '@/settings/data-model/fiel
import { useSelectSettingsFormInitialValues } from '@/settings/data-model/fields/forms/select/hooks/useSelectSettingsFormInitialValues';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import { Button } from '@/ui/input/button/components/Button';
import { TextInput } from '@/ui/input/components/TextInput';
import { useTheme } from '@emotion/react';
import { Section } from '@react-email/components';
import { useState } from 'react';
import { H2Title } from 'twenty-ui';
import { H2Title, IconChevronRight, IconSearch } from 'twenty-ui';
import { FieldMetadataType } from '~/generated-metadata/graphql';

export const settingsDataModelFieldTypeFormSchema = z.object({
Expand All @@ -42,41 +44,44 @@ type SettingsDataModelFieldTypeSelectProps = {
onFieldTypeSelect: () => void;
};

const StyledContainer = styled.div`
const StyledTypeSelectContainer = styled.div`
display: flex;
flex-direction: column;
gap: inherit;
width: 100%;
`;

const StyledButton = styled(Button)`
const StyledButton = styled(Button)<{ isActive: boolean }>`
background: ${({ theme, isActive }) =>
isActive ? theme.background.quaternary : theme.background.secondary};
height: 40px;
width: calc(50% - ${({ theme }) => theme.spacing(1)});
width: 100%;
border-radius: ${({ theme }) => theme.border.radius.md};
`;
const StyledButtonContainer = styled.div`
const StyledContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
justify-content: flex-start;
flex-wrap: wrap;
width: 100%;
`;

const StyledInput = styled.input`
border-radius: ${({ theme }) => theme.border.radius.sm};
border: 1px solid ${({ theme }) => theme.border.color.medium};
background: ${({ theme }) => theme.background.transparent.lighter};
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
margin: 0;
outline: none;
height: 32px;
padding: 0 ${({ theme }) => theme.spacing(1)} 0
${({ theme }) => theme.spacing(2)};
const StyledButtonContainer = styled.div`
display: flex;
position: relative;
width: calc(50% - ${({ theme }) => theme.spacing(1)});
`;

const StyledRightChevron = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.secondary};
position: absolute;
right: ${({ theme }) => theme.spacing(2)};
top: 50%;
transform: translateY(-50%);
`;
const StyledSearchInput = styled(TextInput)`
width: 100%;
box-sizing: border-box;
&::placeholder {
color: ${({ theme }) => theme.font.color.light};
font-weight: ${({ theme }) => theme.font.weight.medium};
}
`;

export const SettingsDataModelFieldTypeSelect = ({
Expand All @@ -87,6 +92,7 @@ export const SettingsDataModelFieldTypeSelect = ({
}: SettingsDataModelFieldTypeSelectProps) => {
const { control } = useFormContext<SettingsDataModelFieldTypeFormValues>();
const [searchQuery, setSearchQuery] = useState('');
const theme = useTheme();
const fieldTypeConfigs = Object.entries<SettingsFieldTypeConfig>(
SETTINGS_FIELD_TYPE_CONFIGS,
).filter(
Expand Down Expand Up @@ -125,14 +131,19 @@ export const SettingsDataModelFieldTypeSelect = ({
<Controller
name="type"
control={control}
defaultValue={
fieldMetadataItem && fieldMetadataItem.type in fieldTypeConfigs
? (fieldMetadataItem.type as SettingsSupportedFieldType)
: FieldMetadataType.Text
}
render={({ field: { onChange, value } }) => (
<StyledContainer className={className}>
<StyledTypeSelectContainer className={className}>
<Section>
<StyledInput
type="text"
placeholder="Search a field"
<StyledSearchInput
LeftIcon={IconSearch}
placeholder="Search a type"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
onChange={setSearchQuery}
/>
</Section>
{SETTINGS_FIELD_TYPE_CATEGORIES.map((category) => (
Expand All @@ -143,29 +154,32 @@ export const SettingsDataModelFieldTypeSelect = ({
SETTINGS_FIELD_TYPE_CATEGORY_DESCRIPTIONS[category]
}
/>
<StyledButtonContainer>
<StyledContainer>
{fieldTypeConfigs
.filter(([, config]) => config.category === category)
.map(([key, config]) => (
<StyledButton
key={key}
onClick={() => {
onChange(key as SettingsSupportedFieldType);
resetDefaultValueField(
key as SettingsSupportedFieldType,
);
onFieldTypeSelect();
}}
variant={value === key ? 'primary' : 'secondary'}
title={config.label}
Icon={config.Icon}
size="small"
/>
<StyledButtonContainer>
<StyledButton
key={key}
onClick={() => {
onChange(key as SettingsSupportedFieldType);
resetDefaultValueField(
key as SettingsSupportedFieldType,
);
onFieldTypeSelect();
}}
title={config.label}
Icon={config.Icon}
size="small"
isActive={value === key}
/>
<StyledRightChevron size={theme.icon.size.md} />
</StyledButtonContainer>
))}
</StyledButtonContainer>
</StyledContainer>
</Section>
))}
</StyledContainer>
</StyledTypeSelectContainer>
)}
/>
);
Expand Down

0 comments on commit 3b7c2e7

Please sign in to comment.