mirror of
https://github.com/suitenumerique/docs.git
synced 2026-09-22 09:35:08 +02:00
💄(frontend) update ui to fit design mockups
Update lightly the ui to match the new design mockups, to fit with what was proposed for the duplicate subdocs feature. It updates: - modal closing position - checkbox style - toast style - create a ButtonLink component, a wrapper above the ui-kit component to fit the Next.js routing system.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { Button } from '@gouvfr-lasuite/ui-components';
|
||||
import Link from 'next/link';
|
||||
import styled, { RuleSet } from 'styled-components';
|
||||
import { useRouter } from 'next/router';
|
||||
import { type ComponentProps } from 'react';
|
||||
import styled, { type RuleSet } from 'styled-components';
|
||||
|
||||
export interface LinkProps {
|
||||
$css?: string | RuleSet<object>;
|
||||
@@ -14,3 +17,35 @@ export const StyledLink = styled(Link)<LinkProps>`
|
||||
display: flex;
|
||||
${({ $css }) => $css && (typeof $css === 'string' ? `${$css};` : $css)}
|
||||
`;
|
||||
|
||||
type ButtonLinkProps = ComponentProps<typeof Button> & {
|
||||
href: string;
|
||||
};
|
||||
|
||||
export const ButtonLink = ({
|
||||
children,
|
||||
onClick,
|
||||
ref,
|
||||
...props
|
||||
}: ButtonLinkProps) => {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
onClick={(e) => {
|
||||
if (!e.ctrlKey && !e.metaKey && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
|
||||
if (props.href) {
|
||||
void router.push(props.href);
|
||||
}
|
||||
}
|
||||
onClick?.(e as React.MouseEvent<HTMLButtonElement, MouseEvent>);
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -57,6 +57,28 @@
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkbox
|
||||
*/
|
||||
.c__checkbox:focus-within {
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.c__checkbox .c__checkbox__wrapper:focus-within {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.c__checkbox__wrapper input:focus,
|
||||
.c__checkbox__wrapper input:checked:focus {
|
||||
box-shadow: unset;
|
||||
}
|
||||
|
||||
.c__checkbox input:focus-visible {
|
||||
outline: 2px solid var(--c--globals--colors--brand-400);
|
||||
outline-offset: var(--c--globals--spacings--4xs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal
|
||||
*/
|
||||
@@ -104,6 +126,10 @@
|
||||
/**
|
||||
* Toast
|
||||
*/
|
||||
.c__toast {
|
||||
max-width: min(100%, 100vw);
|
||||
}
|
||||
|
||||
.c__toast__container {
|
||||
z-index: -1;
|
||||
}
|
||||
@@ -111,3 +137,8 @@
|
||||
.c__toast__container:has(.c__toast) {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.c__toast__content__children {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
|
||||
>
|
||||
{t('Export')}
|
||||
</Text>
|
||||
<Box $position="absolute" $css="top: 4px; right: 4px;">
|
||||
<Box $position="absolute" $css="top: 8px; right: 8px;">
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the download modal')}
|
||||
onClick={() => onClose()}
|
||||
|
||||
@@ -202,6 +202,11 @@ const DocTitleInput = ({ doc, onTitleUpdate }: DocTitleProps) => {
|
||||
$align="center"
|
||||
$gap="4px"
|
||||
$minHeight="40px"
|
||||
$css={css`
|
||||
&:focus-within {
|
||||
outline: none;
|
||||
}
|
||||
`}
|
||||
>
|
||||
{!isTopRoot && <DocTitleEmojiPicker doc={doc} />}
|
||||
{/**
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ export const DocMoveModal = ({
|
||||
<Text as="h2" $margin="0" $size="s" $align="flex-start">
|
||||
{t('Choose a new parent doc')}
|
||||
</Text>
|
||||
<Box $position="absolute" $css="top: 4px; right: 4px;">
|
||||
<Box $position="absolute" $css="top: 8px; right: 8px;">
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the move modal')}
|
||||
onClick={onClose}
|
||||
|
||||
+2
-10
@@ -11,7 +11,7 @@ import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Box, ButtonCloseModal, Text, TextErrors } from '@/components';
|
||||
import { useConfig } from '@/core';
|
||||
import { KEY_LIST_DOC_TRASHBIN } from '@/docs/docs-grid';
|
||||
import { useKeyboardAction, useToast } from '@/hooks';
|
||||
import { useToast } from '@/hooks';
|
||||
|
||||
import { KEY_DOC, KEY_LIST_FAVORITE_DOC } from '../api';
|
||||
import { KEY_LIST_DOC } from '../api/useDocs';
|
||||
@@ -72,15 +72,10 @@ export const ModalRemoveDoc = ({
|
||||
return () => cancelAnimationFrame(id);
|
||||
}, []);
|
||||
|
||||
const keyboardAction = useKeyboardAction();
|
||||
|
||||
const handleDelete = () => {
|
||||
removeDoc({ docId: doc.id });
|
||||
};
|
||||
|
||||
const handleCloseKeyDown = keyboardAction(onClose);
|
||||
const handleDeleteKeyDown = keyboardAction(handleDelete);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen
|
||||
@@ -97,7 +92,6 @@ export const ModalRemoveDoc = ({
|
||||
fullWidth
|
||||
autoFocus
|
||||
onClick={onClose}
|
||||
onKeyDown={handleCloseKeyDown}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
@@ -106,7 +100,6 @@ export const ModalRemoveDoc = ({
|
||||
color="error"
|
||||
fullWidth
|
||||
onClick={handleDelete}
|
||||
onKeyDown={handleDeleteKeyDown}
|
||||
>
|
||||
{t('Delete')}
|
||||
</Button>
|
||||
@@ -124,11 +117,10 @@ export const ModalRemoveDoc = ({
|
||||
>
|
||||
{t('Delete a doc')}
|
||||
</Text>
|
||||
<Box $position="absolute" $css="top: 4px; right: 4px;">
|
||||
<Box $position="absolute" $css="top: 8px; right: 8px;">
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the delete modal')}
|
||||
onClick={onClose}
|
||||
onKeyDown={handleCloseKeyDown}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
|
||||
+4
-9
@@ -8,7 +8,7 @@ import { useRouter } from 'next/router';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Text } from '@/components';
|
||||
import { ButtonLink, Text } from '@/components';
|
||||
import { useConfig } from '@/core/config/api/useConfig';
|
||||
import { useLeftPanelStore } from '@/features/left-panel/stores/useLeftPanelStore';
|
||||
import ArrowDownIcon from '@/icons/arrow-drop-down.svg';
|
||||
@@ -26,7 +26,6 @@ interface NewDocButtonProps {
|
||||
}
|
||||
|
||||
export const NewDocButton = ({ onClose }: NewDocButtonProps) => {
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
const { currentDoc } = useDocStore();
|
||||
const { data: config } = useConfig();
|
||||
@@ -34,15 +33,11 @@ export const NewDocButton = ({ onClose }: NewDocButtonProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
<ButtonLink
|
||||
href="/docs/new"
|
||||
data-testid="new-doc-button"
|
||||
color="brand"
|
||||
onClick={(e) => {
|
||||
if (!e.ctrlKey && !e.metaKey && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
void router.push('/docs/new');
|
||||
}
|
||||
onClick={() => {
|
||||
onClose?.();
|
||||
}}
|
||||
icon={<PlusIcon aria-hidden="true" width={24} height={24} />}
|
||||
@@ -55,7 +50,7 @@ export const NewDocButton = ({ onClose }: NewDocButtonProps) => {
|
||||
<Text $withThemeInherited $size="md" $weight="500">
|
||||
{t('New')}
|
||||
</Text>
|
||||
</Button>
|
||||
</ButtonLink>
|
||||
{isDropdownEnabled && <DropdownArrow />}
|
||||
</>
|
||||
);
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ const DocSearchModalGlobal = ({
|
||||
'Search documents by name, navigate using arrows, and select a result with Enter.',
|
||||
)}
|
||||
</Text>
|
||||
<Box $position="absolute" $css="top: 4px; right: 4px;">
|
||||
<Box $position="absolute" $css="top: 8px; right: 8px;">
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the search modal')}
|
||||
onClick={modalProps.onClose}
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ export const ConfirmationLeaveModal = ({
|
||||
>
|
||||
{t('Leave a doc')}
|
||||
</Text>
|
||||
<Box $position="absolute" $css="top: 4px; right: 4px;">
|
||||
<Box $position="absolute" $css="top: 8px; right: 8px;">
|
||||
<ButtonCloseModal
|
||||
aria-label={t('Close the leave modal')}
|
||||
onClick={onClose}
|
||||
|
||||
Reference in New Issue
Block a user