Skip to content

Commit

Permalink
feat: added new dropdown option bottom left
Browse files Browse the repository at this point in the history
  • Loading branch information
web-mi committed Mar 13, 2024
1 parent f91e004 commit 70ebf1b
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 33 deletions.
3 changes: 2 additions & 1 deletion src/components/app/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { userHasBudibaseTools } from '../../api/apiGetTools';
import { browserNotificationsSettings } from '../../utils/notificationHelpers';
import useIsFirstVisit from '../../utils/useIsFirstVisit';
import { useResponsive } from '../../hooks/useResponsive';
import { MENUPLACEMENT_RIGHT } from '../select/SelectDropdown';

export interface NavigationBarProps {
onLogout: any;
Expand Down Expand Up @@ -351,7 +352,7 @@ export const NavigationBar = ({
vertical
iconSize={32}
label={translate('navigation.language')}
menuPlacement="right"
menuPlacement={MENUPLACEMENT_RIGHT}
selectRef={(el) => (ref_select.current = el)}
isInsideMenu={true}
/>
Expand Down
3 changes: 2 additions & 1 deletion src/components/error/Error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useAppConfig } from '../../hooks/useAppConfig';
import { LocaleProvider, AppConfigProvider } from '../../globalState';
import { AppConfigInterface } from '../../globalState/interfaces';
import { useResponsive } from '../../hooks/useResponsive';
import { MENUPLACEMENT_BOTTOM_LEFT } from '../select/SelectDropdown';

const getStatusCode = () => {
const errorRoot = document.getElementById('errorRoot');
Expand Down Expand Up @@ -72,7 +73,7 @@ export const ErrorContent = () => {
return (
<div className={clsx('errorPage', `errorPage--${type}`)}>
<header className={`errorPage__header ${!fromL ? 'mobile' : ''}`}>
<LocaleSwitch />
<LocaleSwitch menuPlacement={MENUPLACEMENT_BOTTOM_LEFT} />
</header>
<div className="errorPage__main">
<span className="errorPage__illustrationWrapper">
Expand Down
4 changes: 1 addition & 3 deletions src/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import { useContext } from 'react';
import { TenantContext } from '../../globalState';
import './header.styles';
import { useTranslation } from 'react-i18next';
import { LocaleSwitch } from '../localeSwitch/LocaleSwitch';
import { useAtomValue } from 'jotai';
import { agencyLogoAtom } from '../../store/agencyLogoAtom';

export const Header = ({ showLocaleSwitch = false }) => {
export const Header = () => {
const { t: translate } = useTranslation();
const { tenant } = useContext(TenantContext);
const agencyLogo = useAtomValue(agencyLogoAtom);
Expand All @@ -29,7 +28,6 @@ export const Header = ({ showLocaleSwitch = false }) => {
text={tenant?.content?.claim || translate('app.claim')}
/>
)}
{showLocaleSwitch && <LocaleSwitch />}
</div>
</header>
);
Expand Down
11 changes: 8 additions & 3 deletions src/components/localeSwitch/LocaleSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { useTranslation } from 'react-i18next';
import { useContext, useEffect, useState } from 'react';
import { UserDataContext, LocaleContext } from '../../globalState';
import { apiPatchUserData } from '../../api/apiPatchUserData';
import { SelectDropdown, SelectDropdownItem } from '../select/SelectDropdown';
import {
MENUPLACEMENT,
MENUPLACEMENT_BOTTOM,
SelectDropdown,
SelectDropdownItem
} from '../select/SelectDropdown';
import { setValueInCookie } from '../sessionCookie/accessSessionCookie';

export interface LocaleSwitchProp {
Expand All @@ -16,7 +21,7 @@ export interface LocaleSwitchProp {
className?: string;
iconSize?: number;
label?: string;
menuPlacement?: 'top' | 'bottom' | 'right';
menuPlacement?: MENUPLACEMENT;
selectRef?: any;
isInsideMenu?: boolean;
}
Expand All @@ -27,7 +32,7 @@ export const LocaleSwitch: React.FC<LocaleSwitchProp> = ({
showIcon = true,
vertical,
iconSize = 20,
menuPlacement = 'bottom',
menuPlacement = MENUPLACEMENT_BOTTOM,
label,
selectRef,
isInsideMenu = false
Expand Down
83 changes: 60 additions & 23 deletions src/components/select/SelectDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import clsx from 'clsx';
import * as React from 'react';
import Select, { defaultStyles } from 'react-select';
import Select, { defaultStyles, MenuPlacement } from 'react-select';
import { components } from 'react-select';
import { CloseCircle } from '../../resources/img/icons';
import { ReactComponent as ArrowDownIcon } from '../../resources/img/icons/arrow-down-light.svg';
Expand All @@ -10,7 +10,7 @@ import './select.react.styles';
import './select.styles';
import { useResponsive } from '../../hooks/useResponsive';
import { useTranslation } from 'react-i18next';
import { ReactNode } from 'react';
import { ReactNode, useMemo } from 'react';

export interface SelectOption {
value: string;
Expand All @@ -26,6 +26,17 @@ export interface SelectOptionsMulti {
option?: SelectOption;
}

export const MENUPLACEMENT_TOP = 'top';
export const MENUPLACEMENT_BOTTOM = 'bottom';
export const MENUPLACEMENT_RIGHT = 'right';
export const MENUPLACEMENT_BOTTOM_LEFT = 'bottomLeft';

export type MENUPLACEMENT =
| typeof MENUPLACEMENT_TOP
| typeof MENUPLACEMENT_BOTTOM
| typeof MENUPLACEMENT_RIGHT
| typeof MENUPLACEMENT_BOTTOM_LEFT;

export interface SelectDropdownItem {
className?: string;
id: string;
Expand All @@ -37,7 +48,7 @@ export interface SelectDropdownItem {
isSearchable?: boolean;
isMulti?: boolean;
isClearable?: boolean;
menuPlacement: 'top' | 'bottom' | 'right';
menuPlacement: MENUPLACEMENT;
menuPosition?: 'absolute' | 'fixed';
defaultValue?: SelectOption | SelectOption[];
hasError?: boolean;
Expand All @@ -51,7 +62,7 @@ export interface SelectDropdownItem {

const colourStyles = (
fromL,
menuPlacement,
menuPlacement: MENUPLACEMENT,
{
control,
singleValue,
Expand Down Expand Up @@ -141,9 +152,9 @@ const colourStyles = (
}),
menu: (styles, state) => ({
...styles,
'marginTop': state.menuPlacement === 'top' ? '0' : '16px',
'marginTop': state.menuPlacement === MENUPLACEMENT_TOP ? '0' : '16px',
'fontWeight': 'normal',
...(menuPlacement === 'right'
...(menuPlacement === MENUPLACEMENT_RIGHT
? {
bottom: '0',
left: '100%',
Expand All @@ -153,18 +164,21 @@ const colourStyles = (
width: 'auto'
}
: {
marginBottom: state.menuPlacement === 'top' ? '16px' : '0'
marginBottom:
state.menuPlacement === MENUPLACEMENT_TOP
? '16px'
: '0',
right:
menuPlacement === MENUPLACEMENT_BOTTOM_LEFT ? 0 : 'auto'
}),
'boxShadow': undefined,
'&:after, &:before': {
content: `''`,
position: 'absolute',
marginTop: '-1px',
marginLeft: '-12px',
bottom: state.menuPlacement === 'top' ? '-9px' : 'auto',
top: state.menuPlacement === 'top' ? 'auto' : '-8px',
zIndex: 2,
...(menuPlacement === 'right'
...(menuPlacement === MENUPLACEMENT_RIGHT
? {
left: '0',
bottom: '5%',
Expand All @@ -177,21 +191,33 @@ const colourStyles = (
width: '12px'
}
: {
left:
menuPlacement === MENUPLACEMENT_BOTTOM_LEFT
? '75%'
: '50%',
bottom:
state.menuPlacement === MENUPLACEMENT_TOP
? '-9px'
: 'auto',
top:
state.menuPlacement === MENUPLACEMENT_TOP
? 'auto'
: '-8px',
borderLeft: '10px solid transparent',
borderRight: '10px solid transparent',
borderTop:
state.menuPlacement === 'top'
state.menuPlacement === MENUPLACEMENT_TOP
? '10px solid #fff'
: 'none',
borderBottom:
state.menuPlacement === 'top'
state.menuPlacement === MENUPLACEMENT_TOP
? 'none'
: '10px solid #fff'
})
},
'&:before': {
zIndex: 1,
...(menuPlacement === 'right'
...(menuPlacement === MENUPLACEMENT_RIGHT
? {
left: '0',
bottom: '5%',
Expand All @@ -202,16 +228,20 @@ const colourStyles = (
borderRight: '10px solid rgba(0,0,0,0.1)'
}
: {
left: '50%',
bottom:
state.menuPlacement === 'top' ? '-14px' : 'auto',
top: state.menuPlacement === 'top' ? 'auto' : '-10px',
state.menuPlacement === MENUPLACEMENT_TOP
? '-14px'
: 'auto',
top:
state.menuPlacement === MENUPLACEMENT_TOP
? 'auto'
: '-10px',
borderTop:
state.menuPlacement === 'top'
state.menuPlacement === MENUPLACEMENT_TOP
? '10px solid rgba(0,0,0,0.1)'
: 'none',
borderBottom:
state.menuPlacement === 'top'
state.menuPlacement === MENUPLACEMENT_TOP
? 'none'
: '10px solid rgba(0,0,0,0.1)'
})
Expand Down Expand Up @@ -351,6 +381,16 @@ export const SelectDropdown = (props: SelectDropdownItem) => {
);
};

const menuPlacement = useMemo<MenuPlacement>(() => {
switch (props.menuPlacement) {
case MENUPLACEMENT_BOTTOM_LEFT:
case MENUPLACEMENT_RIGHT:
return MENUPLACEMENT_BOTTOM;
default:
return props.menuPlacement;
}
}, [props.menuPlacement]);

return (
<div className={clsx(props.className, 'select__wrapper')}>
<Select
Expand All @@ -372,18 +412,15 @@ export const SelectDropdown = (props: SelectDropdownItem) => {
: components.IndicatorSeparator,
MultiValueRemove: CustomMultiValueRemove
}}
defaultMenuIsOpen
value={props.defaultValue ? props.defaultValue : null}
defaultValue={props.defaultValue ? props.defaultValue : null}
onChange={props.handleDropdownSelect}
options={props.selectedOptions}
noOptionsMessage={() => null}
menuPosition={props.menuPosition}
menuShouldBlockScroll={props.menuShouldBlockScroll}
menuPlacement={
props.menuPlacement === 'right'
? 'bottom'
: props.menuPlacement
}
menuPlacement={menuPlacement}
placeholder={props.placeholder ? props.placeholder : ''}
isClearable={props.isClearable}
isSearchable={props.isSearchable}
Expand Down
7 changes: 5 additions & 2 deletions src/components/stageLayout/StageLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { Children, ReactNode, ReactElement, useContext } from 'react';
import { Children, ReactElement, ReactNode, useContext } from 'react';
import { Button } from '../button/Button';
import { Text } from '../text/Text';
import './StageLayout.styles.scss';
Expand All @@ -11,6 +11,7 @@ import { LegalLinksContext } from '../../globalState/provider/LegalLinksProvider
import { useAppConfig } from '../../hooks/useAppConfig';
import { useResponsive } from '../../hooks/useResponsive';
import LegalLinks from '../legalLinks/LegalLinks';
import { MENUPLACEMENT_BOTTOM_LEFT } from '../select/SelectDropdown';

interface StageLayoutProps {
className?: string;
Expand Down Expand Up @@ -46,7 +47,9 @@ export const StageLayout = ({
<div className={`stageLayout__header ${!fromL ? 'mobile' : ''}`}>
{selectableLocales.length > 1 && (
<div>
<LocaleSwitch />
<LocaleSwitch
menuPlacement={MENUPLACEMENT_BOTTOM_LEFT}
/>
</div>
)}
{showLoginLink && (
Expand Down

0 comments on commit 70ebf1b

Please sign in to comment.