✨(app-impress) add footer
Add footer to the impress app.
This commit is contained in:
42
src/frontend/apps/e2e/__tests__/app-impress/footer.spec.ts
Normal file
42
src/frontend/apps/e2e/__tests__/app-impress/footer.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { keyCloakSignIn } from './common';
|
||||
|
||||
test.beforeEach(async ({ page, browserName }) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
});
|
||||
|
||||
test.describe('Footer', () => {
|
||||
test('checks all the elements are visible', async ({ page }) => {
|
||||
const footer = page.locator('footer').first();
|
||||
|
||||
await expect(footer.getByAltText('Marianne Logo')).toBeVisible();
|
||||
|
||||
await expect(
|
||||
footer.getByAltText('Freedom Equality Fraternity Logo'),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
footer.getByRole('link', { name: 'legifrance.gouv.fr' }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
footer.getByRole('link', { name: 'info.gouv.fr' }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
footer.getByRole('link', { name: 'service-public.fr' }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
footer.getByRole('link', { name: 'data.gouv.fr' }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
footer.getByText(
|
||||
'Unless otherwise stated, all content on this site is under licence',
|
||||
),
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -33,6 +33,7 @@ export interface BoxProps {
|
||||
$radius?: CSSProperties['borderRadius'];
|
||||
$transition?: CSSProperties['transition'];
|
||||
$width?: CSSProperties['width'];
|
||||
$zIndex?: CSSProperties['zIndex'];
|
||||
}
|
||||
|
||||
export type BoxType = ComponentPropsWithRef<typeof Box>;
|
||||
@@ -61,6 +62,7 @@ export const Box = styled('div')<BoxProps>`
|
||||
${({ $transition }) => $transition && `transition: ${$transition};`}
|
||||
${({ $width }) => $width && `width: ${$width};`}
|
||||
${({ $css }) => $css && `${$css};`}
|
||||
${({ $zIndex }) => $zIndex && `z-index: ${$zIndex};`}
|
||||
${({ $effect }) => {
|
||||
let effect;
|
||||
switch ($effect) {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import Link from 'next/link';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledLink = styled(Link)`
|
||||
export interface LinkProps {
|
||||
$css?: string;
|
||||
}
|
||||
|
||||
export const StyledLink = styled(Link)<LinkProps>`
|
||||
text-decoration: none;
|
||||
color: #ffffff33;
|
||||
&[aria-current='page'] {
|
||||
color: #ffffff;
|
||||
}
|
||||
display: flex;
|
||||
${({ $css }) => $css && `${$css};`}
|
||||
`;
|
||||
|
||||
119
src/frontend/apps/impress/src/features/footer/Footer.tsx
Normal file
119
src/frontend/apps/impress/src/features/footer/Footer.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
import Image from 'next/image';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { default as IconGouv } from '@/assets/icons/icon-gouv.svg?url';
|
||||
import { default as IconMarianne } from '@/assets/icons/icon-marianne.svg?url';
|
||||
import { Box, StyledLink, Text } from '@/components/';
|
||||
|
||||
import IconLink from './assets/external-link.svg';
|
||||
|
||||
const BlueStripe = styled.div`
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
background: var(--c--theme--colors--primary-600);
|
||||
top: 0;
|
||||
`;
|
||||
|
||||
export const Footer = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box $position="relative" as="footer">
|
||||
<BlueStripe />
|
||||
<Box $padding={{ top: 'large', horizontal: 'big', bottom: 'small' }}>
|
||||
<Box>
|
||||
<Image
|
||||
priority
|
||||
src={IconMarianne}
|
||||
alt={t('Marianne Logo')}
|
||||
width={70}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
$direction="row"
|
||||
$gap="1.5rem"
|
||||
$align="center"
|
||||
$justify="space-between"
|
||||
>
|
||||
<Box>
|
||||
<Box $align="center" $gap="6rem" $direction="row">
|
||||
<Image
|
||||
width={100}
|
||||
priority
|
||||
src={IconGouv}
|
||||
alt={t('Freedom Equality Fraternity Logo')}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
$direction="row"
|
||||
$justify="flex-end"
|
||||
$css={`
|
||||
column-gap: 1.5rem;
|
||||
row-gap: .5rem;
|
||||
flex-wrap: wrap;
|
||||
`}
|
||||
>
|
||||
{[
|
||||
{
|
||||
label: 'legifrance.gouv.fr',
|
||||
href: 'https://legifrance.gouv.fr/',
|
||||
},
|
||||
{
|
||||
label: 'info.gouv.fr',
|
||||
href: 'https://info.gouv.fr/',
|
||||
},
|
||||
{
|
||||
label: 'service-public.fr',
|
||||
href: 'https://service-public.fr/',
|
||||
},
|
||||
{
|
||||
label: 'data.gouv.fr',
|
||||
href: 'https://data.gouv.fr/',
|
||||
},
|
||||
].map(({ label, href }) => (
|
||||
<StyledLink
|
||||
key={label}
|
||||
href={href}
|
||||
target="__blank"
|
||||
$css={`
|
||||
gap:0.2rem;
|
||||
transition: box-shadow 0.3s;
|
||||
&:hover {
|
||||
box-shadow: 0px 2px 0 0 var(--c--theme--colors--greyscale-text);
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Text $weight="bold">{label}</Text>
|
||||
<IconLink width={18} />
|
||||
</StyledLink>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
<Text
|
||||
as="p"
|
||||
$size="m"
|
||||
$margin={{ top: 'big' }}
|
||||
$variation="600"
|
||||
$display="inline"
|
||||
>
|
||||
{t('Unless otherwise stated, all content on this site is under')}{' '}
|
||||
<StyledLink
|
||||
href="https://github.com/etalab/licence-ouverte/blob/master/LO.md"
|
||||
target="__blank"
|
||||
$css={`
|
||||
display:inline-flex;
|
||||
box-shadow: 0px 1px 0 0 var(--c--theme--colors--greyscale-text);
|
||||
`}
|
||||
>
|
||||
<Text $variation="600">licence etalab-2.0</Text>
|
||||
<IconLink width={18} />
|
||||
</StyledLink>
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6Zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 219 B |
@@ -3,13 +3,13 @@ import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { default as IconGouv } from '@/assets/icons/icon-gouv.svg?url';
|
||||
import { default as IconMarianne } from '@/assets/icons/icon-marianne.svg?url';
|
||||
import { Box, Text } from '@/components/';
|
||||
|
||||
import { LanguagePicker } from '../language/';
|
||||
|
||||
import { default as IconGouv } from './assets/icon-gouv.svg?url';
|
||||
import { default as IconImpress } from './assets/icon-impress.svg?url';
|
||||
import { default as IconMarianne } from './assets/icon-marianne.svg?url';
|
||||
import IconMyAccount from './assets/icon-my-account.png';
|
||||
|
||||
export const HEADER_HEIGHT = '100px';
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import { Box } from '@/components';
|
||||
import { Footer } from '@/features/footer/Footer';
|
||||
import { HEADER_HEIGHT, Header } from '@/features/header';
|
||||
|
||||
export function MainLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Box $height="100vh" $css="overflow:hidden;">
|
||||
<Header />
|
||||
<Box $css="flex: 1;" $direction="row">
|
||||
<Box as="main" $height={`calc(100vh - ${HEADER_HEIGHT})`} $width="100%">
|
||||
{children}
|
||||
<Box>
|
||||
<Box $height="100vh">
|
||||
<Header />
|
||||
<Box $css="flex: 1;" $direction="row">
|
||||
<Box
|
||||
as="main"
|
||||
$height={`calc(100vh - ${HEADER_HEIGHT})`}
|
||||
$width="100%"
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Footer />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,21 +9,21 @@ body {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
main ::-webkit-scrollbar {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
main ::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
main ::-webkit-scrollbar-thumb {
|
||||
background-color: #d6dee1;
|
||||
border-radius: 20px;
|
||||
border: 6px solid transparent;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
main ::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #a8bbbf;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user