v0.12.21 adjusted mobile group manager ui

This commit is contained in:
2026-03-24 13:08:30 -04:00
parent 9dd3392e95
commit 65e7cc4007
4 changed files with 183 additions and 68 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "rosterchirp-frontend",
"version": "0.12.20",
"version": "0.12.21",
"private": true,
"scripts": {
"dev": "vite",

View File

@@ -72,6 +72,7 @@ function AllGroupsTab({ allUsers, onRefresh, isMobile = false, onIF, onIB }) {
const [saving, setSaving] = useState(false);
const [deleting, setDeleting] = useState(false);
const [showDelete, setShowDelete] = useState(false);
const [accordionOpen, setAccordionOpen] = useState(false);
const load = useCallback(() =>
api.getUserGroups().then(({ groups }) => setGroups([...(groups||[])].sort((a, b) => a.name.localeCompare(b.name)))).catch(() => {}), []);
@@ -79,6 +80,7 @@ function AllGroupsTab({ allUsers, onRefresh, isMobile = false, onIF, onIB }) {
const selectGroup = async (g) => {
setShowDelete(false);
setAccordionOpen(false);
const { members: mems } = await api.getUserGroup(g.id);
const ids = new Set(mems.map(m => m.id));
setSelected(g); setEditName(g.name); setMembers(ids); setSavedMembers(ids);
@@ -141,24 +143,58 @@ function AllGroupsTab({ allUsers, onRefresh, isMobile = false, onIF, onIB }) {
return (
<div style={{ display:'flex', flexDirection: isMobile ? 'column' : 'row', gap:0, height:'100%', minHeight:0, overflow: isMobile ? 'auto' : 'hidden' }}>
{/* Sidebar list */}
<div style={{ width: isMobile ? '100%' : 220, flexShrink:0, borderRight: isMobile ? 'none' : '1px solid var(--border)', borderBottom: isMobile ? '1px solid var(--border)' : 'none', overflowY: isMobile ? 'visible' : 'auto', padding:'12px 8px' }}>
<div style={{ fontSize:11, fontWeight:700, letterSpacing:'0.8px', textTransform:'uppercase', color:'var(--text-tertiary)', marginBottom:8, paddingLeft:4 }}>User Groups</div>
<button onClick={clearSelection} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:isCreating?'var(--primary-light)':'transparent', color:isCreating?'var(--primary)':'var(--text-secondary)',
cursor:'pointer', fontWeight:isCreating?600:400, fontSize:13, marginBottom:4 }}>+ New Group</button>
{groups.map(g => (
<button key={g.id} onClick={() => selectGroup(g)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:selected?.id===g.id?'var(--primary-light)':'transparent', color:selected?.id===g.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selected?.id===g.id?600:400, fontSize:13, marginBottom:2 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:26, height:26, borderRadius:6, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:9, fontWeight:700, flexShrink:0 }}>UG</div>
<div><div style={{ fontSize:13 }}>{g.name}</div><div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{g.member_count} member{g.member_count!==1?'s':''}</div></div>
</div>
{/* Sidebar — desktop only */}
{!isMobile && (
<div style={{ width:220, flexShrink:0, borderRight:'1px solid var(--border)', overflowY:'auto', padding:'12px 8px' }}>
<div style={{ fontSize:11, fontWeight:700, letterSpacing:'0.8px', textTransform:'uppercase', color:'var(--text-tertiary)', marginBottom:8, paddingLeft:4 }}>User Groups</div>
<button onClick={clearSelection} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:isCreating?'var(--primary-light)':'transparent', color:isCreating?'var(--primary)':'var(--text-secondary)',
cursor:'pointer', fontWeight:isCreating?600:400, fontSize:13, marginBottom:4 }}>+ New Group</button>
{groups.map(g => (
<button key={g.id} onClick={() => selectGroup(g)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:selected?.id===g.id?'var(--primary-light)':'transparent', color:selected?.id===g.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selected?.id===g.id?600:400, fontSize:13, marginBottom:2 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:26, height:26, borderRadius:6, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:9, fontWeight:700, flexShrink:0 }}>UG</div>
<div><div style={{ fontSize:13 }}>{g.name}</div><div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{g.member_count} member{g.member_count!==1?'s':''}</div></div>
</div>
</button>
))}
{groups.length===0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 4px' }}>No groups yet</div>}
</div>
)}
{/* Mobile accordion */}
{isMobile && (
<div style={{ padding:'8px 8px 4px', borderBottom:'1px solid var(--border)', flexShrink:0 }}>
<button onClick={clearSelection} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:isCreating?'var(--primary-light)':'transparent', color:isCreating?'var(--primary)':'var(--text-secondary)',
cursor:'pointer', fontWeight:isCreating?600:400, fontSize:13, marginBottom:6 }}>+ New Group</button>
<button onClick={() => setAccordionOpen(o => !o)} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', width:'100%', padding:'8px 10px',
borderRadius:'var(--radius)', border:'1px solid var(--border)', background:'var(--surface)', cursor:'pointer',
fontSize:13, fontWeight:600, color:'var(--text-primary)', marginBottom: accordionOpen ? 4 : 0 }}>
<span>Edit Existing</span>
<span style={{ fontSize:10, opacity:0.6 }}>{accordionOpen ? '▲' : '▼'}</span>
</button>
))}
{groups.length===0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 4px' }}>No groups yet</div>}
</div>
{accordionOpen && (
<div style={{ maxHeight:200, overflowY:'auto', border:'1px solid var(--border)', borderRadius:'var(--radius)' }}>
{groups.map(g => (
<button key={g.id} onClick={() => selectGroup(g)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 12px',
border:'none', borderBottom:'1px solid var(--border)',
background:selected?.id===g.id?'var(--primary-light)':'transparent', color:selected?.id===g.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selected?.id===g.id?600:400, fontSize:13 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:22, height:22, borderRadius:5, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:8, fontWeight:700, flexShrink:0 }}>UG</div>
<div><div style={{ fontSize:13 }}>{g.name}</div><div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{g.member_count} member{g.member_count!==1?'s':''}</div></div>
</div>
</button>
))}
{groups.length===0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 12px' }}>No groups yet</div>}
</div>
)}
</div>
)}
{/* Form */}
<div style={{ flex:1, overflowY: isMobile ? 'visible' : 'auto', padding: isMobile ? '16px 12px' : '16px 24px' }}>
@@ -238,6 +274,7 @@ function DirectMessagesTab({ allUserGroups, onRefresh, refreshKey, isMobile = fa
const [saving, setSaving] = useState(false);
const [deleting, setDeleting] = useState(false);
const [showDelete, setShowDelete] = useState(false);
const [accordionOpen, setAccordionOpen] = useState(false);
const load = useCallback(() =>
api.getMultiGroupDms().then(({ dms }) => setDms([...(dms||[])].sort((a, b) => a.name.localeCompare(b.name)))).catch(() => {}), []);
@@ -245,7 +282,7 @@ function DirectMessagesTab({ allUserGroups, onRefresh, refreshKey, isMobile = fa
const clearSelection = () => { setSelected(null); setDmName(''); setGroupIds(new Set()); setSavedGroupIds(new Set()); setShowDelete(false); };
const selectDm = (dm) => {
setShowDelete(false); setSelected(dm); setDmName(dm.name);
setShowDelete(false); setAccordionOpen(false); setSelected(dm); setDmName(dm.name);
const ids = new Set(dm.memberGroupIds||[]); setGroupIds(ids); setSavedGroupIds(ids);
};
@@ -282,23 +319,59 @@ function DirectMessagesTab({ allUserGroups, onRefresh, refreshKey, isMobile = fa
return (
<div style={{ display:'flex', flexDirection: isMobile ? 'column' : 'row', gap:0, height:'100%', minHeight:0, overflow: isMobile ? 'auto' : 'hidden' }}>
<div style={{ width: isMobile ? '100%' : 220, flexShrink:0, borderRight: isMobile ? 'none' : '1px solid var(--border)', borderBottom: isMobile ? '1px solid var(--border)' : 'none', overflowY: isMobile ? 'visible' : 'auto', padding:'12px 8px' }}>
<div style={{ fontSize:11, fontWeight:700, letterSpacing:'0.8px', textTransform:'uppercase', color:'var(--text-tertiary)', marginBottom:8, paddingLeft:4 }}>Multi-Group DMs</div>
<button onClick={clearSelection} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:isCreating?'var(--primary-light)':'transparent', color:isCreating?'var(--primary)':'var(--text-secondary)',
cursor:'pointer', fontWeight:isCreating?600:400, fontSize:13, marginBottom:4 }}>+ New Multi-Group DM</button>
{dms.map(dm => (
<button key={dm.id} onClick={() => selectDm(dm)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:selected?.id===dm.id?'var(--primary-light)':'transparent', color:selected?.id===dm.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selected?.id===dm.id?600:400, fontSize:13, marginBottom:2 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:26, height:26, borderRadius:6, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:9, fontWeight:700, flexShrink:0 }}>MG</div>
<div><div style={{ fontSize:13 }}>{dm.name}</div><div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{dm.group_count} group{dm.group_count!==1?'s':''}</div></div>
</div>
{/* Sidebar — desktop only */}
{!isMobile && (
<div style={{ width:220, flexShrink:0, borderRight:'1px solid var(--border)', overflowY:'auto', padding:'12px 8px' }}>
<div style={{ fontSize:11, fontWeight:700, letterSpacing:'0.8px', textTransform:'uppercase', color:'var(--text-tertiary)', marginBottom:8, paddingLeft:4 }}>Multi-Group DMs</div>
<button onClick={clearSelection} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:isCreating?'var(--primary-light)':'transparent', color:isCreating?'var(--primary)':'var(--text-secondary)',
cursor:'pointer', fontWeight:isCreating?600:400, fontSize:13, marginBottom:4 }}>+ New Multi-Group DM</button>
{dms.map(dm => (
<button key={dm.id} onClick={() => selectDm(dm)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:selected?.id===dm.id?'var(--primary-light)':'transparent', color:selected?.id===dm.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selected?.id===dm.id?600:400, fontSize:13, marginBottom:2 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:26, height:26, borderRadius:6, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:9, fontWeight:700, flexShrink:0 }}>MG</div>
<div><div style={{ fontSize:13 }}>{dm.name}</div><div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{dm.group_count} group{dm.group_count!==1?'s':''}</div></div>
</div>
</button>
))}
{dms.length===0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 4px' }}>No multi-group DMs yet</div>}
</div>
)}
{/* Mobile accordion */}
{isMobile && (
<div style={{ padding:'8px 8px 4px', borderBottom:'1px solid var(--border)', flexShrink:0 }}>
<button onClick={clearSelection} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 10px', borderRadius:'var(--radius)', border:'none',
background:isCreating?'var(--primary-light)':'transparent', color:isCreating?'var(--primary)':'var(--text-secondary)',
cursor:'pointer', fontWeight:isCreating?600:400, fontSize:13, marginBottom:6 }}>+ New Multi-Group DM</button>
<button onClick={() => setAccordionOpen(o => !o)} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', width:'100%', padding:'8px 10px',
borderRadius:'var(--radius)', border:'1px solid var(--border)', background:'var(--surface)', cursor:'pointer',
fontSize:13, fontWeight:600, color:'var(--text-primary)', marginBottom: accordionOpen ? 4 : 0 }}>
<span>Edit Existing</span>
<span style={{ fontSize:10, opacity:0.6 }}>{accordionOpen ? '▲' : '▼'}</span>
</button>
))}
{dms.length===0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 4px' }}>No multi-group DMs yet</div>}
</div>
{accordionOpen && (
<div style={{ maxHeight:200, overflowY:'auto', border:'1px solid var(--border)', borderRadius:'var(--radius)' }}>
{dms.map(dm => (
<button key={dm.id} onClick={() => selectDm(dm)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 12px',
border:'none', borderBottom:'1px solid var(--border)',
background:selected?.id===dm.id?'var(--primary-light)':'transparent', color:selected?.id===dm.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selected?.id===dm.id?600:400, fontSize:13 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:22, height:22, borderRadius:5, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:8, fontWeight:700, flexShrink:0 }}>MG</div>
<div><div style={{ fontSize:13 }}>{dm.name}</div><div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{dm.group_count} group{dm.group_count!==1?'s':''}</div></div>
</div>
</button>
))}
{dms.length===0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 12px' }}>No multi-group DMs yet</div>}
</div>
)}
</div>
)}
<div style={{ flex:1, overflowY: isMobile ? 'visible' : 'auto', padding: isMobile ? '16px 12px' : '16px 24px' }}>
<div style={{ display:'flex', flexDirection:'column', gap:18, maxWidth: isMobile ? '100%' : 520 }}>
<div>
@@ -345,6 +418,7 @@ function U2URestrictionsTab({ allUserGroups, isMobile = false, onIF, onIB }) {
const [loading, setLoading] = useState(false);
const [saving, setSaving] = useState(false);
const [search, setSearch] = useState('');
const [accordionOpen, setAccordionOpen] = useState(true);
// Map of groupId → number of restrictions (for showing dots in sidebar)
const [restrictionCounts, setRestrictionCounts] = useState({});
@@ -376,6 +450,7 @@ function U2URestrictionsTab({ allUserGroups, isMobile = false, onIF, onIB }) {
const selectGroup = (g) => {
setSelectedGroup(g);
setSearch('');
setAccordionOpen(false);
loadRestrictions(g);
};
@@ -413,40 +488,80 @@ function U2URestrictionsTab({ allUserGroups, isMobile = false, onIF, onIB }) {
? otherGroups.filter(g => g.name.toLowerCase().includes(search.toLowerCase()))
: otherGroups;
const u2uGroupButton = (g) => {
const hasRestrictions = g.id === selectedGroup?.id ? blockedIds.size > 0 : (restrictionCounts[g.id] || 0) > 0;
return (
<button key={g.id} onClick={() => selectGroup(g)} style={{
display:'block', width:'100%', textAlign:'left', padding:'8px 10px',
borderRadius:'var(--radius)', border:'none',
background: selectedGroup?.id===g.id ? 'var(--primary-light)' : 'transparent',
color: selectedGroup?.id===g.id ? 'var(--primary)' : 'var(--text-primary)',
cursor:'pointer', fontWeight: selectedGroup?.id===g.id ? 600 : 400, fontSize:13, marginBottom:2,
}}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:26, height:26, borderRadius:6, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:9, fontWeight:700, flexShrink:0 }}>UG</div>
<div style={{ flex:1, minWidth:0 }}>
<div style={{ fontSize:13, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{g.name}</div>
<div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{g.member_count} member{g.member_count!==1?'s':''}</div>
</div>
{hasRestrictions && (
<span style={{ width:8, height:8, borderRadius:'50%', background:'var(--error)', flexShrink:0 }} title="Has U2U restrictions" />
)}
</div>
</button>
);
};
return (
<div style={{ display:'flex', flexDirection: isMobile ? 'column' : 'row', gap:0, height:'100%', minHeight:0, overflow: isMobile ? 'auto' : 'hidden' }}>
{/* Group selector sidebar */}
<div style={{ width: isMobile ? '100%' : 220, flexShrink:0, borderRight: isMobile ? 'none' : '1px solid var(--border)', borderBottom: isMobile ? '1px solid var(--border)' : 'none', overflowY: isMobile ? 'visible' : 'auto', padding:'12px 8px' }}>
<div style={{ fontSize:11, fontWeight:700, letterSpacing:'0.8px', textTransform:'uppercase', color:'var(--text-tertiary)', marginBottom:8, paddingLeft:4 }}>
Select Group
{/* Group selector — desktop sidebar */}
{!isMobile && (
<div style={{ width:220, flexShrink:0, borderRight:'1px solid var(--border)', overflowY:'auto', padding:'12px 8px' }}>
<div style={{ fontSize:11, fontWeight:700, letterSpacing:'0.8px', textTransform:'uppercase', color:'var(--text-tertiary)', marginBottom:8, paddingLeft:4 }}>
Select Group
</div>
{allUserGroups.map(g => u2uGroupButton(g))}
{allUserGroups.length === 0 && (
<div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 4px' }}>No user groups yet</div>
)}
</div>
{allUserGroups.map(g => {
const hasRestrictions = g.id === selectedGroup?.id ? blockedIds.size > 0 : (restrictionCounts[g.id] || 0) > 0;
return (
<button key={g.id} onClick={() => selectGroup(g)} style={{
display:'block', width:'100%', textAlign:'left', padding:'8px 10px',
borderRadius:'var(--radius)', border:'none',
background: selectedGroup?.id===g.id ? 'var(--primary-light)' : 'transparent',
color: selectedGroup?.id===g.id ? 'var(--primary)' : 'var(--text-primary)',
cursor:'pointer', fontWeight: selectedGroup?.id===g.id ? 600 : 400, fontSize:13, marginBottom:2,
}}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:26, height:26, borderRadius:6, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:9, fontWeight:700, flexShrink:0 }}>UG</div>
<div style={{ flex:1, minWidth:0 }}>
<div style={{ fontSize:13, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{g.name}</div>
<div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{g.member_count} member{g.member_count!==1?'s':''}</div>
</div>
{hasRestrictions && (
<span style={{ width:8, height:8, borderRadius:'50%', background:'var(--error)', flexShrink:0 }} title="Has U2U restrictions" />
)}
</div>
</button>
);
})}
{allUserGroups.length === 0 && (
<div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 4px' }}>No user groups yet</div>
)}
</div>
)}
{/* Mobile accordion — expanded by default, collapses on selection */}
{isMobile && (
<div style={{ padding:'8px 8px 4px', borderBottom:'1px solid var(--border)', flexShrink:0 }}>
<button onClick={() => setAccordionOpen(o => !o)} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', width:'100%', padding:'8px 10px',
borderRadius:'var(--radius)', border:'1px solid var(--border)', background:'var(--surface)', cursor:'pointer',
fontSize:13, fontWeight:600, color:'var(--text-primary)', marginBottom: accordionOpen ? 4 : 0 }}>
<span>Select Group</span>
<span style={{ fontSize:10, opacity:0.6 }}>{accordionOpen ? '▲' : '▼'}</span>
</button>
{accordionOpen && (
<div style={{ maxHeight:200, overflowY:'auto', border:'1px solid var(--border)', borderRadius:'var(--radius)' }}>
{allUserGroups.map(g => {
const hasRestrictions = g.id === selectedGroup?.id ? blockedIds.size > 0 : (restrictionCounts[g.id] || 0) > 0;
return (
<button key={g.id} onClick={() => selectGroup(g)} style={{ display:'block', width:'100%', textAlign:'left', padding:'8px 12px',
border:'none', borderBottom:'1px solid var(--border)',
background:selectedGroup?.id===g.id?'var(--primary-light)':'transparent', color:selectedGroup?.id===g.id?'var(--primary)':'var(--text-primary)',
cursor:'pointer', fontWeight:selectedGroup?.id===g.id?600:400, fontSize:13 }}>
<div style={{ display:'flex', alignItems:'center', gap:8 }}>
<div style={{ width:22, height:22, borderRadius:5, background:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', color:'white', fontSize:8, fontWeight:700, flexShrink:0 }}>UG</div>
<div style={{ flex:1, minWidth:0 }}>
<div style={{ fontSize:13, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{g.name}</div>
<div style={{ fontSize:11, color:'var(--text-tertiary)' }}>{g.member_count} member{g.member_count!==1?'s':''}</div>
</div>
{hasRestrictions && <span style={{ width:8, height:8, borderRadius:'50%', background:'var(--error)', flexShrink:0 }} />}
</div>
</button>
);
})}
{allUserGroups.length === 0 && <div style={{ fontSize:13, color:'var(--text-tertiary)', padding:'8px 12px' }}>No user groups yet</div>}
</div>
)}
</div>
)}
{/* Restriction editor */}
<div style={{ flex:1, overflowY: isMobile ? 'visible' : 'auto', padding: isMobile ? '16px 12px' : '16px 24px' }}>