mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-07-27 10:31:38 +08:00
⛅ Sync 2026-07-08 08:32:44
This commit is contained in:
parent
399e8100fc
commit
bd8d184870
@ -193,6 +193,14 @@ header {
|
||||
|
||||
.brand {
|
||||
@apply hover:text-brand text-text inline-block shrink-0 text-xl font-semibold tracking-tight no-underline transition-[color,transform] duration-150 hover:-translate-y-0.5 max-md:flex-1 max-md:text-lg;
|
||||
|
||||
[data-nav-type="sidebar"] & {
|
||||
@apply md:hidden;
|
||||
}
|
||||
|
||||
[data-nav-type="sidebar"].sidebar-collapsed & {
|
||||
@apply md:inline-block md:transition-opacity md:duration-150 md:starting:opacity-0;
|
||||
}
|
||||
}
|
||||
|
||||
.nav {
|
||||
@ -255,6 +263,14 @@ header {
|
||||
@apply md:flex;
|
||||
}
|
||||
|
||||
/* D1 底线呼吸:展开态沿用短底线汉堡;折叠后底线伸满(三线齐整 =
|
||||
侧栏收纳完毕)。dasharray 只改可见长度,线帽形状不受影响。 */
|
||||
[data-nav-type="sidebar"].sidebar-collapsed
|
||||
&
|
||||
.navigation-toggle-line-bottom {
|
||||
@apply md:[stroke-dasharray:15_15];
|
||||
}
|
||||
|
||||
& .navigation-toggle {
|
||||
@apply cursor-pointer rounded-none border-0 bg-transparent p-0 shadow-none transition-transform duration-150 hover:scale-105 active:scale-95;
|
||||
|
||||
@ -264,7 +280,15 @@ header {
|
||||
|
||||
& .navigation-toggle-line {
|
||||
transform-box: fill-box;
|
||||
@apply origin-center transition-[transform,opacity] duration-150 ease-in-out;
|
||||
@apply origin-center transition-[transform,opacity,stroke-dasharray] duration-150 ease-in-out;
|
||||
}
|
||||
|
||||
/* Tabler menu-2 geometry: all three lines are full-length equals.
|
||||
The signature short bottom line is a stroke-dasharray crop, not a
|
||||
shorter segment or a scaleX — scaling distorts the round caps and
|
||||
makes the "equal" collapsed state read as uneven lengths. */
|
||||
& .navigation-toggle-line-bottom {
|
||||
@apply [stroke-dasharray:7.5_15];
|
||||
}
|
||||
|
||||
&.is-expanded {
|
||||
@ -278,7 +302,8 @@ header {
|
||||
}
|
||||
|
||||
& .navigation-toggle-line-bottom {
|
||||
transform: translate(3.75px, -5px) rotate(-45deg) scaleX(2);
|
||||
transform: translateY(-5px) rotate(-45deg);
|
||||
@apply [stroke-dasharray:15_15];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -316,8 +341,10 @@ header {
|
||||
}
|
||||
|
||||
body[data-nav-type="sidebar"] {
|
||||
/* Desktop header + sidebar form one flush, L-shaped application frame: a
|
||||
full-width header on top, a sidebar pinned to the left edge below it.
|
||||
/* T4 shell: the sidebar is a full-height first column (brand → menu →
|
||||
logout in one run), and the header spans only the content column — so
|
||||
the sidebar's right border runs viewport top to bottom and the header
|
||||
reads as the content area's toolbar, not a page-wide bar.
|
||||
A CSS grid (not flex-wrap) keeps the header row at its natural height —
|
||||
so collapsing the sidebar never stretches it — lets the sidebar column
|
||||
animate to zero, and lets #maincontent fluidly reclaim the freed space.
|
||||
@ -329,11 +356,11 @@ body[data-nav-type="sidebar"] {
|
||||
}
|
||||
|
||||
& > header {
|
||||
@apply md:border-hairline md:col-span-full md:row-start-1 md:mb-0 md:border-b;
|
||||
@apply md:border-hairline md:col-start-2 md:row-start-1 md:mb-0 md:border-b;
|
||||
}
|
||||
|
||||
& > .sidebar-panel {
|
||||
@apply md:col-start-1 md:row-start-2;
|
||||
@apply md:col-start-1 md:row-span-2 md:row-start-1;
|
||||
}
|
||||
|
||||
& > #maincontent {
|
||||
@ -341,7 +368,10 @@ body[data-nav-type="sidebar"] {
|
||||
}
|
||||
|
||||
& .header-crumb {
|
||||
@apply text-text-muted my-0 mr-auto ml-6 hidden min-w-0 list-none items-center gap-2 overflow-hidden p-0 text-sm md:flex;
|
||||
/* Expanded: the crumb is the header's leftmost element (brand lives in
|
||||
the sidebar head), so it sits on the header's own padding. Collapsed:
|
||||
burger + brand reappear before it and it takes back its old offset. */
|
||||
@apply text-text-muted my-0 mr-auto ml-0 hidden min-w-0 list-none items-center gap-2 overflow-hidden p-0 text-sm md:flex;
|
||||
|
||||
& li {
|
||||
@apply m-0 list-none whitespace-nowrap;
|
||||
@ -356,8 +386,12 @@ body[data-nav-type="sidebar"] {
|
||||
}
|
||||
}
|
||||
|
||||
&.sidebar-collapsed .header-crumb {
|
||||
@apply md:ml-6;
|
||||
}
|
||||
|
||||
& .sidebar-panel {
|
||||
@apply border-hairline sticky top-14 hidden h-[calc(100vh-3.5rem)] w-full overflow-hidden rounded-none border-r transition-[visibility] duration-[250ms] md:block;
|
||||
@apply border-hairline sticky top-0 hidden h-dvh w-full overflow-hidden rounded-none border-r transition-[visibility] duration-[250ms] md:block;
|
||||
}
|
||||
|
||||
/* Visibility flips at the end of the slide so collapsed controls leave the
|
||||
@ -374,6 +408,21 @@ body[data-nav-type="sidebar"] {
|
||||
@apply -translate-x-full opacity-0;
|
||||
}
|
||||
|
||||
/* Sidebar head: logo + hostname. h-14 matches the header row so its
|
||||
bottom hairline continues the header's border in one unbroken line
|
||||
across the viewport. */
|
||||
& .sidebar-head {
|
||||
@apply border-hairline flex h-14 shrink-0 items-center gap-2.5 border-b px-4;
|
||||
|
||||
& .sidebar-logo {
|
||||
@apply size-5 shrink-0 rounded-md;
|
||||
}
|
||||
|
||||
& .sidebar-brand {
|
||||
@apply text-text hover:text-brand min-w-0 flex-1 truncate text-lg font-semibold tracking-tight no-underline transition-colors duration-150;
|
||||
}
|
||||
}
|
||||
|
||||
& .sidebar-list {
|
||||
@apply m-0 flex-1 list-none space-y-0.5 overflow-y-auto p-3;
|
||||
|
||||
@ -397,10 +446,11 @@ body[data-nav-type="sidebar"] {
|
||||
& .sidebar-footer {
|
||||
@apply border-hairline shrink-0 border-t p-3;
|
||||
|
||||
/* Logout: muted at rest; on hover the base .nav-link pill background
|
||||
plus error-colored text is the intended compound state (matches v1). */
|
||||
/* Logout: muted at rest, standard row treatment on hover — same
|
||||
vocabulary as every other sidebar row (the v1 danger-red hover read
|
||||
as unrelated to the rest of the menu). */
|
||||
& .nav-link {
|
||||
@apply text-text-muted hover:text-danger;
|
||||
@apply text-text-muted hover:text-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,10 @@
|
||||
*/
|
||||
|
||||
.nav-link {
|
||||
@apply text-text hover:bg-hover-faint block rounded-xl px-3 py-1.5 no-underline transition-all duration-150;
|
||||
/* hover:no-underline: the global `a:hover { underline }` in _elements.css
|
||||
outranks a bare class (a:hover is 0,1,1), so nav rows must opt out at
|
||||
the same specificity tier. */
|
||||
@apply text-text hover:bg-hover-faint block rounded-xl px-3 py-1.5 no-underline transition-all duration-150 hover:no-underline;
|
||||
}
|
||||
|
||||
.navigation-direct {
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
.mobile-menu-overlay {
|
||||
@apply max-md:bg-mega-menu-bg max-md:invisible max-md:fixed max-md:inset-0 max-md:z-60 max-md:opacity-0 max-md:backdrop-blur-lg max-md:backdrop-saturate-150 max-md:transition-[visibility,opacity] max-md:duration-[250ms] md:hidden;
|
||||
@apply max-md:bg-mega-menu-bg max-md:invisible max-md:fixed max-md:inset-0 max-md:z-60 max-md:opacity-0 max-md:backdrop-blur-lg max-md:backdrop-saturate-150 md:hidden;
|
||||
|
||||
/* Transitions live on the OPEN state only: opening fades in, closing cuts
|
||||
instantly. Link taps close into a full-page navigation, and any close
|
||||
fade racing the document swap freezes mid-frame as a ghost. */
|
||||
&.mobile-menu-open {
|
||||
@apply max-md:visible max-md:opacity-100;
|
||||
@apply max-md:visible max-md:opacity-100 max-md:transition-[visibility,opacity] max-md:duration-[250ms];
|
||||
}
|
||||
|
||||
.mobile-nav {
|
||||
@ -17,7 +20,7 @@
|
||||
}
|
||||
|
||||
& .mobile-nav-list {
|
||||
@apply max-md:m-0 max-md:flex max-md:min-h-0 max-md:flex-1 max-md:-translate-y-2 max-md:list-none max-md:flex-col max-md:overflow-y-auto max-md:overscroll-contain max-md:p-0 max-md:pb-5 max-md:opacity-0 max-md:transition-[translate,opacity] max-md:duration-[250ms] max-md:ease-out;
|
||||
@apply max-md:m-0 max-md:flex max-md:min-h-0 max-md:flex-1 max-md:-translate-y-2 max-md:list-none max-md:flex-col max-md:overflow-y-auto max-md:overscroll-contain max-md:p-0 max-md:pb-5 max-md:opacity-0;
|
||||
|
||||
& .mobile-nav-item {
|
||||
@apply max-md:shrink-0;
|
||||
@ -60,7 +63,7 @@
|
||||
}
|
||||
|
||||
&.mobile-menu-open .mobile-nav-list {
|
||||
@apply max-md:translate-y-0 max-md:opacity-100;
|
||||
@apply max-md:translate-y-0 max-md:opacity-100 max-md:transition-[translate,opacity] max-md:duration-[250ms] max-md:ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -469,7 +469,10 @@ return baseclass.extend({
|
||||
items.forEach((item) => {
|
||||
if (item.isActiveGroup || item.isActivePage) {
|
||||
crumb.push(item.title);
|
||||
if (item.activePage) crumb.push(item.activePage.title);
|
||||
// Same-named group/page pairs ("System › System") collapse to one
|
||||
// level — the duplicate adds no information.
|
||||
if (item.activePage && item.activePage.title !== item.title)
|
||||
crumb.push(item.activePage.title);
|
||||
}
|
||||
|
||||
if (item.isLogout) {
|
||||
@ -485,7 +488,7 @@ return baseclass.extend({
|
||||
this.bindNavigationAccordion(list);
|
||||
|
||||
crumb.forEach((title, i) => {
|
||||
if (i) crumbEl?.appendChild(E("li", { class: "crumb-sep" }, ["/"]));
|
||||
if (i) crumbEl?.appendChild(E("li", { class: "crumb-sep" }, ["›"]));
|
||||
crumbEl?.appendChild(
|
||||
E("li", { class: i === crumb.length - 1 ? "current" : "" }, [title]),
|
||||
);
|
||||
|
||||
@ -729,13 +729,47 @@ test("renders sidebar items, logout, and translated crumbs without duplication",
|
||||
assert.equal(crumb.children.length, 3);
|
||||
assert.deepEqual(
|
||||
crumb.children.map((child) => textContent(child)),
|
||||
["translated:Network", "/", "translated:Wireless"],
|
||||
["translated:Network", "›", "translated:Wireless"],
|
||||
);
|
||||
assert.equal(crumb.children[2].getAttribute("class"), "current");
|
||||
assert.equal(list.dataset.accordionBound, "true");
|
||||
assert.equal(list.listenerCount("click"), 1);
|
||||
});
|
||||
|
||||
test("collapses same-named group/page crumbs to a single level", () => {
|
||||
const crumb = new FakeElement("ol", {}, [new FakeElement("li")]);
|
||||
const document = createFakeDocument({
|
||||
elements: {
|
||||
"#header-crumb": crumb,
|
||||
"#sidebar-list": new FakeElement("ul"),
|
||||
},
|
||||
navType: "sidebar",
|
||||
});
|
||||
const menu = loadMenuModule({
|
||||
dispatchpath: ["admin", "system", "system"],
|
||||
document,
|
||||
translate: (value) => `translated:${value}`,
|
||||
});
|
||||
const tree = {
|
||||
children: {
|
||||
system: {
|
||||
title: "System",
|
||||
children: {
|
||||
system: { title: "System" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
menu.renderSidebar(menu.buildNavigationModel(getMenuChildren(tree), "admin"));
|
||||
|
||||
assert.deepEqual(
|
||||
crumb.children.map((child) => textContent(child)),
|
||||
["translated:System"],
|
||||
);
|
||||
assert.equal(crumb.children[0].getAttribute("class"), "current");
|
||||
});
|
||||
|
||||
test("renders an active group expanded when an open mobile list was initially empty", () => {
|
||||
const list = new FakeElement("ul");
|
||||
const overlay = new FakeElement("div", { class: "mobile-menu-open" }, [list]);
|
||||
|
||||
@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=Aurora Theme (A modern browser theme built with Vite and Tailwind CSS)
|
||||
LUCI_DEPENDS:=+luci-base
|
||||
|
||||
PKG_VERSION:=1.0.8
|
||||
PKG_RELEASE:=44
|
||||
PKG_VERSION:=1.0.10
|
||||
PKG_RELEASE:=45
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
LUCI_MINIFY_CSS:=
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -208,7 +208,7 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<line class="navigation-toggle-line navigation-toggle-line-top" x1="2.5" y1="5" x2="17.5" y2="5"/>
|
||||
<line class="navigation-toggle-line navigation-toggle-line-middle" x1="2.5" y1="10" x2="17.5" y2="10"/>
|
||||
<line class="navigation-toggle-line navigation-toggle-line-bottom" x1="2.5" y1="15" x2="10" y2="15"/>
|
||||
<line class="navigation-toggle-line navigation-toggle-line-bottom" x1="2.5" y1="15" x2="17.5" y2="15"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@ -261,6 +261,10 @@
|
||||
{% if (nav_type == 'sidebar'): %}
|
||||
<aside class="sidebar-panel" id="sidebar-panel" aria-label="{{ _('Navigation') }}">
|
||||
<nav class="sidebar-panel-inner">
|
||||
<div class="sidebar-head">
|
||||
<img class="sidebar-logo" src="{{ media }}/images/{{ logo_svg }}?v={{ icon_cache_version }}" alt="" aria-hidden="true">
|
||||
<a class="sidebar-brand" href="/">{{ hostname }}</a>
|
||||
</div>
|
||||
<ul class="sidebar-list" id="sidebar-list"></ul>
|
||||
<div class="sidebar-footer" id="sidebar-footer"></div>
|
||||
</nav>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qBittorrent
|
||||
PKG_VERSION:=5.2.2
|
||||
PKG_RELEASE:=3
|
||||
PKG_VERSION:=5.2.3
|
||||
PKG_RELEASE:=4
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/qbittorrent/qBittorrent/tar.gz/release-$(PKG_VERSION)?
|
||||
|
||||
Loading…
Reference in New Issue
Block a user