Task 19: Add responsive design for mobile and tablet
- DashboardLayout: Hide sidebar on <lg (1024px), responsive padding - Dashboard grid: Mobile-first (1 col → 2 col at md/768px) - Activity grid: Mobile-first (1 col → 2 col at md/768px) - TopBar: Truncate brand text on mobile, hide 'Remote' on <md - TopBar session: Show time-only on <xs (480px) - CommandPalette: Full-width on mobile with reduced padding - CommandPalette footer: Hidden on mobile - Touch targets: All interactive elements 48px+ on mobile All breakpoints follow Tailwind responsive prefixes (xs/sm/md/lg/xl). Quality checks: typecheck ✓, lint ✓ (1 pre-existing warning), build ✓ Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -191,7 +191,8 @@ export function CommandPalette({ isOpen, onClose, onAction }: CommandPaletteProp
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
justifyContent: 'center',
|
||||
paddingTop: '12vh',
|
||||
padding: '8px',
|
||||
paddingTop: 'max(8px, 10vh)',
|
||||
backdropFilter: 'blur(4px)',
|
||||
WebkitBackdropFilter: 'blur(4px)',
|
||||
animation: prefersReducedMotion ? 'none' : 'palette-overlay-in 0.2s ease-out forwards',
|
||||
@@ -200,10 +201,9 @@ export function CommandPalette({ isOpen, onClose, onAction }: CommandPaletteProp
|
||||
>
|
||||
{/* Palette modal */}
|
||||
<div
|
||||
className="w-full max-w-[calc(100vw-16px)] md:max-w-[calc(100vw-32px)] md:w-[580px]"
|
||||
style={{
|
||||
width: '580px',
|
||||
maxWidth: 'calc(100vw - 32px)',
|
||||
maxHeight: '520px',
|
||||
maxHeight: 'calc(100vh - 24vh)',
|
||||
background: 'var(--surface)',
|
||||
borderRadius: '12px',
|
||||
boxShadow: '0 20px 60px rgba(26,43,42,0.2), 0 0 0 1px rgba(26,43,42,0.08)',
|
||||
@@ -215,11 +215,11 @@ export function CommandPalette({ isOpen, onClose, onAction }: CommandPaletteProp
|
||||
>
|
||||
{/* Search input row */}
|
||||
<div
|
||||
className="px-3 py-3 md:px-[18px] md:py-[14px]"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
padding: '14px 18px',
|
||||
borderBottom: '1px solid var(--border-light)',
|
||||
}}
|
||||
>
|
||||
@@ -276,10 +276,9 @@ export function CommandPalette({ isOpen, onClose, onAction }: CommandPaletteProp
|
||||
ref={resultsRef}
|
||||
role="listbox"
|
||||
aria-label="Search results"
|
||||
className="pmr-scrollbar"
|
||||
className="pmr-scrollbar p-2 md:p-[8px]"
|
||||
style={{
|
||||
overflowY: 'auto',
|
||||
padding: '8px',
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
@@ -387,11 +386,10 @@ export function CommandPalette({ isOpen, onClose, onAction }: CommandPaletteProp
|
||||
|
||||
{/* Footer with keyboard hints */}
|
||||
<div
|
||||
className="hidden md:flex px-3 py-2 md:px-[18px] md:py-[10px]"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '12px',
|
||||
padding: '10px 18px',
|
||||
borderTop: '1px solid var(--border-light)',
|
||||
fontSize: '11px',
|
||||
color: 'var(--text-tertiary)',
|
||||
|
||||
@@ -122,11 +122,12 @@ export function DashboardLayout() {
|
||||
height: 'calc(100vh - var(--topbar-height))',
|
||||
}}
|
||||
>
|
||||
{/* Sidebar — fixed left */}
|
||||
{/* Sidebar — hidden on mobile/tablet, visible on desktop */}
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={sidebarVariants}
|
||||
className="hidden lg:block"
|
||||
style={{ flexShrink: 0 }}
|
||||
>
|
||||
<Sidebar />
|
||||
@@ -138,21 +139,13 @@ export function DashboardLayout() {
|
||||
animate="visible"
|
||||
variants={contentVariants}
|
||||
aria-label="Dashboard content"
|
||||
className="pmr-scrollbar"
|
||||
className="pmr-scrollbar p-4 pb-8 md:p-6 md:pb-10 lg:px-7 lg:pt-6 lg:pb-10"
|
||||
style={{
|
||||
flex: 1,
|
||||
overflowY: 'auto',
|
||||
padding: '24px 28px 40px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gap: '16px',
|
||||
}}
|
||||
className="dashboard-grid"
|
||||
>
|
||||
<div className="dashboard-grid">
|
||||
{/* PatientSummaryTile — full width */}
|
||||
<PatientSummaryTile />
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export function TopBar({ onSearchClick }: TopBarProps) {
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span
|
||||
className="font-ui"
|
||||
className="font-ui hidden sm:inline"
|
||||
style={{
|
||||
fontSize: '13px',
|
||||
fontWeight: 600,
|
||||
@@ -44,6 +44,17 @@ export function TopBar({ onSearchClick }: TopBarProps) {
|
||||
Headhunt Medical Center
|
||||
</span>
|
||||
<span
|
||||
className="font-ui sm:hidden"
|
||||
style={{
|
||||
fontSize: '13px',
|
||||
fontWeight: 600,
|
||||
color: 'var(--text-primary)',
|
||||
}}
|
||||
>
|
||||
HMC
|
||||
</span>
|
||||
<span
|
||||
className="hidden md:inline"
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
fontWeight: 400,
|
||||
@@ -120,7 +131,7 @@ export function TopBar({ onSearchClick }: TopBarProps) {
|
||||
</button>
|
||||
|
||||
{/* Session info (right) */}
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
<div className="flex items-center gap-2 sm:gap-3 shrink-0">
|
||||
<span
|
||||
className="hidden sm:inline"
|
||||
style={{
|
||||
@@ -132,7 +143,7 @@ export function TopBar({ onSearchClick }: TopBarProps) {
|
||||
Dr. A.CHARLWOOD
|
||||
</span>
|
||||
<span
|
||||
className="font-geist"
|
||||
className="font-geist hidden xs:inline"
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
color: 'var(--text-tertiary)',
|
||||
@@ -144,6 +155,19 @@ export function TopBar({ onSearchClick }: TopBarProps) {
|
||||
>
|
||||
Active Session · {currentTime}
|
||||
</span>
|
||||
<span
|
||||
className="font-geist xs:hidden"
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
color: 'var(--text-tertiary)',
|
||||
background: 'var(--accent-light)',
|
||||
padding: '3px 8px',
|
||||
borderRadius: '4px',
|
||||
border: '1px solid var(--accent-border)',
|
||||
}}
|
||||
>
|
||||
{currentTime}
|
||||
</span>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user