From 87b61d608871bc3e08ff427d57910d3d7327780f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Mon, 7 Sep 2026 15:01:58 +0200 Subject: [PATCH] select styled --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/assets.rs | 3 +- static/css/styles.css | 419 +++++++++++++++++--------------------- static/editor.html | 8 +- static/home.html | 2 +- static/js/home.js | 6 +- static/js/image-upload.js | 4 +- static/js/note-editor.js | 5 + static/js/preferences.js | 46 +++-- static/js/select.js | 314 ++++++++++++++++++++++++++++ static/js/theme.js | 1 + static/js/vendor-libs.js | 6 +- static/workspace.html | 2 +- 14 files changed, 551 insertions(+), 269 deletions(-) create mode 100644 static/js/select.js diff --git a/Cargo.lock b/Cargo.lock index 786efa5..be8e75c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "rustpad" -version = "0.2.65" +version = "0.2.66" dependencies = [ "argon2", "aws-config", diff --git a/Cargo.toml b/Cargo.toml index b98cc69..f936f6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustpad" -version = "0.2.65" +version = "0.2.66" edition = "2024" rust-version = "1.94" description = "Collaborative Markdown notepad built with Axum, WebSockets and SQLite, PostgreSQL and MySQL" diff --git a/src/assets.rs b/src/assets.rs index c4857df..a351676 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -42,6 +42,7 @@ const MODULES: &[&str] = &[ "url-state", "vendor-libs", "security", + "select", ]; pub fn render_html( @@ -152,7 +153,7 @@ impl<'a> AssetUrls<'a> { fn entrypoint(&self, name: &str) -> String { let entrypoint = self.url(&format!("js/{name}.js")); format!( - r#""#, + r#""#, escape_js_string(&entrypoint) ) } diff --git a/static/css/styles.css b/static/css/styles.css index 71e01f5..39f8fbb 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -797,8 +797,7 @@ textarea:focus { flex: 1; } -.editor-toolbar button, -.editor-toolbar select { +.editor-toolbar button { min-height: 34px; border: 1px solid transparent; border-radius: 7px; @@ -808,18 +807,12 @@ textarea:focus { font-size: .78rem; } -.editor-toolbar button:hover, -.editor-toolbar select:hover { +.editor-toolbar button:hover { border-color: var(--border); background: var(--surface-2); color: var(--text); } -.editor-toolbar select { - border-color: var(--border); - background: var(--surface-raised); -} - .view-switch { padding: 3px; border: 1px solid var(--border); @@ -832,7 +825,6 @@ textarea:focus { color: var(--text); } -/* Focus mode removes the toolbar row and leaves only compact floating controls. */ .pad-page .toolbar-collapse-toggle { display: inline-grid; flex: 0 0 auto; @@ -889,19 +881,19 @@ textarea:focus { backdrop-filter: blur(10px); } -.pad-page.toolbar-collapsed .editor-toolbar > :not(.toolbar-collapse-toggle):not(.view-switch) { +.pad-page.toolbar-collapsed .editor-toolbar> :not(.toolbar-collapse-toggle):not(.view-switch) { display: none !important; } -.pad-page.toolbar-collapsed .editor-toolbar > .toolbar-collapse-toggle, -.pad-page.toolbar-collapsed .editor-toolbar > .view-switch { +.pad-page.toolbar-collapsed .editor-toolbar>.toolbar-collapse-toggle, +.pad-page.toolbar-collapsed .editor-toolbar>.view-switch { position: static; display: inline-flex !important; width: auto; margin: 0; } -.pad-page.toolbar-collapsed .editor-toolbar > .toolbar-collapse-toggle { +.pad-page.toolbar-collapsed .editor-toolbar>.toolbar-collapse-toggle { order: 1; width: 36px; min-width: 36px; @@ -910,7 +902,7 @@ textarea:focus { padding: 0; } -.pad-page.toolbar-collapsed .editor-toolbar > .view-switch { +.pad-page.toolbar-collapsed .editor-toolbar>.view-switch { order: 2; } @@ -1271,8 +1263,6 @@ dialog::backdrop { } .toast-region--modal { - /* A manual popover enters the browser top layer above the active dialog. - Reset popover defaults while keeping the regular toast viewport geometry. */ top: auto; left: auto; margin: 0; @@ -1284,7 +1274,6 @@ dialog::backdrop { } .app-dialog.has-modal-toast-region { - /* Fallback for browsers without the Popover API. */ overflow: visible; } @@ -1399,8 +1388,13 @@ dialog::backdrop { } @keyframes toast-countdown { - from { transform: scaleX(1); } - to { transform: scaleX(0); } + from { + transform: scaleX(1); + } + + to { + transform: scaleX(0); + } } @media (max-width: 520px) { @@ -1697,7 +1691,6 @@ dialog::backdrop { } } -/* Home: standalone note and workspace are separate choices. */ .home-layout--wide { width: min(1040px, calc(100% - 32px)); } @@ -1743,7 +1736,6 @@ dialog::backdrop { } } -/* Collaborative editor additions */ .editor-shell { display: grid; grid-template-columns: auto minmax(0, 1fr); @@ -2008,7 +2000,6 @@ dialog::backdrop { } } -/* Layout safeguards and home footer */ .app-header__main, .document-heading { min-width: 0; @@ -2074,7 +2065,6 @@ dialog::backdrop { } } -/* Compact line numbers; author labels sit over the edited text, not in the gutter. */ .line-gutter { width: 48px; } @@ -2124,7 +2114,6 @@ dialog::backdrop { } } -/* Editor display preferences and author overlay */ .editor-shell { position: relative; } @@ -2155,10 +2144,10 @@ dialog::backdrop { font-size: .72rem; } -.editor-controls select { - width: auto; +.editor-controls .app-select--field .app-select-trigger { min-height: 30px; - padding: 3px 24px 3px 7px; + height: 30px; + padding: 3px 8px; border-radius: 6px; font-size: .74rem; } @@ -2230,7 +2219,6 @@ dialog::backdrop { word-break: normal; } -/* Keep line numbers exactly aligned with the logical text lines. */ .line-gutter { box-sizing: border-box; font-size: var(--editor-font-size, 18px); @@ -2247,7 +2235,6 @@ dialog::backdrop { font-size: calc(var(--editor-font-size, 18px) - 2px); } -/* Image crop/resize dialog. */ .image-editor-dialog { width: min(920px, calc(100% - 28px)); max-width: none; @@ -2329,42 +2316,17 @@ dialog::backdrop { font-weight: 700; } -.image-editor-controls select, +.image-editor-controls .app-select--field, .image-editor-controls input { width: 100%; } -.image-editor-controls select { +.image-editor-controls .app-select--field .app-select-trigger { min-height: 40px; - padding: 0 36px 0 12px; - border: 1px solid var(--border-strong); + height: 40px; border-radius: 9px; - background-color: var(--control-bg); - background-image: linear-gradient(45deg, transparent 50%, var(--select-arrow) 50%), - linear-gradient(135deg, var(--select-arrow) 50%, transparent 50%); - background-position: calc(100% - 16px) 17px, calc(100% - 11px) 17px; - background-repeat: no-repeat; - background-size: 5px 5px, 5px 5px; - box-shadow: inset 0 1px 0 var(--wash-soft); - color: var(--text); font-size: .84rem; font-weight: 600; - appearance: none; - -webkit-appearance: none; - cursor: pointer; - transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease; -} - -.image-editor-controls select:hover { - border-color: var(--select-border); - background-color: var(--surface-hover); -} - -.image-editor-controls select:focus, -.image-editor-controls select:focus-visible { - border-color: var(--focus); - outline: none; - box-shadow: 0 0 0 3px var(--focus-ring), inset 0 1px 0 var(--wash-soft); } .image-editor-controls input[type="range"] { @@ -2470,7 +2432,6 @@ dialog::backdrop { } } -/* Wider published page workspace. */ .public-header { padding-inline: max(20px, calc((100vw - 1180px) / 2)); } @@ -2492,7 +2453,6 @@ dialog::backdrop { padding: clamp(24px, 4vw, 52px); } -/* Preview and attachment management */ .preview { overscroll-behavior: contain; scrollbar-gutter: stable; @@ -2919,7 +2879,6 @@ dialog::backdrop { } } -/* Choice shown when a video file is uploaded. */ .video-insert-dialog { width: min(560px, calc(100vw - 24px)); max-width: 560px; @@ -2955,7 +2914,7 @@ dialog::backdrop { gap: 12px; } -.video-choice-actions > button { +.video-choice-actions>button { display: grid; justify-items: start; gap: 5px; @@ -2975,11 +2934,11 @@ dialog::backdrop { line-height: 1.4; } -.video-choice-actions > .action-button--primary span { +.video-choice-actions>.action-button--primary span { color: var(--on-accent); } -.video-choice-actions > .action-button--secondary span { +.video-choice-actions>.action-button--secondary span { color: var(--text-secondary); } @@ -3238,7 +3197,6 @@ dialog::backdrop { cursor: default; } -/* Preview editing and source line numbers. */ .preview { position: relative; padding: 12px 24px 12px 62px; @@ -3361,7 +3319,6 @@ dialog::backdrop { color: var(--text-subtle); } -/* Task-list layout. Keep the checkbox in the same marker gutter as a bullet. */ .markdown-body .task-list-item { position: relative; display: block; @@ -3755,7 +3712,6 @@ dialog::backdrop { gap: 6px; } -/* Account footer and authentication dialog. */ .home-footer { width: min(1040px, calc(100% - 32px)); margin: auto auto 24px; @@ -3893,7 +3849,7 @@ dialog::backdrop { #profile-dialog, #profile-dialog .identity-panel, #profile-dialog .identity-fields, -#profile-dialog .identity-fields > *, +#profile-dialog .identity-fields>*, #profile-dialog .profile-actions, #profile-dialog .profile-theme-field, #profile-dialog .profile-language-field, @@ -4080,13 +4036,13 @@ dialog::backdrop { grid-template-columns: minmax(0, 1fr); } - #profile-dialog .identity-fields > *, + #profile-dialog .identity-fields>*, #profile-dialog .profile-actions, #profile-dialog .form-message { grid-column: 1; } - #profile-dialog .profile-actions > button { + #profile-dialog .profile-actions>button { min-width: 0; white-space: normal; } @@ -4142,7 +4098,6 @@ dialog::backdrop { background: var(--danger-hover); } -/* Native hidden must win over component display declarations. */ [hidden] { display: none !important; } @@ -4364,7 +4319,6 @@ dialog::backdrop { flex-direction: column; } -/* Stable scrolling and collapsible Markdown sections. */ .editor-shell { width: 100%; max-width: 100%; @@ -4419,7 +4373,6 @@ dialog::backdrop { margin-bottom: 0; } -/* Full-height editor: keep header/footer visible and scroll only the work area. */ .pad-page { height: 100dvh; min-height: 0; @@ -4475,7 +4428,6 @@ dialog::backdrop { } } -/* A collapsible section has one source-line marker; its rendered Markdown does not repeat line numbers inside. */ .markdown-details__content .preview-source-line::before { display: none; } @@ -4488,7 +4440,6 @@ dialog::backdrop { overflow: auto; } -/* Ephemeral room presence and chat */ .room-details { position: relative; display: inline-block; @@ -4685,7 +4636,6 @@ dialog::backdrop { filter: brightness(1.15); } -/* Sharing panel */ .share-panel { display: grid; gap: 18px; @@ -4783,7 +4733,7 @@ dialog::backdrop { } .share-link-row input, -.share-link-row select { +.share-link-row .app-select--field { min-width: 0; } @@ -4811,7 +4761,6 @@ dialog::backdrop { } } -/* Share dialog */ .share-dialog { width: min(900px, calc(100% - 28px)); max-width: 900px; @@ -4904,30 +4853,13 @@ dialog::backdrop { font-size: .76rem; } -.share-dialog select { +.share-dialog .app-select--field { width: 100%; +} + +.share-dialog .app-select--field .app-select-trigger { min-height: 42px; - padding: 0 38px 0 12px; - border: 1px solid var(--border-strong); - border-radius: 8px; - background-color: var(--surface-toolbar); - color: var(--text); - appearance: none; - background-image: linear-gradient(45deg, transparent 50%, var(--select-arrow) 50%), linear-gradient(135deg, var(--select-arrow) 50%, transparent 50%); - background-position: calc(100% - 16px) 17px, calc(100% - 11px) 17px; - background-size: 5px 5px, 5px 5px; - background-repeat: no-repeat; - cursor: pointer; -} - -.share-dialog select:hover { - border-color: var(--select-border); -} - -.share-dialog select:focus { - border-color: var(--focus); - box-shadow: 0 0 0 3px var(--focus-ring); - outline: none; + height: 42px; } .share-dialog input[type="text"], @@ -5043,7 +4975,6 @@ dialog::backdrop { } } -/* Refined sharing dialog and shared-resource attribution. */ .share-dialog { border: 1px solid var(--border-strong); border-radius: 18px; @@ -5157,9 +5088,9 @@ dialog::backdrop { gap: 4px; } - .resource-actions > button, - .resource-actions > .resource-password-menu, - .resource-password-menu > summary { + .resource-actions>button, + .resource-actions>.resource-password-menu, + .resource-password-menu>summary { width: 100%; min-width: 0; } @@ -5202,7 +5133,6 @@ dialog::backdrop { } } -/* Markdown alerts. */ .markdown-body .markdown-alert { margin: 1em 0; padding: .8em 1em; @@ -5239,7 +5169,6 @@ dialog::backdrop { background: var(--status-danger-bg); } -/* Fenced code line numbers for every language: ```lang=, ```lang=101, ```= or ```=101. */ .markdown-body pre.code-with-lines code { counter-reset: none; } @@ -5264,7 +5193,6 @@ dialog::backdrop { user-select: none; } -/* Generated table of contents. */ .markdown-body .markdown-toc { margin: 1em 0; padding: .8em 1em; @@ -5278,12 +5206,11 @@ dialog::backdrop { padding-left: 1.35em; } -/* Top-level entries are already numbered by their headings, so omit redundant bullets. */ -.markdown-body .markdown-toc > ul { +.markdown-body .markdown-toc>ul { padding-left: 0; } -.markdown-body .markdown-toc > ul > li { +.markdown-body .markdown-toc>ul>li { list-style: none; } @@ -5303,7 +5230,6 @@ dialog::backdrop { margin-left: 0; } -/* Nested Markdown lists keep markers and source-line numbers in separate gutters. */ .markdown-body ul, .markdown-body ol { padding-left: 1.75em; @@ -5323,7 +5249,6 @@ dialog::backdrop { list-style: none; } -/* Keep the editor gutter inside the mobile workspace. */ @media (max-width: 720px) { .pad-page .editor-shell { grid-template-columns: 38px minmax(0, 1fr); @@ -5518,7 +5443,6 @@ dialog::backdrop { gap: 10px; } -/* Per-character authorship overlay. The textarea remains the editable surface. */ .authorship-layer { position: absolute; z-index: 1; @@ -5560,7 +5484,6 @@ dialog::backdrop { } } -/* Multiple authors can contribute to one line. */ .owner-label-group { position: absolute; right: calc(var(--editor-rendered-font-size, 14px) * .57); @@ -5581,12 +5504,10 @@ dialog::backdrop { transform: none; } -/* Keep public TOC targets visible below the sticky page header. */ .public-content :is(h1, h2, h3, h4, h5, h6)[id] { scroll-margin-top: 88px; } -/* Shared semantic action buttons. Keep legacy class names as aliases. */ .action-button, .primary-button, .secondary-button, @@ -5699,7 +5620,7 @@ dialog::backdrop { min-width: 0; } -.profile-language-field > span:first-child { +.profile-language-field>span:first-child { color: var(--text-label); font-size: .86rem; font-weight: 750; @@ -5877,7 +5798,7 @@ dialog::backdrop { line-height: 1; } -.profile-language-field > small { +.profile-language-field>small { color: var(--text-muted); line-height: 1.45; } @@ -5964,8 +5885,6 @@ dialog::backdrop { } } -/* Keep the view controls visible on Full HD displays using 125% scaling. - Only the formatting group becomes horizontally scrollable. */ @media (min-width: 1500px) and (max-width: 1699px) { .pad-page .editor-toolbar { flex-wrap: nowrap; @@ -5995,7 +5914,6 @@ dialog::backdrop { } } -/* Responsive note editor -------------------------------------------------- */ @media (max-width: 1499px) { .pad-page { display: flex; @@ -6329,8 +6247,7 @@ dialog::backdrop { padding: 6px; } - .pad-page .editor-toolbar button, - .pad-page .editor-toolbar select { + .pad-page .editor-toolbar button { min-height: 32px; padding-inline: 8px; } @@ -6357,7 +6274,6 @@ dialog::backdrop { cursor: not-allowed; } -/* Per-note author color override */ .use-global-color { display: inline-grid; width: 1.75rem; @@ -6376,7 +6292,6 @@ dialog::backdrop { color: var(--text); } -/* Quick actions appear when the editor header switches to its compact menu. */ .mobile-editor-bubble { display: none; } @@ -6501,7 +6416,6 @@ dialog::backdrop { } } -/* Movable quick actions for compact editor screens. */ @media (max-width: 1499px) { .pad-page .mobile-editor-bubble { user-select: none; @@ -6563,7 +6477,6 @@ dialog::backdrop { } } -/* Authorship display modes */ .editor-column-label { display: flex; align-items: center; @@ -6643,7 +6556,6 @@ dialog::backdrop { } } -/* Keep the whole editor surface consistent in Simple and Full modes. */ .editor-shell { background: var(--surface-inset); } @@ -6666,7 +6578,6 @@ dialog::backdrop { z-index: 5; } -/* Stable editor canvas in both authorship modes. */ .pad-page .editor-column, .pad-page .editor-shell { background: var(--surface-inset); @@ -6690,7 +6601,6 @@ dialog::backdrop { background: transparent !important; } -/* The authorship canvas must paint the whole editable area, not only text rows. */ .pad-page .authorship-layer { width: auto; height: auto; @@ -6714,7 +6624,6 @@ dialog::backdrop { line-height: 1.45; } -/* Full-height editor/gutter separator, independent of the number of text lines. */ .pad-page .editor-shell::after { position: absolute; z-index: 6; @@ -6744,9 +6653,6 @@ dialog::backdrop { } } -/* Fill the editor column with the actual editor shell. - The grid version could size the shell to its content in Full authorship mode, - so the gutter separator stopped after the last rendered line. */ .pad-page .editor-column { display: flex; flex-direction: column; @@ -6765,7 +6671,6 @@ dialog::backdrop { min-height: 0; } -/* Published page action and settings in one dropdown. */ .page-settings { position: relative; } @@ -6880,7 +6785,6 @@ dialog::backdrop { background: var(--surface-hover); } -/* Keep the Simple/Full switch inside the editor label frame. */ .authorship-mode-control { padding: 1px; border-radius: 7px; @@ -6894,7 +6798,6 @@ dialog::backdrop { line-height: 20px; } -/* Final UI fixes: opaque Page settings and per-note authorship controls. */ .page-settings-menu { background: var(--surface-card); opacity: 1; @@ -6947,7 +6850,6 @@ dialog::backdrop { } } -/* Shared editor display settings */ .authorship-controls { display: flex; align-items: center; @@ -7020,7 +6922,6 @@ dialog::backdrop { white-space: pre-wrap; } -/* Keep generated individual links below the new-link form. */ .share-link-list-wrap { display: grid; gap: 8px; @@ -7080,7 +6981,6 @@ dialog::backdrop { } } -/* Upload progress toast --------------------------------------------------- */ .toast-card--upload { grid-template-columns: minmax(0, 1fr) 28px; } @@ -7133,9 +7033,17 @@ dialog::backdrop { } @keyframes upload-toast-indeterminate { - 0% { transform: translateX(-120%); } - 50% { transform: translateX(180%); } - 100% { transform: translateX(420%); } + 0% { + transform: translateX(-120%); + } + + 50% { + transform: translateX(180%); + } + + 100% { + transform: translateX(420%); + } } .upload-toast__meta { @@ -7195,7 +7103,6 @@ dialog::backdrop { border-color: color-mix(in srgb, var(--accent) 55%, var(--border-strong)) !important; } -/* Optional links to exact editor lines. */ .line-number-button { display: block; width: 100%; @@ -7233,7 +7140,6 @@ dialog::backdrop { color: var(--text); } -/* Personal editor preferences in the compact mobile action bar. */ @media (max-width: 1499px) { .mobile-editor-options { position: relative; @@ -7288,14 +7194,17 @@ dialog::backdrop { font-size: .78rem; } - .mobile-editor-options__panel select { + .mobile-editor-options__panel .app-select--field { width: 100%; + } + + .mobile-editor-options__panel .app-select--field .app-select-trigger { min-height: 34px; + height: 34px; } } -/* Note editor polish: clearer actions, lighter canvas, and aligned split columns. */ .pad-page .header-actions>.secondary-button:not(.danger-button), .pad-page .page-settings>summary.secondary-button { border-color: var(--note-action-border); @@ -7395,7 +7304,6 @@ dialog::backdrop { display: none; } -/* Unified RustPad resource identity used by notes and workspaces. */ .resource-brand { display: grid; flex: 0 0 auto; @@ -7464,7 +7372,6 @@ dialog::backdrop { } } -/* Search, pagination and theme-aware scrollbars. */ * { scrollbar-width: thin; scrollbar-color: var(--border-strong) var(--surface-inset); @@ -7520,36 +7427,14 @@ dialog::backdrop { white-space: nowrap; } -.page-size-label select { +.page-size-label .app-select--field { min-width: 78px; +} + +.page-size-label .app-select--field .app-select-trigger { min-height: 40px; - padding: 0 34px 0 12px; - border: 1px solid var(--border-strong); + height: 40px; border-radius: 10px; - background-color: var(--surface-toolbar); - background-image: linear-gradient(45deg, transparent 50%, var(--select-arrow) 50%), - linear-gradient(135deg, var(--select-arrow) 50%, transparent 50%); - background-position: calc(100% - 16px) 16px, calc(100% - 11px) 16px; - background-repeat: no-repeat; - background-size: 5px 5px, 5px 5px; - box-shadow: inset 0 1px 0 var(--wash-soft); - color: var(--text); - font-weight: 700; - appearance: none; - -webkit-appearance: none; - cursor: pointer; - transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease; -} - -.page-size-label select:hover { - border-color: var(--select-border); - background-color: var(--surface-hover); -} - -.page-size-label select:focus-visible { - border-color: var(--focus); - outline: none; - box-shadow: 0 0 0 3px var(--focus-ring), inset 0 1px 0 var(--wash-soft); } .page-size-label:focus-within { @@ -7591,8 +7476,6 @@ dialog::backdrop { } } -/* Share links: keep one-time URLs readable without storing plaintext tokens. */ - .share-link-once { color: var(--muted-2) !important; } @@ -7601,7 +7484,6 @@ dialog::backdrop { color: var(--warning); } -/* Keep editor mode/view controls inside the viewport at browser zoom. */ .control-label-short { display: none; } @@ -7674,7 +7556,6 @@ dialog::backdrop { } } -/* History content wraps vertically and never creates a horizontal scrollbar. */ .history-panel { max-width: 100vw; min-width: 0; @@ -7838,7 +7719,6 @@ dialog::backdrop { font-size: .68rem; } -/* Mobile upload action shown directly below the formatting controls. */ .mobile-upload-button { display: none; } @@ -7906,16 +7786,10 @@ dialog::backdrop { } } -/* Published-note permalinks ------------------------------------------------ */ .public-content .preview-source-line { scroll-margin-top: 88px; } -/* - * Line linking is opt-in on published notes. When regular line numbers are - * hidden, enabling links restores the same gutter so link targets stay inside - * the document instead of protruding past its left edge. - */ .public-page .public-content { transition: padding-left .18s ease; } @@ -7924,11 +7798,6 @@ dialog::backdrop { padding-left: clamp(24px, 4vw, 52px); } -/* - * The permalink occupies the same gutter slot as the regular source number. - * It stays invisible until the row is approached, then behaves like the - * clickable editor line number and remains visible briefly after copying. - */ .public-content .public-permalink { position: absolute; top: 0; @@ -7965,8 +7834,8 @@ dialog::backdrop { opacity: 0; } -.public-page.line-links-enabled .public-content .preview-source-line:hover > .public-permalink, -.public-page.line-links-enabled .public-content .preview-source-line:focus-within > .public-permalink, +.public-page.line-links-enabled .public-content .preview-source-line:hover>.public-permalink, +.public-page.line-links-enabled .public-content .preview-source-line:focus-within>.public-permalink, .public-page.line-links-enabled .public-content .public-permalink:focus-visible { opacity: 1; transform: translateX(0); @@ -7992,7 +7861,8 @@ dialog::backdrop { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 24%, transparent); } -@media (hover: none), (pointer: coarse) { +@media (hover: none), +(pointer: coarse) { .public-page.line-links-enabled .public-content .public-permalink { opacity: .62; transform: none; @@ -8009,7 +7879,6 @@ dialog::backdrop { } } -/* Per-user, per-note navigation-bar focus mode ---------------------------- */ .pad-page .navbar-collapse-toggle { position: fixed; top: max(3px, env(safe-area-inset-top)); @@ -8034,7 +7903,7 @@ dialog::backdrop { transition: width .14s ease, opacity .14s ease, transform .14s ease, color .14s ease, background-color .14s ease; } -.pad-page .navbar-collapse-toggle > span { +.pad-page .navbar-collapse-toggle>span { position: relative; display: block; width: 14px; @@ -8042,8 +7911,8 @@ dialog::backdrop { transition: transform .18s ease; } -.pad-page .navbar-collapse-toggle > span::before, -.pad-page .navbar-collapse-toggle > span::after { +.pad-page .navbar-collapse-toggle>span::before, +.pad-page .navbar-collapse-toggle>span::after { content: ""; position: absolute; top: 3px; @@ -8053,19 +7922,19 @@ dialog::backdrop { background: currentColor; } -.pad-page .navbar-collapse-toggle > span::before { +.pad-page .navbar-collapse-toggle>span::before { left: 0; transform: rotate(-36deg); transform-origin: right center; } -.pad-page .navbar-collapse-toggle > span::after { +.pad-page .navbar-collapse-toggle>span::after { right: 0; transform: rotate(36deg); transform-origin: left center; } -.pad-page .app-header:hover + .navbar-collapse-toggle, +.pad-page .app-header:hover+.navbar-collapse-toggle, .pad-page .navbar-collapse-toggle:hover, .pad-page .navbar-collapse-toggle:focus-visible, .pad-page.navbar-collapsed .navbar-collapse-toggle:hover, @@ -8077,7 +7946,7 @@ dialog::backdrop { outline: none; } -.pad-page.navbar-collapsed .navbar-collapse-toggle > span { +.pad-page.navbar-collapsed .navbar-collapse-toggle>span { transform: rotate(180deg); } @@ -8094,7 +7963,8 @@ dialog::backdrop { flex: 1 1 0; } -@media (hover: none), (pointer: coarse) { +@media (hover: none), +(pointer: coarse) { .pad-page .navbar-collapse-toggle { width: 32px; color: var(--text); @@ -8103,7 +7973,6 @@ dialog::backdrop { } } -/* Compact interface preferences in application headers. */ .header-preferences { display: flex; align-items: center; @@ -8111,20 +7980,20 @@ dialog::backdrop { flex: 0 0 auto; } -.header-preference-picker { +.app-select { position: relative; flex: 0 0 auto; } -.header-preference-picker > summary { +.app-select>summary { list-style: none; } -.header-preference-picker > summary::-webkit-details-marker { +.app-select>summary::-webkit-details-marker { display: none; } -.header-preference-trigger { +.app-select-trigger { display: inline-flex; min-width: 38px; height: 36px; @@ -8141,19 +8010,25 @@ dialog::backdrop { transition: background-color .14s ease, border-color .14s ease, color .14s ease, box-shadow .14s ease; } -.header-preference-trigger:hover, -.header-preference-picker[open] > .header-preference-trigger { +.app-select-trigger:hover, +.app-select[open]>.app-select-trigger, +.app-select.is-open>.app-select-trigger { border-color: var(--border-strong); background: var(--surface-3); color: var(--text); } -.header-preference-trigger:focus-visible { +.app-select-trigger:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; } -.header-preference-trigger__icon { +.app-select-trigger:disabled { + cursor: default; + opacity: .6; +} + +.app-select-trigger__icon { display: grid; width: 17px; height: 17px; @@ -8161,7 +8036,7 @@ dialog::backdrop { place-items: center; } -.header-preference-trigger__icon svg { +.app-select-trigger__icon svg { width: 17px; height: 17px; fill: none; @@ -8171,7 +8046,7 @@ dialog::backdrop { stroke-width: 1.7; } -.header-preference-trigger__value { +.app-select-trigger__value { max-width: 72px; overflow: hidden; color: var(--text); @@ -8182,24 +8057,25 @@ dialog::backdrop { white-space: nowrap; } -.header-preference-picker--language .header-preference-trigger__value { +.app-select--language .app-select-trigger__value { min-width: 18px; text-align: center; letter-spacing: .04em; } -.header-preference-trigger__chevron { +.app-select-trigger__chevron { color: var(--muted-2); font-size: .68rem; line-height: 1; transition: transform .14s ease; } -.header-preference-picker[open] .header-preference-trigger__chevron { +.app-select[open] .app-select-trigger__chevron, +.app-select.is-open .app-select-trigger__chevron { transform: rotate(180deg); } -.header-preference-menu { +.app-select-menu { position: absolute; top: calc(100% + 7px); right: 0; @@ -8216,11 +8092,15 @@ dialog::backdrop { box-shadow: 0 14px 34px var(--shadow-38), inset 0 1px 0 var(--wash-soft); } -.header-preference-picker--language .header-preference-menu { +.app-select-menu[hidden] { + display: none; +} + +.app-select--language .app-select-menu { min-width: 190px; } -.header-preference-option { +.app-select-option { display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: center; @@ -8235,19 +8115,24 @@ dialog::backdrop { text-align: left; } -.header-preference-option:hover, -.header-preference-option:focus-visible { +.app-select-option:hover, +.app-select-option:focus-visible { border-color: var(--border-strong); outline: 0; background: var(--surface-hover); } -.header-preference-option[aria-selected="true"] { +.app-select-option[aria-selected="true"] { border-color: var(--accent-a35); background: var(--accent-soft); } -.header-preference-option__check { +.app-select-option:disabled { + cursor: default; + opacity: .48; +} + +.app-select-option__check { display: grid; width: 18px; height: 18px; @@ -8257,7 +8142,7 @@ dialog::backdrop { font-weight: 900; } -.header-preference-option__copy { +.app-select-option__copy { overflow: hidden; font-size: .78rem; font-weight: 650; @@ -8265,19 +8150,87 @@ dialog::backdrop { white-space: nowrap; } +.app-select-option__group { + display: block; + margin-bottom: 1px; + color: var(--muted-2); + font-size: .65rem; + font-weight: 700; +} + +.app-select-native { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0 0 0 0) !important; + clip-path: inset(50%) !important; + border: 0 !important; + white-space: nowrap !important; + opacity: 0 !important; + pointer-events: none !important; +} + +.app-select--field { + display: inline-block; + max-width: 100%; + vertical-align: middle; +} + +.app-select--field .app-select-trigger { + width: 100%; + min-width: 0; + min-height: 40px; + height: 40px; + justify-content: space-between; + padding: 0 11px 0 12px; + border-color: var(--border-strong); + background: var(--surface-toolbar); + color: var(--text); + font-size: .82rem; + font-weight: 700; +} + +.app-select--field .app-select-trigger__value { + flex: 1 1 auto; + max-width: none; + color: inherit; + font-size: inherit; + font-weight: inherit; + text-align: left; +} + +.app-select-menu--portal { + position: fixed; + top: 0; + right: auto; + left: 0; + z-index: 10000; + min-width: 0; + max-height: min(320px, calc(100dvh - 16px)); + overflow: auto; + overscroll-behavior: contain; +} + +.app-select-menu--portal .app-select-option__copy { + max-width: min(320px, calc(100vw - 72px)); +} + .home-header { justify-content: space-between; } @media (max-width: 720px) { - .header-preference-trigger { + .app-select--header>.app-select-trigger { min-width: 36px; height: 34px; padding-inline: 8px; } - .header-preference-picker--theme .header-preference-trigger__value, - .header-preference-trigger__chevron { + .app-select--header.app-select--theme .app-select-trigger__value, + .app-select--header .app-select-trigger__chevron { display: none; } @@ -8298,18 +8251,18 @@ dialog::backdrop { gap: 4px; } - .header-preference-trigger { + .app-select--header>.app-select-trigger { width: 34px; min-width: 34px; height: 34px; padding: 0; } - .header-preference-trigger__value { + .app-select--header .app-select-trigger__value { display: none; } - .header-preference-menu { + .app-select--header .app-select-menu { max-width: calc(100vw - 20px); } @@ -8325,4 +8278,4 @@ dialog::backdrop { .public-header__actions .header-preferences { margin-left: auto; } -} +} \ No newline at end of file diff --git a/static/editor.html b/static/editor.html index b5488c9..10196f6 100644 --- a/static/editor.html +++ b/static/editor.html @@ -120,13 +120,13 @@ -