Skip to content
Merged

css #357

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions selfdrive/carrot/web/css/pages/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -536,10 +536,7 @@
overflow: hidden;
opacity: 1;
transform: translateY(0);
transition:
grid-template-rows 0.24s cubic-bezier(.2, 0, 0, 1),
opacity 0.16s ease,
transform 0.2s cubic-bezier(.2, 0, 0, 1);
will-change: grid-template-rows, opacity, transform;
}

.setting-profile-section.is-collapsed .setting-profile-section__body {
Expand All @@ -554,6 +551,15 @@
overflow: hidden;
}

.setting-profile-section.is-collapsing .setting-profile-section__body {
pointer-events: none;
animation: setting-profile-section-fold 0.24s cubic-bezier(.2, 0, 0, 1) both;
}

.setting-profile-section.is-expanding .setting-profile-section__body {
animation: setting-profile-section-fold 0.24s cubic-bezier(.2, 0, 0, 1) reverse both;
}

.setting-subnav__tab--profile {
border-color: color-mix(in srgb, var(--md-primary) 34%, var(--md-outline-var));
}
Expand Down Expand Up @@ -760,16 +766,30 @@
}
}

@keyframes setting-profile-section-fold {
from {
grid-template-rows: 1fr;
opacity: 1;
transform: translateY(0);
}
to {
grid-template-rows: 0fr;
opacity: 0;
transform: translateY(-4px);
}
}

@media (prefers-reduced-motion: reduce) {
.setting-profile-panel,
.page--setting #items > .setting.ui-stagger-item,
.page--setting #items > .setting-profile-section.ui-stagger-item,
.page--setting #deviceItems > .setting.ui-stagger-item {
.page--setting #deviceItems > .setting.ui-stagger-item,
.setting-profile-section.is-collapsing .setting-profile-section__body,
.setting-profile-section.is-expanding .setting-profile-section__body {
animation: none;
}

.setting-profile-section__header,
.setting-profile-section__body,
.setting-profile-section__chevron,
.setting-toolbar-action {
transition: none;
Expand Down Expand Up @@ -1222,7 +1242,8 @@
display: none;
}

.page--setting.setting-layout-split #groupList .groupBtn .setting-group-label {
.page--setting.setting-layout-split #groupList .groupBtn .setting-group-label,
.page--setting.setting-layout-split #deviceGroupList .groupBtn .setting-group-label {
display: inline-block;
min-width: max-content;
transform: translateX(0);
Expand All @@ -1231,7 +1252,10 @@

.page--setting.setting-layout-split #groupList .groupBtn.is-overflowing:hover .setting-group-label,
.page--setting.setting-layout-split #groupList .groupBtn.is-overflowing:focus .setting-group-label,
.page--setting.setting-layout-split #groupList .groupBtn.is-overflowing:active .setting-group-label {
.page--setting.setting-layout-split #groupList .groupBtn.is-overflowing:active .setting-group-label,
.page--setting.setting-layout-split #deviceGroupList .groupBtn.is-overflowing:hover .setting-group-label,
.page--setting.setting-layout-split #deviceGroupList .groupBtn.is-overflowing:focus .setting-group-label,
.page--setting.setting-layout-split #deviceGroupList .groupBtn.is-overflowing:active .setting-group-label {
animation: setting-left-text-pan 4.2s ease-in-out 1;
}

