Skip to content

Commit

Permalink
Merge pull request #255 from kortirso/issue_237
Browse files Browse the repository at this point in the history
IS-237 modified closing dropdowns after outside click
  • Loading branch information
kortirso committed Feb 8, 2024
2 parents e9d2d16 + 1e749d9 commit 573b261
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 40 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## Unreleased
### Modified
- navigation styles for better mobile
- closing dropdowns after outside click

## [1.1.6] - 2024-02-06
### Added
Expand Down
14 changes: 13 additions & 1 deletion app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,19 @@
min-height: 42px;
}

.form-dropdown {
.dropdown .dropdown-content {
@apply hidden;
}

.dropdown-toggle-icon {
@apply transition-transform rotate-0;
}

.dropdown.opened .dropdown-toggle-icon {
@apply rotate-180;
}

.dropdown.opened .dropdown-content {
@apply block absolute z-10 left-0 w-full border border-stone-200 rounded-sm max-h-72 overflow-x-scroll;

top: 42px;
Expand Down
11 changes: 11 additions & 0 deletions app/javascript/application.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,15 @@ document.addEventListener('DOMContentLoaded', () => {
document.querySelector('.navigation-menu').classList.toggle('hidden');
});
};

// Clicking outside of an open dropdown menu closes it
window.addEventListener('click', function (e) {
if (!e.target.matches('.dropdown-toggle')) {
document.querySelectorAll('.dropdown.opened').forEach((form) => {
if (!form.contains(e.target)) {
form.classList.remove('opened')
}
})
}
})
});
4 changes: 2 additions & 2 deletions app/javascript/assets/Chevron.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';

export const Chevron = ({ rotated }) => (
export const Chevron = ({ className }) => (
<svg
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="1.5rem"
height="1.5rem"
className={rotated ? 'transition-transform rotate-180' : 'transition-transform rotate-0'}
className={className}
>
<path
d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z"
Expand Down
22 changes: 4 additions & 18 deletions app/javascript/components/Transfers/Transfers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,11 @@ export const Transfers = ({
sortBy: 'points',
page: 0,
search: '',
openDropdown: null,
onlyWatched: false
});

const [teamState, setTeamState] = useState({
uuid: null,
openDropdown: false
})

// fields for initial squad
Expand Down Expand Up @@ -489,10 +487,7 @@ export const Transfers = ({
result[key] = localizeValue(values.name);
return result;
}, {})}
isOpen={teamState.openDropdown}
onOpen={() => setTeamState({ ...teamState, openDropdown: true })}
onClose={() => setTeamState({ ...teamState, openDropdown: false })}
onSelect={(value) => setTeamState({ ...teamState, uuid: value, openDropdown: false })}
onSelect={(value) => setTeamState({ ...teamState, uuid: value })}
selectedValue={teamState.uuid}
placeholder={strings.transfers.selectFavouriteTeam}
/>
Expand Down Expand Up @@ -641,10 +636,7 @@ export const Transfers = ({
},
{ all: strings.transfers.allPlayers },
)}
isOpen={filterState.openDropdown === 'position'}
onOpen={() => setFilterState({ ...filterState, openDropdown: 'position' })}
onClose={() => setFilterState({ ...filterState, openDropdown: null })}
onSelect={(value) => setFilterState({ ...filterState, position: value, page: 0, openDropdown: null })}
onSelect={(value) => setFilterState({ ...filterState, position: value, page: 0 })}
selectedValue={filterState.position}
/>
<Dropdown
Expand All @@ -656,19 +648,13 @@ export const Transfers = ({
},
{ all: strings.transfers.allTeams },
)}
isOpen={filterState.openDropdown === 'team'}
onOpen={() => setFilterState({ ...filterState, openDropdown: 'team' })}
onClose={() => setFilterState({ ...filterState, openDropdown: null })}
onSelect={(value) => setFilterState({ ...filterState, team: value, page: 0, openDropdown: null })}
onSelect={(value) => setFilterState({ ...filterState, team: value, page: 0 })}
selectedValue={filterState.team}
/>
<Dropdown
title={strings.transfers.sort}
items={pageState.sortItems}
isOpen={filterState.openDropdown === 'sortBy'}
onOpen={() => setFilterState({ ...filterState, openDropdown: 'sortBy' })}
onClose={() => setFilterState({ ...filterState, openDropdown: null })}
onSelect={(value) => setFilterState({ ...filterState, sortBy: value, page: 0, openDropdown: null })}
onSelect={(value) => setFilterState({ ...filterState, sortBy: value, page: 0 })}
selectedValue={filterState.sortBy}
/>
<div className="form-field mb-4">
Expand Down
56 changes: 38 additions & 18 deletions app/javascript/components/atoms/Dropdown.jsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,57 @@
import React from 'react';
import React, { useRef } from 'react';

import { Chevron } from '../../assets';

export const Dropdown = ({
title,
items,
isOpen,
onOpen,
onClose,
onSelect,
selectedValue,
placeholder = ''
}) => (
<div className="form-field">
<label className="form-label">{title}</label>
<div className="relative cursor-pointer">
<div className="form-value flex justify-between items-center" onClick={() => isOpen ? onClose() : onOpen()}>
{selectedValue ? items[selectedValue] : placeholder}
<Chevron rotated={isOpen} />
</div>
{isOpen && (
<ul className="form-dropdown">
}) => {
const dropdownRef = useRef();

const onDropdownToggle = () => {
const currentState = Array.from(dropdownRef.current.classList).includes('opened');

// close opened dropdowns
document.querySelectorAll('.dropdown.opened').forEach((form) => form.classList.remove('opened'));

// open current dropdown if it was closed
if (!currentState) dropdownRef.current.classList.toggle('opened')
};

const onDropdownSelect = (value) => {
dropdownRef.current.classList.toggle('opened');
onSelect(value);
};

return (
<div
ref={dropdownRef}
className="dropdown form-field"
>
<label className="form-label">{title}</label>
<div className="relative cursor-pointer">
<div
className="dropdown-toggle form-value flex justify-between items-center"
onClick={() => onDropdownToggle()}
>
{selectedValue ? items[selectedValue] : placeholder}
<Chevron className='dropdown-toggle-icon' />
</div>
<ul className="dropdown-content">
{Object.entries(items).map(([key, value]) => (
<li
className="bg-white hover:bg-stone-200 py-2 px-3"
onClick={() => onSelect(key)}
onClick={() => onDropdownSelect(key)}
key={key}
>
{value}
</li>
))}
</ul>
)}
</div>
</div>
</div>
);
);
};
2 changes: 1 addition & 1 deletion app/javascript/components/atoms/Toggle.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const Toggle = ({ header, children }) => {
<div className="bg-stone-200 border-b border-stone-300">
<div className="py-2 px-4 cursor-pointer flex justify-between items-center" onClick={() => setIsOpen(!isOpen)}>
<h3 className="m-0 text-lg">{header}</h3>
<Chevron rotated={isOpen} />
<Chevron className={isOpen ? 'transition-transform rotate-180' : 'transition-transform rotate-0'} />
</div>
{children && isOpen ? (
<div dangerouslySetInnerHTML={{ __html: children }} className="px-4 pb-4 bg-white border-t border-stone-300"></div>
Expand Down

0 comments on commit 573b261

Please sign in to comment.