📱(frontend) refine ui to display well on mobile

Rework thread panel, attachment and thread-messsage header
This commit is contained in:
jbpenrath
2025-05-28 19:08:07 +02:00
committed by Jean-Baptiste PENRATH
parent e4375c6d7a
commit 9f37feec4c
9 changed files with 54 additions and 39 deletions
@@ -1,5 +1,6 @@
@use "sass:map";
@use "../../../../styles/cunningham-tokens" as *;
@use "../../../../styles/utils" as *;
.message-form {
display: flex;
@@ -77,6 +78,17 @@
align-items: center;
}
.attachment-uploader__input > .c__button {
white-space: nowrap;
}
@media screen and (max-width: breakpoint(xs)) {
.attachment-uploader__input {
flex-direction: column;
align-items: flex-start;
}
}
.attachment-uploader__input__helper-text {
font-size: 0.875rem;
color: var(--c--theme--colors--greyscale-600);
@@ -92,6 +104,6 @@
.attachment-bucket__list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(min(350px, 100%), 1fr));
gap: 10px;
}
@@ -8,7 +8,6 @@ import {
PanelResizeHandle,
} from "react-resizable-panels";
import { DropdownMenuOption,LeftPanel } from "@gouvfr-lasuite/ui-kit";
import { RightPanel } from "../right-panel";
import { useControllableState } from "../hooks/useControllableState";
export type MainLayoutProps = {
icon?: React.ReactNode;
@@ -35,9 +34,7 @@ export const AppLayout = ({
children,
hideLeftPanelOnDesktop = false,
leftPanelContent,
rightPanelContent,
enableResize = false,
rightPanelIsOpen = false,
...props
}: PropsWithChildren<MainLayoutProps>) => {
const [isLeftPanelOpen, setIsLeftPanelOpen] = useControllableState(
@@ -125,16 +122,8 @@ export const AppLayout = ({
)}
</>
)}
<Panel order={1}>
<div className="c__main-layout__content__center">
<div className="c__main-layout__content__center__children">
{children}
</div>
<RightPanel isOpen={rightPanelIsOpen}>
{rightPanelContent}
</RightPanel>
</div>
<Panel order={1} style={{ width: "100%" }}>
{children}
</Panel>
</PanelGroup>
</div>
@@ -71,6 +71,7 @@
gap: var(--c--theme--spacings--2xs);
line-height: 1;
min-width: 0;
max-width: 100%;
}
.thread-item__senders,
@@ -80,6 +81,7 @@
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
display: inline-block;
}
.thread-item__senders-container {
@@ -131,4 +133,4 @@
.thread-item__date {
width: 76px;
text-align: right;
}
}
@@ -1,3 +1,5 @@
@use "../../../../../../styles/utils" as *;
.thread-message {
border-radius: 8px;
background-color: white;
@@ -16,7 +18,7 @@
}
.thread-message__header-column--right {
gap: var(--c--theme--spacings--);
gap: var(--c--theme--spacings--xs);
}
.thread-message__header-actions {
@@ -31,6 +33,17 @@
justify-content: space-between;
}
@media screen and (max-width: breakpoint(tablet)) {
.thread-message__header-rows {
flex-direction: column-reverse;
}
.thread-message__header-column--right {
justify-content: space-between;
}
}
.thread-message__header-rows > div > * {
margin-block: 0;
}
@@ -44,6 +57,10 @@
color: var(--c--theme--colors--greyscale-500);
}
.thread-message__date {
text-align: right;
}
.thread-message__correspondents {
display: grid;
grid-template-columns: max-content 1fr;
@@ -57,13 +74,13 @@
.thread-message__correspondents dd {
margin: 0;
word-break: break-word;
}
.thread-message__body {
width: 100%;
height: auto;
border: none;
overflow: auto;
}
.thread-message__footer {
@@ -61,11 +61,6 @@ export const ThreadMessage = forwardRef<HTMLElement, ThreadMessageProps>(
</div>
<div className="thread-message__header-column thread-message__header-column--right flex-row flex-align-center">
<div className="thread-message__metadata">
{
message.attachments.length > 0 && (
<span className="material-icons">attachment</span>
)
}
{message.sent_at && (
<p className="thread-message__date">{
new Date(message.sent_at).toLocaleString(i18n.language, {
@@ -77,12 +72,17 @@ export const ThreadMessage = forwardRef<HTMLElement, ThreadMessageProps>(
})
}</p>
)}
</div>
{message.is_draft && (
<Badge>
{t('thread_message.draft')}
</Badge>
)}
{
message.attachments.length > 0 && (
<span className="material-icons">attachment</span>
)
}
</div>
<div className="thread-message__header-actions">
{hasSeveralRecipients && (
<Tooltip content={t('actions.reply_all')}>
@@ -50,14 +50,14 @@ const MessageBody = ({ rawHtmlBody, rawTextBody }: MessageBodyProps) => {
<meta http-equiv="Content-Security-Policy" content="${CSP}">
<base target="_blank">
<style>
body {
html, body {
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
line-height: 1.5;
color: #24292e;
overflow-y: hidden;
padding-bottom: 1rem;
}
img { max-width: 100%; height: auto; }
a { color: #0366d6; text-decoration: none; }
@@ -89,7 +89,7 @@ const MessageBody = ({ rawHtmlBody, rawTextBody }: MessageBodyProps) => {
const resizeIframe = useCallback(() => {
if (iframeRef.current?.contentWindow) {
const height = iframeRef.current.contentWindow.document.body.getBoundingClientRect().height;
const height = iframeRef.current.contentWindow.document.documentElement.getBoundingClientRect().height;
iframeRef.current.style.height = `${height}px`;
}
}, [iframeRef]);
@@ -110,4 +110,4 @@ const MessageBody = ({ rawHtmlBody, rawTextBody }: MessageBodyProps) => {
)
}
export default MessageBody;
export default MessageBody;
+3 -1
View File
@@ -64,7 +64,9 @@ export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
return (
<>
<Head>
<title>{t("app_title")}</title>
<title>{t("app_title")}</title>
<meta name="description" content={t("app_description")} />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link rel="icon" href="/images/favicon-light.svg" type="image/svg+xml" />
<link
rel="icon"
-7
View File
@@ -1,5 +1,4 @@
import { GlobalLayout } from "@/features/layouts/components/global/global-layout";
import Head from "next/head";
import { useTranslation } from "react-i18next";
import { Hero, HomeGutter, Footer, ProConnectButton } from "@gouvfr-lasuite/ui-kit";
import { login, useAuth } from "@/features/auth";
@@ -20,12 +19,6 @@ export default function HomePage() {
return (
<div className="app__home">
<Head>
<title>{t("app_title")}</title>
<meta name="description" content={t("app_description")} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.png" />
</Head>
<HomeGutter>
<Hero
logo={<img src="/images/app-icon.svg" alt="Messages Logo" width={64} />}
+2 -2
View File
@@ -6,10 +6,10 @@
.thread-list-panel {
flex: 1;
min-width: 280px;
min-width: min(280px, 100vw);
}
.thread__resize-handle {
background: var(--c--theme--colors--greyscale-200);
width: 1px;
}
}