updated apps
This commit is contained in:
@@ -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