On mobile the filter operator and value fields span the row instead of fixed desktop widths, and empty value rows are hidden. "Add filter" becomes an M3 tonal button on all widths so it stands out from the outlined filter fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
213 lines
11 KiB
CSS
213 lines
11 KiB
CSS
/*
|
|
* Mobile overrides at core's responsive.css breakpoint. The core file stays in place
|
|
* (a theme file named responsive.css would replace it); it loads after the theme,
|
|
* hence the `html` prefix on conflicting selectors.
|
|
*/
|
|
|
|
@media screen and (max-width: 899px) {
|
|
/* Top app bar */
|
|
html #header { background-color: var(--md-sys-color-surface-container); color: var(--md-sys-color-on-surface); }
|
|
html #header a.mobile-toggle-button { color: var(--md-sys-color-on-surface-variant); border-inline-start: 0; }
|
|
html #project-jump .drdn-trigger {
|
|
border: 0;
|
|
color: var(--md-sys-color-on-surface);
|
|
font: var(--md-sys-typescale-title-large);
|
|
line-height: 50px;
|
|
}
|
|
html #project-jump.drdn { padding-inline-start: 8px; }
|
|
/* Header icons: Material Symbols masks instead of core's scaled "^" and "≡" text glyphs */
|
|
html #project-jump .drdn-trigger:before {
|
|
content: '';
|
|
inset-block: 0;
|
|
margin-block: auto;
|
|
inline-size: 24px;
|
|
block-size: 24px;
|
|
padding: 0;
|
|
transform: none;
|
|
opacity: 1;
|
|
background-color: var(--md-sys-color-on-surface-variant);
|
|
mask: url(../images/arrow-drop-down.svg) center / 24px no-repeat;
|
|
}
|
|
html #header a.mobile-toggle-button {
|
|
inline-size: 48px;
|
|
block-size: 48px;
|
|
margin-block-start: 8px;
|
|
margin-inline-end: 8px;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
line-height: normal;
|
|
}
|
|
html #header a.mobile-toggle-button:hover { background-image: var(--nm-state-hover); }
|
|
html .mobile-toggle-button:after {
|
|
content: '';
|
|
inline-size: 24px;
|
|
block-size: 24px;
|
|
margin: 12px;
|
|
background-color: currentColor;
|
|
mask: url(../images/menu.svg) center / 24px no-repeat;
|
|
}
|
|
|
|
/* Flyout: M3 modal navigation drawer. It slides over the page behind a scrim instead of
|
|
core's push, which shoves page and header off screen. Tapping the scrim hits #main,
|
|
which core's responsive.js already binds to close the flyout. */
|
|
html.flyout-is-active :is(#wrapper, #header) { inset-inline-end: 0; }
|
|
html .flyout-menu {
|
|
--nm-drawer-width: min(360px, calc(100vw - 56px)); /* M3 modal drawer; core's 250px squeezes the appearance picker */
|
|
position: fixed;
|
|
inset-block: 0;
|
|
inset-inline-end: calc(-1 * var(--nm-drawer-width));
|
|
inline-size: var(--nm-drawer-width);
|
|
z-index: 10001; /* over core's fixed header (9999) and the scrim */
|
|
block-size: auto;
|
|
overflow-y: auto;
|
|
overscroll-behavior: contain;
|
|
visibility: hidden;
|
|
transition: inset-inline-end 250ms cubic-bezier(0.2, 0, 0, 1), visibility 250ms;
|
|
border-start-start-radius: var(--md-sys-shape-corner-large);
|
|
border-end-start-radius: var(--md-sys-shape-corner-large);
|
|
box-shadow: var(--md-sys-elevation-level1);
|
|
background-color: var(--md-sys-color-surface-container-low);
|
|
color: var(--md-sys-color-on-surface);
|
|
padding-inline: 12px;
|
|
box-sizing: border-box;
|
|
}
|
|
html.flyout-is-active .flyout-menu { inset-inline-end: 0; visibility: visible; }
|
|
html.flyout-is-active #main::after {
|
|
content: '';
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 10000;
|
|
background-color: color-mix(in srgb, var(--md-sys-color-scrim) 32%, transparent);
|
|
}
|
|
html .flyout-menu h3 {
|
|
block-size: auto;
|
|
margin-block: 16px 4px;
|
|
padding-inline: 16px;
|
|
border: 0;
|
|
background-color: transparent;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
font: var(--md-sys-typescale-title-small);
|
|
letter-spacing: var(--md-sys-typescale-title-small-tracking);
|
|
text-transform: none;
|
|
}
|
|
/* M3 drawer dividers between groups; headings alone look like one more nav item */
|
|
html .flyout-menu > :is(h3, .flyout-menu__sidebar:has(#sidebar-wrapper > *), .nm-appearance) {
|
|
display: block; /* the sidebar group is a span */
|
|
margin-block-start: 8px;
|
|
padding-block-start: 8px;
|
|
border-block-start: 1px solid var(--md-sys-color-outline-variant);
|
|
}
|
|
html .flyout-menu > h3 { padding-block-start: 16px; }
|
|
/* Sidebar forms (e.g. activity filters) line up with the nav labels; a field stacks under
|
|
its label, which is a bare text node, so grid is the only way to put it on its own row */
|
|
html .flyout-menu__sidebar :is(form > p, li:has(> input[type="checkbox"])) { padding-inline: 16px; }
|
|
html .flyout-menu__sidebar p:has(> :is(select, input:not([type="submit"], [type="checkbox"], [type="radio"]))) {
|
|
display: grid;
|
|
gap: 4px;
|
|
color: var(--md-sys-color-on-surface-variant);
|
|
font: var(--md-sys-typescale-label-large);
|
|
}
|
|
html .flyout-menu__sidebar p > :is(select, input:not([type="submit"], [type="checkbox"], [type="radio"])) { inline-size: 100%; box-sizing: border-box; }
|
|
html .flyout-menu__sidebar li:has(> input[type="checkbox"]) { display: flex; align-items: center; gap: 12px; min-block-size: 40px; border: 0; }
|
|
html .flyout-menu .flyout-menu__sidebar li:has(> input[type="checkbox"]) a { block-size: auto; padding: 0; line-height: inherit; }
|
|
html .flyout-menu h4 { color: var(--md-sys-color-on-surface); }
|
|
html .flyout-menu a { color: var(--md-sys-color-on-surface-variant); }
|
|
html .flyout-menu ul li a, html .flyout-menu ul li:first-child a {
|
|
block-size: 48px;
|
|
line-height: 48px;
|
|
margin-inline-start: 0;
|
|
padding-inline: 16px;
|
|
border: 0;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
font: var(--md-sys-typescale-label-large);
|
|
line-height: 48px;
|
|
}
|
|
html .flyout-menu ul li a:hover { background-image: var(--nm-state-hover); }
|
|
html .flyout-menu ul li a.selected {
|
|
background-color: var(--md-sys-color-secondary-container);
|
|
color: var(--md-sys-color-on-secondary-container);
|
|
}
|
|
html .flyout-menu #watchers ul li, html .flyout-menu ul.queries li, html .flyout-menu__avatar { border-block-start: 0; }
|
|
html .flyout-menu .icon svg, html .flyout-menu .icon-only svg { color: inherit; stroke: currentColor; }
|
|
html .flyout-menu__search input[type='text'] {
|
|
block-size: 48px;
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
background-color: var(--md-sys-color-surface-container-highest);
|
|
color: var(--md-sys-color-on-surface);
|
|
padding-inline-start: 52px;
|
|
}
|
|
/* Search pill, avatar row and nav labels share one inline start: the icon and the
|
|
avatar sit where the nav labels begin (drawer padding 12px + item padding 16px) */
|
|
html .flyout-menu .flyout-menu__search { padding-inline: 0; }
|
|
html .search-magnifier--flyout { inset-inline-start: 28px; }
|
|
html .flyout-menu .flyout-menu__avatar { padding-inline-start: 16px; }
|
|
|
|
html .cal .week-number { background-color: var(--md-sys-color-surface-container); border-color: var(--md-sys-color-outline-variant); }
|
|
/* Page actions become M3 outlined buttons, like Apply / Clear. The forum topic wraps its
|
|
actions in a quote-reply controller, so core's #content > .contextual misses them. */
|
|
html #content > [data-controller="quote-reply"] > .contextual {
|
|
inline-size: 100%;
|
|
margin-block-end: 8px;
|
|
padding-inline-start: 0;
|
|
white-space: normal;
|
|
}
|
|
html :is(#content > .contextual > a, #content > .contextual .drdn, #content > [data-controller="quote-reply"] > .contextual > a, p.buttons a) {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
block-size: 40px;
|
|
margin-block: 4px;
|
|
margin-inline: 0 4px;
|
|
padding-block: 0;
|
|
padding-inline: 16px;
|
|
border: 1px solid var(--md-sys-color-outline);
|
|
border-radius: var(--md-sys-shape-corner-full);
|
|
box-sizing: border-box;
|
|
font: var(--md-sys-typescale-label-large);
|
|
letter-spacing: var(--md-sys-typescale-label-large-tracking);
|
|
}
|
|
|
|
/* A scrolling table takes its natural width instead of squeezing text columns to a
|
|
word per line; it scrolls inside its card */
|
|
html .autoscroll > table.list { inline-size: max-content; min-inline-size: 100%; }
|
|
/* Tables core does not wrap scroll themselves, so they no longer push the whole content
|
|
area sideways; thead and tbody share one anonymous table, so columns stay aligned.
|
|
ponytail: a table narrower than the screen would leave a gap inside its border, so small
|
|
summary tables are excluded by class; add others here if one shows a gap */
|
|
html #content table.list:not(.autoscroll > table, .issue-report) { display: block; overflow-x: auto; max-inline-size: 100%; }
|
|
|
|
/* Form fields run full width; a select keeps room for the icon button after it */
|
|
html form .attributes select { inline-size: 100%; }
|
|
html form .attributes select:has(+ .icon-only) { inline-size: calc(100% - 36px); }
|
|
html .tabular input[type="radio"] { inline-size: auto; }
|
|
|
|
/* Query filters: operator and values run full width under the checkbox label instead of
|
|
the desktop's fixed 180px / 260px columns. A flex-basis of 0 overrides those widths, so
|
|
"between" fields split the row and a multi-select toggle keeps its spot after the field. */
|
|
html #filters-table .filter { row-gap: 8px; margin-block-end: 8px; }
|
|
html #filters-table .filter :is(.operator, .values) { flex: 1 1 100%; }
|
|
html #filters-table .filter .values:not(:has(> span:not([style*="none"]))) { display: none; } /* e.g. status "open" */
|
|
html #filters-table .filter .operator select { inline-size: 100%; }
|
|
html #filters-table .filter .values > span { display: flex; flex: 1 1 0; align-items: center; gap: 8px; }
|
|
html #filters-table .filter .values .value:not([size="3"]) { flex: 1 1 0; min-inline-size: 0; }
|
|
html .add-filter { justify-content: stretch; margin-block-start: 16px; } /* full-width button */
|
|
|
|
/* Wiki toolbar: buttons wrap instead of being cut off */
|
|
html #content .jstTabs.tabs { clear: both; block-size: auto; overflow: visible; } /* below the floated field label */
|
|
html #content .jstTabs.tabs ul { position: static; display: flex; flex-wrap: wrap; inline-size: auto; min-inline-size: 0; }
|
|
html #content .jstTabs.tabs li.tab-elements { flex: 1 1 auto; min-inline-size: 0; block-size: auto; }
|
|
html #content .jstTabs .jstElements { display: flex; flex-wrap: wrap; white-space: normal; }
|
|
html #content .jstTabs.tabs li.tab-elements::before { display: none; } /* core's full-height strut for vertical centring */
|
|
|
|
/* Subtasks and related issues: the progress bar fits its cell, the subject leaves room
|
|
for both icon buttons */
|
|
html :is(#issue_tree, #relations) td.done_ratio table.progress { inline-size: 100%; }
|
|
html :is(#issue_tree, #relations):not(.with-related-issues-table-headers) .issue:has(.buttons a) > td.subject { padding-inline-end: 72px; }
|
|
|
|
html div#version-summary { margin-block-start: 16px; }
|
|
|
|
/* Core gives the current, previous and next page a third of the row each */
|
|
html .pagination ul.pages li:is(.current, .previous, .next) { inline-size: auto; overflow: visible; }
|
|
|
|
/* The desktop sidebar card has no place on mobile; its content moves into the flyout */
|
|
#sidebar { margin: 0; border-radius: 0; }
|
|
}
|