design: the window can now resize to l=380px

This commit is contained in:
2026-04-22 13:03:25 +02:00
parent 7de1fa2850
commit 9d181f3676
4 changed files with 331 additions and 219 deletions

View File

@ -4,6 +4,7 @@ import { useStore } from "../store";
export default function Sidebar() {
const { guides, openGuide, activeGuideGid, view } = useStore();
const [search, setSearch] = useState("");
const [collapsed, setCollapsed] = useState(false);
const filtered = guides.filter(g =>
g.name.toLowerCase().includes(search.toLowerCase())
@ -11,84 +12,123 @@ export default function Sidebar() {
return (
<aside style={{
width: "220px", flexShrink: 0,
background: "#161b22", borderRight: "1px solid #2d3748",
display: "flex", flexDirection: "column", overflow: "hidden",
width: collapsed ? "32px" : "220px",
flexShrink: 0,
background: "#161b22",
borderRight: "1px solid #2d3748",
display: "flex",
flexDirection: "column",
overflow: "hidden",
transition: "width 0.2s ease",
}}>
<div style={{ padding: "10px 12px", borderBottom: "1px solid #2d3748" }}>
<input
value={search}
onChange={e => setSearch(e.target.value)}
placeholder="Rechercher un Dofus…"
style={{
width: "100%", background: "#0d1117", border: "1px solid #2d3748",
borderRadius: "6px", padding: "6px 10px", color: "#e2e8f0",
fontSize: "12px", outline: "none",
}}
onFocus={e => (e.target.style.borderColor = "#f0c040")}
onBlur={e => (e.target.style.borderColor = "#2d3748")}
/>
</div>
{/* Toggle button */}
<button
onClick={() => setCollapsed(c => !c)}
title={collapsed ? "Ouvrir le menu" : "Réduire le menu"}
style={{
width: "100%", height: "36px", flexShrink: 0,
background: "transparent", border: "none",
borderBottom: "1px solid #2d3748",
color: "#4a5568", cursor: "pointer",
display: "flex", alignItems: "center",
justifyContent: collapsed ? "center" : "flex-end",
padding: "0 10px",
transition: "all 0.15s",
}}
onMouseEnter={e => (e.currentTarget.style.color = "#f0c040")}
onMouseLeave={e => (e.currentTarget.style.color = "#4a5568")}
>
<span style={{
fontSize: "12px",
transform: collapsed ? "rotate(180deg)" : "rotate(0deg)",
transition: "transform 0.2s ease",
display: "inline-block",
}}>
</span>
</button>
<div style={{ flex: 1, overflowY: "auto", padding: "8px 0", scrollbarWidth: "none" }}>
{filtered.length === 0 ? (
<div style={{ padding: "16px 12px", color: "#4a5568", fontSize: "12px", textAlign: "center" }}>
Aucun guide synchronisé
{!collapsed && (
<>
{/* Search */}
<div style={{ padding: "10px 12px", borderBottom: "1px solid #2d3748" }}>
<input
value={search}
onChange={e => setSearch(e.target.value)}
placeholder="Rechercher un Dofus…"
style={{
width: "100%", background: "#0d1117", border: "1px solid #2d3748",
borderRadius: "6px", padding: "6px 10px", color: "#e2e8f0",
fontSize: "12px", outline: "none",
}}
onFocus={e => (e.target.style.borderColor = "#f0c040")}
onBlur={e => (e.target.style.borderColor = "#2d3748")}
/>
</div>
) : (
filtered.map(guide => {
const pct = guide.total_quests > 0
? Math.round((guide.completed_quests / guide.total_quests) * 100)
: 0;
const isActive = guide.gid === activeGuideGid && view === "guide";
return (
<button
key={guide.gid}
onClick={() => openGuide(guide.gid)}
style={{
width: "100%", textAlign: "left", background: isActive ? "rgba(240,192,64,0.08)" : "transparent",
border: "none", borderLeft: isActive ? "2px solid #f0c040" : "2px solid transparent",
padding: "8px 12px", cursor: "pointer", transition: "all 0.12s",
}}
onMouseEnter={e => {
if (!isActive) (e.currentTarget as HTMLElement).style.background = "rgba(255,255,255,0.03)";
}}
onMouseLeave={e => {
if (!isActive) (e.currentTarget as HTMLElement).style.background = "transparent";
}}
>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<span style={{
fontSize: "12px", fontWeight: isActive ? 600 : 400,
color: isActive ? "#f0c040" : "#e2e8f0",
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
maxWidth: "140px",
}}>
{guide.name}
</span>
<span style={{
fontSize: "10px", color: pct === 100 ? "#4ade80" : "#94a3b8",
fontWeight: 600, flexShrink: 0,
}}>
{pct}%
</span>
</div>
<div style={{
marginTop: "4px", height: "2px", background: "#2d3748",
borderRadius: "1px", overflow: "hidden",
}}>
<div style={{
height: "100%", width: `${pct}%`,
background: pct === 100 ? "#4ade80" : pct > 50 ? "#f0c040" : "#4a9eff",
transition: "width 0.3s ease",
}} />
</div>
</button>
);
})
)}
</div>
{/* Guide list */}
<div style={{ flex: 1, overflowY: "auto", padding: "8px 0", scrollbarWidth: "none" }}>
{filtered.length === 0 ? (
<div style={{ padding: "16px 12px", color: "#4a5568", fontSize: "12px", textAlign: "center" }}>
Aucun guide synchronisé
</div>
) : (
filtered.map(guide => {
const pct = guide.total_quests > 0
? Math.round((guide.completed_quests / guide.total_quests) * 100)
: 0;
const isActive = guide.gid === activeGuideGid && view === "guide";
return (
<button
key={guide.gid}
onClick={() => openGuide(guide.gid)}
style={{
width: "100%", textAlign: "left",
background: isActive ? "rgba(240,192,64,0.08)" : "transparent",
border: "none", borderLeft: isActive ? "2px solid #f0c040" : "2px solid transparent",
padding: "8px 12px", cursor: "pointer", transition: "all 0.12s",
}}
onMouseEnter={e => {
if (!isActive) (e.currentTarget as HTMLElement).style.background = "rgba(255,255,255,0.03)";
}}
onMouseLeave={e => {
if (!isActive) (e.currentTarget as HTMLElement).style.background = "transparent";
}}
>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<span style={{
fontSize: "12px", fontWeight: isActive ? 600 : 400,
color: isActive ? "#f0c040" : "#e2e8f0",
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
maxWidth: "140px",
}}>
{guide.name}
</span>
<span style={{
fontSize: "10px", color: pct === 100 ? "#4ade80" : "#94a3b8",
fontWeight: 600, flexShrink: 0,
}}>
{pct}%
</span>
</div>
<div style={{
marginTop: "4px", height: "2px", background: "#2d3748",
borderRadius: "1px", overflow: "hidden",
}}>
<div style={{
height: "100%", width: `${pct}%`,
background: pct === 100 ? "#4ade80" : pct > 50 ? "#f0c040" : "#4a9eff",
transition: "width 0.3s ease",
}} />
</div>
</button>
);
})
)}
</div>
</>
)}
</aside>
);
}