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:
@ -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;
|
||||||
|
|||||||
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -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 && (
|
||||||
|
|||||||
Reference in New Issue
Block a user