# Responsive System โ€” Shapeshifting Glass > *"Content is like water โ€” it should flow into whatever container it's poured into."* > โ€” Ethan Marcotte --- ## ๐ŸŽฏ Filosofi Responsif BETE menggunakan pendekatan **mobile-first** dengan tiga prinsip: 1. **Content parity** โ€” Konten yang sama di semua ukuran, layout yang berbeda 2. **Touch-optimized** โ€” Target 44ร—44px minimum di mobile 3. **Progressive enhancement** โ€” Desktop mendapat fitur tambahan (hover, sidebar, multi-column) --- ## ๐Ÿ“ Breakpoint System ```css :root { --bp-sm: 640px; /* Mobile landscape */ --bp-md: 768px; /* Tablet portrait */ --bp-lg: 1024px; /* Tablet landscape / small desktop */ --bp-xl: 1280px; /* Desktop */ --bp-2xl: 1536px; /* Wide desktop */ } ``` ### Layout Behavior Matrix | Viewport | Sidebar | Header | Content Grid | Font Size | |----------|---------|--------|-------------|-----------| | < 640px | Bottom tab (56px) | Compact | 1 col | sm | | 640-768 | Bottom tab | Compact | 1-2 col | sm | | 768-1024 | Icon 64px | Standard | 2 col | base | | 1024-1280 | Full 256px | Standard | 2-3 col | base | | > 1280px | Full 256px | Full | 3-4 col | base+ | --- ## ๐Ÿ“ฑ Mobile Adaptations ### Navigation - **< 768px:** Bottom tab bar menggantikan sidebar - **Tab icons:** Home, Live, Messages, Settings (maks 5 tabs) - **Tab bar height:** 56px (dengan safe area padding untuk notched phones) ### Content - **Cards:** Full-width (margin 16px), stacked vertical - **Tables:** Horizontal scroll atau card view alternatif - **Charts:** Simplified (less data points, larger labels) - **Modals:** Full-screen drawer dari bawah (bottom sheet) ### Touch Targets ```css /* Minimum 44ร—44px untuk semua interactive elements */ .button, .nav-item, .tab-item { min-height: 44px; min-width: 44px; } /* Forms on mobile */ .input, .select { height: 48px; /* Larger tap target */ font-size: 16px; /* Prevent iOS zoom on focus */ } ``` --- ## ๐Ÿ’ป Desktop Adaptations ### Navigation - **โ‰ฅ 1024px:** Full sidebar (256px) dengan label teks - **Sidebar states:** Collapsed (icon-only, 64px) โ†” Expanded (256px) - **Keyboard shortcuts:** Didokumentasikan di help panel ### Content - **Multi-column grids:** 2-4 columns depending on container width - **Sticky elements:** Sidebar, header, filter bars - **Hover previews:** Tooltips, popovers untuk informasi tambahan - **Drag & drop:** Dukungan untuk reorder, upload area --- ## ๐Ÿงฉ Responsive Component Patterns ### Pattern 1: Responsive Card Grid ```css .card-grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-3); } @media (min-width: 640px) { .card-grid { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 1024px) { .card-grid { grid-template-columns: repeat(3, 1fr); } } @media (min-width: 1280px) { .card-grid { grid-template-columns: repeat(4, 1fr); } } ``` ### Pattern 2: Responsive Sidebar + Content ```tsx function DashboardLayout() { const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const isMobile = useMediaQuery('(max-width: 767px)'); return (
{/* Mobile: slide-in drawer */} {isMobile && ( )} {/* Desktop: persistent sidebar */} {!isMobile && ( setSidebarCollapsed(!sidebarCollapsed)} /> )}
setMobileMenuOpen(true)} />
{children}
); } ``` ### Pattern 3: Responsive Typography (Fluid) ```css /* Fluid type scale โ€” sudah didefinisikan di core/02-typography.md */ --fs-body: clamp(0.94rem, 0.94rem + 0.03vw, 1.00rem); --fs-h2: clamp(1.50rem, 1.50rem + 0.12vw, 1.88rem); ``` ### Pattern 4: Container Queries (for reusable components) ```css .card-grid-component { container-type: inline-size; container-name: card-list; } @container card-list (max-width: 400px) { .card-item { grid-template-columns: 1fr; } } @container card-list (min-width: 401px) { .card-item { grid-template-columns: 1fr 1fr; } } ``` --- ## ๐ŸŽฏ Responsive Decision Tree ``` Layout component โ†’ โ”œโ”€โ”€ Apakah ini navigasi? โ”‚ โ”œโ”€โ”€ Mobile โ†’ Bottom tab bar (56px) โ”‚ โ”œโ”€โ”€ Tablet โ†’ Icon sidebar (64px) + hamburger โ”‚ โ””โ”€โ”€ Desktop โ†’ Full sidebar (256px) โ”‚ โ”œโ”€โ”€ Apakah ini konten list/grid? โ”‚ โ”œโ”€โ”€ 1 item โ†’ Single column โ”‚ โ”œโ”€โ”€ 2-4 items โ†’ 2 col (tablet), 3-4 col (desktop) โ”‚ โ””โ”€โ”€ > 4 items โ†’ auto-fill grid with minmax โ”‚ โ”œโ”€โ”€ Apakah ini modal/dialog? โ”‚ โ”œโ”€โ”€ Mobile โ†’ Bottom sheet (full width, 80% height) โ”‚ โ””โ”€โ”€ Desktop โ†’ Centered modal (max-w-lg) โ”‚ โ””โ”€โ”€ Apakah ini form? โ”œโ”€โ”€ Mobile โ†’ Stacked, full-width, larger inputs โ””โ”€โ”€ Desktop โ†’ Multi-column, side labels ``` --- ## ๐Ÿ“ Responsive Spacing Scale ```css .content-padding { padding: var(--sp-3); /* Mobile: 16px */ } @media (min-width: 768px) { .content-padding { padding: var(--sp-4); } /* Tablet: 24px */ } @media (min-width: 1024px) { .content-padding { padding: var(--sp-5); } /* Desktop: 32px */ } ``` --- ## ๐Ÿงช Testing Responsive Design ```typescript // Test utility untuk responsive behavior const VIEWPORTS = { mobile: { width: 375, height: 667 }, tablet: { width: 768, height: 1024 }, desktop: { width: 1280, height: 800 }, wide: { width: 1920, height: 1080 }, }; describe('DashboardLayout', () => { it('shows MobileTabBar on mobile', () => { cy.viewport(VIEWPORTS.mobile); cy.get('[data-testid="mobile-tab-bar"]').should('be.visible'); cy.get('[data-testid="sidebar"]').should('not.be.visible'); }); it('shows sidebar on desktop', () => { cy.viewport(VIEWPORTS.desktop); cy.get('[data-testid="sidebar"]').should('be.visible'); cy.get('[data-testid="mobile-tab-bar"]').should('not.be.visible'); }); }); ``` --- ## โš ๏ธ Anti-Patterns Responsive ### โŒ Hanya media query untuk satu breakpoint ```css /* โŒ JANGAN โ€” hanya mobile dan desktop */ .panel { padding: 16px; } @media (min-width: 1024px) { .panel { padding: 32px; } } /* โœ… Gunakan fluid atau multiple breakpoints */ .panel { padding: clamp(16px, 3vw, 32px); } ``` ### โŒ Hidden content on mobile ```tsx // โŒ JANGAN โ€” "out of sight, out of mind" tapi konten hilang {isMobile ? null : } // โœ… Simplified version untuk mobile ``` ### โŒ Fixed width containers ```css /* โŒ JANGAN โ€” overflow on smaller screens */ .container { width: 1200px; } /* โœ… Gunakan max-width + padding */ .container { max-width: 1200px; margin: 0 auto; padding: 0 var(--sp-4); } ``` --- ## ๐Ÿ”— Referensi | Sumber | Konsep | |--------|--------| | [Every Layout](https://every-layout.dev/) | Reusable layout patterns | | [Container Queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_container_queries) | CSS container queries | | [Utopia.fyi](https://utopia.fyi/) | Fluid type & space calculator | --- *"Layout adalah air yang mengalir โ€” ia mengambil bentuk wadahnya tanpa kehilangan esensi."* โ„๏ธ๐Ÿฉต