scrollable details + sticky header
This commit is contained in:
parent
2e021f6ac9
commit
e11c4ef755
|
@ -418,17 +418,15 @@
|
|||
<summary><h2 i18n-text="sections"></h2></summary>
|
||||
<ol id="toc"></ol>
|
||||
</details>
|
||||
<details id="lint" data-pref="editor.lint.expanded" class="hidden-unless-compact ignore-pref-if-compact">
|
||||
<details id="lint" data-pref="editor.lint.expanded" class="ignore-pref-if-compact" hidden>
|
||||
<summary>
|
||||
<h2 i18n-text="linterIssues">: <span id="issue-count"></span>
|
||||
<h2><span i18n-text="linterIssues"></span><span id="issue-count"></span>
|
||||
<a id="lint-help" class="svg-inline-wrapper intercepts-click" tabindex="0">
|
||||
<svg class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
|
||||
</a>
|
||||
</h2>
|
||||
</summary>
|
||||
<div class="lint-scroll-container">
|
||||
<div class="lint-report-container"></div>
|
||||
</div>
|
||||
<div class="lint-report-container"></div>
|
||||
</details>
|
||||
</div>
|
||||
<div id="header-resizer" i18n-title="headerResizerHint"></div>
|
||||
|
|
55
edit/base.js
55
edit/base.js
|
@ -6,14 +6,7 @@
|
|||
/* global initBeautifyButton */// beautify.js
|
||||
/* global prefs */
|
||||
/* global t */// localization.js
|
||||
/* global
|
||||
FIREFOX
|
||||
debounce
|
||||
getOwnTab
|
||||
sessionStore
|
||||
tryJSONparse
|
||||
tryURL
|
||||
*/// toolbox.js
|
||||
/* global FIREFOX getOwnTab sessionStore tryJSONparse tryURL */// toolbox.js
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
|
@ -56,6 +49,13 @@ const editor = {
|
|||
|
||||
const baseInit = (() => {
|
||||
const domReady = waitForSelector('#sections');
|
||||
const mq = matchMedia('(max-width: 850px)');
|
||||
(mq.onchange = e => {
|
||||
document.documentElement.classList.toggle('compact-layout', e.matches);
|
||||
for (const el of $$('details[data-pref]')) {
|
||||
el.open = e.matches ? false : prefs.get(el.dataset.pref);
|
||||
}
|
||||
})(mq);
|
||||
|
||||
return {
|
||||
domReady,
|
||||
|
@ -120,45 +120,6 @@ const baseInit = (() => {
|
|||
}
|
||||
})();
|
||||
|
||||
//#endregion
|
||||
//#region init layout/resize
|
||||
|
||||
baseInit.domReady.then(() => {
|
||||
let headerHeight;
|
||||
detectLayout(true);
|
||||
window.on('resize', () => detectLayout());
|
||||
|
||||
function detectLayout(now) {
|
||||
const compact = window.innerWidth <= 850;
|
||||
if (compact) {
|
||||
document.body.classList.add('compact-layout');
|
||||
if (!editor.isUsercss) {
|
||||
if (now) fixedHeader();
|
||||
else debounce(fixedHeader, 250);
|
||||
window.on('scroll', fixedHeader, {passive: true});
|
||||
}
|
||||
} else {
|
||||
document.body.classList.remove('compact-layout', 'fixed-header');
|
||||
window.off('scroll', fixedHeader);
|
||||
}
|
||||
for (const el of $$('details[data-pref]')) {
|
||||
el.open = compact ? false : prefs.get(el.dataset.pref);
|
||||
}
|
||||
}
|
||||
|
||||
function fixedHeader() {
|
||||
const headerFixed = $('.fixed-header');
|
||||
if (!headerFixed) headerHeight = $('#header').clientHeight;
|
||||
const scrollPoint = headerHeight - 43;
|
||||
if (window.scrollY >= scrollPoint && !headerFixed) {
|
||||
$('body').style.setProperty('--fixed-padding', ` ${headerHeight}px`);
|
||||
$('body').classList.add('fixed-header');
|
||||
} else if (window.scrollY < scrollPoint && headerFixed) {
|
||||
$('body').classList.remove('fixed-header');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//#endregion
|
||||
//#region init header
|
||||
|
||||
|
|
271
edit/edit.css
271
edit/edit.css
|
@ -1,5 +1,6 @@
|
|||
:root {
|
||||
--fixed-padding: unset;
|
||||
--pad: 1rem;
|
||||
--pad05: calc(0.5 * var(--pad));
|
||||
}
|
||||
|
||||
body {
|
||||
|
@ -70,7 +71,7 @@ html:not(.is-new-style) #heading::after {
|
|||
#popup-button:hover {
|
||||
filter: drop-shadow(0 0 3px hsl(180, 70%, 50%));
|
||||
}
|
||||
.usercss body:not(.compact-layout) #popup-button {
|
||||
.usercss:not(.compact-layout) #popup-button {
|
||||
right: 24px;
|
||||
}
|
||||
/************ checkbox & select************/
|
||||
|
@ -91,10 +92,10 @@ label {
|
|||
#header {
|
||||
width: var(--header-width);
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
padding: 1rem;
|
||||
padding-top: var(--pad);
|
||||
box-shadow: 0 0 3rem -1.2rem black;
|
||||
box-sizing: border-box;
|
||||
z-index: 10;
|
||||
|
@ -222,56 +223,61 @@ input:invalid {
|
|||
margin-left: 0;
|
||||
}
|
||||
/* collapsibles */
|
||||
#header details {
|
||||
margin-right: var(--header-resizer-width);
|
||||
}
|
||||
#header details[open] {
|
||||
overflow-y: auto;
|
||||
margin-top: calc(1.5*var(--pad));
|
||||
}
|
||||
#header details[open] summary {
|
||||
position: absolute;
|
||||
margin-top: calc(-1.5*var(--pad));
|
||||
}
|
||||
#header summary {
|
||||
align-items: center;
|
||||
margin-left: -13px;
|
||||
margin-left: .25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
#header summary + * {
|
||||
padding: .5rem 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#header summary h2 {
|
||||
display: inline-block;
|
||||
border-bottom: 1px dotted transparent;
|
||||
margin-top: .1em;
|
||||
margin-bottom: .1em;
|
||||
margin-left: -13px;
|
||||
margin: 0 0 0 -13px;
|
||||
padding-left: 13px; /* clicking directly on details-marker doesn't set pref so we cover it with h2 */
|
||||
max-width: calc(var(--header-width) - 2*var(--pad));
|
||||
vertical-align: middle;
|
||||
}
|
||||
#header summary h2,
|
||||
#header summary h2 > :first-child {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#header summary:hover h2 {
|
||||
border-color: #bbb;
|
||||
}
|
||||
|
||||
#header summary svg {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
#header details > :not(summary) {
|
||||
margin: 0 0 0 var(--pad);
|
||||
padding: calc(var(--pad)/4) 0;
|
||||
}
|
||||
#details-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
margin-top: var(--pad05);
|
||||
}
|
||||
|
||||
#header details[open] + details[open] {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
#actions .buttons {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#actions .buttons > * {
|
||||
margin: 0 .25rem .5rem 0;
|
||||
}
|
||||
|
||||
#options:not([open]) + #lint h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
#lint:not([open]) h2 {
|
||||
margin-bottom: 0;
|
||||
margin: 0 .25rem var(--pad05) 0;
|
||||
}
|
||||
|
||||
#publish > div > * {
|
||||
|
@ -426,8 +432,6 @@ input:invalid {
|
|||
}
|
||||
#toc {
|
||||
counter-reset: codelabel;
|
||||
margin: 0;
|
||||
padding: .5rem 0;
|
||||
}
|
||||
#toc li {
|
||||
white-space: nowrap;
|
||||
|
@ -829,40 +833,13 @@ body:not(.find-open) [data-match-highlight-count="1"] .CodeMirror-selection-high
|
|||
|
||||
/************ lint ************/
|
||||
#lint {
|
||||
overflow: hidden;
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
#lint > summary {
|
||||
position: relative;
|
||||
margin-left: 0;
|
||||
padding-left: 4px;
|
||||
}
|
||||
#lint[open]:not(.hidden-unless-compact) {
|
||||
min-height: 102px;
|
||||
}
|
||||
#lint summary h2 {
|
||||
text-indent: -2px;
|
||||
}
|
||||
#lint > .lint-scroll-container {
|
||||
margin: 1rem 10px 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#lint summary h2 {
|
||||
display: inline-flex;
|
||||
}
|
||||
#lint table {
|
||||
font-size: 100%;
|
||||
border-spacing: 0;
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.0;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -878,7 +855,7 @@ body:not(.find-open) [data-match-highlight-count="1"] .CodeMirror-selection-high
|
|||
#lint table.empty {
|
||||
display: none;
|
||||
}
|
||||
#lint caption {
|
||||
#lint caption:not(:empty) {
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
padding-bottom: 6px;
|
||||
|
@ -908,6 +885,9 @@ body:not(.find-open) [data-match-highlight-count="1"] .CodeMirror-selection-high
|
|||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#issue-count::before {
|
||||
content: ':\A0';
|
||||
}
|
||||
#message-box.center.lint-config #message-box-contents {
|
||||
text-align: left;
|
||||
}
|
||||
|
@ -970,11 +950,6 @@ html:not(.usercss) .usercss-only,
|
|||
display: none !important; /* hide during page init */
|
||||
}
|
||||
|
||||
body:not(.compact-layout) .hidden-unless-compact,
|
||||
body.linter-disabled .hidden-unless-compact {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#options:not([open]) + #lint {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
@ -1021,152 +996,100 @@ body.linter-disabled .hidden-unless-compact {
|
|||
margin-left: 0.2rem;
|
||||
}
|
||||
|
||||
/************ full-width only ************/
|
||||
/* TODO: maybe move more rules here so we don't need to reset them in @media(max-width: 850px) */
|
||||
@media (min-width: 851px) {
|
||||
#header > :not(#details-wrapper):not(#header-resizer) {
|
||||
margin-left: var(--pad);
|
||||
margin-right: var(--pad);
|
||||
}
|
||||
#publish[open],
|
||||
#header details:not([open]) {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
#header details[open]:not(:last-child) {
|
||||
margin-bottom: var(--pad05);
|
||||
}
|
||||
#header details:last-child {
|
||||
padding-bottom: var(--pad);
|
||||
}
|
||||
}
|
||||
|
||||
/************ reponsive layouts ************/
|
||||
@media(max-width: 850px) {
|
||||
body {
|
||||
html:not(.usercss) body {
|
||||
height: 100%;
|
||||
}
|
||||
.usercss body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.usercss #header {
|
||||
position: inherit;
|
||||
}
|
||||
#header {
|
||||
flex: 0 1 auto;
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
height: unset;
|
||||
width: unset;
|
||||
position: inherit;
|
||||
position: sticky;
|
||||
background: #fff;
|
||||
border-right: none;
|
||||
border-bottom: 1px dashed #AAA;
|
||||
padding: .5rem 1rem .5rem .5rem;
|
||||
}
|
||||
.fixed-header {
|
||||
--fixed-height: 40px;
|
||||
padding-top: var(--fixed-padding);
|
||||
}
|
||||
.fixed-header #header {
|
||||
min-height: var(--fixed-height);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.fixed-header #header > *:not(#details-wrapper),
|
||||
.fixed-header #options {
|
||||
display: none !important;
|
||||
}
|
||||
.fixed-header #details-wrapper {
|
||||
padding-top: calc((var(--fixed-height) - 1.2rem) / 2); /* 1.2 is the normal line height */
|
||||
}
|
||||
#header summary + *,
|
||||
#lint > .lint-scroll-container {
|
||||
margin-left: 1rem;
|
||||
padding: .25rem 0 .5rem;
|
||||
}
|
||||
#header input[type="checkbox"] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#header details {
|
||||
margin: 0;
|
||||
padding: var(--pad05) var(--pad05) 0;
|
||||
}
|
||||
#heading,
|
||||
h2 {
|
||||
display: none;
|
||||
}
|
||||
#basic-info {
|
||||
margin-bottom: .5rem;
|
||||
margin: 0 16px var(--pad05) 0; /* for popup icon in simple window */
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#basic-info #name,
|
||||
#basic-info > *:first-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#basic-info > *:not(:last-child) {
|
||||
margin-right: 0.8rem;
|
||||
}
|
||||
#basic-info #name {
|
||||
flex-grow: 1;
|
||||
#header details > :not(summary) {
|
||||
margin-left: var(--pad05);
|
||||
}
|
||||
#options-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
#header h2 {
|
||||
font-size: 14px;
|
||||
}
|
||||
#actions {
|
||||
display: inline-block;
|
||||
}
|
||||
#details-wrapper {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
max-width: 100%;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: .25em 0 var(--pad05);
|
||||
}
|
||||
#options[open] {
|
||||
width: 100%;
|
||||
#details-wrapper details[open] {
|
||||
max-height: 10vh;
|
||||
}
|
||||
#sections-list[open] {
|
||||
max-height: 102px;
|
||||
}
|
||||
#sections-list[open] #toc {
|
||||
max-height: 60px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
#header details:not(#options) {
|
||||
#details-wrapper[data-open^=".."] details {
|
||||
max-width: 50%;
|
||||
}
|
||||
.options-column {
|
||||
flex-grow: 1;
|
||||
padding-right: .5rem;
|
||||
box-sizing: border-box;
|
||||
#details-wrapper[data-open^="..."] {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.options-column > .usercss-only {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#options-wrapper .options-column:nth-child(2) {
|
||||
margin-top: 0;
|
||||
}
|
||||
#options:not([open]),
|
||||
#options[open],
|
||||
#publish[open],
|
||||
#lint:not([open]) {
|
||||
overflow: initial;
|
||||
}
|
||||
#options:not([open]) + #lint:not([open]) {
|
||||
margin-top: 0;
|
||||
}
|
||||
#lint summary {
|
||||
position: static;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#header summary {
|
||||
margin-left: 0;
|
||||
padding-left: 4px;
|
||||
}
|
||||
#header summary h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.option label {
|
||||
margin: 0;
|
||||
}
|
||||
#options [type="number"] {
|
||||
text-align: left; /* workaround the column flow bug in webkit */
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
#options #tabSize-label {
|
||||
position: relative;
|
||||
top: 0.2rem;
|
||||
}
|
||||
#lint > .lint-scroll-container {
|
||||
padding-top: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
#lint {
|
||||
padding: 0;
|
||||
margin: .5rem 0 0;
|
||||
}
|
||||
#lint:not([open]) + #footer {
|
||||
margin: .25em 0 -1em .25em;
|
||||
flex: 0 0 auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#sections {
|
||||
height: unset !important;
|
||||
padding-left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
/* TODO: switch from .single-editor to the global .usercss */
|
||||
#sections > :not(.single-editor) {
|
||||
margin: 0 .5rem;
|
||||
padding: .5rem 0;
|
||||
|
@ -1175,10 +1098,6 @@ body.linter-disabled .hidden-unless-compact {
|
|||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
.usercss #options:not([open]) ~ #lint.hidden ~ #footer,
|
||||
.usercss #lint:not([open]) + #footer {
|
||||
margin-top: -.25em;
|
||||
}
|
||||
#help-popup.big[style="display: block;"],
|
||||
#help-popup[style="display: block;"] {
|
||||
width: max-content;
|
||||
|
|
15
edit/edit.js
15
edit/edit.js
|
@ -1,4 +1,4 @@
|
|||
/* global $ $create messageBoxProxy waitForSheet */// dom.js
|
||||
/* global $$ $ $create messageBoxProxy waitForSheet */// dom.js
|
||||
/* global API msg */// msg.js
|
||||
/* global CodeMirror */
|
||||
/* global SectionsEditor */
|
||||
|
@ -43,6 +43,19 @@ baseInit.ready.then(async () => {
|
|||
new MutationObserver(() => elSec.open && editor.updateToc())
|
||||
.observe(elSec, {attributes: true, attributeFilter: ['open']});
|
||||
|
||||
// Auto-update `data-open` attribute to the number of open details
|
||||
{
|
||||
const wrapper = $('#details-wrapper');
|
||||
const details = $$('details', wrapper);
|
||||
const ds = wrapper.dataset;
|
||||
const update = () => {
|
||||
ds.open = '.'.repeat(details.reduce((res, el) => res + (el.open ? 1 : 0), 0));
|
||||
};
|
||||
for (const el of details) {
|
||||
new MutationObserver(update).observe(el, {attributes: true, attributeFilter: ['open']});
|
||||
}
|
||||
}
|
||||
|
||||
$('#toc').onclick = e =>
|
||||
editor.jumpToEditor([...$('#toc').children].indexOf(e.target));
|
||||
$('#keyMap-help').onclick = () =>
|
||||
|
|
|
@ -312,7 +312,7 @@ linterMan.DEFAULTS = {
|
|||
function updateCount() {
|
||||
const issueCount = Array.from(tables.values())
|
||||
.reduce((sum, table) => sum + table.trs.length, 0);
|
||||
$('#lint').classList.toggle('hidden-unless-compact', issueCount === 0);
|
||||
$('#lint').hidden = !issueCount;
|
||||
$('#issue-count').textContent = issueCount;
|
||||
}
|
||||
|
||||
|
|
|
@ -277,13 +277,15 @@ input[type="number"][data-focused-via-click]:focus {
|
|||
/* header resizer */
|
||||
:root {
|
||||
--header-width: 280px;
|
||||
--header-resizer-width: 8px;
|
||||
}
|
||||
#header-resizer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 6px;
|
||||
width: var(--header-resizer-width);
|
||||
box-sizing: border-box;
|
||||
cursor: e-resize;
|
||||
border-width: 0 1px;
|
||||
border-style: solid;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Stylus",
|
||||
"version": "1.5.22",
|
||||
"minimum_chrome_version": "55",
|
||||
"minimum_chrome_version": "56",
|
||||
"description": "__MSG_description__",
|
||||
"homepage_url": "https://add0n.com/stylus.html",
|
||||
"manifest_version": 2,
|
||||
|
|
Loading…
Reference in New Issue
Block a user