Expand Down
6 changes: 3 additions & 3 deletions selfdrive/carrot/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<link rel="stylesheet" href="/css/components.css?v=2605-04" />
<link rel="stylesheet" href="/css/pages/logs.css?v=2605-15" />
<link rel="stylesheet" href="/css/pages/terminal.css?v=2605-07" />
<link rel="stylesheet" href="/css/pages/settings.css?v=2605-33" />
<link rel="stylesheet" href="/css/pages/settings.css?v=2605-35" />
<link rel="stylesheet" href="/css/pages/tools.css?v=2605-37" />
<link rel="stylesheet" href="/css/pages/drive.css?v=2605-10" />
<link rel="stylesheet" href="/css/responsive.css?v=2605-08" />
Expand Down Expand Up @@ -624,12 +624,12 @@ <h2 id="carrotTitle" class="page-title">Home</h2>
<script src="/js/shared/ui/effects.js?v=2604-72"></script>
<script src="/js/shared/ui/navigation.js?v=2605-14"></script>
<script src="/js/pages/car.js?v=2604-75"></script>
<script src="/js/pages/setting.js?v=2605-15"></script>
<script src="/js/pages/setting.js?v=2605-17"></script>
<script src="/js/pages/setting_device_config.js?v=2605-04"></script>
<script src="/js/pages/setting_device_render.js?v=2605-02"></script>
<script src="/js/pages/setting_device_network.js?v=2605-01"></script>
<script src="/js/pages/setting_device_actions.js?v=2605-02"></script>
<script src="/js/pages/setting_device.js?v=2605-06"></script>
<script src="/js/pages/setting_device.js?v=2605-08"></script>
<script src="/js/pages/tools_web_settings.js?v=2605-04"></script>
<script src="/js/pages/tools_notifications.js?v=2605-18"></script>
<script src="/js/pages/tools.js?v=2605-10"></script>
Expand Down
130 changes: 118 additions & 12 deletions selfdrive/carrot/web/js/pages/setting.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,78 @@ async function loadSettings(options = {}) {
return settingsLoadPromise;
}

let settingOverflowSyncRaf = 0;
let settingOverflowSyncTimer = 0;
let settingOverflowResizeObserver = null;

function measureSettingGroupButtonOverflow(button) {
if (!button) return;
const labelEl = button.querySelector(".setting-group-label");
if (!labelEl) return;
const buttonWidth = button.clientWidth || 0;
if (buttonWidth <= 0) return;
const shift = Math.min(0, buttonWidth - labelEl.scrollWidth - 8);
button.style.setProperty("--setting-label-shift", `${shift}px`);
button.classList.toggle("is-overflowing", shift < 0);
}

function syncSettingGroupLabelOverflow(root = document) {
const scope = root && typeof root.querySelectorAll === "function" ? root : document;
if (scope.matches?.("#groupList .groupBtn, #deviceGroupList .groupBtn")) {
measureSettingGroupButtonOverflow(scope);
}
const selector = (scope.id === "groupList" || scope.id === "deviceGroupList")
? ".groupBtn"
: "#groupList .groupBtn, #deviceGroupList .groupBtn";
scope.querySelectorAll(selector).forEach(measureSettingGroupButtonOverflow);
}

function syncSettingOverflow(root = document) {
syncSettingMarqueeOverflow(root);
syncSettingGroupLabelOverflow(root);
}

function scheduleSettingOverflowSync(root = document, delayMs = 0) {
if (settingOverflowSyncRaf) cancelAnimationFrame(settingOverflowSyncRaf);
if (settingOverflowSyncTimer) {
window.clearTimeout(settingOverflowSyncTimer);
settingOverflowSyncTimer = 0;
}

const run = () => {
settingOverflowSyncRaf = requestAnimationFrame(() => {
settingOverflowSyncRaf = 0;
syncSettingOverflow(root);
});
};

if (delayMs > 0) {
settingOverflowSyncTimer = window.setTimeout(() => {
settingOverflowSyncTimer = 0;
run();
}, delayMs);
} else {
run();
}
}

function initSettingOverflowObservers() {
if (settingOverflowResizeObserver || typeof ResizeObserver !== "function") return;
settingOverflowResizeObserver = new ResizeObserver(() => scheduleSettingOverflowSync(document));
[
"settingScreenHost",
"settingScreenGroups",
"settingScreenItems",
"groupList",
"deviceGroupList",
"items",
"deviceItems",
].forEach((id) => {
const el = document.getElementById(id);
if (el) settingOverflowResizeObserver.observe(el);
});
}

