Created DropdownMenuInnerSelect and implemented it for filter dropdowns (#12626)

This PR introduces a new generic UI component DropdownMenuInnerSelect,
that improves the UI by allowing to have both a dropdown menu header and
a select in the header.

In this PR we implement it just for filter dropdown components.

Fixes https://github.com/twentyhq/core-team-issues/issues/1001
This commit is contained in:
Lucas Bordeau
2025-06-16 16:16:32 +02:00
committed by GitHub
parent ed1593c089
commit e922843afb
6 changed files with 190 additions and 6 deletions

View File

@ -22,6 +22,8 @@ const StyledHeader = styled.li`
background: ${({ theme, onClick }) =>
onClick ? theme.background.transparent.light : 'none'};
}
flex-shrink: 0;
`;
const StyledChildrenWrapper = styled.span`

View File

@ -0,0 +1,88 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownMenuHotkeyScope';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconChevronDown } from 'twenty-ui/display';
import { SelectOption } from 'twenty-ui/input';
import { MenuItemSelect } from 'twenty-ui/navigation';
const StyledDropdownMenuInnerSelectDropdownButton = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
height: ${({ theme }) => theme.spacing(7)};
justify-content: space-between;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
width: 100%;
box-sizing: border-box;
cursor: pointer;
`;
export type DropdownMenuInnerSelectProps = {
selectedOption: SelectOption;
onChange: (value: SelectOption) => void;
options: SelectOption[];
dropdownId: string;
};
export const DropdownMenuInnerSelect = ({
selectedOption,
onChange,
options,
dropdownId,
}: DropdownMenuInnerSelectProps) => {
const theme = useTheme();
const { closeDropdown } = useDropdown(dropdownId);
return (
<Dropdown
clickableComponent={
<StyledDropdownMenuInnerSelectDropdownButton>
<span>{selectedOption.label}</span>
<IconChevronDown size={theme.icon.size.sm} />
</StyledDropdownMenuInnerSelectDropdownButton>
}
dropdownComponents={
<DropdownContent>
<DropdownMenuItemsContainer>
{options.map((selectOption) => (
<MenuItemSelect
key={`dropdown-menu-inner-select-item-${selectOption.value}`}
onClick={() => {
onChange(selectOption);
closeDropdown();
}}
text={selectOption.label}
disabled={selectOption.disabled}
selected={selectOption.value === selectedOption.value}
/>
))}
</DropdownMenuItemsContainer>
</DropdownContent>
}
dropdownHotkeyScope={{
scope: DropdownMenuHotkeyScope.InnerSelect,
customScopes: {
commandMenu: false,
commandMenuOpen: false,
},
}}
dropdownId={dropdownId}
dropdownOffset={{
x: 8,
}}
/>
);
};

View File

@ -0,0 +1,3 @@
export enum DropdownMenuHotkeyScope {
InnerSelect = 'dropdown-menu-inner-select',
}