forked from twentyhq/twenty
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add dropdown on Sort button on table
- Loading branch information
1 parent
bb40c1b
commit 1e635b9
Showing
11 changed files
with
215 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ cd infra/dev | |
|
||
``` | ||
make build | ||
make up | ||
``` | ||
|
||
Once this is completed you should have: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
front/src/components/table/table-header/DropdownButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import styled from '@emotion/styled'; | ||
import { IconProp } from '@fortawesome/fontawesome-svg-core'; | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||
import { useState, useRef } from 'react'; | ||
import { useOutsideAlerter } from '../../../hooks/useOutsideAlerter'; | ||
import { modalBackground } from '../../../layout/styles/themes'; | ||
|
||
type OwnProps = { | ||
label: string; | ||
options: Array<{ label: string; icon: IconProp }>; | ||
}; | ||
|
||
const StyledDropdownButtonContainer = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
position: relative; | ||
`; | ||
|
||
type StyledDropdownButtonProps = { | ||
isUnfolded: boolean; | ||
}; | ||
|
||
const StyledDropdownButton = styled.div<StyledDropdownButtonProps>` | ||
display: flex; | ||
margin-left: ${(props) => props.theme.spacing(3)}; | ||
cursor: pointer; | ||
background: ${(props) => props.theme.primaryBackground}; | ||
padding: ${(props) => props.theme.spacing(1)}; | ||
border-radius: 4px; | ||
filter: ${(props) => (props.isUnfolded ? 'brightness(0.95)' : 'none')}; | ||
&:hover { | ||
filter: brightness(0.95); | ||
} | ||
`; | ||
|
||
const StyledDropdown = styled.ul` | ||
display: flex; | ||
position: absolute; | ||
top: 14px; | ||
right: 0; | ||
border: 1px solid ${(props) => props.theme.primaryBorder}; | ||
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.09); | ||
border-radius: 8px; | ||
padding: 0px; | ||
min-width: 160px; | ||
${modalBackground} | ||
`; | ||
|
||
const StyledDropdownItem = styled.li` | ||
display: flex; | ||
padding: ${(props) => props.theme.spacing(2)} | ||
calc(${(props) => props.theme.spacing(2)} - 2px); | ||
margin: 2px; | ||
background: ${(props) => props.theme.primaryBackground}; | ||
cursor: pointer; | ||
width: 100%; | ||
border-radius: 4px; | ||
color: ${(props) => props.theme.text60}; | ||
&:hover { | ||
filter: brightness(0.95); | ||
} | ||
`; | ||
|
||
const StyledIcon = styled.div` | ||
display: flex; | ||
margin-right: ${(props) => props.theme.spacing(1)}; | ||
`; | ||
|
||
function DropdownButton({ label, options }: OwnProps) { | ||
const [isUnfolded, setIsUnfolded] = useState(false); | ||
|
||
const onButtonClick = () => { | ||
setIsUnfolded(!isUnfolded); | ||
}; | ||
|
||
const onOutsideClick = () => { | ||
setIsUnfolded(false); | ||
}; | ||
|
||
const dropdownRef = useRef(null); | ||
useOutsideAlerter(dropdownRef, onOutsideClick); | ||
|
||
return ( | ||
<StyledDropdownButtonContainer> | ||
<StyledDropdownButton isUnfolded={isUnfolded} onClick={onButtonClick}> | ||
{label} | ||
</StyledDropdownButton> | ||
{isUnfolded && options.length > 0 && ( | ||
<StyledDropdown ref={dropdownRef}> | ||
{options.map((option, index) => ( | ||
<StyledDropdownItem key={index}> | ||
<StyledIcon> | ||
<FontAwesomeIcon icon={option.icon} /> | ||
</StyledIcon> | ||
{option.label} | ||
</StyledDropdownItem> | ||
))} | ||
</StyledDropdown> | ||
)} | ||
</StyledDropdownButtonContainer> | ||
); | ||
} | ||
|
||
export default DropdownButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
front/src/components/table/table-header/__stories__/TableHeader.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import TableHeader from '../TableHeader'; | ||
import { ThemeProvider } from '@emotion/react'; | ||
import { lightTheme } from '../../../../layout/styles/themes'; | ||
import { faBuilding } from '@fortawesome/pro-regular-svg-icons'; | ||
|
||
export default { | ||
title: 'TableHeader', | ||
component: TableHeader, | ||
}; | ||
|
||
export const RegularTableHeader = () => { | ||
return ( | ||
<ThemeProvider theme={lightTheme}> | ||
<TableHeader viewName="Test" viewIcon={faBuilding} /> | ||
</ThemeProvider> | ||
); | ||
}; |
9 changes: 9 additions & 0 deletions
9
front/src/components/table/table-header/__tests__/TableHeader.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { render } from '@testing-library/react'; | ||
|
||
import { RegularTableHeader } from '../__stories__/TableHeader.stories'; | ||
|
||
it('Checks the TableHeader renders', () => { | ||
const { getByText } = render(<RegularTableHeader />); | ||
|
||
expect(getByText('Test')).toBeDefined(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
const onOutsideClick = jest.fn(); | ||
import { useRef } from 'react'; | ||
import TableHeader from '../../components/table/table-header/TableHeader'; | ||
import { render, fireEvent } from '@testing-library/react'; | ||
import { useOutsideAlerter } from '../useOutsideAlerter'; | ||
import { act } from 'react-dom/test-utils'; | ||
|
||
function TestComponent() { | ||
const buttonRef = useRef(null); | ||
useOutsideAlerter(buttonRef, onOutsideClick); | ||
|
||
return ( | ||
<div> | ||
<span>Outside</span> | ||
<button ref={buttonRef}>Inside</button> | ||
</div> | ||
); | ||
} | ||
|
||
export default TableHeader; | ||
|
||
test('clicking the button toggles an answer on/off', async () => { | ||
const { getByText } = render(<TestComponent />); | ||
const inside = getByText('Inside'); | ||
const outside = getByText('Outside'); | ||
await act(() => Promise.resolve()); | ||
|
||
fireEvent.mouseDown(inside); | ||
expect(onOutsideClick).toHaveBeenCalledTimes(0); | ||
|
||
fireEvent.mouseDown(outside); | ||
expect(onOutsideClick).toHaveBeenCalledTimes(1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { useEffect } from 'react'; | ||
|
||
declare type CallbackType = () => void; | ||
|
||
export function useOutsideAlerter( | ||
ref: React.RefObject<HTMLInputElement>, | ||
callback: CallbackType, | ||
) { | ||
useEffect(() => { | ||
function handleClickOutside(event: Event) { | ||
console.log('test3'); | ||
|
||
const target = event.target as HTMLButtonElement; | ||
if (ref.current && !ref.current.contains(target)) { | ||
callback(); | ||
} | ||
} | ||
document.addEventListener('mousedown', handleClickOutside); | ||
return () => { | ||
document.removeEventListener('mousedown', handleClickOutside); | ||
}; | ||
}, [ref]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters