fix: Sidebar scrollbar + einklappbare Gruppen
This commit is contained in:
@@ -158,6 +158,9 @@ function Login({ onLogin }) {
|
|||||||
function Sidebar({ active, setActive, user, onLogout, unreadMsgs=0 }) {
|
function Sidebar({ active, setActive, user, onLogout, unreadMsgs=0 }) {
|
||||||
const [appsOpen, setAppsOpen] = useState(true);
|
const [appsOpen, setAppsOpen] = useState(true);
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
const [collapsedGroups, setCollapsedGroups] = useState({});
|
||||||
|
|
||||||
|
const toggleGroup = (group) => setCollapsedGroups(prev => ({ ...prev, [group]: !prev[group] }));
|
||||||
|
|
||||||
const NavBtn = ({ item, sub=false }) => {
|
const NavBtn = ({ item, sub=false }) => {
|
||||||
const ic = active===item.id ? '#4ecdc4' : 'rgba(255,255,255,0.55)';
|
const ic = active===item.id ? '#4ecdc4' : 'rgba(255,255,255,0.55)';
|
||||||
@@ -220,7 +223,7 @@ function Sidebar({ active, setActive, user, onLogout, unreadMsgs=0 }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<nav style={{ flex:1, padding:'0 8px' }}>
|
<nav style={{ flex:1, padding:'0 8px', overflowY:'auto', overflowX:'hidden' }}>
|
||||||
<NavBtn item={{ id:'dashboard', Icon:HomeIcon, label:'Dashboard' }} />
|
<NavBtn item={{ id:'dashboard', Icon:HomeIcon, label:'Dashboard' }} />
|
||||||
|
|
||||||
{/* Apps Sektion mit Gruppenüberschriften */}
|
{/* Apps Sektion mit Gruppenüberschriften */}
|
||||||
@@ -237,13 +240,26 @@ function Sidebar({ active, setActive, user, onLogout, unreadMsgs=0 }) {
|
|||||||
{!collapsed && <span style={{ flex:1, color:'rgba(255,255,255,0.65)' }}>Apps</span>}
|
{!collapsed && <span style={{ flex:1, color:'rgba(255,255,255,0.65)' }}>Apps</span>}
|
||||||
{!collapsed && <ChevronIcon size={13} color="rgba(255,255,255,0.35)" dir={appsOpen?'down':'right'}/>}
|
{!collapsed && <ChevronIcon size={13} color="rgba(255,255,255,0.35)" dir={appsOpen?'down':'right'}/>}
|
||||||
</button>
|
</button>
|
||||||
{appsOpen && getGroupedTools().map(([group, tools]) => (
|
{appsOpen && getGroupedTools().map(([group, tools]) => {
|
||||||
<div key={group}>
|
const isGroupCollapsed = !!collapsedGroups[group];
|
||||||
{!collapsed && <div style={{ color:'rgba(78,205,196,0.85)', fontSize:9, fontFamily:'monospace',
|
return (
|
||||||
letterSpacing:2, padding:'8px 12px 3px 12px' }}>{group.toUpperCase()}</div>}
|
<div key={group}>
|
||||||
{tools.map(t => <NavBtn key={t.id} item={t} sub />)}
|
{!collapsed && (
|
||||||
</div>
|
<button onClick={() => toggleGroup(group)} style={{
|
||||||
))}
|
width:'100%', display:'flex', alignItems:'center', gap:4,
|
||||||
|
background:'none', border:'none', cursor:'pointer',
|
||||||
|
padding:'8px 12px 3px 12px', marginBottom:0,
|
||||||
|
}}>
|
||||||
|
<span style={{ color:'rgba(78,205,196,0.85)', fontSize:9, fontFamily:'monospace', letterSpacing:2, flex:1, textAlign:'left' }}>
|
||||||
|
{group.toUpperCase()}
|
||||||
|
</span>
|
||||||
|
<ChevronIcon size={10} color="rgba(78,205,196,0.5)" dir={isGroupCollapsed ? 'right' : 'down'} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{!isGroupCollapsed && tools.map(t => <NavBtn key={t.id} item={t} sub />)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
<NavBtn item={{ id:'admin', Icon:AdminIcon, label:'Einstellungen' }} />
|
<NavBtn item={{ id:'admin', Icon:AdminIcon, label:'Einstellungen' }} />
|
||||||
</nav>
|
</nav>
|
||||||
@@ -1552,7 +1568,6 @@ function SearchResultItem({ item, idx, activeIdx, onNavigate, onHover }) {
|
|||||||
if (item.type==='calendar_feed') { icon='📅'; primary=item.name; secondary='Kalender-Abo'; }
|
if (item.type==='calendar_feed') { icon='📅'; primary=item.name; secondary='Kalender-Abo'; }
|
||||||
if (item.type==='calendar_event') { icon='📆'; primary=item.summary; secondary=`${item.feed_name||'Kalender'}${item.start_dt?' · '+formatIcalDate(item.start_dt):''}`; }
|
if (item.type==='calendar_event') { icon='📆'; primary=item.summary; secondary=`${item.feed_name||'Kalender'}${item.start_dt?' · '+formatIcalDate(item.start_dt):''}`; }
|
||||||
if (item.type==='qr') { icon='◻'; primary=item.label||item.url; secondary=`QR-Code · ${item.url}`; }
|
if (item.type==='qr') { icon='◻'; primary=item.label||item.url; secondary=`QR-Code · ${item.url}`; }
|
||||||
if (item.type==='geo') { icon='🗺️'; primary=`vs ${item.opp_name||item.owner_name}`; secondary=item.status==='active'?'Gebietseroberung · laufend':'Gebietseroberung · beendet'; }
|
|
||||||
return (
|
return (
|
||||||
<div onClick={()=>onNavigate(item)} onMouseEnter={()=>onHover(idx)}
|
<div onClick={()=>onNavigate(item)} onMouseEnter={()=>onHover(idx)}
|
||||||
style={{display:'flex',alignItems:'center',gap:10,padding:'9px 14px',cursor:'pointer',
|
style={{display:'flex',alignItems:'center',gap:10,padding:'9px 14px',cursor:'pointer',
|
||||||
@@ -1589,7 +1604,6 @@ const SEARCH_TOOL_INDEX = [
|
|||||||
{type:'tool',label:'Whiteboard',icon:'🖊',sub:'Werkzeuge',id:'whiteboard',keywords:['whiteboard','zeichnen','canvas','board','draw','skizze','malen','zeichen']},
|
{type:'tool',label:'Whiteboard',icon:'🖊',sub:'Werkzeuge',id:'whiteboard',keywords:['whiteboard','zeichnen','canvas','board','draw','skizze','malen','zeichen']},
|
||||||
{type:'tool',label:'Dev-Tools',icon:'🔧',sub:'Werkzeuge',id:'devtools',keywords:['entwickler','developer','tools','werkzeuge']},
|
{type:'tool',label:'Dev-Tools',icon:'🔧',sub:'Werkzeuge',id:'devtools',keywords:['entwickler','developer','tools','werkzeuge']},
|
||||||
{type:'tool',label:'Paywall-Killer',icon:'🔓',sub:'Werkzeuge',id:'paywallkiller',keywords:['paywall','archiv','archive','artikel','zeitung','bild','waz','heise','spiegel','zeit','bypass','umgehen','lesen','gesperrt','bezahlschranke']},
|
{type:'tool',label:'Paywall-Killer',icon:'🔓',sub:'Werkzeuge',id:'paywallkiller',keywords:['paywall','archiv','archive','artikel','zeitung','bild','waz','heise','spiegel','zeit','bypass','umgehen','lesen','gesperrt','bezahlschranke']},
|
||||||
{type:'tool',label:'Hex Wars',icon:'⬡',sub:'Freizeit',id:'gebietseroberung',keywords:['hex wars','spiel','game','multiplayer','gebiet','strategie','raster','einladen','duell','gebietseroberung']},
|
|
||||||
{type:'tool',label:'Media',icon:'🎬',sub:'Freizeit',id:'media',keywords:['kino','film','movie','streaming','demnächst','favoriten','cinema']},
|
{type:'tool',label:'Media',icon:'🎬',sub:'Freizeit',id:'media',keywords:['kino','film','movie','streaming','demnächst','favoriten','cinema']},
|
||||||
{type:'tool',label:'Kino – Aktuell',icon:'🎬',sub:'Media',id:'media',keywords:['kino','kinocharts','charts','laufend','now playing']},
|
{type:'tool',label:'Kino – Aktuell',icon:'🎬',sub:'Media',id:'media',keywords:['kino','kinocharts','charts','laufend','now playing']},
|
||||||
{type:'tool',label:'Kino – Demnächst',icon:'🗓',sub:'Media',id:'media',keywords:['demnächst','neustart','upcoming','vorschau','kino']},
|
{type:'tool',label:'Kino – Demnächst',icon:'🗓',sub:'Media',id:'media',keywords:['demnächst','neustart','upcoming','vorschau','kino']},
|
||||||
@@ -1743,7 +1757,6 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
|
|||||||
else if (item.type === 'push') { setActive('dashboard'); }
|
else if (item.type === 'push') { setActive('dashboard'); }
|
||||||
else if (item.type === 'calendar_feed' || item.type === 'calendar_event') { setActive('dashboard'); }
|
else if (item.type === 'calendar_feed' || item.type === 'calendar_event') { setActive('dashboard'); }
|
||||||
else if (item.type === 'qr') { setActive('devtools'); setDevToolsNav({tool:'qrcode', ts: Date.now()}); }
|
else if (item.type === 'qr') { setActive('devtools'); setDevToolsNav({tool:'qrcode', ts: Date.now()}); }
|
||||||
else if (item.type === 'geo') { setActive('gebietseroberung'); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onKey = e => {
|
const onKey = e => {
|
||||||
@@ -1904,12 +1917,6 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
|
|||||||
<div>
|
<div>
|
||||||
<div style={{padding:'7px 14px 4px',color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:9,letterSpacing:1}}>KALENDER-EINTRÄGE</div>
|
<div style={{padding:'7px 14px 4px',color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:9,letterSpacing:1}}>KALENDER-EINTRÄGE</div>
|
||||||
{results.calendar_events.map((item,i)=>(<SearchResultItem key={`ce${i}`} item={{...item,type:'calendar_event'}} idx={0} activeIdx={-1} onNavigate={navigate} onHover={()=>{}}/>))}
|
{results.calendar_events.map((item,i)=>(<SearchResultItem key={`ce${i}`} item={{...item,type:'calendar_event'}} idx={0} activeIdx={-1} onNavigate={navigate} onHover={()=>{}}/>))}
|
||||||
{results.geo_games?.length>0 && (
|
|
||||||
<>
|
|
||||||
<div style={secHead}>GEBIETSEROBERUNG</div>
|
|
||||||
{results.geo_games.map((item,i)=>(<SearchResultItem key={`geo${i}`} item={{...item,type:'geo'}} idx={0} activeIdx={-1} onNavigate={navigate} onHover={()=>{}}/>))}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{results.calendar_feeds?.length>0 && (
|
{results.calendar_feeds?.length>0 && (
|
||||||
|
|||||||
Reference in New Issue
Block a user