function renderGroups(options = {}) {
const box = document.getElementById("groupList");
const animateGroups = options.animateGroups !== false;
Expand All @@ -560,13 +632,7 @@ function renderGroups(options = {}) {
const text = Number.isFinite(Number(count)) ? `${label} (${count})` : label;
button.title = text;
button.innerHTML = `<span class="setting-group-label">${escapeHtml(text)}</span>`;
requestAnimationFrame(() => {
const labelEl = button.querySelector(".setting-group-label");
if (!labelEl) return;
const shift = Math.min(0, button.clientWidth - labelEl.scrollWidth - 8);
button.style.setProperty("--setting-label-shift", `${shift}px`);
button.classList.toggle("is-overflowing", shift < 0);
});
requestAnimationFrame(() => measureSettingGroupButtonOverflow(button));
}

if (!animateGroups && box.dataset.groupsSignature === signature && box.children.length === groups.length) {
Expand All @@ -588,6 +654,7 @@ function renderGroups(options = {}) {
setGroupButtonLabel(button, label, g.count);
button.onclick = () => selectGroup(g.group);
});
scheduleSettingOverflowSync(box);
return;
}

Expand Down Expand Up @@ -617,6 +684,7 @@ function renderGroups(options = {}) {
b.onclick = () => selectGroup(g.group);
box.appendChild(b);
});
scheduleSettingOverflowSync(box);
}

