// Android (Material 3) shared components and screens
// Wrapped in AndroidDevice (412 × 892), inner content ~396 × 820.
const M = {
// Material 3 token mapping for our blue brand
primary: '#1B5BFF',
onPrimary: '#FFFFFF',
primaryContainer: '#DCE7FF',
onPrimaryContainer: '#0B1F4D',
secondary: '#5B9EFF',
tertiary: '#22C29A',
error: '#E5484D',
surface: '#FAFBFE',
surfaceDim: '#EFF3FA',
surfaceContainer: '#EEF3FF',
surfaceContainerHigh: '#E2EAFA',
surfaceContainerLow: '#F5F7FC',
surfaceVariant: '#E4E8F2',
onSurface: '#0B132B',
onSurfaceVariant: '#5B6784',
outline: '#B5BFD4',
outlineVar: '#D9DFEC',
};
// ── Material Top App Bar ──────────────────────────────────────
function MdAppBar({ title, leading = 'back', trailing = ['bell'], subtitle, tone = 'surface' }) {
const bg = tone === 'primary' ? M.primary : (tone === 'surfaceContainer' ? M.surfaceContainer : M.surface);
const fg = tone === 'primary' ? 'white' : M.onSurface;
const muted = tone === 'primary' ? 'rgba(255,255,255,0.85)' : M.onSurfaceVariant;
const Leading = { back: IconChevL, menu: IconFilter, none: null }[leading];
return (
{Leading && (
)}
{title}
{subtitle &&
{subtitle}
}
{trailing.map((t, i) => {
const I = { bell: IconBell, search: IconSearch, cart: IconCart, more: null, heart: IconHeart, close: IconClose }[t];
return (
);
})}
);
}
// ── Material 3 bottom navigation bar (with active pill) ──────
function MdBottomNav({ active = 'home' }) {
const items = [
{ id: 'home', label: 'Home', Icon: IconHome },
{ id: 'browse', label: 'Browse', Icon: IconSearch },
{ id: 'cart', label: 'Cart', Icon: IconCart, badge: 3 },
{ id: 'orders', label: 'Orders', Icon: IconBox },
{ id: 'profile', label: 'You', Icon: IconUser },
];
return (
{items.map((it) => {
const isActive = it.id === active;
return (
{it.badge && (
{it.badge}
)}
{it.label}
);
})}
);
}
// ── M3 FAB ───────────────────────────────────────────────────
function MdFab({ icon: I = IconRx, label, extended = false, bottom = 116, right = 16 }) {
if (extended) {
return (
{label}
);
}
return (
);
}
// ── M3 Filled / Tonal / Outlined / Text buttons ──────────────
function MdButton({ children, variant = 'filled', icon: I, full = false, style = {} }) {
const base = {
height: 40, borderRadius: 20, padding: '0 24px', border: 'none',
fontSize: 14, fontWeight: 600, letterSpacing: 0.1,
display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
fontFamily: 'Roboto, system-ui, sans-serif', cursor: 'pointer',
width: full ? '100%' : 'auto',
...style,
};
const variants = {
filled: { background: M.primary, color: 'white' },
tonal: { background: M.primaryContainer, color: M.onPrimaryContainer },
outlined: { background: 'transparent', color: M.primary, border: `1px solid ${M.outline}` },
text: { background: 'transparent', color: M.primary, padding: '0 12px' },
elevated: { background: M.surfaceContainerLow, color: M.primary, boxShadow: '0 1px 3px rgba(0,0,0,0.10)' },
};
return ;
}
// ── M3 Filter / Assist chip ──────────────────────────────────
function MdChip({ children, selected = false, icon = null, style = {} }) {
return (
{selected && }
{icon && !selected && icon}
{children}
);
}
// ── Search bar (M3 docked) ───────────────────────────────────
function MdSearchBar({ value = 'Search medicines, brands, tests', leading = 'menu' }) {
const L = { menu: IconFilter, search: IconSearch, back: IconChevL }[leading];
return (
);
}
// ── Section header (Material style) ──────────────────────────
function MdSection({ title, action = 'View all' }) {
return (
{title}
{action &&
{action}
}
);
}
Object.assign(window, {
M, MdAppBar, MdBottomNav, MdFab, MdButton, MdChip, MdSearchBar, MdSection,
});