updated apps
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -17,5 +17,5 @@
|
||||
"iot_class": "calculated",
|
||||
"issue_tracker": "https://github.com/tempus2016/taskmate/issues",
|
||||
"requirements": [],
|
||||
"version": "4.5.0"
|
||||
"version": "4.5.1"
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@
|
||||
"panel.btn_deactivate_chore": "Aufgabe deaktivieren",
|
||||
"panel.btn_delete": "Löschen",
|
||||
"panel.btn_edit": "Bearbeiten",
|
||||
"panel.btn_from_template": "Aus Vorlage",
|
||||
"panel.btn_from_template": "Aus Vorlage erstellen",
|
||||
"panel.btn_reorder_chores": "Neu ordnen",
|
||||
"panel.btn_retry": "Wiederholen",
|
||||
"panel.btn_review": "Überprüfen",
|
||||
|
||||
@@ -562,7 +562,7 @@
|
||||
"panel.btn_delete": "Delete",
|
||||
"panel.btn_edit": "Edit",
|
||||
"panel.btn_clone_chore": "Duplicate",
|
||||
"panel.btn_from_template": "From template",
|
||||
"panel.btn_from_template": "Create from template",
|
||||
"panel.btn_reorder_chores": "Reorder",
|
||||
"panel.btn_retry": "Retry",
|
||||
"panel.btn_review": "Review",
|
||||
|
||||
@@ -562,7 +562,7 @@
|
||||
"panel.btn_delete": "Delete",
|
||||
"panel.btn_edit": "Edit",
|
||||
"panel.btn_clone_chore": "Duplicate",
|
||||
"panel.btn_from_template": "From template",
|
||||
"panel.btn_from_template": "Create from template",
|
||||
"panel.btn_reorder_chores": "Reorder",
|
||||
"panel.btn_retry": "Retry",
|
||||
"panel.btn_review": "Review",
|
||||
|
||||
@@ -531,7 +531,7 @@
|
||||
"panel.btn_deactivate_chore": "Désactiver la tâche",
|
||||
"panel.btn_delete": "Supprimer",
|
||||
"panel.btn_edit": "Modifier",
|
||||
"panel.btn_from_template": "Depuis un modèle",
|
||||
"panel.btn_from_template": "Créer depuis un modèle",
|
||||
"panel.btn_reorder_chores": "Réorganiser",
|
||||
"panel.btn_retry": "Réessayer",
|
||||
"panel.btn_review": "Vérifier",
|
||||
|
||||
@@ -531,7 +531,7 @@
|
||||
"panel.btn_deactivate_chore": "Deaktiver oppgave",
|
||||
"panel.btn_delete": "Slett",
|
||||
"panel.btn_edit": "Rediger",
|
||||
"panel.btn_from_template": "Fra mal",
|
||||
"panel.btn_from_template": "Opprett fra mal",
|
||||
"panel.btn_reorder_chores": "Omorganiser",
|
||||
"panel.btn_retry": "Prøv igjen",
|
||||
"panel.btn_review": "Gjennomgå",
|
||||
|
||||
@@ -531,7 +531,7 @@
|
||||
"panel.btn_deactivate_chore": "Deaktiver oppgåve",
|
||||
"panel.btn_delete": "Slett",
|
||||
"panel.btn_edit": "Rediger",
|
||||
"panel.btn_from_template": "Frå mal",
|
||||
"panel.btn_from_template": "Opprett frå mal",
|
||||
"panel.btn_reorder_chores": "Omorganiser",
|
||||
"panel.btn_retry": "Prøv på nytt",
|
||||
"panel.btn_review": "Gjennomgå",
|
||||
|
||||
@@ -531,7 +531,7 @@
|
||||
"panel.btn_deactivate_chore": "Desativar tarefa",
|
||||
"panel.btn_delete": "Excluir",
|
||||
"panel.btn_edit": "Editar",
|
||||
"panel.btn_from_template": "De modelo",
|
||||
"panel.btn_from_template": "Criar de modelo",
|
||||
"panel.btn_reorder_chores": "Reordenar",
|
||||
"panel.btn_retry": "Tentar novamente",
|
||||
"panel.btn_review": "Revisar",
|
||||
|
||||
@@ -536,7 +536,7 @@
|
||||
"panel.btn_deactivate_chore": "Desativar tarefa",
|
||||
"panel.btn_delete": "Eliminar",
|
||||
"panel.btn_edit": "Editar",
|
||||
"panel.btn_from_template": "A partir de modelo",
|
||||
"panel.btn_from_template": "Criar a partir de modelo",
|
||||
"panel.btn_reorder_chores": "Reordenar",
|
||||
"panel.btn_retry": "Tentar novamente",
|
||||
"panel.btn_review": "Rever",
|
||||
|
||||
@@ -206,6 +206,7 @@ class TaskMateApprovalsCard extends LitElement {
|
||||
|
||||
.item-details {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 0.85em;
|
||||
|
||||
@@ -87,14 +87,16 @@ class TaskMateCalendarCard extends LitElement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
row-gap: 8px;
|
||||
padding: 14px 18px;
|
||||
background: var(--taskmate-header-bg, #3498db);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header-content { display: flex; align-items: center; gap: 10px; }
|
||||
.header-icon { --mdc-icon-size: 28px; opacity: 0.9; }
|
||||
.header-title { font-size: 1.2rem; font-weight: 600; }
|
||||
.header-content { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
||||
.header-icon { --mdc-icon-size: 28px; opacity: 0.9; flex: none; }
|
||||
.header-title { font-size: 1.2rem; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
|
||||
.day-nav {
|
||||
display: flex;
|
||||
@@ -250,7 +252,7 @@ class TaskMateCalendarCard extends LitElement {
|
||||
.cal-head { margin-bottom: 8px; }
|
||||
.cal-name { font-weight: 800; }
|
||||
.cal-chips { gap: 7px; flex-wrap: wrap; }
|
||||
.cal-chip { white-space: nowrap; }
|
||||
.cal-chip { white-space: normal; overflow-wrap: anywhere; }
|
||||
.cal-empty-line { font-size: 12px; font-style: italic; }
|
||||
.cal-card-pl { background: var(--tmd-surface-2); border-radius: 18px; padding: 11px 12px; }
|
||||
|
||||
|
||||
@@ -201,8 +201,9 @@ class TaskMateGraphCard extends LitElement {
|
||||
.empty-state .submessage { font-size: 0.85rem; margin-top: 4px; }
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.card-header { padding: 12px 14px; }
|
||||
.card-header { padding: 12px 14px; flex-wrap: wrap; row-gap: 8px; }
|
||||
.header-title { font-size: 1rem; }
|
||||
.mode-toggle { flex-shrink: 1; }
|
||||
.mode-btn { padding: 3px 8px; font-size: 0.7rem; }
|
||||
.card-content { padding: 12px; }
|
||||
}
|
||||
|
||||
@@ -262,6 +262,7 @@ export function createIncentiveCard(P) {
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.form-field label { font-size: 0.8rem; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.4px; }
|
||||
.form-field input {
|
||||
@@ -342,7 +343,9 @@ export function createIncentiveCard(P) {
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
animation: toast-in 0.25s ease, toast-out 0.3s ease 2s forwards;
|
||||
white-space: nowrap;
|
||||
white-space: normal;
|
||||
max-width: calc(100vw - 32px);
|
||||
text-align: center;
|
||||
}
|
||||
@keyframes toast-in {
|
||||
from { opacity: 0; transform: translateX(-50%) translateY(12px); }
|
||||
|
||||
@@ -324,6 +324,7 @@ class TaskMateOverviewCard extends LitElement {
|
||||
|
||||
/* Overview — children grid */
|
||||
.ov-kids { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; max-height: 360px; overflow-y: auto; }
|
||||
@media (max-width: 480px) { .ov-kids { grid-template-columns: repeat(2, 1fr); } }
|
||||
.ov-kid { text-align: center; padding: 11px; border-radius: 16px; background: var(--tmd-surface-2); position: relative; }
|
||||
.ov-kid.tm-clickable { cursor: pointer; }
|
||||
.ov-kid-flags { position: absolute; top: 6px; right: 7px; display: flex; gap: 4px; }
|
||||
|
||||
@@ -133,6 +133,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
this._bulkMode = false; // chores multi-select mode
|
||||
this._bulkSel = new Set(); // selected chore ids for bulk actions
|
||||
this._activeTab = "children";
|
||||
this._mobileNavOpen = false; // mobile section-picker dropdown state
|
||||
this._dialog = null;
|
||||
this._dialogInitialHash = null; // for confirm-on-leave
|
||||
this._filter = ""; // per-tab search/filter
|
||||
@@ -413,11 +414,13 @@ class TaskMatePanel extends HTMLElement {
|
||||
const act = t.dataset.act;
|
||||
|
||||
if (act === "tab") {
|
||||
this._activeTab = t.dataset.tab; this._filter = ""; this._render();
|
||||
this._activeTab = t.dataset.tab; this._filter = ""; this._mobileNavOpen = false; this._render();
|
||||
// Settings tab lists HA users for the parent-role picker (#661); load then repaint.
|
||||
if (this._activeTab === "settings") this._ensureHaUsers().then(() => this._render());
|
||||
return;
|
||||
}
|
||||
if (act === "toggle-mobile-nav") { this._mobileNavOpen = !this._mobileNavOpen; this._render(); return; }
|
||||
if (act === "close-mobile-nav") { this._mobileNavOpen = false; this._render(); return; }
|
||||
if (act === "close-dialog") { this._closeDialog(); return; }
|
||||
if (act === "clear-field") { this._setEntityField(t.dataset.field, ""); this._render(); return; }
|
||||
if (act === "pick-entity") { this._setEntityField(t.dataset.field, t.dataset.value); this._closeEntityDropdown(); this._render(); return; }
|
||||
@@ -2136,7 +2139,6 @@ class TaskMatePanel extends HTMLElement {
|
||||
this._zoneCache = {};
|
||||
this._applyDesign();
|
||||
this._bindHaPickers();
|
||||
this._scrollActiveMobileTabIntoView();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2157,10 +2159,6 @@ class TaskMatePanel extends HTMLElement {
|
||||
savedScroll = dialogBody ? dialogBody.scrollTop : 0;
|
||||
}
|
||||
|
||||
const mtabsZone = this.querySelector('[data-zone="mtabs"]');
|
||||
const existingMtabs = mtabsZone ? mtabsZone.querySelector(".tm-mobile-tabs") : null;
|
||||
const savedMtabsScroll = existingMtabs ? existingMtabs.scrollLeft : 0;
|
||||
|
||||
if (this._dialog) {
|
||||
const openSet = this._dialog._openAdvanced instanceof Set ? this._dialog._openAdvanced : new Set();
|
||||
this.querySelectorAll("details.tm-advanced[data-section]").forEach(el => {
|
||||
@@ -2190,13 +2188,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
if (newBody) newBody.scrollTop = savedScroll;
|
||||
}
|
||||
|
||||
if (savedMtabsScroll) {
|
||||
const newMtabs = this.querySelector(".tm-mobile-tabs");
|
||||
if (newMtabs) newMtabs.scrollLeft = savedMtabsScroll;
|
||||
}
|
||||
|
||||
this._applyDesign();
|
||||
this._scrollActiveMobileTabIntoView();
|
||||
}
|
||||
|
||||
// The admin panel intentionally stays CLASSIC regardless of the global card
|
||||
@@ -2207,19 +2199,6 @@ class TaskMatePanel extends HTMLElement {
|
||||
if (shell) shell.removeAttribute("data-tm-design");
|
||||
}
|
||||
|
||||
_scrollActiveMobileTabIntoView() {
|
||||
const nav = this.querySelector(".tm-mobile-tabs");
|
||||
if (!nav) return;
|
||||
const active = nav.querySelector(".tm-mtab-active");
|
||||
if (!active) return;
|
||||
const navRect = nav.getBoundingClientRect();
|
||||
const btnRect = active.getBoundingClientRect();
|
||||
if (btnRect.left < navRect.left || btnRect.right > navRect.right) {
|
||||
const target = active.offsetLeft - (nav.clientWidth - active.offsetWidth) / 2;
|
||||
nav.scrollTo({ left: Math.max(0, target), behavior: "smooth" });
|
||||
}
|
||||
}
|
||||
|
||||
_sidebarGroups() {
|
||||
const counts = this._state ? {
|
||||
children: (this._state.children || []).length,
|
||||
@@ -2324,19 +2303,43 @@ class TaskMatePanel extends HTMLElement {
|
||||
|
||||
_mobileTabs() {
|
||||
const groups = this._sidebarGroups();
|
||||
const open = !!this._mobileNavOpen;
|
||||
const current = groups.flatMap(g => g.items).find(it => it.id === this._activeTab)
|
||||
|| { id: this._activeTab, label: "", icon: "mdi:cog-outline" };
|
||||
const curUrgent = current.id === "activity" && current.count > 0;
|
||||
const curShowCount = current.count != null && current.count > 0;
|
||||
return `
|
||||
<nav class="tm-mobile-tabs">
|
||||
${groups.flatMap(g => g.items).map(it => {
|
||||
const active = it.id === this._activeTab;
|
||||
const urgent = it.id === "activity" && it.count > 0;
|
||||
const showCount = it.count != null && it.count > 0;
|
||||
return `
|
||||
<button type="button" class="tm-mtab ${active ? "tm-mtab-active" : ""}" data-act="tab" data-tab="${it.id}">
|
||||
${this._esc(it.label)}${showCount ? `<span class="tm-mtab-pill ${urgent ? "tm-mtab-pill-urgent" : ""}">${it.count}</span>` : ""}
|
||||
</button>
|
||||
`;
|
||||
}).join("")}
|
||||
</nav>
|
||||
<div class="tm-mobilenav ${open ? "tm-mobilenav-open" : ""}">
|
||||
<button type="button" class="tm-mnav-trigger" data-act="toggle-mobile-nav"
|
||||
aria-haspopup="true" aria-expanded="${open ? "true" : "false"}">
|
||||
<span class="tm-mnav-ico"><ha-icon icon="${this._esc(current.icon)}"></ha-icon></span>
|
||||
<span class="tm-mnav-main">
|
||||
<span class="tm-mnav-crumb">TaskMate</span>
|
||||
<span class="tm-mnav-title">${this._esc(current.label)}</span>
|
||||
</span>
|
||||
${curShowCount ? `<span class="tm-mnav-count ${curUrgent ? "tm-mnav-count-urgent" : ""}">${current.count}</span>` : ""}
|
||||
<span class="tm-mnav-chev"><ha-icon icon="mdi:chevron-down"></ha-icon></span>
|
||||
</button>
|
||||
${open ? `
|
||||
<div class="tm-mnav-scrim" data-act="close-mobile-nav"></div>
|
||||
<nav class="tm-mnav-sheet">
|
||||
${groups.map(g => `
|
||||
<div class="tm-mnav-grp-head">${this._esc(g.head)}</div>
|
||||
${g.items.map(it => {
|
||||
const active = it.id === this._activeTab;
|
||||
const urgent = it.id === "activity" && it.count > 0;
|
||||
const showCount = it.count != null && it.count > 0;
|
||||
return `
|
||||
<button type="button" class="tm-mnav-item ${active ? "tm-mnav-item-active" : ""}" data-act="tab" data-tab="${it.id}">
|
||||
<ha-icon class="tm-mnav-item-ico" icon="${this._esc(it.icon)}"></ha-icon>
|
||||
<span class="tm-mnav-item-label">${this._esc(it.label)}</span>
|
||||
${showCount ? `<span class="tm-mnav-count ${urgent ? "tm-mnav-count-urgent" : ""}">${it.count}</span>` : ""}
|
||||
</button>`;
|
||||
}).join("")}
|
||||
`).join("")}
|
||||
</nav>
|
||||
` : ""}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -2441,7 +2444,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
<div class="tm-meta">${child.availability_entity ? `<code>${this._esc(child.availability_entity)}</code>${child.availability_inverted ? ` <em>${this._t("panel.child_inverted")}</em>` : ""}` : `${this._t("panel.child_no_availability")}`}${child.unavailability_entity ? ` · ${this._t("panel.child_busy_label")} <code>${this._esc(child.unavailability_entity)}</code>` : ""}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tm-stats-row">
|
||||
<div class="tm-stats-row" style="grid-template-columns: 1fr 1fr;">
|
||||
<div class="tm-stat tm-stat-highlight"><div class="tm-stat-value">${this._fmtNum(child.points || 0)}</div><div class="tm-stat-label">${this._esc(pointsName)}</div></div>
|
||||
<div class="tm-stat"><div class="tm-stat-value">${this._fmtNum(child.level || 1)}</div><div class="tm-stat-label">${this._t("panel.child_stat_level")}</div></div>
|
||||
<div class="tm-stat"><div class="tm-stat-value">${this._fmtNum(child.total_points_earned || 0)}</div><div class="tm-stat-label">${this._t("panel.child_stat_earned")}</div></div>
|
||||
@@ -3381,7 +3384,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
const count = (tpl.chores || []).length;
|
||||
const pts = (tpl.chores || []).reduce((s, c) => s + (c.points || 0), 0);
|
||||
return `
|
||||
<div class="tm-manage-tpl ${locked ? "tm-manage-tpl-locked" : ""}">
|
||||
<div class="tm-manage-tpl ${locked ? "tm-manage-tpl-locked" : ""}" data-act="tpl-select" data-id="${this._esc(tpl.id)}" style="cursor:pointer">
|
||||
<div class="tm-tpl-icon"><ha-icon icon="${this._esc(tpl.icon || "mdi:clipboard-list")}"></ha-icon></div>
|
||||
<div class="tm-manage-tpl-info">
|
||||
<div class="tm-manage-tpl-name">${this._esc(tpl.name)}${locked ? ' <span class="tm-text-vfaint" style="font-size:12px">🔒</span>' : ""}</div>
|
||||
@@ -3740,9 +3743,9 @@ class TaskMatePanel extends HTMLElement {
|
||||
</div></div>
|
||||
<div class="tm-section-body">
|
||||
${(this._haUsers || []).filter(u => !u.is_admin).map(u => `
|
||||
<label class="tm-setting-row" style="cursor:pointer">
|
||||
<label class="tm-setting-row tm-role-row">
|
||||
<div class="tm-setting-label">${this._esc(u.name)}</div>
|
||||
<input type="checkbox" data-parent-user="${this._esc(u.id)}" ${(s.parent_user_ids || []).includes(u.id) ? "checked" : ""}>
|
||||
<input type="checkbox" class="tm-role-check" data-parent-user="${this._esc(u.id)}" ${(s.parent_user_ids || []).includes(u.id) ? "checked" : ""}>
|
||||
</label>`).join("")
|
||||
|| `<p class="tm-meta">${this._t("panel.settings_parents_empty")}</p>`}
|
||||
</div>
|
||||
@@ -4084,7 +4087,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
<h4>${this._t("panel.notif_recipients_parents")}</h4>
|
||||
${ns.recipients.parents.map(p => `
|
||||
<div class="tm-row" style="display:flex;gap:10px;align-items:center;padding:8px 0;border-top:1px solid var(--tm-border,#3a3a3a)">
|
||||
<input type="text" value="${this._esc(p.name)}" data-act="notif-rename-parent" data-parent-id="${this._esc(p.id)}" style="flex:1;background:transparent;border:none;color:inherit;font-size:14px;font-weight:500">
|
||||
<input type="text" value="${this._esc(p.name)}" data-act="notif-rename-parent" data-parent-id="${this._esc(p.id)}" style="flex:1;min-width:60px;background:transparent;border:none;color:inherit;font-size:14px;font-weight:500">
|
||||
<select class="tm-notif-select" data-act="notif-set-parent-notify" data-parent-id="${this._esc(p.id)}">
|
||||
${optTags(p.notify_service)}
|
||||
</select>
|
||||
@@ -4127,7 +4130,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
<td>
|
||||
<div style="display:flex;gap:10px;align-items:flex-start">
|
||||
<input type="checkbox" class="tm-notif-switch" data-act="notif-set-master" data-type-id="${this._esc(t.id)}" ${active ? "checked" : ""}>
|
||||
<div>
|
||||
<div style="max-width:240px;white-space:normal">
|
||||
<strong>${this._t("notification." + t.id + ".name")}</strong>
|
||||
<div class="tm-meta">${this._t("notification." + t.id + ".description")}</div>
|
||||
${t.id === "streak_at_risk" ? `
|
||||
@@ -4183,8 +4186,8 @@ class TaskMatePanel extends HTMLElement {
|
||||
_renderNotifCustomSection(ns, recipients) {
|
||||
return `
|
||||
<div class="tm-card" style="margin-bottom:16px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<h3>${this._t("panel.notif_section_custom")}</h3>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:10px;justify-content:space-between;align-items:center">
|
||||
<h3 style="margin:0">${this._t("panel.notif_section_custom")}</h3>
|
||||
<button type="button" class="tm-btn tm-btn-raised" data-act="notif-add-custom">+ ${this._t("panel.notif_add_custom")}</button>
|
||||
</div>
|
||||
<p class="tm-meta">${this._t("panel.notif_section_custom_desc")}</p>
|
||||
@@ -5426,8 +5429,8 @@ class TaskMatePanel extends HTMLElement {
|
||||
}
|
||||
@keyframes tm-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.45; } }
|
||||
|
||||
/* ===== Mobile tabs (hidden by default, shown on narrow) ===== */
|
||||
.tm-mobile-tabs { display: none; }
|
||||
/* ===== Mobile section picker (hidden by default, shown on narrow) ===== */
|
||||
.tm-mobilenav { display: none; }
|
||||
|
||||
/* Approval banner */
|
||||
.tm-approval-banner {
|
||||
@@ -5945,6 +5948,11 @@ class TaskMatePanel extends HTMLElement {
|
||||
border-top: 1px solid var(--tm-border-soft);
|
||||
}
|
||||
.tm-setting-row:first-child { border-top: 0; }
|
||||
.tm-role-row { grid-template-columns: 1fr auto; cursor: pointer; }
|
||||
.tm-role-check {
|
||||
width: 20px; height: 20px; margin: 0;
|
||||
justify-self: end; accent-color: var(--tm-accent); cursor: pointer;
|
||||
}
|
||||
.tm-setting-label { color: var(--tm-text); font-size: 13px; font-weight: 500; }
|
||||
.tm-setting-label small { display: block; color: var(--tm-text-faint); font-weight: 400; font-size: 12px; margin-top: 2px; }
|
||||
.tm-difficulty-mults { display: flex; gap: 12px; flex-wrap: wrap; }
|
||||
@@ -5965,7 +5973,17 @@ class TaskMatePanel extends HTMLElement {
|
||||
grid-template-columns: 56px minmax(140px, 1fr) auto 36px;
|
||||
gap: 12px;
|
||||
}
|
||||
.tm-period-row ha-icon-picker { max-width: 56px; }
|
||||
.tm-period-row ha-icon-picker {
|
||||
width: 56px; max-width: 56px; height: 56px;
|
||||
border-radius: var(--tm-radius-sm, 8px); overflow: hidden;
|
||||
/* Older HA renders the picker as a filled mwc-textfield: drop the fill
|
||||
and its dark active-indicator line so no stray underline shows. */
|
||||
--mdc-text-field-fill-color: transparent;
|
||||
--mdc-text-field-idle-line-color: transparent;
|
||||
--mdc-text-field-hover-line-color: transparent;
|
||||
--mdc-text-field-focused-line-color: transparent;
|
||||
--mdc-text-field-disabled-line-color: transparent;
|
||||
}
|
||||
.tm-period-row > .tm-input { max-width: none; }
|
||||
.tm-vacation-row {
|
||||
grid-template-columns: minmax(140px, 1fr) auto 36px;
|
||||
@@ -6563,7 +6581,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
background: var(--tm-surface-0); border: 1px solid var(--tm-border);
|
||||
border-radius: var(--tm-radius-sm); padding: 7px 10px;
|
||||
color: var(--tm-text); font-size: 12.5px; font-family: inherit;
|
||||
cursor: pointer; max-width: 240px; transition: border-color 0.1s;
|
||||
cursor: pointer; min-width: 0; max-width: 240px; transition: border-color 0.1s;
|
||||
}
|
||||
.tm-notif-select:hover { border-color: var(--tm-border-strong); }
|
||||
.tm-notif-select:focus { outline: 0; border-color: var(--tm-accent); box-shadow: var(--tm-shadow-focus); }
|
||||
@@ -6602,54 +6620,112 @@ class TaskMatePanel extends HTMLElement {
|
||||
.tm-sidebar { display: none; }
|
||||
.tm-menu-btn { display: inline-flex; }
|
||||
.tm-topbar { padding: 0 12px; }
|
||||
.tm-mobile-tabs {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
overscroll-behavior: contain;
|
||||
touch-action: pan-x;
|
||||
scrollbar-width: none;
|
||||
padding: 0 12px;
|
||||
/* Redundant with the section picker below — hide on mobile. */
|
||||
.tm-crumbs { display: none; }
|
||||
.tm-approval-pill { margin-left: auto; }
|
||||
|
||||
/* Section picker replaces the old horizontal tab strip. */
|
||||
.tm-main { position: relative; }
|
||||
.tm-mobilenav {
|
||||
display: block;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
flex-shrink: 0;
|
||||
background: var(--tm-surface-0);
|
||||
border-bottom: 1px solid var(--tm-border);
|
||||
flex-shrink: 0;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.tm-mobile-tabs::-webkit-scrollbar { display: none; }
|
||||
.tm-mtab {
|
||||
position: relative;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: var(--tm-text-faint);
|
||||
padding: 12px 14px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
white-space: nowrap;
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
transition: color 0.1s var(--tm-easing);
|
||||
}
|
||||
.tm-mtab:hover { color: var(--tm-text); }
|
||||
.tm-mtab-active { color: var(--tm-text); }
|
||||
.tm-mtab-active::after {
|
||||
content: ""; position: absolute;
|
||||
left: 14px; right: 14px; bottom: -1px;
|
||||
height: 2px; background: var(--tm-accent);
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
.tm-mtab-pill {
|
||||
.tm-mnav-trigger {
|
||||
width: 100%;
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
background: var(--tm-surface-2);
|
||||
color: var(--tm-text-muted);
|
||||
font-size: 10.5px; font-weight: 600;
|
||||
padding: 1px 6px; border-radius: 999px;
|
||||
border: 1px solid var(--tm-border);
|
||||
border-radius: var(--tm-radius-md, 12px);
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
color: var(--tm-text);
|
||||
text-align: left;
|
||||
transition: background 0.12s var(--tm-easing), border-color 0.12s var(--tm-easing);
|
||||
}
|
||||
.tm-mtab-active .tm-mtab-pill {
|
||||
.tm-mnav-trigger:active { background: var(--tm-surface-3); }
|
||||
.tm-mobilenav-open .tm-mnav-trigger { border-color: var(--tm-accent); }
|
||||
.tm-mnav-ico {
|
||||
width: 30px; height: 30px; flex-shrink: 0;
|
||||
border-radius: var(--tm-radius-sm, 8px);
|
||||
background: var(--tm-accent-soft);
|
||||
color: var(--tm-accent-text);
|
||||
display: grid; place-items: center;
|
||||
--mdc-icon-size: 20px;
|
||||
}
|
||||
.tm-mtab-pill-urgent {
|
||||
background: var(--tm-warning-soft) !important;
|
||||
color: var(--tm-warning) !important;
|
||||
.tm-mnav-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
||||
.tm-mnav-crumb { font-size: 11px; color: var(--tm-text-faint); line-height: 1.2; }
|
||||
.tm-mnav-title {
|
||||
font-size: 15px; font-weight: 600; line-height: 1.25;
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
}
|
||||
.tm-mnav-chev {
|
||||
color: var(--tm-text-muted); flex-shrink: 0;
|
||||
--mdc-icon-size: 22px;
|
||||
transition: transform 0.18s var(--tm-easing);
|
||||
}
|
||||
.tm-mobilenav-open .tm-mnav-chev { transform: rotate(180deg); }
|
||||
.tm-mnav-count {
|
||||
flex-shrink: 0;
|
||||
background: var(--tm-surface-0);
|
||||
border: 1px solid var(--tm-border);
|
||||
color: var(--tm-text-muted);
|
||||
font-size: 11px; font-weight: 600;
|
||||
padding: 1px 7px; border-radius: 999px;
|
||||
}
|
||||
.tm-mnav-count-urgent {
|
||||
background: var(--tm-warning-soft);
|
||||
border-color: transparent;
|
||||
color: var(--tm-warning);
|
||||
}
|
||||
.tm-mnav-scrim {
|
||||
position: absolute;
|
||||
top: 100%; left: 0; right: 0;
|
||||
height: 100vh;
|
||||
background: rgba(10, 15, 22, 0.32);
|
||||
z-index: 30;
|
||||
animation: tm-mnav-fade 0.18s var(--tm-easing);
|
||||
}
|
||||
.tm-mnav-sheet {
|
||||
position: absolute;
|
||||
top: calc(100% + 6px); left: 8px; right: 8px;
|
||||
z-index: 31;
|
||||
background: var(--tm-surface-0);
|
||||
border: 1px solid var(--tm-border);
|
||||
border-radius: var(--tm-radius-md, 14px);
|
||||
box-shadow: 0 20px 48px rgba(0, 0, 0, 0.24);
|
||||
max-height: calc(100vh - 200px);
|
||||
overflow-y: auto;
|
||||
padding: 4px 0 8px;
|
||||
animation: tm-mnav-drop 0.18s var(--tm-easing);
|
||||
}
|
||||
.tm-mnav-grp-head {
|
||||
font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
|
||||
text-transform: uppercase; color: var(--tm-text-faint);
|
||||
padding: 12px 16px 4px;
|
||||
}
|
||||
.tm-mnav-item {
|
||||
display: flex; align-items: center; gap: 12px; width: 100%;
|
||||
background: none; border: 0; font-family: inherit; cursor: pointer;
|
||||
padding: 11px 16px; color: var(--tm-text); text-align: left;
|
||||
}
|
||||
.tm-mnav-item:active { background: var(--tm-surface-2); }
|
||||
.tm-mnav-item-ico {
|
||||
flex-shrink: 0; color: var(--tm-text-muted);
|
||||
--mdc-icon-size: 20px;
|
||||
}
|
||||
.tm-mnav-item-label { flex: 1; font-size: 15px; }
|
||||
.tm-mnav-item-active { background: var(--tm-accent-soft); color: var(--tm-accent-text); }
|
||||
.tm-mnav-item-active .tm-mnav-item-ico { color: var(--tm-accent-text); }
|
||||
@keyframes tm-mnav-fade { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes tm-mnav-drop {
|
||||
from { opacity: 0; transform: translateY(-8px) scale(0.985); }
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
.tm-body { padding: 16px; }
|
||||
.tm-toolbar { flex-direction: column; align-items: stretch; }
|
||||
@@ -6658,6 +6734,7 @@ class TaskMatePanel extends HTMLElement {
|
||||
.tm-scrim { padding: 0; }
|
||||
.tm-dialog-body .tm-field-row { grid-template-columns: 1fr; }
|
||||
.tm-setting-row { grid-template-columns: 1fr; gap: 6px; padding: 12px 16px; }
|
||||
.tm-role-row { grid-template-columns: 1fr auto; gap: 12px; align-items: center; }
|
||||
.tm-section-head, .tm-setting-row { padding-left: 16px; padding-right: 16px; }
|
||||
.tm-timeline-row { grid-template-columns: 1fr auto; }
|
||||
.tm-timeline-time, .tm-timeline-icon { display: none; }
|
||||
|
||||
@@ -311,8 +311,8 @@ class TaskMatePointsCard extends LitElement {
|
||||
background: var(--card-background-color, white);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
min-width: 300px;
|
||||
max-width: 400px;
|
||||
min-width: 0;
|
||||
max-width: min(400px, calc(100vw - 24px));
|
||||
box-shadow: var(--ha-card-box-shadow, 0 8px 32px rgba(0, 0, 0, 0.2));
|
||||
animation: slide-up 0.3s ease;
|
||||
}
|
||||
@@ -480,6 +480,8 @@ class TaskMatePointsCard extends LitElement {
|
||||
bottom: 24px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
max-width: calc(100vw - 24px);
|
||||
white-space: normal;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
color: var(--text-primary-color, #fff);
|
||||
|
||||
@@ -237,6 +237,7 @@ class TaskMateRewardProgressCard extends LitElement {
|
||||
|
||||
.progress-stat-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 0.82rem;
|
||||
@@ -426,6 +427,7 @@ class TaskMateRewardProgressCard extends LitElement {
|
||||
.rp-frac { font-size: 18px; }
|
||||
.rp-need { font-size: 12px; }
|
||||
.rp-kids { grid-template-columns: repeat(var(--n, 3), 1fr); gap: 9px; margin-top: 16px; }
|
||||
@media (max-width: 430px) { .rp-kids { grid-template-columns: repeat(auto-fit, minmax(64px, 1fr)); } }
|
||||
.rp-kid { background: var(--tmd-surface-2); border: 1px solid var(--tmd-border);
|
||||
border-radius: var(--tmd-radius-sm); padding: 10px; display: flex;
|
||||
flex-direction: column; align-items: center; gap: 4px; }
|
||||
|
||||
@@ -302,7 +302,7 @@ class TaskMateRewardsCard extends LitElement {
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
white-space: nowrap;
|
||||
min-width: 70px;
|
||||
min-width: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ class TaskMateRewardsCard extends LitElement {
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 400px) {
|
||||
@media (max-width: 430px) {
|
||||
.card-header {
|
||||
padding: 14px 18px;
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ class TaskMateStreakCard extends LitElement {
|
||||
border-radius: 10px; padding: 11px; }
|
||||
.sk-combo-label { font-size: 10px; }
|
||||
.sk-combo { font-size: 24px; color: var(--tmd-accent); }
|
||||
.sk-segs { display: flex; gap: 4px; margin-top: 9px; }
|
||||
.sk-segs { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 9px; }
|
||||
.sk-seg { flex: 1; height: 8px; border-radius: 2px; background: #0b1424; }
|
||||
.sk-seg.on { background: var(--tmd-accent);
|
||||
box-shadow: 0 0 8px color-mix(in srgb, var(--tmd-accent) 70%, transparent); }
|
||||
@@ -243,7 +243,7 @@ class TaskMateStreakCard extends LitElement {
|
||||
/* Clean Pro */
|
||||
.sk-grid-cp { display: flex; flex-direction: column; gap: 13px; }
|
||||
.sk-row-cp .num { font-size: 17px; }
|
||||
.sk-segs-cp { display: flex; gap: 5px; margin-top: 8px; }
|
||||
.sk-segs-cp { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
|
||||
.sk-seg-cp { flex: 1; height: 9px; border-radius: 3px; background: var(--tmd-surface-2); }
|
||||
.sk-seg-cp.on { background: var(--tmd-good); }
|
||||
.sk-badges-cp { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 9px; }
|
||||
|
||||
Reference in New Issue
Block a user