Merge pull request #69 from twentyhq/sammy/t-130-when-a-sort-is-selected-i-see-the-sort

feature: add property isActive for dropdown buttons
This commit is contained in:
Charles Bochet
2023-04-24 18:39:35 +02:00
committed by GitHub
3 changed files with 90 additions and 49 deletions

View File

@ -1,14 +1,14 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useRef, ReactNode } from 'react';
import { useState, useRef } from 'react';
import { useOutsideAlerter } from '../../../hooks/useOutsideAlerter'; import { useOutsideAlerter } from '../../../hooks/useOutsideAlerter';
import { modalBackground } from '../../../layout/styles/themes'; import { modalBackground } from '../../../layout/styles/themes';
import { SortType } from './SortAndFilterBar';
type OwnProps = { type OwnProps = {
label: string; label: string;
options: Array<SortType>; isActive: boolean;
onSortSelect?: (id: string) => void; children?: ReactNode;
isUnfolded?: boolean;
setIsUnfolded?: React.Dispatch<React.SetStateAction<boolean>>;
}; };
const StyledDropdownButtonContainer = styled.div` const StyledDropdownButtonContainer = styled.div`
@ -20,6 +20,7 @@ const StyledDropdownButtonContainer = styled.div`
type StyledDropdownButtonProps = { type StyledDropdownButtonProps = {
isUnfolded: boolean; isUnfolded: boolean;
isActive: boolean;
}; };
const StyledDropdownButton = styled.div<StyledDropdownButtonProps>` const StyledDropdownButton = styled.div<StyledDropdownButtonProps>`
@ -27,6 +28,7 @@ const StyledDropdownButton = styled.div<StyledDropdownButtonProps>`
margin-left: ${(props) => props.theme.spacing(3)}; margin-left: ${(props) => props.theme.spacing(3)};
cursor: pointer; cursor: pointer;
background: ${(props) => props.theme.primaryBackground}; background: ${(props) => props.theme.primaryBackground};
color: ${(props) => (props.isActive ? props.theme.blue : 'none')};
padding: ${(props) => props.theme.spacing(1)}; padding: ${(props) => props.theme.spacing(1)};
border-radius: 4px; border-radius: 4px;
filter: ${(props) => (props.isUnfolded ? 'brightness(0.95)' : 'none')}; filter: ${(props) => (props.isUnfolded ? 'brightness(0.95)' : 'none')};
@ -85,15 +87,19 @@ const StyledIcon = styled.div`
margin-right: ${(props) => props.theme.spacing(1)}; margin-right: ${(props) => props.theme.spacing(1)};
`; `;
function DropdownButton({ label, options, onSortSelect }: OwnProps) { function DropdownButton({
const [isUnfolded, setIsUnfolded] = useState(false); label,
isActive,
children,
isUnfolded = false,
setIsUnfolded,
}: OwnProps) {
const onButtonClick = () => { const onButtonClick = () => {
setIsUnfolded(!isUnfolded); setIsUnfolded && setIsUnfolded(!isUnfolded);
}; };
const onOutsideClick = () => { const onOutsideClick = () => {
setIsUnfolded(false); setIsUnfolded && setIsUnfolded(false);
}; };
const dropdownRef = useRef(null); const dropdownRef = useRef(null);
@ -101,31 +107,21 @@ function DropdownButton({ label, options, onSortSelect }: OwnProps) {
return ( return (
<StyledDropdownButtonContainer> <StyledDropdownButtonContainer>
<StyledDropdownButton isUnfolded={isUnfolded} onClick={onButtonClick}> <StyledDropdownButton
isUnfolded={isUnfolded}
onClick={onButtonClick}
isActive={isActive}
>
{label} {label}
</StyledDropdownButton> </StyledDropdownButton>
{isUnfolded && options.length > 0 && ( {isUnfolded && (
<StyledDropdown ref={dropdownRef}> <StyledDropdown ref={dropdownRef}>{children}</StyledDropdown>
{options.map((option, index) => (
<StyledDropdownItem
key={index}
onClick={() => {
setIsUnfolded(false);
if (onSortSelect) {
onSortSelect(option.id);
}
}}
>
<StyledIcon>
{option.icon && <FontAwesomeIcon icon={option.icon} />}
</StyledIcon>
{option.label}
</StyledDropdownItem>
))}
</StyledDropdown>
)} )}
</StyledDropdownButtonContainer> </StyledDropdownButtonContainer>
); );
} }
DropdownButton.StyledDropdownItem = StyledDropdownItem;
DropdownButton.StyledIcon = StyledIcon;
export default DropdownButton; export default DropdownButton;

View File

@ -0,0 +1,50 @@
import { useCallback, useState } from 'react';
import DropdownButton from './DropdownButton';
import { SortType } from './SortAndFilterBar';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
type OwnProps = {
sorts: SortType[];
setSorts: (sorts: SortType[]) => void;
sortsAvailable: SortType[];
};
export function SortDropdownButton({
sortsAvailable,
setSorts,
sorts,
}: OwnProps) {
const [isUnfolded, setIsUnfolded] = useState(false);
const onSortItemSelect = useCallback(
(sort: SortType) => {
const newSorts = [sort];
setSorts(newSorts);
},
[setSorts],
);
return (
<DropdownButton
label="Sort"
isActive={sorts.length > 0}
isUnfolded={isUnfolded}
setIsUnfolded={setIsUnfolded}
>
{sortsAvailable.map((option, index) => (
<DropdownButton.StyledDropdownItem
key={index}
onClick={() => {
setIsUnfolded(false);
onSortItemSelect(option);
}}
>
<DropdownButton.StyledIcon>
{option.icon && <FontAwesomeIcon icon={option.icon} />}
</DropdownButton.StyledIcon>
{option.label}
</DropdownButton.StyledDropdownItem>
))}
</DropdownButton>
);
}

View File

@ -4,6 +4,7 @@ import DropdownButton from './DropdownButton';
import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { IconProp } from '@fortawesome/fontawesome-svg-core';
import SortAndFilterBar, { SortType } from './SortAndFilterBar'; import SortAndFilterBar, { SortType } from './SortAndFilterBar';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { SortDropdownButton } from './SortDropdownButton';
type OwnProps = { type OwnProps = {
viewName: string; viewName: string;
@ -50,19 +51,12 @@ function TableHeader({
onSortsUpdate, onSortsUpdate,
sortsAvailable, sortsAvailable,
}: OwnProps) { }: OwnProps) {
const [sorts, setSorts] = useState([] as Array<SortType>); const [sorts, innerSetSorts] = useState([] as Array<SortType>);
const onSortItemSelect = useCallback( const setSorts = useCallback(
(sortId: string) => { (sorts: SortType[]) => {
const newSorts = [ innerSetSorts(sorts);
{ onSortsUpdate && onSortsUpdate(sorts);
label: 'Created at',
order: 'asc',
id: sortId,
} satisfies SortType,
];
setSorts(newSorts);
onSortsUpdate && onSortsUpdate(newSorts);
}, },
[onSortsUpdate], [onSortsUpdate],
); );
@ -70,7 +64,7 @@ function TableHeader({
const onSortItemUnSelect = useCallback( const onSortItemUnSelect = useCallback(
(sortId: string) => { (sortId: string) => {
const newSorts = [] as SortType[]; const newSorts = [] as SortType[];
setSorts(newSorts); innerSetSorts(newSorts);
onSortsUpdate && onSortsUpdate(newSorts); onSortsUpdate && onSortsUpdate(newSorts);
}, },
[onSortsUpdate], [onSortsUpdate],
@ -86,13 +80,14 @@ function TableHeader({
{viewName} {viewName}
</StyledViewSection> </StyledViewSection>
<StyledFilters> <StyledFilters>
<DropdownButton label="Filter" options={[]} /> <DropdownButton label="Filter" isActive={false}></DropdownButton>
<DropdownButton <SortDropdownButton
label="Sort" setSorts={setSorts}
options={sortsAvailable} sorts={sorts}
onSortSelect={onSortItemSelect} sortsAvailable={sortsAvailable}
/> />
<DropdownButton label="Settings" options={[]} />
<DropdownButton label="Settings" isActive={false}></DropdownButton>
</StyledFilters> </StyledFilters>
</StyledTableHeader> </StyledTableHeader>
{sorts.length > 0 && ( {sorts.length > 0 && (