feat(ui): extend minimal doctor design across all screens
CI / ruff · pytest (pull_request) Successful in 2m16s
CI / ruff · pytest (pull_request) Successful in 2m16s
Refs #85
This commit is contained in:
@@ -3,13 +3,14 @@ import { Link, NavLink } from "react-router-dom";
|
||||
|
||||
import { ru } from "../content/ru";
|
||||
import { useDialog } from "../dialog/DialogContext";
|
||||
import { useSession } from "../session/SessionContext";
|
||||
import { HotlineCard, useHelp } from "./HelpSheet";
|
||||
import { Icon, LogoMark, type IconName } from "./Icon";
|
||||
|
||||
/*
|
||||
* Layout from docs/mock (series 2).
|
||||
* Shared patient workspace, following the approved doctor dashboard.
|
||||
* phone: content → «Экстренная помощь» block → bottom tab bar (signed in)
|
||||
* desktop: navy sidebar | content | right rail (optional `aside` + emergency panel)
|
||||
* desktop: white sidebar | workspace header | content + emergency panel
|
||||
* bare: one centred column on every width (questionnaires)
|
||||
*/
|
||||
|
||||
@@ -87,6 +88,10 @@ function Sidebar({ signedIn }: { signedIn: boolean }) {
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
<div className="sidebar__note">
|
||||
<strong>{ru.product.supportTitle}</strong>
|
||||
<span>{ru.product.supportText}</span>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
@@ -122,6 +127,24 @@ function Rail({ aside }: { aside?: ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
function WorkspaceHeader({ signedIn, bare = false }: { signedIn: boolean; bare?: boolean }) {
|
||||
const { session } = useSession();
|
||||
return (
|
||||
<header className={`workspace${bare ? " workspace--bare" : ""}`}>
|
||||
<div className="workspace__brand">
|
||||
<LogoMark size={30} />
|
||||
<span>{bare ? ru.product.name : signedIn ? ru.product.workspace : ru.nav.signIn}</span>
|
||||
</div>
|
||||
{signedIn && !bare ? (
|
||||
<Link className="workspace__profile" to="/profile">
|
||||
<span className="avatar"><Icon name="user" size={18} /></span>
|
||||
<span>{session?.displayName || ru.nav.profile}</span>
|
||||
</Link>
|
||||
) : <span className="workspace__tag">{ru.product.tagline}</span>}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export function AppShell({
|
||||
children,
|
||||
signedIn = true,
|
||||
@@ -144,6 +167,7 @@ export function AppShell({
|
||||
return (
|
||||
<div className="app app--bare">
|
||||
<div className="app__main">
|
||||
<WorkspaceHeader signedIn={signedIn} bare />
|
||||
<main className="screen" id="main">
|
||||
{children}
|
||||
{sos && <EmergencyBlock />}
|
||||
@@ -155,6 +179,7 @@ export function AppShell({
|
||||
<div className={`app${signedIn && !focus ? " app--tabs" : ""}`}>
|
||||
<Sidebar signedIn={signedIn} />
|
||||
<div className="app__main">
|
||||
<WorkspaceHeader signedIn={signedIn} />
|
||||
<main className="screen" id="main">
|
||||
{children}
|
||||
{sos && <EmergencyBlock />}
|
||||
|
||||
@@ -163,8 +163,8 @@ export function Icon({ name, size = 22, label }: { name: IconName; size?: number
|
||||
export function LogoMark({ size = 32 }: { size?: number }) {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" aria-hidden="true" focusable="false">
|
||||
<rect width="32" height="32" rx="9" fill="var(--c-teal)" />
|
||||
<path d="M13 7h6v6h6v6h-6v6h-6v-6H7v-6h6z" fill="#fff" />
|
||||
<rect width="32" height="32" rx="9" fill="var(--c-primary)" />
|
||||
<path d="M16 8v16M8 16h16" stroke="#fff" strokeWidth="2" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ export const ru = {
|
||||
product: {
|
||||
name: "Сопровождение пациента",
|
||||
tagline: "между визитами к врачу",
|
||||
workspace: "Личный кабинет",
|
||||
supportTitle: "Рядом между визитами",
|
||||
supportText: "Наблюдение за самочувствием и поддержка назначенного лечения.",
|
||||
},
|
||||
nav: {
|
||||
today: "Сегодня",
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import "@fontsource/golos-text/400.css";
|
||||
import "@fontsource/golos-text/500.css";
|
||||
import "@fontsource/golos-text/600.css";
|
||||
import "@fontsource/golos-text/700.css";
|
||||
import "./theme/tokens.css";
|
||||
import "./theme/global.css";
|
||||
|
||||
|
||||
+387
-106
File diff suppressed because it is too large
Load Diff
+33
-33
@@ -1,45 +1,45 @@
|
||||
/*
|
||||
* Design tokens — single source of colours, type and spacing (docs/mock, series 2).
|
||||
* Shared visual language with dashboard/theme.py and the approved doctor workspace.
|
||||
* Capacitor wraps this same bundle; a React Native port maps these 1:1 to a theme object.
|
||||
*/
|
||||
:root {
|
||||
/* Ink & surfaces */
|
||||
--c-navy: #0f2747; /* primary buttons, headings, desktop sidebar */
|
||||
--c-navy-hover: #0a1d37;
|
||||
--c-navy-soft: #e8eef6;
|
||||
--c-text: #13294b;
|
||||
--c-text-2: #4d5d73;
|
||||
--c-text-3: #7a889b;
|
||||
--c-page: #ffffff;
|
||||
--c-page-desk: #f4f7fb; /* desktop canvas behind white panels */
|
||||
--c-primary: #285e4e; /* primary buttons and active navigation */
|
||||
--c-primary-hover: #204b3e;
|
||||
--c-primary-soft: #edf3ee;
|
||||
--c-text: #213b38;
|
||||
--c-text-2: #526660;
|
||||
--c-text-3: #63736f;
|
||||
--c-page: #f6f7f3;
|
||||
--c-page-desk: #f6f7f3; /* desktop canvas behind white panels */
|
||||
--c-surface: #ffffff;
|
||||
--c-tile: #f3f7fb; /* soft card fill */
|
||||
--c-border: #e2e9f1;
|
||||
--c-border-strong: #c9d4e1;
|
||||
--c-tile: #f4f6f2; /* soft card fill */
|
||||
--c-border: #e1e7e3;
|
||||
--c-border-strong: #b4c6ba;
|
||||
|
||||
/* Selection & positive: teal */
|
||||
--c-teal: #17a08f;
|
||||
--c-teal-strong: #0e7e71;
|
||||
--c-teal-soft: #e3f5f2;
|
||||
/* Selection & positive */
|
||||
--c-teal: #527f61;
|
||||
--c-teal-strong: #38634b;
|
||||
--c-teal-soft: #eef4ee;
|
||||
|
||||
/* Info: blue */
|
||||
--c-blue: #2f7fdb;
|
||||
--c-blue-soft: #eaf3fd;
|
||||
/* Informational surfaces */
|
||||
--c-blue: #38634b;
|
||||
--c-blue-soft: #edf3ee;
|
||||
|
||||
/* Help & crisis: red */
|
||||
--c-red: #e2383b;
|
||||
--c-red-strong: #c62b2e;
|
||||
--c-red-soft: #fdeded;
|
||||
--c-red-line: #f7d3d3;
|
||||
--c-red: #a83236;
|
||||
--c-red-strong: #a83236;
|
||||
--c-red-soft: #faeeee;
|
||||
--c-red-line: #e7cbcb;
|
||||
|
||||
/* Warning */
|
||||
--c-amber: #e69a12;
|
||||
--c-amber-soft: #fff4dd;
|
||||
--c-amber: #805714;
|
||||
--c-amber-soft: #fbf3e4;
|
||||
|
||||
--c-focus: #2f7fdb;
|
||||
--c-focus: #598d7a;
|
||||
|
||||
/* Type: Golos Text (OFL), bundled locally — works offline. */
|
||||
--font: "Golos Text", system-ui, -apple-system, "Segoe UI", sans-serif;
|
||||
/* Same offline system stack as the doctor workspace. */
|
||||
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
|
||||
--fs-12: 0.75rem;
|
||||
--fs-13: 0.8125rem;
|
||||
--fs-14: 0.875rem;
|
||||
@@ -63,14 +63,14 @@
|
||||
--s-12: 48px;
|
||||
|
||||
/* Radii: tiles > buttons > chips */
|
||||
--r-tile: 16px;
|
||||
--r-btn: 12px;
|
||||
--r-chip: 999px;
|
||||
--r-tile: 12px;
|
||||
--r-btn: 8px;
|
||||
--r-chip: 5px;
|
||||
|
||||
--tap: 52px;
|
||||
--nav-h: 64px;
|
||||
--sidebar-w: 232px;
|
||||
--rail-w: 300px;
|
||||
--sidebar-w: 228px;
|
||||
--rail-w: 264px;
|
||||
|
||||
--safe-top: env(safe-area-inset-top, 0px);
|
||||
--safe-bottom: env(safe-area-inset-bottom, 0px);
|
||||
|
||||
Reference in New Issue
Block a user