From 25d06e579122b353e8ba0c8fdf2319600c2f7de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Rialland?= Date: Thu, 27 Apr 2023 14:41:57 +0200 Subject: [PATCH] =?UTF-8?q?Am=C3=A9liore=20le=20Drawer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/source/components/Feedback/index.tsx | 2 +- site/source/components/SearchButton.tsx | 4 - .../components/conversation/ChoicesInput.tsx | 4 +- site/source/design-system/drawer/Drawer.tsx | 87 ++-- site/source/design-system/field/DateField.tsx | 5 +- site/source/design-system/popover/Popover.tsx | 12 +- site/source/design-system/switch/Switch.tsx | 26 +- ...seClickOutside.ts => useOnClickOutside.ts} | 0 site/source/hooks/useOnKeyDown.ts | 19 + .../components/AllerPlusLoinRevenus.tsx | 431 +++++++++--------- 10 files changed, 324 insertions(+), 266 deletions(-) rename site/source/hooks/{useClickOutside.ts => useOnClickOutside.ts} (100%) create mode 100644 site/source/hooks/useOnKeyDown.ts diff --git a/site/source/components/Feedback/index.tsx b/site/source/components/Feedback/index.tsx index 410ccfd00..587ba7cc1 100644 --- a/site/source/components/Feedback/index.tsx +++ b/site/source/components/Feedback/index.tsx @@ -21,7 +21,7 @@ import { Strong } from '@/design-system/typography' import { H4 } from '@/design-system/typography/heading' import { StyledLink } from '@/design-system/typography/link' import { Body } from '@/design-system/typography/paragraphs' -import { useOnClickOutside } from '@/hooks/useClickOutside' +import { useOnClickOutside } from '@/hooks/useOnClickOutside' import { useSitePaths } from '@/sitePaths' import * as safeLocalStorage from '../../storage/safeLocalStorage' diff --git a/site/source/components/SearchButton.tsx b/site/source/components/SearchButton.tsx index de1fb0f29..1929c9f14 100644 --- a/site/source/components/SearchButton.tsx +++ b/site/source/components/SearchButton.tsx @@ -54,10 +54,6 @@ const StyledButton = styled(Button)` flex: 0; align-items: center; margin-right: ${({ theme }) => theme.spacings.md}; - @media (max-width: ${({ theme }) => theme.breakpointsWidth.sm}) { - order: 3; - margin-right: 0; - } ` const StyledIcon = styled.svg` diff --git a/site/source/components/conversation/ChoicesInput.tsx b/site/source/components/conversation/ChoicesInput.tsx index 89373c3a2..8383cb1ac 100644 --- a/site/source/components/conversation/ChoicesInput.tsx +++ b/site/source/components/conversation/ChoicesInput.tsx @@ -347,8 +347,9 @@ export const SwitchInput = (props: { label?: string id?: string key?: string + invertLabel?: boolean }) => { - const { onChange, id, label, defaultSelected, key } = props + const { onChange, id, label, defaultSelected, key, invertLabel } = props return ( {label} diff --git a/site/source/design-system/drawer/Drawer.tsx b/site/source/design-system/drawer/Drawer.tsx index 62e23f43d..7cbb0adb8 100644 --- a/site/source/design-system/drawer/Drawer.tsx +++ b/site/source/design-system/drawer/Drawer.tsx @@ -1,15 +1,18 @@ import FocusTrap from 'focus-trap-react' -import React, { ReactNode, useCallback, useEffect, useState } from 'react' +import { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import ReactDOM from 'react-dom' import { Trans } from 'react-i18next' import styled, { css } from 'styled-components' +import { useOnClickOutside } from '@/hooks/useOnClickOutside' +import { useOnKeyDown } from '@/hooks/useOnKeyDown' + import { Button } from '../buttons' import { Grid } from '../layout' import { CloseButton, CloseButtonContainer } from '../popover/Popover' export type DrawerButtonProps = { - onClick: () => void + onPress: () => void ['aria-expanded']: boolean ['aria-haspopup']: | boolean @@ -32,14 +35,15 @@ export const Drawer = ({ cancelLabel, isDismissable = true, }: { - trigger: ({ onClick }: DrawerButtonProps) => ReactNode + trigger: (props: DrawerButtonProps) => ReactNode children: ReactNode confirmLabel?: string cancelLabel?: string - onConfirm: () => void + onConfirm?: () => void onCancel?: () => void isDismissable?: boolean }) => { + const panel = useRef(null) const [isOpen, setIsOpen] = useState(false) const [isMounted, setIsMounted] = useState(false) @@ -55,8 +59,10 @@ export const Drawer = ({ const scrollY = document.body.style.top document.body.style.position = '' document.body.style.top = '' - // Avoid scroll jump - window.scrollTo(0, parseInt(scrollY || '0') * -1) + if (scrollY) { + // Avoid scroll jump + window.scrollTo(0, parseInt(scrollY) * -1) + } } } @@ -67,8 +73,9 @@ export const Drawer = ({ } }, [isMounted]) - const closeDrawer = () => { + const closeDrawer = useCallback(() => { setIsOpen(false) + disablePageScrolling(false) setTimeout(() => { setIsMounted(false) @@ -76,18 +83,21 @@ export const Drawer = ({ onCancel() } }, 500) - } + }, [onCancel]) - const handleDeactivate = useCallback(() => { - disablePageScrolling(false) - }, []) + useOnClickOutside(panel, () => { + closeDrawer() + }) + useOnKeyDown('Escape', () => { + closeDrawer() + }) return ( <> {trigger({ 'aria-expanded': isOpen, 'aria-haspopup': 'dialog', - onClick: openDrawer, + onPress: openDrawer, })} {isMounted && ReactDOM.createPortal( @@ -96,13 +106,10 @@ export const Drawer = ({ { - closeDrawer() - handleDeactivate() - }, + fallbackFocus: panel.current ?? undefined, }} > - + {isDismissable && ( {/* TODO : replace with Link when in design system */} @@ -129,15 +136,10 @@ export const Drawer = ({ )} - - {React.Children.map(children, (child) => { - if (React.isValidElement(child)) { - return React.cloneElement(child, { closeDrawer } as { - closeDrawer: () => void - }) - } - })} - + + + {children} + {onConfirm && ( @@ -197,12 +199,15 @@ const DrawerBackground = styled.div<{ $isOpen?: boolean }>` const DrawerPanel = styled.div<{ $isOpen: boolean }>` + display: flex; + flex-direction: column; width: 500px; max-width: 100vw; height: 100vh; - overflow-x: hidden; - overflow-y: auto; - background-color: ${({ theme }) => theme.colors.extended.grey[100]}; + background-color: ${({ theme }) => + theme.darkMode + ? theme.colors.extended.dark[600] + : theme.colors.extended.grey[100]}; transition: transform 0.5s ease-in-out; position: fixed; right: 0; @@ -216,6 +221,11 @@ const DrawerPanel = styled.div<{ `} ` +const DrawerContentWrapper = styled.div` + overflow: auto; + flex-grow: 1; +` + const DrawerContent = styled.div` padding: 0 ${({ theme }) => theme.spacings.xxl}; padding-bottom: 2rem; @@ -223,14 +233,12 @@ const DrawerContent = styled.div` ` const DrawerFooter = styled.div` - position: sticky; - bottom: 0; - left: 0; - right: 0; - background: ${({ theme }) => theme.colors.extended.grey[100]}; + background-color: ${({ theme }) => + theme.darkMode + ? theme.colors.extended.dark[600] + : theme.colors.extended.grey[100]}; padding: ${({ theme }) => theme.spacings.xl}; box-shadow: 0px 1px 15px rgba(0, 0, 0, 0.15); - z-index: 10; ` const StyledGrid = styled(Grid)` @@ -239,11 +247,4 @@ const StyledGrid = styled(Grid)` gap: ${({ theme }) => theme.spacings.md}; ` -const StyledCloseButtonContainer = styled(CloseButtonContainer)` - position: sticky; - top: 0; - left: 0; - right: 0; - background: ${({ theme }) => theme.colors.extended.grey[100]}; - z-index: 10; -` +const StyledCloseButtonContainer = styled(CloseButtonContainer)`` diff --git a/site/source/design-system/field/DateField.tsx b/site/source/design-system/field/DateField.tsx index a3d70aceb..001bec5a6 100644 --- a/site/source/design-system/field/DateField.tsx +++ b/site/source/design-system/field/DateField.tsx @@ -11,7 +11,7 @@ import { DayPicker, useInput } from 'react-day-picker' import { useTranslation } from 'react-i18next' import styled from 'styled-components' -import { useOnClickOutside } from '@/hooks/useClickOutside' +import { useOnClickOutside } from '@/hooks/useOnClickOutside' import { Button } from '../buttons' import { Emoji } from '../emoji' @@ -133,6 +133,7 @@ export default function DateField(props: DateFieldProps) {
theme.spacings.xxl}; justify-content: flex-end; + background-color: ${({ theme }) => + theme.darkMode + ? theme.colors.extended.dark[600] + : theme.colors.extended.grey[100]}; ` + export const CloseButton = styled.button` display: inline-flex; align-items: center; @@ -263,6 +268,11 @@ export const CloseButton = styled.button` :hover { text-decoration: underline; } + :focus { + ${FocusStyle} + box-shadow: inset 0 0 0 3px #ffffff; + outline-offset: -2px; + } ` const PopoverContent = styled.div` diff --git a/site/source/design-system/switch/Switch.tsx b/site/source/design-system/switch/Switch.tsx index 2d4563095..e0b87c386 100644 --- a/site/source/design-system/switch/Switch.tsx +++ b/site/source/design-system/switch/Switch.tsx @@ -86,8 +86,15 @@ const LabelBody = styled(Body)` cursor: pointer; ` -const Text = styled.span` - margin-right: ${({ theme }) => theme.spacings.xxs}; +const Text = styled.span<{ invertLabel?: boolean }>` + ${({ theme, invertLabel: $invertLabel }) => + $invertLabel + ? css` + margin-left: ${theme.spacings.xxs}; + ` + : css` + margin-right: ${theme.spacings.xxs}; + `}; ` type AriaSwitchProps = Parameters[0] @@ -98,6 +105,10 @@ export type SwitchProps = AriaSwitchProps & { children?: ReactNode className?: string role?: string + /** + * Invert the position of the label and the switch + */ + invertLabel?: boolean } export const Switch = (props: SwitchProps) => { @@ -106,6 +117,7 @@ export const Switch = (props: SwitchProps) => { light = false, children, className, + invertLabel = false, ...ariaProps } = props const state = useToggleState(ariaProps) @@ -116,8 +128,10 @@ export const Switch = (props: SwitchProps) => { const { isSelected } = state return ( - - {children && {children}} + + {children && !invertLabel && ( + {children} + )} { disabled={isDisabled} > { disabled={isDisabled} /> + {children && invertLabel && ( + {children} + )} ) } diff --git a/site/source/hooks/useClickOutside.ts b/site/source/hooks/useOnClickOutside.ts similarity index 100% rename from site/source/hooks/useClickOutside.ts rename to site/source/hooks/useOnClickOutside.ts diff --git a/site/source/hooks/useOnKeyDown.ts b/site/source/hooks/useOnKeyDown.ts new file mode 100644 index 000000000..a1ceb4b71 --- /dev/null +++ b/site/source/hooks/useOnKeyDown.ts @@ -0,0 +1,19 @@ +import { useEffect } from 'react' + +export const useOnKeyDown = ( + keyPress: string | null, + handler: (event: KeyboardEvent) => void +) => { + useEffect(() => { + const listener = (event: KeyboardEvent) => { + if (!keyPress || event.key === keyPress) { + handler(event) + } + } + window.addEventListener('keydown', listener) + + return () => { + window.removeEventListener('keydown', listener) + } + }, [handler, keyPress]) +} diff --git a/site/source/pages/simulateurs/comparaison-statuts/components/AllerPlusLoinRevenus.tsx b/site/source/pages/simulateurs/comparaison-statuts/components/AllerPlusLoinRevenus.tsx index ec0faf518..8cdade922 100644 --- a/site/source/pages/simulateurs/comparaison-statuts/components/AllerPlusLoinRevenus.tsx +++ b/site/source/pages/simulateurs/comparaison-statuts/components/AllerPlusLoinRevenus.tsx @@ -18,7 +18,7 @@ import { Grid, Spacing } from '@/design-system/layout' import { Tag, TagType } from '@/design-system/tag' import { Tooltip } from '@/design-system/tooltip' import { Strong } from '@/design-system/typography' -import { H1, H4, H5 } from '@/design-system/typography/heading' +import { H2, H4, H5 } from '@/design-system/typography/heading' import { Link, StyledLink } from '@/design-system/typography/link' import { Body } from '@/design-system/typography/paragraphs' import { answerQuestion } from '@/store/actions/actions' @@ -62,8 +62,14 @@ const AllerPlusLoinRevenus = ({ return ( void }) => ( - )} @@ -105,226 +111,229 @@ const AllerPlusLoinRevenus = ({ }} > <> -

+

Aller plus loin sur les revenus -

+

Calculer vos revenus

- - - {t( - 'comparateur.allerPlusLoin.tableCaption', - "Tableau affichant le détail du calcul du revenu net pour la SASU, l'entreprise individuelle (EI) et l'auto-entreprise (AE)." - )} - - - - Type de structure - - - SASU - - - - - - - EI + + + + {t( + 'comparateur.allerPlusLoin.tableCaption', + "Tableau affichant le détail du calcul du revenu net pour la SASU, l'entreprise individuelle (EI) et l'auto-entreprise (AE)." + )} + + + + Type de structure + + + SASU - - + - - - - AE - - - - - - - - - - - - {' '} - Chiffre d'affaires - - - - - - - - - - - Charges - - - - - - - - - - -{' '} - Cotisations - - - - - - - - - - - - - - - - - - - - - Impôts - - - - - - - - - - - - - - - - - - - - - - - - - {' '} - - Revenu net - - - - - + + + + EI + + + + + + + + AE + + + + + + + + + + - + {' '} + Chiffre d'affaires + + + + + + + + + -{' '} + Charges + + + + + + + + + + -{' '} + Cotisations + + + + - - - - - - + + + + - - - - - - + + + + - - - - - - + + + + + + - Impôts + + + + + + + + + + + + + + + + + + + + + + + - + {' '} + + Revenu net + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bénéficier de l'ACRE

@@ -358,10 +367,9 @@ const AllerPlusLoinRevenus = ({ id="activation-acre" onChange={(value: boolean) => setAcreValue(value)} defaultSelected={defaultValueACRE as boolean} + label="Activer l'ACRE dans la simulation" + invertLabel /> - {(acreValue || defaultValueACRE) && ( @@ -378,10 +386,9 @@ const AllerPlusLoinRevenus = ({ id="activation-acre-ae" onChange={(value: boolean) => setAEAcreValue(value)} defaultSelected={isAutoEntrepreneurACREEnabled} + label="Je suis éligible à l'ACRE pour mon auto-entreprise" + invertLabel /> - )} @@ -462,10 +469,9 @@ const AllerPlusLoinRevenus = ({ id="versement-liberatoire" onChange={setVersementLiberatoireValue} defaultSelected={defaultValueVersementLiberatoire as boolean} + label="Activer le versement libératoire dans la simulation." + invertLabel /> -
@@ -497,16 +503,14 @@ const FlexCentered = styled.div` align-items: center; ` -const Label = styled.label` - margin-left: ${({ theme }) => theme.spacings.md}; - font-family: ${({ theme }) => theme.fonts.main}; - font-size: 1rem; -` - const StyledArrowRightIcon = styled(ArrowRightIcon)` margin-left: ${({ theme }) => theme.spacings.sm}; ` +const WrapperTable = styled.div` + overflow: auto; +` + const StyledTable = styled.table` width: 100%; text-align: left; @@ -519,6 +523,13 @@ const StyledTable = styled.table` border-spacing: ${({ theme }) => theme.spacings.md}!important; } + th { + color: ${({ theme }) => + theme.darkMode + ? theme.colors.extended.grey[200] + : theme.colors.extended.grey[800]}; + } + thead th { text-align: center; font-size: 0.75rem;