feat: AnyDay tab edit via double-click; remove pencil icons; fix active tab style
CSS: - Active tab no longer shows accent underline; instead border-bottom matches the someday area bg (#f9f9f9 / #1a1a1b dark), creating a raised browser-tab look where the active tab visually merges with the content below - margin-bottom: -1px to cover the tab bar border-bottom on active tab JSX: - Double-click on any tab now opens TabVisualsPopover (edit tab) - Pencil icon and dissolve-X button removed from tab wrappers - TabVisualsPopover extended with: rename input, dissolve button (dissolve removes the tab grouping; lists are kept) - onRename and onDissolve props added to TabVisualsPopover v1.107.3
This commit is contained in:
parent
85912beb4b
commit
6ccf61f09a
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.107.2",
|
||||
"version": "1.107.3",
|
||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -1677,9 +1677,14 @@ h3 {
|
||||
color: var(--weekly-text, #222);
|
||||
font-weight: 700;
|
||||
border-color: var(--weekly-border, #e5e7eb);
|
||||
border-bottom-color: var(--weekly-accent, #6366f1);
|
||||
border-bottom-color: #f9f9f9;
|
||||
background: var(--weekly-bg, #fff);
|
||||
box-shadow: 0 -1px 0 0 var(--weekly-bg, #fff);
|
||||
box-shadow: none;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.weekly-container.dark-mode .someday-tab-btn-h.active {
|
||||
border-bottom-color: #1a1a1b;
|
||||
}
|
||||
|
||||
.someday-tab-btn-h.drag-over {
|
||||
|
||||
@ -8069,16 +8069,14 @@ export default function WeeklyView() {
|
||||
<button
|
||||
className={`someday-tab-btn-h ${activeSomedayTab === tab ? "active" : ""} ${dragOverTab === tab ? "drag-over" : ""}`}
|
||||
onClick={() => setSomedayTab(tab)}
|
||||
onDoubleClick={() => {
|
||||
setEditingTabName(tab);
|
||||
setRenamingTabValue(tab);
|
||||
}}
|
||||
onDoubleClick={(e) => { e.stopPropagation(); setEditingTabVisualsName(editingTabVisualsName === tab ? null : tab); }}
|
||||
style={tv.color ? {
|
||||
background: activeSomedayTab === tab ? tv.color : `${tv.color}22`,
|
||||
color: activeSomedayTab === tab ? "#fff" : tv.color,
|
||||
borderColor: tv.color,
|
||||
borderBottomColor: activeSomedayTab === tab ? "transparent" : tv.color,
|
||||
} : undefined}
|
||||
title={t.renameTab}
|
||||
title={profile.language === "de" ? "Doppelklick zum Bearbeiten" : "Double-click to edit"}
|
||||
>
|
||||
{tv.icon && (
|
||||
<span style={{ display: "inline-flex", alignItems: "center", marginRight: "4px" }}>
|
||||
@ -8089,16 +8087,6 @@ export default function WeeklyView() {
|
||||
</button>
|
||||
);
|
||||
})()}
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); setEditingTabVisualsName(editingTabVisualsName === tab ? null : tab); }}
|
||||
title={profile.language === "de" ? "Tab-Stil bearbeiten" : "Edit tab style"}
|
||||
style={{ background: "none", border: "none", cursor: "pointer", padding: "2px", color: "#bbb", display: "inline-flex", alignItems: "center" }}
|
||||
><Pencil size={10} /></button>
|
||||
<button
|
||||
className="someday-tab-dissolve-h"
|
||||
onClick={(e) => { e.stopPropagation(); dissolveTab(tab); }}
|
||||
title={t.dissolveTab}
|
||||
><X size={10} /></button>
|
||||
{editingTabVisualsName === tab && (
|
||||
<TabVisualsPopover
|
||||
tabName={tab}
|
||||
@ -8106,6 +8094,8 @@ export default function WeeklyView() {
|
||||
darkMode={darkMode}
|
||||
language={profile.language}
|
||||
onChange={(updates) => updateTabVisuals(tab, updates)}
|
||||
onRename={(newName) => { renameTab(tab, newName); setEditingTabVisualsName(null); }}
|
||||
onDissolve={() => dissolveTab(tab)}
|
||||
onClose={() => setEditingTabVisualsName(null)}
|
||||
/>
|
||||
)}
|
||||
@ -10999,6 +10989,8 @@ function TabVisualsPopover({
|
||||
darkMode,
|
||||
language,
|
||||
onChange,
|
||||
onRename,
|
||||
onDissolve,
|
||||
onClose,
|
||||
}: {
|
||||
tabName: string;
|
||||
@ -11006,9 +10998,12 @@ function TabVisualsPopover({
|
||||
darkMode: boolean;
|
||||
language: string;
|
||||
onChange: (updates: { color?: string | null; icon?: string | null }) => void;
|
||||
onRename: (newName: string) => void;
|
||||
onDissolve: () => void;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const [iconPickerOpen, setIconPickerOpen] = useState(false);
|
||||
const [renameValue, setRenameValue] = useState(tabName);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
const onDoc = (e: MouseEvent) => {
|
||||
@ -11018,36 +11013,50 @@ function TabVisualsPopover({
|
||||
return () => document.removeEventListener("mousedown", onDoc);
|
||||
}, [onClose]);
|
||||
const de = language === "de";
|
||||
const labelStyle = { fontSize: "0.75rem", color: darkMode ? "#9ca3af" : "#666", flex: 1 } as const;
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "calc(100% + 4px)",
|
||||
top: "calc(100% + 6px)",
|
||||
left: 0,
|
||||
zIndex: 100,
|
||||
background: darkMode ? "#1e1e2e" : "#fff",
|
||||
border: `1px solid ${darkMode ? "#444" : "#e5e7eb"}`,
|
||||
borderRadius: "10px",
|
||||
padding: "10px",
|
||||
padding: "12px",
|
||||
boxShadow: "0 8px 24px rgba(0,0,0,0.18)",
|
||||
minWidth: "220px",
|
||||
minWidth: "230px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "8px",
|
||||
gap: "10px",
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Header */}
|
||||
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<span style={{ fontSize: "0.78rem", fontWeight: 600, color: darkMode ? "#d1d5db" : "#444" }}>
|
||||
{de ? `Tab-Stil: ${tabName}` : `Tab style: ${tabName}`}
|
||||
<span style={{ fontSize: "0.78rem", fontWeight: 700, color: darkMode ? "#d1d5db" : "#333" }}>
|
||||
{de ? "Tab bearbeiten" : "Edit tab"}
|
||||
</span>
|
||||
<button onClick={onClose} style={{ background: "none", border: "none", cursor: "pointer", color: darkMode ? "#9ca3af" : "#888", padding: "2px" }}>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</div>
|
||||
{/* Rename */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<span style={{ fontSize: "0.75rem", color: darkMode ? "#9ca3af" : "#666", flex: 1 }}>{de ? "Icon" : "Icon"}</span>
|
||||
<span style={labelStyle}>{de ? "Name" : "Name"}</span>
|
||||
<input
|
||||
value={renameValue}
|
||||
onChange={(e) => setRenameValue(e.target.value)}
|
||||
onBlur={() => { if (renameValue.trim() && renameValue.trim() !== tabName) onRename(renameValue.trim()); }}
|
||||
onKeyDown={(e) => { if (e.key === "Enter") { if (renameValue.trim() && renameValue.trim() !== tabName) onRename(renameValue.trim()); (e.target as HTMLInputElement).blur(); } }}
|
||||
style={{ flex: 1, fontSize: "0.8rem", border: `1px solid ${darkMode ? "#444" : "#e5e7eb"}`, borderRadius: "6px", padding: "4px 8px", background: darkMode ? "#2a2a3a" : "#f9f9f9", color: darkMode ? "#e5e7eb" : "#222", outline: "none" }}
|
||||
/>
|
||||
</div>
|
||||
{/* Icon */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<span style={labelStyle}>{de ? "Icon" : "Icon"}</span>
|
||||
<button
|
||||
onClick={() => setIconPickerOpen((v) => !v)}
|
||||
style={{ width: "32px", height: "32px", borderRadius: "8px", border: `1px solid ${darkMode ? "#444" : "#e5e7eb"}`, background: darkMode ? "#2a2a3a" : "#fff", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}
|
||||
@ -11061,7 +11070,7 @@ function TabVisualsPopover({
|
||||
)}
|
||||
</div>
|
||||
{iconPickerOpen && (
|
||||
<div style={{ position: "absolute", top: "70px", left: "10px", zIndex: 110 }}>
|
||||
<div style={{ position: "absolute", top: "110px", left: "10px", zIndex: 110 }}>
|
||||
<IconPicker
|
||||
selectedIcon={visuals.icon || ""}
|
||||
onSelect={(name) => { onChange({ icon: name }); setIconPickerOpen(false); }}
|
||||
@ -11069,8 +11078,9 @@ function TabVisualsPopover({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* Color */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<span style={{ fontSize: "0.75rem", color: darkMode ? "#9ca3af" : "#666", flex: 1 }}>{de ? "Farbe" : "Color"}</span>
|
||||
<span style={labelStyle}>{de ? "Farbe" : "Color"}</span>
|
||||
<input
|
||||
type="color"
|
||||
value={visuals.color || "#6366f1"}
|
||||
@ -11083,6 +11093,18 @@ function TabVisualsPopover({
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{/* Dissolve / delete */}
|
||||
<div style={{ borderTop: `1px solid ${darkMode ? "#374151" : "#e5e7eb"}`, paddingTop: "8px" }}>
|
||||
<button
|
||||
onClick={() => { onDissolve(); onClose(); }}
|
||||
style={{ width: "100%", display: "flex", alignItems: "center", gap: "8px", padding: "6px 8px", fontSize: "0.8rem", color: "#ef4444", background: "none", border: "none", cursor: "pointer", borderRadius: "6px", textAlign: "left" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(239,68,68,0.08)")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.background = "none")}
|
||||
>
|
||||
<Trash2 size={13} />
|
||||
{de ? "Tab auflösen (Listen bleiben)" : "Dissolve tab (lists stay)"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user