Améliore la navigation dans l'assistant au choix du statut pour les mobiles

pull/2782/head
Johan Girod 2023-08-02 11:39:37 +02:00
parent 218a8ea059
commit f14584753b
10 changed files with 63 additions and 55 deletions

View File

@ -1,22 +1,15 @@
import { useEffect } from 'react'
/**
* @deprecated Prefer the use of useIsEmbedded() if possible */
export function isIframe() {
try {
return window.self !== window.top
} catch (e) {
return true
}
}
import { useIsEmbedded } from '../hooks/useIsEmbedded'
export function useIframeResizer() {
export function IframeResizer() {
const isEmbedded = useIsEmbedded()
useEffect(() => {
// The code below communicate with the iframe.js script on a host site
// to automatically resize the iframe when its inner content height
// change.
if (!isIframe()) {
if (!isEmbedded) {
return
}
@ -28,5 +21,7 @@ export function useIframeResizer() {
observer.observe(window.document.body)
return () => observer.disconnect()
}, [])
}, [isEmbedded])
return null
}

View File

@ -15,15 +15,14 @@ import DesignSystemThemeProvider from '@/design-system/root'
import { H1, H4 } from '@/design-system/typography/heading'
import { Link } from '@/design-system/typography/link'
import { Body, Intro } from '@/design-system/typography/paragraphs'
import { useIframeResizer } from '@/hooks/useIframeResizer'
import { EmbededContextProvider } from '@/hooks/useIsEmbedded'
import { Message } from '../design-system'
import * as safeLocalStorage from '../storage/safeLocalStorage'
import { store } from '../store/store'
import { inIframe } from '../utils'
import { TrackingContext } from './ATInternetTracking'
import { createTracker } from './ATInternetTracking/Tracker'
import { IframeResizer } from './IframeResizer'
import { ServiceWorker } from './ServiceWorker'
import { DarkModeProvider } from './utils/DarkModeContext'
@ -40,8 +39,6 @@ export default function Provider({
basename,
children,
}: ProviderProps): JSX.Element {
useIframeResizer()
return (
<EmbededContextProvider>
<DarkModeProvider>
@ -49,8 +46,8 @@ export default function Provider({
<ErrorBoundary showDialog fallback={ErrorFallback}>
{!import.meta.env.SSR &&
import.meta.env.MODE === 'production' &&
'serviceWorker' in navigator &&
!inIframe() && <ServiceWorker />}
'serviceWorker' in navigator && <ServiceWorker />}
<IframeResizer />
<OverlayProvider>
<ReduxProvider store={store}>
<ThemeColorsProvider>

View File

@ -3,6 +3,7 @@ import { Trans, useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { useRegisterSW } from 'virtual:pwa-register/react'
import { useIsEmbedded } from '@/hooks/useIsEmbedded'
import { getItem, removeItem, setItem } from '@/storage/safeLocalStorage'
import { Message } from '../design-system'
@ -43,6 +44,7 @@ const pwaPromptDelayKey = 'update-pwa-prompt-delay'
export const ServiceWorker = () => {
const { t } = useTranslation()
const [showPrompt, setShowPrompt] = useState(false)
const isEmbedded = useIsEmbedded()
const {
needRefresh: [needRefresh, setNeedRefresh],
@ -85,6 +87,9 @@ export const ServiceWorker = () => {
console.error('SW registration error', error)
},
})
if (isEmbedded) {
return null
}
return (
<PromptContainer>

View File

@ -86,7 +86,7 @@ export default function SimulateurOrAssistantPage() {
{title && !inIframe && (
<>
<H1>
<StyledSpan>{title}</StyledSpan>
<StyledSpan>{title}</StyledSpan>{' '}
{year && (
<Chip type="secondary" icon={<Emoji emoji="📆" />}>
{year}

View File

@ -1,6 +1,6 @@
import { createGlobalStyle, css } from 'styled-components'
import { isIframe } from '@/hooks/useIframeResizer'
import { inIframe } from '@/utils'
export const SROnly = css`
position: absolute !important;
@ -112,7 +112,7 @@ html {
html, body, #js, #js > *, [data-overlay-container] {
${
isIframe()
inIframe()
? css`
min-height: 100%;
`

View File

@ -12,12 +12,12 @@ export default function Layout({
}) {
return (
<>
<Grid container spacing={5}>
<Grid item sm={12} md={7} lg={8}>
<Grid container spacing={4}>
<Grid item xs={12} md={8} lg={8}>
<H3 as="h2">{title}</H3>
{children}
</Grid>
<Grid item sm={12} md={5} lg={4}>
<Grid item xs={12} md={4} lg={4}>
<StatutsPossibles />
</Grid>
</Grid>

View File

@ -42,13 +42,19 @@ export default function Navigation({
<TrackPage chapter3="pas_a_pas" name={currentStep} />
{!small && <Spacing xs />}
<StyledNavigation $small={small}>
<Grid container spacing={2}>
<Grid
container
spacing={2}
css={`
flex-wrap: wrap-reverse;
`}
>
{children && (
<Grid item xs={12}>
{children}
</Grid>
)}
<Grid item>
<Grid item xs={12} sm="auto">
<Button
light
size={small ? 'XS' : 'MD'}
@ -60,7 +66,7 @@ export default function Navigation({
</Button>
</Grid>
{nextStep && !assistantIsCompleted && (
<Grid item>
<Grid item xs={12} sm="auto">
<Button
size={small ? 'XS' : 'MD'}
onPress={onNextStep}
@ -76,7 +82,7 @@ export default function Navigation({
</Grid>
)}
{assistantIsCompleted && (
<Grid item>
<Grid item xs={12} sm="auto">
<Button
to={choixDuStatutPath['résultat'][assistantIsCompleted]}
aria-label={t('Suivant, voir le résultat')}
@ -101,7 +107,7 @@ const StyledNavigation = styled.div<{ $small: boolean }>`
${({ $small }) =>
!$small &&
css`
height: 110px;
height: fit-content;
`}
position: sticky;
padding: ${({ theme, $small }) => theme.spacings[$small ? 'sm' : 'lg']} 1rem;
@ -117,7 +123,7 @@ const StyledNavigation = styled.div<{ $small: boolean }>`
const Shadow = styled.div`
z-index: 1;
position: sticky;
bottom: 35px;
bottom: 30px;
transform: translateY(-200%);
clip-path: inset(-5px 0px -5px -5px);
height: 25px;

View File

@ -8,7 +8,6 @@ import { useEngine } from '@/components/utils/EngineContext'
import { Message } from '@/design-system'
import { H5 } from '@/design-system/typography/heading'
import { Li, Ul } from '@/design-system/typography/list'
import { SmallBody } from '@/design-system/typography/paragraphs'
export default function StatutsPossibles() {
const engine = useEngine()
@ -33,10 +32,6 @@ export default function StatutsPossibles() {
return (
<StyledMessage>
<H5 as="h2"> Statuts disponibles</H5>
<SmallBody>
Les statuts disponibles diffèrent en fonction de l'activité
professionnelle que vous exercez
</SmallBody>
<StyledUl noMarker as={FlipMove} typeName="ul">
{statuts.map((statut) => (
@ -51,7 +46,7 @@ const StyledMessage = styled(Message)`
padding-top: 2rem;
border: none;
position: sticky;
top: 0;
top: 1rem;
border-radius: 0.5rem;
background: ${({ theme }) =>
theme.darkMode

View File

@ -6,6 +6,7 @@ import { Appear } from '@/components/ui/animate'
import { Chip } from '@/design-system'
import { Button, HelpButtonWithPopover } from '@/design-system/buttons'
import { ChevronIcon } from '@/design-system/icons'
import { Grid } from '@/design-system/layout'
import { H4, H5, H6 } from '@/design-system/typography/heading'
import { Link } from '@/design-system/typography/link'
import { Li, Ul } from '@/design-system/typography/list'
@ -33,27 +34,34 @@ export const Result = ({ item, hideGuichetUnique }: ResultProps) => {
return (
<>
<H5 as="h3">{title}</H5>
<SmallBody
css={`
display: flex;
justify-content: space-between;
align-items: center;
`}
>
<Chip>Code : {codeApe}</Chip>
<Button
size="XXS"
light
color="secondary"
onPress={() => setOpen((x) => !x)}
aria-expanded={open}
aria-controls={`info-${codeApe}`}
aria-label={!open ? t('En savoir plus') : t('Replier')}
<SmallBody>
<Grid
container
css={`
align-items: center;
justify-content: space-between;
`}
>
{!open ? t('En savoir plus') : t('Replier')}&nbsp;
<StyledChevron aria-hidden $isOpen={open} />
</Button>
<Grid item>
<Chip>Code : {codeApe}</Chip>
</Grid>
<Grid item>
<Button
size="XXS"
light
color="secondary"
onPress={() => setOpen((x) => !x)}
aria-expanded={open}
aria-controls={`info-${codeApe}`}
aria-label={!open ? t('En savoir plus') : t('Replier')}
>
{!open ? t('En savoir plus') : t('Replier')}&nbsp;
<StyledChevron aria-hidden $isOpen={open} />
</Button>
</Grid>
</Grid>
</SmallBody>
{open && (
<Appear id={`info-${codeApe}`}>
{contenuCentral.length ? (

View File

@ -41,6 +41,8 @@ export const debounce = <T>(waitFor: number, fn: (...args: T[]) => void) => {
export const fetcher = (url: RequestInfo) => fetch(url).then((r) => r.json())
/**
* @deprecated Prefer the use of useIsEmbedded() if possible */
export function inIframe(): boolean {
try {
return window.self !== window.top