fix: mobile someday tabs and inline new tab input

Show horizontal scrollable tab bar on mobile (≤768px) above someday
lists. Hide vertical tabs in label column on small screens.
Replace browser prompt for new tab name with inline input field.

v1.25.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
mARTin 2026-03-10 21:38:38 +01:00
parent 3016293cd9
commit ff6ed1f949
3 changed files with 83 additions and 3 deletions

View File

@ -1,6 +1,6 @@
{
"name": "my-weekly-todo-list",
"version": "1.25.0",
"version": "1.25.1",
"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": {

View File

@ -1559,6 +1559,33 @@ h3 {
color: var(--weekly-text, #333);
}
/* Mobile Someday Tabs Bar */
.someday-tabs-mobile {
display: none;
}
@media (max-width: 768px) {
.someday-tabs-mobile {
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
padding: 6px 8px;
overflow-x: auto;
border-bottom: 1px solid var(--weekly-border);
scrollbar-width: none;
}
.someday-tabs-mobile::-webkit-scrollbar {
display: none;
}
/* Hide the vertical tabs in label column on mobile */
.someday-tabs {
display: none !important;
}
}
/* Preferences Slide-in Panel */
.preferences-panel {
position: fixed;

View File

@ -1429,6 +1429,8 @@ export default function WeeklyView() {
const [activeSomedayTab, setActiveSomedayTab] = useState<string | null>(null);
const [editingTabName, setEditingTabName] = useState<string | null>(null);
const [renamingTabValue, setRenamingTabValue] = useState("");
const [newTabForListId, setNewTabForListId] = useState<string | null>(null);
const [newTabNameValue, setNewTabNameValue] = useState("");
useEffect(() => {
if (typeof window !== "undefined") {
@ -6486,6 +6488,22 @@ export default function WeeklyView() {
</div>
)}
<div ref={somedayGridRef} style={{ flex: 1, minWidth: 0, overflowX: "auto" }}>
{/* Mobile tabs bar (visible only on small screens) */}
{somedayExpanded && somedayTabs.length > 0 && (
<div className="someday-tabs-mobile">
<button
className={`someday-tab-btn-h ${activeSomedayTab === null ? "active" : ""}`}
onClick={() => setSomedayTab(null)}
>{t.allTabs}</button>
{somedayTabs.map(tab => (
<button
key={tab}
className={`someday-tab-btn-h ${activeSomedayTab === tab ? "active" : ""}`}
onClick={() => setSomedayTab(tab)}
>{tab}</button>
))}
</div>
)}
{somedayExpanded && (
<div
className={`weekly-someday-lists-grid cols-${Math.min(7, Math.max(1, viewDays))}`}
@ -6759,8 +6777,9 @@ export default function WeeklyView() {
onChange={(e) => {
const val = e.target.value;
if (val === "__new__") {
const name = prompt(t.newTabName || "New tab name:");
if (name?.trim()) assignListToTab(list.id, name.trim());
e.target.value = list.tab || "";
setNewTabForListId(list.id);
setNewTabNameValue("");
} else {
assignListToTab(list.id, val || null);
}
@ -6781,6 +6800,40 @@ export default function WeeklyView() {
<option value="__new__">+ {t.newTab || "New tab"}</option>
</select>
</div>
{newTabForListId === list.id && (
<input
className="someday-tab-new-input"
value={newTabNameValue}
onChange={(e) => setNewTabNameValue(e.target.value)}
onBlur={() => {
if (newTabNameValue.trim()) {
assignListToTab(list.id, newTabNameValue.trim());
}
setNewTabForListId(null);
setNewTabNameValue("");
}}
onKeyDown={(e) => {
if (e.key === "Enter") e.currentTarget.blur();
if (e.key === "Escape") {
setNewTabForListId(null);
setNewTabNameValue("");
}
}}
placeholder={t.newTabName || "Tab name..."}
autoFocus
onClick={(e) => e.stopPropagation()}
style={{
fontSize: "0.7rem",
border: "1px solid var(--weekly-border)",
borderRadius: "4px",
padding: "2px 6px",
background: "var(--weekly-bg)",
color: "var(--weekly-text)",
width: "80px",
outline: "none",
}}
/>
)}
<button
className="someday-list-delete-btn"
onClick={(e) => {