function getSettingGroupMeta(group) {
Expand Down Expand Up @@ -1300,10 +1368,28 @@ function syncSettingMarqueeOverflow(root = document) {
root.querySelectorAll(".setting-marquee").forEach((el) => {
const content = el.querySelector(".setting-marquee__content");
if (!content) return;
const elWidth = el.clientWidth || 0;
if (elWidth <= 0) return;
const overflow = content.scrollWidth > el.clientWidth + 2;
const distance = Math.max(0, content.scrollWidth - el.clientWidth + 18);
const nextDistance = `${distance}px`;
const prevDistance = el.style.getPropertyValue("--setting-marquee-distance");
const wasOverflowing = el.classList.contains("is-overflowing");
el.style.setProperty("--setting-marquee-distance", nextDistance);
el.scrollLeft = 0;
if (!overflow) {
el.classList.remove("is-overflowing");
content.style.animation = "";
return;
}

if (!wasOverflowing || prevDistance !== nextDistance) {
el.classList.remove("is-overflowing");
content.style.animation = "none";
void content.offsetWidth;
content.style.animation = "";
}
el.classList.toggle("is-overflowing", overflow);
el.style.setProperty("--setting-marquee-distance", `${distance}px`);
});
}

Expand Down Expand Up @@ -2153,9 +2239,21 @@ async function renderItems(group, options = {}) {
const bodyInner = document.createElement("div");
bodyInner.className = "setting-profile-section__bodyInner";
header.onclick = () => {
const nextExpanded = section.classList.toggle("is-collapsed") ? false : true;
const wasCollapsed = section.classList.contains("is-collapsed");
const nextExpanded = wasCollapsed;
section.classList.remove("is-expanding", "is-collapsing");
if (section.__settingProfileMotionTimer) {
window.clearTimeout(section.__settingProfileMotionTimer);
}
void section.offsetWidth;
section.classList.toggle("is-collapsed", !nextExpanded);
section.classList.add(nextExpanded ? "is-expanding" : "is-collapsing");
settingProfileSectionExpandedState.set(stateKey, nextExpanded);
header.setAttribute("aria-expanded", nextExpanded ? "true" : "false");
section.__settingProfileMotionTimer = window.setTimeout(() => {
section.classList.remove("is-expanding", "is-collapsing");
section.__settingProfileMotionTimer = null;
}, 280);
};
body.appendChild(bodyInner);
section.appendChild(header);
Expand Down Expand Up @@ -2347,7 +2445,7 @@ async function renderItems(group, options = {}) {
});

itemsBox.dataset.renderedGroup = group;
requestAnimationFrame(() => syncSettingMarqueeOverflow(itemsBox));
scheduleSettingOverflowSync(itemsBox);

if (pendingSettingFocus?.group === group) {
requestAnimationFrame(() => focusSettingItem(pendingSettingFocus.name));
Expand Down Expand Up @@ -2528,11 +2626,19 @@ window.addEventListener("carrot:paramsrestored", (event) => {

window.addEventListener("resize", () => {
scheduleSettingViewportLayoutSync(false);
requestAnimationFrame(() => syncSettingMarqueeOverflow(document.getElementById("items") || document));
scheduleSettingOverflowSync(document, 80);
}, { passive: true });

window.addEventListener("orientationchange", () => {
scheduleSettingViewportLayoutSync(true);
window.setTimeout(() => syncSettingMarqueeOverflow(document.getElementById("items") || document), 160);
scheduleSettingOverflowSync(document, 180);
}, { passive: true });

if (window.visualViewport) {
window.visualViewport.addEventListener("resize", () => {
scheduleSettingOverflowSync(document, 80);
}, { passive: true });
}

initSettingOverflowObservers();

50 changes: 45 additions & 5 deletions selfdrive/carrot/web/js/pages/setting_device.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,55 @@ function renderDeviceGroups(options = {}) {
if (!groupContainer) return;
const animateGroups = options.animateGroups !== false;

groupContainer.innerHTML = "";
if (subnavContainer) subnavContainer.innerHTML = "";

const visibleGroups = getVisibleDeviceGroups();
if (!visibleGroups.some((group) => group.id === CURRENT_DEVICE_GROUP)) {
CURRENT_DEVICE_GROUP = visibleGroups[0]?.id || "Device";
}
const groupEntries = visibleGroups.map((group) => ({
group,
label: getDeviceGroupLabel(group.id),
}));
const signature = groupEntries.map((entry) => `${entry.group.id}:${entry.label}`).join("|");

if (
!animateGroups &&
groupContainer.dataset.deviceGroupsSignature === signature &&
groupContainer.children.length === groupEntries.length &&
(!subnavContainer || subnavContainer.children.length === groupEntries.length)
) {
Array.from(groupContainer.children).forEach((button, index) => {
const entry = groupEntries[index];
button.className = "btn groupBtn";
if (entry.group.id === CURRENT_DEVICE_GROUP) button.classList.add("active");
button.dataset.deviceGroup = entry.group.id;
button.innerHTML = `<span class="setting-group-label">${escapeHtml(entry.label)}</span>`;
button.onclick = () => selectDeviceGroup(entry.group.id);
});

if (subnavContainer && subnavContainer.children.length === groupEntries.length) {
Array.from(subnavContainer.children).forEach((tab, index) => {
const entry = groupEntries[index];
tab.className = "setting-subnav__tab";
if (entry.group.id === CURRENT_DEVICE_GROUP) tab.classList.add("is-active");
tab.dataset.deviceGroup = entry.group.id;
tab.textContent = entry.label;
tab.onclick = () => selectDeviceGroup(entry.group.id);
});
}
if (typeof scheduleSettingOverflowSync === "function") scheduleSettingOverflowSync(groupContainer);
return;
}

groupContainer.innerHTML = "";
groupContainer.dataset.deviceGroupsSignature = signature;
if (subnavContainer) {
subnavContainer.innerHTML = "";
subnavContainer.dataset.deviceGroupsSignature = signature;
}

visibleGroups.forEach((group, index) => {
const label = getDeviceGroupLabel(group.id);
groupEntries.forEach((entry, index) => {
const group = entry.group;
const label = entry.label;
const button = document.createElement("button");
button.type = "button";
button.className = animateGroups ? "btn groupBtn ui-stagger-item" : "btn groupBtn";
Expand All @@ -173,6 +212,7 @@ function renderDeviceGroups(options = {}) {
subnavContainer.appendChild(tab);
}
});
if (typeof scheduleSettingOverflowSync === "function") scheduleSettingOverflowSync(groupContainer);
}

function applyDeviceItemsStagger(container) {
Expand Down
Loading