🎨 Améliorations mode sombre (#2457)

* feat: Add base modification

* feat: Ajoute contexte

* feat: copie colle

* feat: Ajoute ForceThemeProvider

* feat: Improve Footer

* feat: Ajoute ForceTheme a footer

* feat: Améliore Popover

* feat: Plusieurs correctifs

* feat: mods

* feat: Correctifs

* feat: Améliore plan de site

* feat: mise à jour prop container

* fixs

* fix: pass darkmode value to theme

* fix: Corrige l'affichage du menu mobile de la doc en mode sombre

* feat: Nettoyage

* feat: Force dark sur titre uniquement
pull/2402/head
Benjamin Arias 2023-01-24 17:42:11 +01:00 committed by GitHub
parent 51424e0fa8
commit cbae57e3b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 398 additions and 320 deletions

View File

@ -22,6 +22,7 @@ import logo from '@/images/logo-monentreprise.svg'
import { TrackingContext } from './ATInternetTracking'
import { createTracker } from './ATInternetTracking/Tracker'
import { ServiceWorker } from './ServiceWorker'
import { DarkModeProvider } from './contexts/DarkModeContext'
import { Message } from './design-system'
import * as safeLocalStorage from './storage/safeLocalStorage'
import { store } from './store'
@ -45,77 +46,79 @@ export default function Provider({
const { t } = useTranslation()
return (
<DesignSystemThemeProvider>
<GlobalStyle />
<ErrorBoundary
showDialog
fallback={(errorData) => (
<main style={{ height: '100vh' }}>
<Container>
<Link href="/" aria-label={t("Retourner à la page d'accueil")}>
<img
src={logo}
alt="Logo mon-entreprise"
style={{
maxWidth: '200px',
width: '100%',
marginTop: '1rem',
}}
></img>
</Link>
<H1>Une erreur est survenue</H1>
<Intro>
L'équipe technique mon-entreprise a été automatiquement
prévenue.
</Intro>
<Body>
Vous pouvez également nous contacter directement à l'adresse{' '}
<Link
href="mailto:contact@mon-entreprise.beta.gouv.fr"
aria-label={t(
'Envoyer un courriel à contact@mon-entreprise.beta.gouv.fr, nouvelle fenêtre'
)}
>
contact@mon-entreprise.beta.gouv.fr
</Link>{' '}
si vous souhaitez partager une remarque. Veuillez nous excuser
pour la gêne occasionnée.
</Body>
<Grid container>
<Grid item xs={12} lg={6}>
<Message type="info">
<H4>Cause de l'erreur :</H4>
<Body>
{errorData.error.name} : {errorData.error.message}
</Body>
</Message>
<DarkModeProvider>
<DesignSystemThemeProvider>
<GlobalStyle />
<ErrorBoundary
showDialog
fallback={(errorData) => (
<main style={{ height: '100vh' }}>
<Container>
<Link href="/" aria-label={t("Retourner à la page d'accueil")}>
<img
src={logo}
alt="Logo mon-entreprise"
style={{
maxWidth: '200px',
width: '100%',
marginTop: '1rem',
}}
></img>
</Link>
<H1>Une erreur est survenue</H1>
<Intro>
L'équipe technique mon-entreprise a été automatiquement
prévenue.
</Intro>
<Body>
Vous pouvez également nous contacter directement à l'adresse{' '}
<Link
href="mailto:contact@mon-entreprise.beta.gouv.fr"
aria-label={t(
'Envoyer un courriel à contact@mon-entreprise.beta.gouv.fr, nouvelle fenêtre'
)}
>
contact@mon-entreprise.beta.gouv.fr
</Link>{' '}
si vous souhaitez partager une remarque. Veuillez nous excuser
pour la gêne occasionnée.
</Body>
<Grid container>
<Grid item xs={12} lg={6}>
<Message type="info">
<H4>Cause de l'erreur :</H4>
<Body>
{errorData.error.name} : {errorData.error.message}
</Body>
</Message>
</Grid>
</Grid>
</Grid>
</Container>
</main>
)}
>
{!import.meta.env.SSR &&
import.meta.env.MODE === 'production' &&
'serviceWorker' in navigator &&
!inIframe() && <ServiceWorker />}
<OverlayProvider>
<ReduxProvider store={store}>
<ThemeColorsProvider>
<DisableAnimationOnPrintProvider>
<SiteNameContext.Provider value={basename}>
<I18nextProvider i18n={i18next}>
<BrowserRouterProvider basename={basename}>
{children}
</BrowserRouterProvider>
</I18nextProvider>
</SiteNameContext.Provider>
</DisableAnimationOnPrintProvider>
</ThemeColorsProvider>
</ReduxProvider>
</OverlayProvider>
</ErrorBoundary>
</DesignSystemThemeProvider>
</Container>
</main>
)}
>
{!import.meta.env.SSR &&
import.meta.env.MODE === 'production' &&
'serviceWorker' in navigator &&
!inIframe() && <ServiceWorker />}
<OverlayProvider>
<ReduxProvider store={store}>
<ThemeColorsProvider>
<DisableAnimationOnPrintProvider>
<SiteNameContext.Provider value={basename}>
<I18nextProvider i18n={i18next}>
<BrowserRouterProvider basename={basename}>
{children}
</BrowserRouterProvider>
</I18nextProvider>
</SiteNameContext.Provider>
</DisableAnimationOnPrintProvider>
</ThemeColorsProvider>
</ReduxProvider>
</OverlayProvider>
</ErrorBoundary>
</DesignSystemThemeProvider>
</DarkModeProvider>
)
}

View File

@ -2,13 +2,11 @@ import { Trans, useTranslation } from 'react-i18next'
import { PopoverWithTrigger } from '@/design-system'
import { H2 } from '@/design-system/typography/heading'
import { Link } from '@/design-system/typography/link'
import { Link, StyledLink } from '@/design-system/typography/link'
import { Body } from '@/design-system/typography/paragraphs'
import { useDarkMode } from '@/hooks/useDarkMode'
export default function LegalNotice() {
const { t } = useTranslation()
const [darkMode] = useDarkMode()
return (
<PopoverWithTrigger
@ -51,15 +49,14 @@ export default function LegalNotice() {
<br />
San Francisco, CA 94107 <br />
Site web :&nbsp;
<a
<StyledLink
href="https://www.netlify.com"
aria-label="https://www.netlify.com, nouvelle fenêtre"
target="_blank"
rel="noreferrer"
style={darkMode ? { color: '#9EBBF1' } : { color: '#2E5FB6' }}
>
https://www.netlify.com
</a>
</StyledLink>
</Trans>
</Body>
<H2>
@ -67,14 +64,13 @@ export default function LegalNotice() {
</H2>
<Body>
<Trans i18nKey="legalNotice.contact.content">
<a
<StyledLink
href="mailto:contact@mon-entreprise.beta.gouv.fr"
target="_blank"
rel="noreferrer"
style={darkMode ? { color: '#9EBBF1' } : { color: '#2E5FB6' }}
>
contact@mon-entreprise.beta.gouv.fr
</a>
</StyledLink>
</Trans>
</Body>{' '}
</PopoverWithTrigger>

View File

@ -19,7 +19,6 @@
}
.payslip__container h3 {
border-bottom: 1px solid rgba(0, 0, 0, 0.85);
color: #1D458C;
background-color: inherit;
print-color-adjust: exact !important;
margin: 0;
@ -43,7 +42,6 @@
.payslip__container h5 {
margin: 0;
color: #1D458C;
background-color: inherit;
margin-bottom: 0.5rem;
margin-top: 0.5rem;

View File

@ -16,11 +16,12 @@ const QuestionsContainer = styled.div`
border-radius: ${({ theme }) =>
`0 0 ${theme.box.borderRadius} ${theme.box.borderRadius}`};
background: ${({ theme }) => {
const colorPalette = theme.colors.bases.primary
const palettePrimary = theme.colors.bases.primary
const paletteGrey = theme.colors.extended.grey
return theme.darkMode
? `linear-gradient(60deg, ${colorPalette[800]} 0%, ${colorPalette[700]} 100%);`
: `linear-gradient(60deg, ${colorPalette[200]} 0%, ${colorPalette[100]} 100%);`
? `linear-gradient(60deg, ${paletteGrey[800]} 0%, ${paletteGrey[700]} 100%);`
: `linear-gradient(60deg, ${palettePrimary[200]} 0%, ${palettePrimary[100]} 100%);`
}};
`

View File

@ -84,15 +84,12 @@ export function SimulationGoal({
</RuleLink>
{rule.rawNode.résumé && (
<SmallBody
css={`
margin-bottom: 0;
`}
<StyledSmallBody
className={small ? 'sr-only' : ''}
id={`${dottedName.replace(/\s|\./g, '')}-description`}
>
{rule.rawNode.résumé}
</SmallBody>
</StyledSmallBody>
)}
</StyledGoalHeader>
</Grid>
@ -171,3 +168,7 @@ const StyledGoal = styled.div`
padding: 0;
}
`
const StyledSmallBody = styled(SmallBody)`
margin-bottom: 0;
`

View File

@ -1,8 +1,9 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import styled, { ThemeProvider, css } from 'styled-components'
import styled, { css } from 'styled-components'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import { Grid } from '@/design-system/layout'
import { Link } from '@/design-system/typography/link'
import { firstStepCompletedSelector } from '@/selectors/simulationSelectors'
@ -46,12 +47,12 @@ export function SimulationGoals({
aria-labelledby="simulator-legend-label"
aria-live="polite"
>
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: true })}>
<ForceThemeProvider forceTheme="dark">
<div className="sr-only" aria-hidden id="simulator-legend-label">
{legend}
</div>
{children}
</ThemeProvider>
</ForceThemeProvider>
</StyledSimulationGoals>
</WatchInitialRender>
)

View File

@ -29,10 +29,10 @@ export function CompanyDetails({
spacing={3}
>
<Grid item xs={12} lg>
<H4 data-test-id="currently-selected-company" as={headingTag}>
<StyledH4 data-test-id="currently-selected-company" as={headingTag}>
<Value expression="entreprise . nom" linkToRule={false} />{' '}
<Value expression="entreprise . SIREN" linkToRule={false} />
</H4>
</StyledH4>
<Body>
<Trans>
Entreprise créée le{' '}
@ -64,3 +64,9 @@ export function CompanyDetails({
}
const StyledCompanyContainer = styled(Message).attrs({ border: false })``
const StyledH4 = styled(H4)`
& span {
color: ${({ theme }) => theme.colors.bases.primary[700]};
}
`

View File

@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { FabriqueSocialEntreprise } from '@/api/fabrique-social'
import { ForceThemeProvider, ThemeType } from '@/contexts/DarkModeContext'
import { Message } from '@/design-system'
import { Card } from '@/design-system/card'
import { SearchField } from '@/design-system/field'
@ -24,6 +25,7 @@ export function CompanySearchField(props: {
onValue?: () => void
onClear?: () => void
onSubmit?: (search: FabriqueSocialEntreprise | null) => void
forceTheme?: ThemeType
}) {
const { t } = useTranslation()
const refResults = useRef<FabriqueSocialEntreprise[] | null>(null)
@ -62,14 +64,17 @@ export function CompanySearchField(props: {
return (
<Grid container>
<Grid item xs={12}>
<SearchField
data-test-id="company-search-input"
state={state}
isSearchStalled={searchPending}
onClear={onClear}
{...searchFieldProps}
/>
<ForceThemeProvider forceTheme={props?.forceTheme}>
<SearchField
data-test-id="company-search-input"
state={state}
isSearchStalled={searchPending}
onClear={onClear}
{...searchFieldProps}
/>
</ForceThemeProvider>
</Grid>
<Grid item xs={12}>
{state.value && !searchPending && (
<Results results={results} onSubmit={onSubmit} />

View File

@ -305,7 +305,7 @@ const StyledAnswerList = styled(Grid)`
theme.darkMode
? theme.colors.extended.dark[500]
: theme.colors.bases.primary[100]};
color: inherit;
color: ${({ theme }) => theme.colors.bases.primary[800]};
color-adjust: exact !important;
outline: solid
${({ theme }) =>

View File

@ -1,10 +1,11 @@
import { Helmet } from 'react-helmet-async'
import { Trans, useTranslation } from 'react-i18next'
import { useLocation } from 'react-router-dom'
import styled, { ThemeProvider } from 'styled-components'
import styled from 'styled-components'
import FeedbackButton from '@/components/Feedback'
import LegalNotice from '@/components/LegalNotice'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import { Button } from '@/design-system/buttons'
import { Emoji } from '@/design-system/emoji'
import { FooterContainer } from '@/design-system/footer'
@ -84,7 +85,7 @@ export default function Footer() {
</Container>
<Container backgroundColor={(theme) => theme.colors.bases.primary[700]}>
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: true })}>
<ForceThemeProvider forceTheme="dark">
<FooterContainer
className="print-hidden"
role="navigation"
@ -206,7 +207,7 @@ export default function Footer() {
</nav>
</FooterColumn>
</FooterContainer>
</ThemeProvider>
</ForceThemeProvider>
</Container>
</footer>
</>

View File

@ -9,7 +9,13 @@ import { Body, SmallBody } from '@/design-system/typography/paragraphs'
import { TrackPage, TrackingContext } from '../../../ATInternetTracking'
import * as safeLocalStorage from '../../../storage/safeLocalStorage'
export default function Privacy({ label }: { label?: string }) {
export default function Privacy({
label,
noUnderline = true,
}: {
label?: string
noUnderline?: boolean
}) {
const tracker = useContext(TrackingContext)
const [valueChanged, setValueChanged] = useState(false)
const { t } = useTranslation()
@ -31,7 +37,7 @@ export default function Privacy({ label }: { label?: string }) {
return (
<PopoverWithTrigger
trigger={(buttonProps) => (
<Link {...buttonProps} aria-haspopup="dialog" noUnderline>
<Link {...buttonProps} aria-haspopup="dialog" noUnderline={noUnderline}>
{label ?? <Trans>Gestion des données personnelles</Trans>}
</Link>
)}

View File

@ -1,5 +1,5 @@
import { formatValue } from 'publicodes'
import React, { useRef } from 'react'
import { useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import styled, { keyframes } from 'styled-components'

View File

@ -1,4 +1,5 @@
import { ReactNode, createContext, useEffect, useState } from 'react'
import { ReactNode, createContext, useState } from 'react'
import { ThemeProvider } from 'styled-components'
import { useIsEmbedded } from '@/components/utils/useIsEmbedded'
import { getItem, setItem } from '@/storage/safeLocalStorage'
@ -37,34 +38,33 @@ export const DarkModeProvider = ({ children }: { children: ReactNode }) => {
console.log(darkMode ? 'Nuit' : 'Jour')
}
useEffect(() => {
if (!window.matchMedia) {
return
}
const onDarkModeChange = (e: MediaQueryListEvent) => {
setDarkMode(e.matches)
}
const matchDarkMode = window.matchMedia('(prefers-color-scheme: dark)')
// safari 13 doesn't have addEventListener
matchDarkMode.addEventListener
? matchDarkMode.addEventListener('change', onDarkModeChange)
: matchDarkMode.addListener(onDarkModeChange)
return () => {
// safari 13 doesn't have removeEventListener
matchDarkMode.removeEventListener
? matchDarkMode.removeEventListener('change', onDarkModeChange)
: matchDarkMode.removeListener(onDarkModeChange)
}
})
const finalDarkMode = !useIsEmbedded() && darkMode
return (
<DarkModeContext.Provider value={[finalDarkMode, setDarkMode]}>
{/* <ThemeProvider theme={(theme) => ({ ...theme, darkMode: finalDarkMode })}> */}
{children}
{/* </ThemeProvider> */}
</DarkModeContext.Provider>
)
}
export type ThemeType = 'light' | 'dark'
export const ForceThemeProvider = ({
children,
forceTheme,
}: {
children: ReactNode
forceTheme?: ThemeType
}) => {
return (
<ThemeProvider
theme={(theme) => ({
...theme,
darkMode:
forceTheme === undefined ? theme.darkMode : forceTheme === 'dark',
})}
>
{children}
</ThemeProvider>
)
}

View File

@ -33,7 +33,7 @@ const InfoBulleText = styled.span`
border-radius: 3px;
font-family: 'Roboto';
background-color: white;
color: inherit;
color: ${({ theme }) => theme.colors.extended.grey[800]};
transition: opacity 0.2s, transform 0.2s;
opacity: 0;
box-shadow: 0px 2px 4px -1px rgba(41, 117, 209, 0.2),

View File

@ -47,7 +47,7 @@ export function Article({
<StyledHeader as={titleProps.as}>
{titleProps.children} {icon}
</StyledHeader>
<Body>{children}</Body>
<Content>{children}</Content>
<StyledBody
css={`
display: flex;
@ -83,13 +83,17 @@ const StyledHeader = styled(H4)`
theme.darkMode
? theme.colors.bases.primary[200]
: theme.colors.bases.primary[600]};
background-color: inherit;
background-color: transparent;
`
const StyledChevron = styled(ChevronIcon)`
margin-left: ${({ theme }) => theme.spacings.xxs};
`
const Content = styled(Body)`
background-color: transparent;
`
const StyledBody = styled(Body)`
&,
& * {

View File

@ -1,7 +1,8 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import styled, { ThemeProvider, css } from 'styled-components'
import styled, { css } from 'styled-components'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import { Palette, SmallPalette } from '@/types/styled'
import { Emoji } from '../emoji'
@ -25,7 +26,7 @@ export function Chip({
const { t } = useTranslation()
return (
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: false })}>
<ForceThemeProvider forceTheme="light">
<StyledChip className={className} type={type}>
{icon && (
<StyledIconWrapper type={type}>
@ -44,7 +45,7 @@ export function Chip({
)}
{children}
</StyledChip>
</ThemeProvider>
</ForceThemeProvider>
)
}
const StyledIconWrapper = styled.span<{

View File

@ -146,8 +146,11 @@ const StyledNumberFieldContainer = styled(StyledContainer)`
`
const StyledUnit = styled(StyledSuffix)`
color: ${({ theme }) => theme.colors.extended.grey[600]};
background-color: inherit;
color: ${({ theme }) =>
theme.darkMode
? theme.colors.extended.grey[200]
: theme.colors.extended.grey[600]};
background-color: transparent;
padding-left: 0 !important;
white-space: nowrap;
`

View File

@ -118,7 +118,10 @@ export const VisibleRadio = styled.span`
}
:hover ${OutsideCircle} {
border-color: ${({ theme }) => theme.colors.bases.primary[700]};
border-color: ${({ theme }) =>
theme.darkMode
? theme.colors.bases.primary[500]
: theme.colors.bases.primary[700]};
}
`

View File

@ -11,6 +11,7 @@ import styled, { css } from 'styled-components'
import { SearchIcon } from '@/design-system/icons'
import { Loader } from '@/design-system/icons/Loader'
import { FocusStyle } from '../global-style'
import {
StyledContainer,
StyledDescription,
@ -32,6 +33,9 @@ const SearchInput = styled(StyledInput)`
const SearchInputContainer = styled(StyledInputContainer)`
padding-left: 0.5rem;
:focus-within {
${FocusStyle}
}
`
const IconContainer = styled.div<{ hasLabel?: boolean }>`
@ -102,7 +106,7 @@ export default function SearchField(
const StyledClearButton = styled.button`
position: absolute;
right: 0;
background: none;
background: transparent;
border: none;
font-size: 2rem;
line-height: 2rem;
@ -112,6 +116,5 @@ const StyledClearButton = styled.button`
darkMode &&
css`
color: white !important;
background-color: inherit;
`}
`

View File

@ -36,7 +36,7 @@ export const Label = styled.label`
css`
@media not print {
color: ${theme.colors.extended.grey[100]} !important;
background-color: inherit;
background-color: transparent;
}
`}
`
@ -71,7 +71,7 @@ const Button = styled.button<ButtonProps>`
css`
@media not print {
color: ${theme.colors.extended.grey[100]} !important;
background-color: inherit;
background-color: transparent;
}
`}
`

View File

@ -78,14 +78,14 @@ export const StyledTextArea = styled.textarea`
`}
color: ${({ theme }) =>
theme.colors.extended.grey[theme.darkMode ? 200 : 600]};
background-color: inherit;
background-color: transparent;
}
${({ theme }) =>
theme.darkMode &&
css`
@media not print {
color: ${theme.colors.extended.grey[100]} !important;
background-color: inherit;
background-color: transparent;
}
`}
`
@ -107,7 +107,7 @@ export const StyledLabel = styled.label`
css`
@media not print {
color: ${theme.colors.extended.grey[100]} !important;
background-color: inherit;
background-color: transparent;
}
`}
`
@ -121,7 +121,7 @@ export const StyledDescription = styled(ExtraSmallBody)`
export const StyledErrorMessage = styled(StyledDescription)`
color: ${({ theme }) => theme.colors.extended.error[400]} !important;
background-color: inherit;
background-color: transparent;
`
export const StyledSuffix = styled.span`

View File

@ -133,7 +133,8 @@ export const StyledInputContainer = styled.div<{
}>`
border-radius: ${({ theme }) => theme.box.borderRadius};
border: ${({ theme }) =>
`${theme.box.borderWidth} solid ${
`${theme.box.borderWidth} solid
${
theme.darkMode
? theme.colors.extended.grey[100]
: theme.colors.extended.grey[700]
@ -213,6 +214,10 @@ export const StyledInputContainer = styled.div<{
: css`calc(${hasLabel ? LABEL_HEIGHT : '0rem'} + ${
theme.spacings.xs
}) ${theme.spacings.sm} ${theme.spacings.xs}`};
color: ${({ theme }) =>
theme.darkMode
? theme.colors.extended.grey[100]
: theme.colors.extended.grey[800]};
}
${({ small }) =>

View File

@ -224,4 +224,29 @@ figure {
a:focus {
${FocusStyle}
}
// Corrige l'affichage du menu mobile de la documentation
#mobile-menu-portal-id {
& nav {
background: ${({ theme }) => theme.darkMode && theme.colors.extended.dark[800]};
}
& svg {
fill: ${({ theme }) => theme.darkMode && theme.colors.extended.grey[100]};
}
li.active .content {
background-color: ${({ theme }) =>
theme.darkMode && theme.colors.extended.dark[600]};
}
}
#rules-nav-open-nav-button button {
color: ${({ theme }) => theme.darkMode && theme.colors.extended.grey[100]};
border-color: ${({ theme }) =>
theme.darkMode && theme.colors.extended.grey[100]};
&:hover {
color: ${({ theme }) => theme.darkMode && theme.colors.extended.grey[800]};
border-color: ${({ theme }) =>
theme.darkMode && theme.colors.extended.grey[800]};
}
}
`

View File

@ -1,7 +1,7 @@
import { ReactNode } from 'react'
import styled, { DefaultTheme, ThemeProvider } from 'styled-components'
import styled, { DefaultTheme } from 'styled-components'
import { useDarkMode } from '@/hooks/useDarkMode'
import { ForceThemeProvider, ThemeType } from '@/contexts/DarkModeContext'
const InnerContainer = styled.div`
margin-right: auto;
@ -44,43 +44,36 @@ const InnerContainer = styled.div`
`
type OuterContainerProps = {
backgroundColor?: (theme: DefaultTheme) => string
$backgroundColor?: (theme: DefaultTheme) => string
}
type ContainerProps = {
children: ReactNode
darkMode?: boolean
forceTheme?: ThemeType
backgroundColor?: (theme: DefaultTheme) => string
}
export default function Container({
backgroundColor,
darkMode,
forceTheme,
children,
}: ContainerProps) {
const [defaultDarkMode] = useDarkMode()
return (
<ThemeProvider
theme={(theme) => ({
...theme,
darkMode: darkMode ?? defaultDarkMode ?? theme?.darkMode,
})}
>
<ForceThemeProvider forceTheme={forceTheme}>
<OuterOuterContainer>
<OuterContainer backgroundColor={backgroundColor}>
<OuterContainer $backgroundColor={backgroundColor}>
<InnerContainer>{children}</InnerContainer>
</OuterContainer>
</OuterOuterContainer>
</ThemeProvider>
</ForceThemeProvider>
)
}
const OuterContainer = styled.div<OuterContainerProps>`
flex: 1;
min-width: 100vw;
background-color: ${({ theme, backgroundColor }) =>
backgroundColor ? backgroundColor(theme) : theme.colors};
background-color: ${({ theme, $backgroundColor }) =>
$backgroundColor ? $backgroundColor(theme) : theme.colors};
@media print {
min-width: initial;
}

View File

@ -1,7 +1,8 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import styled, { DefaultTheme, ThemeProvider, css } from 'styled-components'
import styled, { DefaultTheme, css } from 'styled-components'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import { Palette, SmallPalette } from '@/types/styled'
import { Emoji } from '../emoji'
@ -40,7 +41,7 @@ export function Message({
}
return (
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: false })}>
<ForceThemeProvider forceTheme="light">
<StyledMessage
className={className}
messageType={type}
@ -66,7 +67,7 @@ export function Message({
)}
<Wrapper role={role}>{children}</Wrapper>
</StyledMessage>
</ThemeProvider>
</ForceThemeProvider>
)
}
const StyledIconWrapper = styled.div<{
@ -112,6 +113,15 @@ const StyledMessage = styled.div<StyledMessageProps>`
> * {
margin: -${mini ? theme.spacings.xs : 0} 0;
}
& p,
& span,
& li {
color: ${({ theme }) => theme.colors.extended.grey[800]};
}
& a,
& button {
color: ${(colorSpace as Palette)[700] ?? colorSpace[600]};
}
`
}}
`

View File

@ -12,7 +12,9 @@ import FocusTrap from 'focus-trap-react'
import React, { RefObject, useEffect, useRef, useState } from 'react'
import styled, { ThemeProvider, css, keyframes } from 'styled-components'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import { Grid } from '@/design-system/layout'
import { useDarkMode } from '@/hooks/useDarkMode'
import { getIframeOffset, wrapperDebounceEvents } from '@/utils'
import { Container } from '../layout'
@ -74,75 +76,73 @@ export default function Popover(
}
return (
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: false })}>
<OverlayContainer>
<Underlay {...underlayProps} $offsetTop={offsetTop}>
<Container>
<OverlayContainer>
<Underlay {...underlayProps} $offsetTop={offsetTop}>
<Container>
<Grid
container
css={`
justify-content: center;
`}
>
<Grid
container
item
sm={small ? 10 : 12}
md={small ? 8 : 12}
css={`
justify-content: center;
min-width: 0;
`}
>
<Grid
item
sm={small ? 10 : 12}
md={small ? 8 : 12}
css={`
min-width: 0;
`}
>
<FocusTrap>
<PopoverContainer
{...dialogProps}
{...modalProps}
{...overlayProps}
$offsetTop={offsetTop}
ref={ref}
>
{props.isDismissable && (
<CloseButtonContainer>
{/* TODO : replace with Link when in design system */}
<CloseButton {...closeButtonProps} ref={closeButtonRef}>
Fermer
<svg
role="img"
aria-hidden
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.69323 17.2996C6.30271 16.9091 6.30271 16.276 6.69323 15.8854L15.8856 6.69304C16.2761 6.30252 16.9093 6.30252 17.2998 6.69304C17.6904 7.08356 17.6904 7.71673 17.2998 8.10725L8.10744 17.2996C7.71692 17.6902 7.08375 17.6902 6.69323 17.2996Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.6635 6.69306C7.05402 6.30254 7.68719 6.30254 8.07771 6.69306L17.2701 15.8854C17.6606 16.276 17.6606 16.9091 17.2701 17.2997C16.8796 17.6902 16.2464 17.6902 15.8559 17.2997L6.6635 8.10727C6.27297 7.71675 6.27297 7.08359 6.6635 6.69306Z"
/>
</svg>
</CloseButton>
</CloseButtonContainer>
<FocusTrap>
<PopoverContainer
{...dialogProps}
{...modalProps}
{...overlayProps}
$offsetTop={offsetTop}
ref={ref}
>
{props.isDismissable && (
<CloseButtonContainer>
{/* TODO : replace with Link when in design system */}
<CloseButton {...closeButtonProps} ref={closeButtonRef}>
Fermer
<svg
role="img"
aria-hidden
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.69323 17.2996C6.30271 16.9091 6.30271 16.276 6.69323 15.8854L15.8856 6.69304C16.2761 6.30252 16.9093 6.30252 17.2998 6.69304C17.6904 7.08356 17.6904 7.71673 17.2998 8.10725L8.10744 17.2996C7.71692 17.6902 7.08375 17.6902 6.69323 17.2996Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.6635 6.69306C7.05402 6.30254 7.68719 6.30254 8.07771 6.69306L17.2701 15.8854C17.6606 16.276 17.6606 16.9091 17.2701 17.2997C16.8796 17.6902 16.2464 17.6902 15.8559 17.2997L6.6635 8.10727C6.27297 7.71675 6.27297 7.08359 6.6635 6.69306Z"
/>
</svg>
</CloseButton>
</CloseButtonContainer>
)}
{/* tabIndex -1 is for text selection in popover, see https://github.com/adobe/react-spectrum/issues/1604#issuecomment-781574668 */}
<PopoverContent ref={contentRef}>
{title && (
<H2 as="h1" {...titleProps}>
{title}
</H2>
)}
{/* tabIndex -1 is for text selection in popover, see https://github.com/adobe/react-spectrum/issues/1604#issuecomment-781574668 */}
<PopoverContent ref={contentRef}>
{title && (
<H2 as="h1" {...titleProps}>
{title}
</H2>
)}
{children}
</PopoverContent>
</PopoverContainer>
</FocusTrap>
</Grid>
{children}
</PopoverContent>
</PopoverContainer>
</FocusTrap>
</Grid>
</Container>
</Underlay>
</OverlayContainer>
</ThemeProvider>
</Grid>
</Container>
</Underlay>
</OverlayContainer>
)
}
@ -164,8 +164,7 @@ const Underlay = styled.div<UnderlayProps>`
left: 0;
overflow: auto;
z-index: 200; // to be in front of the menu of the Publicodes doc
background: ${({ theme }) =>
theme.darkMode ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.5)'};
background: rgba(0, 0, 0, 0.5);
animation: ${appear} 0.2s;
display: flex;
${({ $offsetTop }) =>
@ -185,8 +184,7 @@ const PopoverContainer = styled.div<{ $offsetTop: number | null }>`
theme.darkMode
? theme.colors.extended.dark[600]
: theme.colors.extended.grey[100]};
box-shadow: ${({ theme }) =>
theme.darkMode ? theme.elevationsDarkMode[4] : theme.elevations[4]};
box-shadow: ${({ theme }) => theme.elevations[4]};
display: flex;
margin-bottom: 1rem;
flex-direction: column;
@ -210,7 +208,11 @@ const PopoverContainer = styled.div<{ $offsetTop: number | null }>`
export const CloseButtonContainer = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.colors.extended.grey[300]};
${({ theme }) =>
theme.darkMode &&
css`
color: ${theme.colors.extended.grey[100]};
`}
display: flex;
align-items: center;
height: ${({ theme }) => theme.spacings.xxl};
@ -225,19 +227,20 @@ export const CloseButton = styled.button`
color: ${({ theme }) =>
theme.darkMode
? theme.colors.bases.primary[400]
? theme.colors.bases.primary[100]
: theme.colors.bases.primary[700]};
font-family: ${({ theme }) => theme.fonts.main};
font-weight: 700;
font-size: ${({ theme }) => theme.baseFontSize};
line-height: 24px;
padding: ${({ theme }) => theme.spacings.sm};
path {
fill: ${({ theme }) => theme.colors.bases.primary[700]};
}
svg {
width: ${({ theme }) => theme.spacings.lg};
height: ${({ theme }) => theme.spacings.lg};
fill: ${({ theme }) =>
theme.darkMode
? theme.colors.extended.grey[100]
: theme.colors.bases.primary[700]};
}
:hover {
text-decoration: underline;

View File

@ -6,7 +6,6 @@ import styled, {
css,
} from 'styled-components'
import { DarkModeProvider } from '@/contexts/DarkModeContext'
import urssafTheme from '@/design-system/theme'
import { useDarkMode } from '@/hooks/useDarkMode'
@ -16,13 +15,12 @@ type SystemRootProps = {
const SystemRoot = ({ children }: SystemRootProps) => {
const userAgent = typeof navigator !== 'undefined' && navigator.userAgent
const [darkMode] = useDarkMode()
return (
<StyleSheetManager disableCSSOMInjection={isbot(userAgent)}>
<ThemeProvider theme={urssafTheme}>
<DarkModeProvider>
<Background>{children}</Background>
</DarkModeProvider>
<ThemeProvider theme={{ ...urssafTheme, darkMode }}>
<Background>{children}</Background>
</ThemeProvider>
</StyleSheetManager>
)

View File

@ -12,7 +12,8 @@ export const U = styled.u`
text-decoration: underline;
`
export const Code = styled.code`
background-color: #eee;
background-color: ${({ theme }) =>
theme.darkMode ? theme.colors.extended.grey[600] : '#eee'};
color: inherit;
padding: 0.25rem;
border-radius: 0.25rem;

View File

@ -14,7 +14,7 @@ export const StyledLinkHover = css`
text-decoration: underline;
color: ${({ theme }) =>
theme.darkMode
? theme.colors.bases.primary[100]
? theme.colors.bases.primary[300]
: theme.colors.bases.primary[800]};
`

View File

@ -4,7 +4,7 @@ export const baseParagraphStyle = css`
font-family: ${({ theme }) => theme.fonts.main};
font-weight: normal;
color: ${({ theme }) => theme.colors.extended.grey[800]};
background-color: inherit;
background-color: transparent;
@media not print {
${({ theme }) =>

View File

@ -12,7 +12,7 @@ export default function IframeFooter() {
>
<FeedbackButton isEmbedded />
<Spacing xl />
<Privacy />
<Privacy noUnderline={false} />
<Spacing lg />
</div>
</>

View File

@ -60,7 +60,7 @@ export default function Landing() {
</PageHeader>
</Container>
<Container
darkMode
forceTheme="dark"
backgroundColor={(theme) => theme.colors.bases.primary[600]}
>
<SearchOrCreate />

View File

@ -2,7 +2,6 @@ import { useCallback, useEffect } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { generatePath, useNavigate } from 'react-router-dom'
import { ThemeProvider } from 'styled-components'
import { resetCompany } from '@/actions/companyActions'
import {
@ -12,6 +11,7 @@ import {
import { CompanyDetails } from '@/components/company/Details'
import { CompanySearchField } from '@/components/company/SearchField'
import { useEngine } from '@/components/utils/EngineContext'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import AnswerGroup from '@/design-system/answer-group'
import { Button } from '@/design-system/buttons'
import { Emoji } from '@/design-system/emoji'
@ -36,7 +36,7 @@ export default function SearchOrCreate() {
const { t } = useTranslation()
return (
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: true })}>
<ForceThemeProvider forceTheme="dark">
<Grid container spacing={3}>
<Grid item xl={8} lg={10} md={12}>
{companySIREN ? (
@ -79,7 +79,10 @@ export default function SearchOrCreate() {
<H3 as="h2">
<Trans>Rechercher votre entreprise</Trans>{' '}
</H3>
<CompanySearchField onSubmit={handleCompanySubmit} />
<CompanySearchField
onSubmit={handleCompanySubmit}
forceTheme="dark"
/>
<Spacing md />
<Button
@ -104,7 +107,7 @@ export default function SearchOrCreate() {
)}
</Grid>
</Grid>
</ThemeProvider>
</ForceThemeProvider>
)
}

View File

@ -1,7 +1,7 @@
import { Trans, useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { H1 } from '@/design-system/typography/heading'
import { H1, H3 } from '@/design-system/typography/heading'
import { Link } from '@/design-system/typography/link'
import { Li, Ul } from '@/design-system/typography/list'
import { useSitePaths } from '@/sitePaths'
@ -29,83 +29,83 @@ export default function Plan() {
<StyledUl>
<Li>
<h2>
<H3 as="h2">
<Link to={absoluteSitePaths.index}>
<Trans>Page d'accueil</Trans>
</Link>
</h2>
</H3>
</Li>
<Li>
<h2>
<H3 as="h2">
<HeaderLink to={absoluteSitePaths.créer.index}>
<Trans>Créer une entreprise</Trans>
</HeaderLink>
</h2>
</H3>
<Ul>
<Li>
<h3>
<H3 as="h2">
<Link to={absoluteSitePaths.créer.après}>
<Trans>Après la création</Trans>
</Link>
</h3>
</H3>
</Li>
<Li>
<h3>
<H3 as="h2">
<Link to={absoluteSitePaths.créer.guideStatut.index}>
<Trans>Choix du statut juridique</Trans>
</Link>
</h3>
</H3>
</Li>
</Ul>
</Li>
<Li>
<h2>
<H3 as="h2">
<HeaderLink to={absoluteSitePaths.gérer.index}>
<Trans>Gérer mon activité</Trans>
</HeaderLink>
</h2>
</H3>
<Ul>
<Li>
<h3>
<H3>
<Link to={absoluteSitePaths.gérer.embaucher}>
<Trans>Embaucher</Trans>
</Link>
</h3>
</H3>
</Li>
<Li>
<h3>
<H3>
<Link to={absoluteSitePaths.gérer.sécuritéSociale}>
<Trans>Protection sociale</Trans>
</Link>
</h3>
</H3>
</Li>
<Li>
<h3>
<H3>
<Link to={absoluteSitePaths.gérer.déclarationIndépendant.index}>
<Trans>
Assistant à la détermination des charges sociales
déductibles
</Trans>
</Link>
</h3>
</H3>
</Li>
<Li>
<h3>
<H3>
<Link to={absoluteSitePaths.gérer.formulaireMobilité}>
<Trans>Demande de mobilité internationale</Trans>
</Link>
</h3>
</H3>
</Li>
</Ul>
</Li>
<Li>
<h2>
<H3 as="h2">
<HeaderLink to={absoluteSitePaths.simulateurs.index}>
<Trans>Simulateurs disponibles</Trans>
</HeaderLink>
</h2>
</H3>
<Ul>
{Object.entries(absoluteSitePaths.simulateurs)
@ -118,7 +118,7 @@ export default function Plan() {
.map(([simulateurKey, simulateurPath]: [string, string]) => {
return (
<Li key={`list-item-${simulateurKey}`}>
<h3>
<H3>
<Link to={simulateurPath}>
{
metadata[
@ -127,19 +127,19 @@ export default function Plan() {
].title
}
</Link>
</h3>
</H3>
</Li>
)
})}
<Li key="list-item-comparaison">
<h3>
<H3>
<Link to={absoluteSitePaths.simulateurs.comparaison}>
<Trans>Assistant au choix du statut juridique</Trans>
</Link>
</h3>
</H3>
</Li>
<Li key="list-item-economie-collaborative">
<h3>
<H3>
<Link
to={absoluteSitePaths.simulateurs.économieCollaborative.index}
>
@ -148,86 +148,86 @@ export default function Plan() {
ligne
</Trans>
</Link>
</h3>
</H3>
</Li>
</Ul>
</Li>
<Li>
<h2>
<H3 as="h2">
<Link to={absoluteSitePaths.nouveautés}>
<Trans>Nouveautés</Trans>
</Link>
</h2>
</H3>
</Li>
<Li>
<h2>
<H3 as="h2">
<Link to={absoluteSitePaths.budget}>
<Trans>Budget</Trans>
</Link>
</h2>
</H3>
</Li>
<Li>
<h2>
<H3 as="h2">
<Link to={absoluteSitePaths.accessibilité}>
<Trans>Accessibilité</Trans>
</Link>
</h2>
</H3>
</Li>
<Li>
<h2>
<H3 as="h2">
<Link to={absoluteSitePaths.stats}>
<Trans>Statistiques</Trans>
</Link>
</h2>
</H3>
</Li>
<Li>
<h2>
<H3 as="h2">
<HeaderLink to={absoluteSitePaths.développeur.index}>
<Trans>Outils pour les développeurs</Trans>
</HeaderLink>
</h2>
</H3>
<Ul>
<Li key="list-item-développeur-api">
<h3>
<H3>
<Link to={absoluteSitePaths.développeur.api}>
<Trans>API REST de simulation</Trans>
</Link>
</h3>
</H3>
</Li>
<Li key="list-item-développeur-iframe">
<h3>
<H3>
<Link to={absoluteSitePaths.développeur.iframe}>
<Trans>Intégrer le module Web</Trans>
</Link>
</h3>
</H3>
</Li>
<Li key="list-item-développeur-library">
<h3>
<H3>
<Link to={absoluteSitePaths.développeur.library}>
<Trans>
Utiliser les calculs des simulateurs dans votre application
</Trans>
</Link>
</h3>
</H3>
</Li>
<Li key="list-item-développeur-spreadsheet">
<h3>
<H3>
<Link to={absoluteSitePaths.développeur.spreadsheet}>
<Trans>Utiliser avec un tableur</Trans>
</Link>
</h3>
</H3>
</Li>
</Ul>
</Li>
<Li>
<h2>
<H3 as="h2">
<Link to={absoluteSitePaths.documentation.index}>
<Trans>Documentation</Trans>
</Link>
</h2>
</H3>
</Li>
</StyledUl>
</>

View File

@ -18,6 +18,7 @@ const Info = styled(Body)`
padding: 1rem;
border: 2px solid ${({ theme }) => theme.colors.extended.info['300']};
border-radius: 0.35rem;
color: ${({ theme }) => theme.colors.bases.tertiary[700]};
`
export const FormulaireS2 = ({

View File

@ -82,7 +82,8 @@ export const Thead = styled.thead`
export const Tbody = styled.tbody`
${Tr}:nth-child(odd) {
background: ${({ theme }) => theme.colors.extended.grey[200]};
background: ${({ theme }) =>
theme.darkMode ? 'transparent' : theme.colors.extended.grey[200]};
}
`

View File

@ -1,8 +1,6 @@
import { Trans, useTranslation } from 'react-i18next'
import { ThemeProvider } from 'styled-components'
import PageHeader from '@/components/PageHeader'
import DefaultHelmet from '@/components/utils/DefaultHelmet'
import { useIsEmbedded } from '@/components/utils/useIsEmbedded'
import { Chip } from '@/design-system'
import InfoBulle from '@/design-system/InfoBulle'
@ -228,7 +226,7 @@ export function SimulateurCard({
const { t } = useTranslation()
return (
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: false })}>
<>
{small ? (
<Grid item xs={12} sm={6} md={6} lg={4} {...props}>
<SmallCard
@ -274,6 +272,6 @@ export function SimulateurCard({
</Card>
</Grid>
)}
</ThemeProvider>
</>
)
}

View File

@ -1,5 +1,6 @@
import { utils } from 'publicodes'
import { Trans, useTranslation } from 'react-i18next'
import styled from 'styled-components'
import Value, { Condition } from '@/components/EngineValue'
import { FromTop } from '@/components/ui/animate'
@ -21,7 +22,7 @@ export default function ResultatsSimples() {
<Spacing lg />
<Container
darkMode
forceTheme="dark"
backgroundColor={(theme) => theme.colors.bases.primary[600]}
>
{' '}
@ -126,7 +127,7 @@ export default function ResultatsSimples() {
<Article
to={`/documentation/${utils.encodeRuleName(dottedName)}`}
ctaLabel={
<Intro>
<StyledIntro>
<Value
expression={r.dottedName}
displayedUnit="€"
@ -134,7 +135,7 @@ export default function ResultatsSimples() {
precision={0}
linkToRule={false}
/>
</Intro>
</StyledIntro>
}
title={
<>
@ -156,3 +157,9 @@ export default function ResultatsSimples() {
</>
)
}
const StyledIntro = styled(Intro)`
& a {
color: ${({ theme }) => theme.colors.extended.grey[100]};
}
`

View File

@ -112,7 +112,7 @@ export function DéclarationRevenuSection({ progress }: { progress: number }) {
return (
<Container
darkMode={!déclarationRevenusManuel}
forceTheme={!déclarationRevenusManuel ? 'dark' : undefined}
backgroundColor={
!déclarationRevenusManuel
? (theme) => theme.colors.bases.primary[600]

View File

@ -36,7 +36,7 @@ export default function Cotisations() {
<Spacing lg />
<WhenAlreadyDefined dottedName="DRI . cotisations . appelées en 2021">
<Container
darkMode
forceTheme="dark"
backgroundColor={(theme) => theme.colors.bases.primary[600]}
>
<FromTop>

View File

@ -303,7 +303,7 @@ function ResultSection() {
return (
<FromTop>
<Container
darkMode
forceTheme="dark"
backgroundColor={(theme) => theme.colors.bases.primary[600]}
>
<H2>Vos déclarations fiscales</H2>

View File

@ -228,6 +228,7 @@ export default function EndBlock({ fields, missingValues }: EndBlockProps) {
})
}}
download="demande-mobilité-internationale.pdf"
id="button-download"
>
Télécharger le fichier
</Button>

View File

@ -15,7 +15,7 @@ export default function FieldsPDF({ fields }: FieldsPDFProps) {
return (
<>
{fields.map(
({ rawNode: { type, question, note, API }, title, dottedName }) => (
({ rawNode: { type, question, note }, title, dottedName }) => (
<View style={styles.field} key={dottedName} wrap={false}>
{type === 'groupe' ? (
<>

View File

@ -35,6 +35,7 @@ import { useEngine } from '@/components/utils/EngineContext'
import { ScrollToTop } from '@/components/utils/Scroll'
import { Markdown } from '@/components/utils/markdown'
import useSimulationConfig from '@/components/utils/useSimulationConfig'
import { ForceThemeProvider } from '@/contexts/DarkModeContext'
import { Message, Popover } from '@/design-system'
import { Button } from '@/design-system/buttons'
import { Container, Grid, Spacing } from '@/design-system/layout'
@ -270,14 +271,13 @@ function Home() {
<Spacing xl />
</PageHeader>
<Container
backgroundColor={(theme) => theme.colors.bases.primary[600]}
darkMode
>
<Container backgroundColor={(theme) => theme.colors.bases.primary[600]}>
<FromTop>
<FormsImage src={forms} alt="" />
<Spacing xs />
<H2>Simulateurs pour votre entreprise</H2>
<ForceThemeProvider forceTheme="dark">
<H2>Simulateurs pour votre entreprise</H2>
</ForceThemeProvider>
<Grid
container
spacing={3}