AllLangHelp_scalc.mk | 1 Package_html_media.mk | 5 Package_html_static.mk | 3 help3xsl/default.css | 2219 +++++++++++------ help3xsl/help2.js | 169 + help3xsl/online_transform.xsl | 2841 +++++++++++----------- source/media/helpimg/moon-line.svg | 1 source/media/helpimg/search-line.svg | 1 source/media/helpimg/service-line.svg | 1 source/media/helpimg/sun-line.svg | 1 source/media/navigation/libo-symbol-black-alt.svg | 48 source/text/scalc/00/00000405.xhp | 4 source/text/scalc/01/05120000.xhp | 3 source/text/scalc/01/easyconditional.xhp | 53 14 files changed, 3168 insertions(+), 2182 deletions(-)
New commits: commit abe900ae2e1c0d21f00571cc4ae4e60265ab6aab Author: Tulio Macedo <[email protected]> AuthorDate: Wed Aug 5 22:20:16 2026 -0300 Commit: Olivier Hallot <[email protected]> CommitDate: Thu Aug 6 11:19:25 2026 +0200 improvment for help display - light and dark mode - theme selector - color refactoring - layout enhancement Change-Id: I492112ff8b745cfd928bdf8296a8e3928e774849 Reviewed-on: https://gerrit.libreoffice.org/c/help/+/209022 Reviewed-by: Olivier Hallot <[email protected]> Tested-by: Jenkins diff --git a/Package_html_media.mk b/Package_html_media.mk index d8ac6f1950..ee8d483fa7 100644 --- a/Package_html_media.mk +++ b/Package_html_media.mk @@ -389,6 +389,10 @@ $(eval $(call gb_Package_add_files_with_dir,helpcontent2_html_media,$(LIBO_SHARE helpimg/impress_remote01.png \ helpimg/impress_remote02.png \ helpimg/legacy_rect.png \ + helpimg/moon-line.svg \ + helpimg/sun-line.svg \ + helpimg/search-line.svg \ + helpimg/service-line.svg \ navigation/favicon.ico \ navigation/libo-base.svg \ navigation/libo-basic.svg \ @@ -398,6 +402,7 @@ $(eval $(call gb_Package_add_files_with_dir,helpcontent2_html_media,$(LIBO_SHARE navigation/libo-impress.svg \ navigation/libo-math.svg \ navigation/libo-symbol-black.svg \ + navigation/libo-symbol-black-alt.svg \ navigation/libo-symbol-white.svg \ navigation/libo-writer.svg \ screenshots/modules/sdraw/ui/copydlg/DuplicateDialog.png \ diff --git a/Package_html_static.mk b/Package_html_static.mk index a75f8ac09d..845aa412d9 100644 --- a/Package_html_static.mk +++ b/Package_html_static.mk @@ -20,11 +20,12 @@ $(eval $(call gb_Package_add_files,helpcontent2_html_static,$(LIBO_SHARE_HELP_FO a11y-toggle.js \ flexsearch.compact.debug.js \ help.js \ + help2.js \ normalize.css \ paginathing.js \ polyfills.js \ prism.js \ - prism.css \ + prism.css \ )) # vim: set noet sw=4 ts=4: diff --git a/help3xsl/default.css b/help3xsl/default.css index df7bfba75d..0d71ec1b77 100644 --- a/help3xsl/default.css +++ b/help3xsl/default.css @@ -16,115 +16,755 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ /* -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ LIBREOFFICE HELP IN BROWSER + -+ DEFAULT STYLESHEET + -+ WESTERN LANGUAGES + -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -We use px as the unit for navigation elements and fonts because we do -not want them to scale with browser-set font size. -We use rem as the unit for article and footer contents because they -do not break anything related to layout by scaling. - -*/ + + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + LIBREOFFICE HELP IN BROWSER + + + DEFAULT STYLESHEET + + + WESTERN LANGUAGES + + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + We use px as the unit for navigation elements and fonts because we do + not want them to scale with browser-set font size. + We use rem as the unit for article and footer contents because they + do not break anything related to layout by scaling. + + */ + :root { - --font-mono: Menlo, "Cascadia Mono", "Cascadia Code", Consolas, "DejaVu Sans Mono", monospace; - --font-body: Ubuntu, Cantarell, "Segoe UI Variable", "Segoe UI", "Noto Sans", "DejaVu Sans", "Lucida Grande", sans-serif, FreeSerif, NanumGothic, "Noto Sans Tibetan", Taprom; - --background-color: #f7f8f7; - --heading-color: #007c3c; - --hover-color: green; - --link-color: #023a86; - --visited-color: purple; - --selection: #FFEB9F; -} -/* Enable disable Javascript */ -#WarnJS { - margin: 20px; - display: block; + /* ============================================================ + * PRIMITIVE PALETTES + * Shades 50–950. Anchor at 700. + * 50–200 very light · 800–950 very dark. + * ============================================================ */ + + /* --- Neutral (logo gray) --- */ + --color-neutral-700: oklch(34.07% 0.00004 271.152); + --color-neutral-50: oklch(from var(--color-neutral-700) calc(l + 0.6497) calc(c * 0.1) h); + --color-neutral-100: oklch(from var(--color-neutral-700) calc(l + 0.6413) calc(c * 0.15) h); + --color-neutral-200: oklch(from var(--color-neutral-700) calc(l + 0.6293) calc(c * 0.22) h); + --color-neutral-300: oklch(from var(--color-neutral-700) calc(l + 0.6093) calc(c * 0.35) h); + --color-neutral-400: oklch(from var(--color-neutral-700) calc(l + 0.5593) calc(c * 0.55) h); + --color-neutral-500: oklch(from var(--color-neutral-700) calc(l + 0.4893) calc(c * 0.75) h); + --color-neutral-600: oklch(from var(--color-neutral-700) calc(l + 0.3993) calc(c * 0.90) h); + --color-neutral-800: oklch(from var(--color-neutral-700) calc(l - 0.12) c h); + --color-neutral-900: oklch(from var(--color-neutral-700) calc(l - 0.18) c h); + --color-neutral-950: oklch(from var(--color-neutral-700) calc(l - 0.22) c h); + + /* --- Brand (brand green) --- */ + --color-brand-700: oklch(44% 0.18 142); + --color-brand-50: oklch(from var(--color-brand-700) calc(l + 0.54) calc(c * 0.08) h); + --color-brand-100: oklch(from var(--color-brand-700) calc(l + 0.53) calc(c * 0.12) h); + --color-brand-200: oklch(from var(--color-brand-700) calc(l + 0.51) calc(c * 0.18) h); + --color-brand-300: oklch(from var(--color-brand-700) calc(l + 0.49) calc(c * 0.30) h); + --color-brand-400: oklch(from var(--color-brand-700) calc(l + 0.43) calc(c * 0.50) h); + --color-brand-500: oklch(from var(--color-brand-700) calc(l + 0.34) calc(c * 0.72) h); + --color-brand-600: oklch(from var(--color-brand-700) calc(l + 0.22) calc(c * 0.88) h); + --color-brand-800: oklch(from var(--color-brand-700) calc(l - 0.11) c h); + --color-brand-900: oklch(from var(--color-brand-700) calc(l - 0.19) c h); + --color-brand-950: oklch(from var(--color-brand-700) calc(l - 0.25) c h); + + /* --- Amber (ex-Draw): alerts/warnings --- */ + --color-amber-700: oklch(50.932% 0.10883 50.845); + --color-amber-50: oklch(from var(--color-amber-700) calc(l + 0.4811) calc(c * 0.1) h); + --color-amber-100: oklch(from var(--color-amber-700) calc(l + 0.4727) calc(c * 0.15) h); + --color-amber-200: oklch(from var(--color-amber-700) calc(l + 0.4607) calc(c * 0.22) h); + --color-amber-300: oklch(from var(--color-amber-700) calc(l + 0.4407) calc(c * 0.35) h); + --color-amber-400: oklch(from var(--color-amber-700) calc(l + 0.3907) calc(c * 0.55) h); + --color-amber-500: oklch(from var(--color-amber-700) calc(l + 0.3207) calc(c * 0.75) h); + --color-amber-600: oklch(from var(--color-amber-700) calc(l + 0.2307) calc(c * 0.90) h); + --color-amber-800: oklch(from var(--color-amber-700) calc(l - 0.24) c h); + --color-amber-900: oklch(from var(--color-amber-700) calc(l - 0.32) c h); + --color-amber-950: oklch(from var(--color-amber-700) calc(l - 0.38) c h); + + /* --- Violet (ex-Base): donation/institutional --- */ + --color-violet-700: oklch(36.725% 0.15614 307.081); + --color-violet-50: oklch(from var(--color-violet-700) calc(l + 0.6231) calc(c * 0.1) h); + --color-violet-100: oklch(from var(--color-violet-700) calc(l + 0.6148) calc(c * 0.15) h); + --color-violet-200: oklch(from var(--color-violet-700) calc(l + 0.6028) calc(c * 0.22) h); + --color-violet-300: oklch(from var(--color-violet-700) calc(l + 0.5828) calc(c * 0.35) h); + --color-violet-400: oklch(from var(--color-violet-700) calc(l + 0.5328) calc(c * 0.55) h); + --color-violet-500: oklch(from var(--color-violet-700) calc(l + 0.4628) calc(c * 0.75) h); + --color-violet-600: oklch(from var(--color-violet-700) calc(l + 0.3728) calc(c * 0.90) h); + --color-violet-800: oklch(from var(--color-violet-700) calc(l - 0.14) c h); + --color-violet-900: oklch(from var(--color-violet-700) calc(l - 0.20) c h); + --color-violet-950: oklch(from var(--color-violet-700) calc(l - 0.25) c h); + + /* --- Red (ex-Impress): errors --- */ + --color-red-700: oklch(43.625% 0.17148 28.802); + --color-red-50: oklch(from var(--color-red-700) calc(l + 0.5541) calc(c * 0.1) h); + --color-red-100: oklch(from var(--color-red-700) calc(l + 0.5458) calc(c * 0.15) h); + --color-red-200: oklch(from var(--color-red-700) calc(l + 0.5338) calc(c * 0.22) h); + --color-red-300: oklch(from var(--color-red-700) calc(l + 0.5138) calc(c * 0.35) h); + --color-red-400: oklch(from var(--color-red-700) calc(l + 0.4638) calc(c * 0.55) h); + --color-red-500: oklch(from var(--color-red-700) calc(l + 0.3938) calc(c * 0.75) h); + --color-red-600: oklch(from var(--color-red-700) calc(l + 0.3038) calc(c * 0.90) h); + --color-red-800: oklch(from var(--color-red-700) calc(l - 0.21) c h); + --color-red-900: oklch(from var(--color-red-700) calc(l - 0.28) c h); + --color-red-950: oklch(from var(--color-red-700) calc(l - 0.33) c h); + + /* --- Blue (ex-Writer): info/notes --- */ + --color-blue-700: oklch(33.41% 0.13665 261.542); + --color-blue-50: oklch(from var(--color-blue-700) calc(l + 0.6563) calc(c * 0.1) h); + --color-blue-100: oklch(from var(--color-blue-700) calc(l + 0.6479) calc(c * 0.15) h); + --color-blue-200: oklch(from var(--color-blue-700) calc(l + 0.6359) calc(c * 0.22) h); + --color-blue-300: oklch(from var(--color-blue-700) calc(l + 0.6159) calc(c * 0.35) h); + --color-blue-400: oklch(from var(--color-blue-700) calc(l + 0.5659) calc(c * 0.55) h); + --color-blue-500: oklch(from var(--color-blue-700) calc(l + 0.4959) calc(c * 0.75) h); + --color-blue-600: oklch(from var(--color-blue-700) calc(l + 0.4059) calc(c * 0.90) h); + --color-blue-800: oklch(from var(--color-blue-700) calc(l - 0.15) c h); + --color-blue-900: oklch(from var(--color-blue-700) calc(l - 0.21) c h); + --color-blue-950: oklch(from var(--color-blue-700) calc(l - 0.25) c h); + + + /* ============================================================ + * Semantic variables — surface and text and components colors. + * Preserved nomenclature — all values anchored to the new palette. + * ============================================================ */ + + /* --- Tipografy --- */ + --font-mono: Menlo, "Cascadia Mono", "Cascadia Code", Consolas, "DejaVu Sans Mono", monospace; + --font-body: Ubuntu, Cantarell, "Segoe UI Variable", "Segoe UI", "Noto Sans", "DejaVu Sans", "Lucida Grande", sans-serif, FreeSerif, NanumGothic, "Noto Sans Tibetan", Taprom; + + /* --- Surface and text --- */ + --background-color: var(--color-neutral-50); + --heading-color: var(--color-neutral-300); + --text-color: var(--color-neutral-700); + --text-title-color: var(--color-neutral-700); + --text-accent-color: var(--color-violet-700); + --link-color: var(--color-blue-700); + --hover-color: var(--color-blue-600); + --visited-color: var(--color-violet-800); + --table-background: var(--color-neutral-300); + + /* --- Callouts --- */ + --warning-color: var(--color-amber-700); + --warning-background: var(--color-amber-300); + --tip-color: var(--color-brand-700); + --tip-background: var(--color-brand-200); + --note-color: var(--color-blue-700); + --note-background: var(--color-blue-200); + + /* --- Components --- */ + --code-bg: oklch(from var(--color-neutral-700) l c h / 4%); + --widget-bg: linear-gradient(to bottom, var(--color-neutral-200), var(--color-neutral-50)); + --widget-border-color: var(--text-title-color); + --widget-color: var(--text-color); + --widget-font-weight: normal; + --howtoget-bg: var(--color-violet-300); + --howtoget-border-color: var(--color-violet-700); + --howtoget-header-bg: var(--color-neutral-50); + --youtube-placeholder-bg: oklch(from var(--background-color) calc(l - 0.05) c h); + --pagination-color: inherit; + --pagination-link-color: var(--link-color); + --pagination-active-bg: var(--color-blue-800); + --pagination-active-color: var(--color-neutral-50); + --pagination-disabled-color: inherit; + --treeview-hover-border-color: oklch(from var(--color-neutral-700) l c h / 5%); + --contents-current-bg: oklch(from var(--color-neutral-700) l c h / 10%); + --contents-current-border-color: var(--color-neutral-500); + --xapian-search-color: var(--color-neutral-50); + --sf-table-bg: inherit; + --donation-hover-bg: linear-gradient(135deg, var(--color-violet-400) 0%, var(--color-violet-600) 100%); + --table-border-color: var(--color-neutral-400); + --table-stripe-bg: var(--color-neutral-200); + --image-bg: transparent; + --table-head-bg: var(--color-brand-700); + --table-head-color: var(--color-neutral-50); + --table-head-border-style: none; + --table-head-border-color: transparent; + --table-head-border-width: 0; } -#WarnJS h1 { - color: red; - font-weight: bold; - text-align: center; + +/* ============================================================ + * Precedence of theme icons (sun/moon) — default: light mode + * ============================================================ */ + +#theme-toggle { + position: relative; + display: grid; + place-items: center; + width: 2.5rem; + height: 2.5rem; + background: none; + border: 0; + cursor: pointer; + color: var(--text-color); +} + +#theme-toggle .sun, +#theme-toggle .moon { + grid-area: 1 / 1; + width: 2rem; + height: 2rem; + background-color: var(--text-color); + -webkit-mask: no-repeat center / contain; + mask: no-repeat center / contain; + transition: + opacity 0.3s ease, + transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), + background-color 0.2s linear; +} + +#theme-toggle .sun { + -webkit-mask-image: url("media/helpimg/sun-line.svg"); + mask-image: url("media/helpimg/sun-line.svg"); +} + +#theme-toggle .moon { + -webkit-mask-image: url("media/helpimg/moon-line.svg"); + mask-image: url("media/helpimg/moon-line.svg"); +} + + +#theme-toggle .sun, +#TopLeftHeader .sun { + opacity: 0; + transform: rotate(0deg) scale(1); +} + +#theme-toggle .moon, +#TopLeftHeader .moon { + opacity: 1; + transform: rotate(90deg) scale(0); +} + +#DonationFrame .service { + width: 1.5rem; + height: 1.5rem; + padding: 0.5rem 0.5rem 0.5rem 0.5rem; + background-color: var(--text-accent-color); + border-radius: 0.25rem; + transition: background-color 0.3s ease; + -webkit-mask-image: url("media/helpimg/service-line.svg"); + mask-image: url("media/helpimg/service-line.svg"); +} + +.xapian-omega-search-button .search { + width: .5rem; + height: .5rem; + padding: 0.5rem 0.5rem 0.5rem 0.5rem; + background-color: var(--background-color); + border-radius: 0.25rem; + transition: background-color 0.3s ease; + -webkit-mask-image: url("media/helpimg/search-line.svg"); + mask-image: url("media/helpimg/search-line.svg"); +} + +/* ============================================================ + * DARK MODE — AUTOMATIC (SO prefers-color-scheme: dark) + * ============================================================ */ +@media (prefers-color-scheme: dark) { + :root { + --background-color: var(--color-neutral-900); + --text-color: var(--color-neutral-50); + --text-title-color: var(--color-neutral-100); + --text-accent-color: var(--color-violet-100); + --heading-color: var(--color-neutral-700); + --link-color: var(--color-blue-400); + --hover-color: var(--color-blue-400); + --visited-color: var(--color-violet-200); + --table-background: var(--color-neutral-800); + + --warning-color: var(--color-amber-300); + --warning-background: var(--color-amber-800); + --tip-color: var(--color-brand-300); + --tip-background: var(--color-brand-800); + --note-color: var(--color-blue-300); + --note-background: var(--color-blue-800); + + --code-bg: var(--color-neutral-950); + --widget-bg: var(--color-neutral-800); + --widget-border-color: var(--text-title-color); + --widget-color: var(--text-color); + --widget-font-weight: bold; + --howtoget-bg: var(--color-violet-900); + --howtoget-border-color: var(--color-violet-200); + --howtoget-header-bg: var(--color-neutral-700); + --youtube-placeholder-bg: oklch(from var(--background-color) calc(l + 0.05) c h); + --pagination-color: var(--color-neutral-50); + --pagination-link-color: var(--color-violet-300); + --pagination-active-bg: var(--color-violet-800); + --pagination-active-color: var(--color-neutral-50); + --pagination-disabled-color: var(--color-neutral-500); + --treeview-hover-border-color: var(--color-violet-300); + --contents-current-bg: var(--color-neutral-800); + --contents-current-border-color: var(--color-violet-300); + --xapian-search-color: var(--color-neutral-900); + --sf-table-bg: var(--color-neutral-900); + --donation-hover-bg: linear-gradient(135deg, var(--color-violet-600) 0%, var(--color-violet-800) 100%); + --table-border-color: var(--color-neutral-600); + --table-stripe-bg: var(--color-neutral-900); + --image-bg: var(--color-neutral-200); + --table-head-bg: var(--color-brand-800); + --table-head-color: var(--color-neutral-50); + --table-head-border-style: solid; + --table-head-border-color: var(--color-neutral-500); + --table-head-border-width: thin; + } + + #theme-toggle .sun, + #TopLeftHeader .sun { + opacity: 1; + transform: rotate(-90deg) scale(0); + } + + #theme-toggle .moon, + #TopLeftHeader .moon { + opacity: 0; + transform: rotate(0deg) scale(1); + } + + ::selection { + color: var(--color-neutral-900); + background-color: var(--color-neutral-50); + } +} + + +/* ============================================================ + * DARK MODE + * Shade inversion: light anchors → dark anchors and vice-versa. + * ============================================================ */ +html.dark-mode { + /* --- Surface and text --- */ + --background-color: var(--color-neutral-900); + --text-color: var(--color-neutral-50); + --text-title-color: var(--color-neutral-100); + --text-accent-color: var(--color-violet-100); + --heading-color: var(--color-neutral-700); + --link-color: var(--color-blue-400); + --hover-color: var(--color-blue-400); + --visited-color: var(--color-violet-200); + --table-background: var(--color-neutral-800); + + /* --- Callouts --- */ + --warning-color: var(--color-amber-300); + --warning-background: var(--color-amber-800); + --tip-color: var(--color-brand-300); + --tip-background: var(--color-brand-800); + --note-color: var(--color-blue-300); + --note-background: var(--color-blue-800); + + /* --- Components --- */ + --code-bg: var(--color-neutral-950); + --widget-bg: var(--color-neutral-800); + --widget-border-color: var(--text-title-color); + --widget-color: var(--text-color); + --widget-font-weight: bold; + --howtoget-bg: var(--color-violet-900); + --howtoget-border-color: var(--color-violet-200); + --howtoget-header-bg: var(--color-neutral-700); + --youtube-placeholder-bg: oklch(from var(--background-color) calc(l + 0.05) c h); + --pagination-color: var(--color-neutral-50); + --pagination-link-color: var(--color-violet-300); + --pagination-active-bg: var(--color-violet-800); + --pagination-active-color: var(--color-neutral-50); + --pagination-disabled-color: var(--color-neutral-500); + --treeview-hover-border-color: var(--color-violet-300); + --contents-current-bg: var(--color-neutral-800); + --contents-current-border-color: var(--color-violet-300); + --xapian-search-color: var(--color-neutral-900); + --sf-table-bg: var(--color-neutral-900); + --donation-hover-bg: linear-gradient(135deg, var(--color-violet-600) 0%, var(--color-violet-800) 100%); + --table-border-color: var(--color-neutral-600); + --table-stripe-bg: var(--color-neutral-900); + --image-bg: var(--color-neutral-200); + --table-head-bg: var(--color-brand-900); + --table-head-color: var(--color-neutral-50); + --table-head-border-style: solid; + --table-head-border-color: var(--color-neutral-500); + --table-head-border-width: thin; + + #theme-toggle { + position: relative; + } + /* --- Theme icons (sun/moon) --- */ + #theme-toggle .sun, + #TopLeftHeader .sun { + opacity: 0; + transform: rotate(-90deg) scale(0); + } + + #theme-toggle .moon, + #TopLeftHeader .moon { + opacity: 1; + transform: rotate(0deg) scale(1); + } + + ::selection { + color: var(--color-neutral-900); + background-color: var(--color-neutral-50); + } +} + +/* ============================================================ + * LIGHT MODE — MANUAL OVERRIDE + * Forces light theme when the OS is in dark mode + * ============================================================ */ +html.light-mode { + --background-color: var(--color-neutral-50); + --heading-color: var(--color-neutral-300); + --text-color: var(--color-neutral-700); + --text-title-color: var(--color-neutral-700); + --text-accent-color: var(--color-violet-700); + --link-color: var(--color-blue-700); + --hover-color: var(--color-blue-600); + --visited-color: var(--color-violet-800); + --table-background: var(--color-neutral-300); + + --warning-color: var(--color-amber-700); + --warning-background: var(--color-amber-300); + --tip-color: var(--color-brand-700); + --tip-background: var(--color-brand-200); + --note-color: var(--color-blue-700); + --note-background: var(--color-blue-200); + + --code-bg: oklch(from var(--color-neutral-700) l c h / 4%); + --widget-bg: linear-gradient(to bottom, var(--color-neutral-200), var(--color-neutral-50)); + --widget-border-color: var(--text-title-color); + --widget-color: var(--text-color); + --widget-font-weight: normal; + --howtoget-bg: var(--color-violet-300); + --howtoget-border-color: var(--color-violet-900); + --howtoget-header-bg: var(--color-neutral-50); + --youtube-placeholder-bg: oklch(from var(--background-color) calc(l - 0.05) c h); + --pagination-color: inherit; + --pagination-link-color: var(--link-color); + --pagination-active-bg: var(--color-blue-800); + --pagination-active-color: var(--color-neutral-50); + --pagination-disabled-color: inherit; + --treeview-hover-border-color: oklch(from var(--color-neutral-700) l c h / 5%); + --contents-current-bg: oklch(from var(--color-neutral-700) l c h / 10%); + --contents-current-border-color: var(--color-neutral-500); + --xapian-search-color: var(--color-neutral-50); + --sf-table-bg: inherit; + --donation-hover-bg: linear-gradient(135deg, var(--color-violet-400) 0%, var(--color-violet-600) 100%); + --table-border-color: var(--color-neutral-400); + --table-stripe-bg: var(--color-neutral-200); + --image-bg: transparent; + --table-head-bg: var(--color-brand-700); + --table-head-color: var(--color-neutral-50); + --table-head-border-style: none; + --table-head-border-color: transparent; + --table-head-border-width: 0; + + #theme-toggle { + position: relative; + } + /* Theme icons: show sun, hide moon */ + #theme-toggle .sun, + #TopLeftHeader .sun { + opacity: 1; + transform: rotate(0deg) scale(1); + } + + #theme-toggle .moon, + #TopLeftHeader .moon { + opacity: 0; + transform: rotate(90deg) scale(0); + } + + ::selection { + color: var(--color-neutral-50); + background-color: var(--color-neutral-900); + } +} + + +/* ============================================================ + * GLOBAL STYLES + * ============================================================ */ + +body { + background-color: var(--background-color); + color: var(--text-color); + margin: 0; + line-height: normal; + font-family: var(--font-body); + font-size: 1.15rem; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr minmax(1em, auto) minmax(1em, auto); + grid-template-areas: + "header" + "leftside" + "main " + "footer "; +} + +a { + color: var(--link-color); + + &:hover { + color: var(--hover-color); + } + + &:visited { + color: var(--visited-color); + } +} + +.header { + grid-area: header; + display: grid; + grid-template-columns: 1fr auto; + grid-template-areas: + "TopLeftHeader theme-toggle" + "search search" + "donationFrame donationFrame"; + gap: 1rem; + padding: .6rem .9rem; + background-color: var(--heading-color); + position: sticky; + top: 0; + z-index: 100; + align-items: center; +} + +footer, +#langs, +#modules { + background-color: var(--background-color); + color: var(--text-color); } -body, -p, h1, h2, h3, h4, h5, -h6, -.listitem, -.description, -.listitemintable, -.tablecontent { - font-family: var(--font-body); +h6 { + margin-bottom: 0.67rem; + color: var(--text-title-color); + border-bottom-color: var(--text-title-color); } -.input { - background-color: rgb(0 0 0 / 4%); - transition-property: background-color; - transition-duration: 150ms; - border-bottom: 1px dashed rgb(0 0 0 / 10%); - font-family: var(--font-mono); + +#theme-toggle { + grid-area: theme-toggle; + align-self: start; + margin-top: .5rem; + position: relative; + width: 40px; + height: 40px; + border: none; + background: transparent; + cursor: pointer; + overflow: hidden; } -[data-tooltip] { - position: relative; + +#theme-toggle i { + color: var(--text-color); + position: absolute; + top: 4px; + left: 4px; + font-size: 1.8rem; + transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.5s ease; } -[data-tooltip]::before { - content: ""; + +.symbol, +.logo { + text-decoration: none; +} + +.logo p { + font-size: 24px; +} + +.logo { + grid-area: logo; +} + +#TopLeftHeader { + position: relative; + display: grid; + grid-area: TopLeftHeader; + grid-template-columns: auto 1fr; + grid-template-areas: + "symbol logo" + "dropdowns dropdowns"; + gap: .5rem; + align-items: center; +} + +#TopLeftHeader img { position: absolute; - top: -6px; - left: 50%; - transform: translateX(-50%); - border-width: 4px 6px 0; - border-style: solid; - border-color: rgb(0 0 0 / 70%) transparent transparent; - z-index: 100; - opacity: 0; - pointer-events: none; + top: 4px; + left: 4px; + width: 52px; + height: 60px; + transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.5s ease; } -[data-tooltip]::after { - content: attr(data-tooltip); + +.symbol { + grid-area: symbol; + padding: 8px 8px 8px 20px; + width: 52px; + height: 60px; +} + +.symbol img { + width: 100%; + height: 100%; +} + +.dropdowns { + grid-area: dropdowns; + display: flex; + flex-direction: row; + gap: 1.5rem; + width: 100%; +} + +#SearchFrame { + grid-area: search; + width: 100%; +} + + +#DonationFrame { + grid-area: donationFrame; + width: 100%; + display: flex; + justify-content: center; +} + +#DonationFrame a { + display: flex; + align-items: center; + gap: .5rem; + padding: .5rem 1rem; + font-weight: bold; + width: fit-content; + min-width: 12.5rem; + border-radius: 5rem; + transition: background-color 0.8s ease-in-out, color 0.8s ease-in-out; + text-decoration: none; + color: var(--text-accent-color); + background: transparent; + border: 2px solid var(--text-accent-color); + + &:hover { + background: var(--donation-hover-bg); + background-clip: padding-box; + border: 2px solid var(--text-accent-color); + /* color: var(--color-neutral-50); */ + box-shadow: 0 4px 12px rgb(0 0 0 / 12%); + animation: mover-e-voltar 0.25s cubic-bezier(0.4, 0, 0.2, 1); + } +} + +#DonationFrame i { + font-size: 2rem; +} + +@keyframes mover-e-voltar { + 0% { + transform: translateY(0); + } + + 50% { + transform: translateY(-8px); + } + + 100% { + transform: translateY(0); + } +} + +/* Base product dropdown details menu */ +details.products { + display: none; + grid-area: modules-toggle; +} + +/* Floating product menu list layout */ +details.products #products { position: absolute; - left: 50%; - top: -6px; - transform: translateX(-50%) translateY(-100%); - background: rgb(0 0 0 / 70%); - text-align: center; - color: #fff; - padding: 4px 2px; - font-size: 12px; - min-width: 80px; - border-radius: 5px; - opacity: 0; - pointer-events: none; + top: 100%; + left: 0; + z-index: 1000; + background-color: var(--heading-color); + color: var(--text-color); + border: 1px solid var(--color-neutral-300); + list-style: none; + padding: 8px 0; + margin: 4px 0 0 0; + min-width: 160px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } -[data-tooltip]:hover::before, [data-tooltip]:hover::after { - opacity: 1; - pointer-events: auto; + +details.products #products li { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + cursor: pointer; } -body { - background-color: var(--background-color); - margin: 0; - line-height: normal; + +details.products #products li:hover { + background-color: var(--hover-color); } -::selection { - background: var(--selection); + +details.products li { + list-style: none; } -a { - text-decoration-color: rgb(0 0 0 / 15%); + +.contents-treeview label, +.contents-treeview label::before { + cursor: pointer; color: var(--link-color); } -a:hover { - text-decoration: underline; - color: var(--hover-color); + + +/* ============================================================ + * CALLOUTS (note / tip / warning) + * ============================================================ */ +.note, +.tip, +.warning { + display: flex; + align-items: center; + border-radius: 2px; + box-shadow: 0 2px 5px -3px rgb(0 0 0 / 10%); + padding: 0.2em; + margin-top: 15px; +} + +.note { + border-left: 2px solid var(--note-color); + background-color: var(--note-background); +} + +.tip { + border-left: 2px solid var(--tip-color); + background-color: var(--tip-background); +} + +.warning { + border-left: 2px solid var(--warning-color); + background-color: var(--warning-background); } -a:visited { - color: var(--visited-color); + +.noteicon, +.notetext { + padding: 0.3em; } + +.noteicon { + flex-shrink: 0; +} + +/* ============================================================ + * CÓDIGO & PRISM + * ============================================================ */ +code[class*="language-"], +pre[class*="language-"] { + white-space: pre-wrap; +} + +pre[class*="language-"]>code { + z-index: 0; +} + pre, .code, .codeintable, @@ -134,159 +774,161 @@ pre, .literalintable, .path, .pathintable { - background-color: rgb(0 0 0 / 4%); + background-color: var(--code-bg); border-radius: 2px; display: inline; padding: 1px 3px; font-family: var(--font-mono); overflow-wrap: anywhere; } + .code, -.codeintable{ - display:inline-block; -} -/* prevent SVGs without width from overflowing the container */ -img[src$=".svg"] { - max-width: 100%; +.codeintable { + display: inline-block; } + .literal { white-space: normal; word-break: keep-all; overflow-wrap: break-word; } + .smathcode { border-radius: 2px; padding: 1px 3px; font-family: var(--font-mono); } + +/* ============================================================ + * TIPOGRAFIA & ÊNFASE + * ============================================================ */ .acronym, .emph, .menuitem { font-weight: bold; } + .related { font-weight: bold; margin-top: 1.67rem; - border-top: 2px solid var(--heading-color); - color: var(--heading-color); + border-top: 2px solid var(--text-accent-color); + color: var(--text-accent-color); } + .keycode { font-family: var(--font-mono); - font-style:italic; + font-style: italic; } + +/* ============================================================ + * WIDGET + * ============================================================ */ .widget { padding: 1px 10px; - background: #f0f0f0; - background: linear-gradient(to bottom,#f0f0f0,#fcfcfc); + background: var(--widget-bg); border-radius: 3px; - color: #303030; - border: 1px solid #a0a0a0; + color: var(--widget-color); + border: 1px solid var(--widget-border-color); border-bottom-width: 2px; white-space: nowrap; + font-weight: var(--widget-font-weight); } -/* div's for warning, tip and note */ -.note, -.tip, -.warning { - display: flex; - align-items: center; - border-radius: 2px; - box-shadow: 0 2px 5px -3px rgb(0 0 0 / 10%); - padding: 0.2em; - margin-top: 15px; -} -.note { - border-left: 2px solid #309048; - background-color: #d9f1dd; -} -.tip { - border-left: 2px solid #0063b1; - background-color: #cde5f7; -} -.warning { - border-left: 2px solid #ed8733; - background-color: #f6f1d2; -} -.noteicon, .notetext { - padding: 0.3em; -} -.notetext p{ - margin-left:0px; -} -.noteicon { - flex-shrink: 0; + +/* ============================================================ + * IMAGENS + * ============================================================ */ +.iconimage { + background: oklch(from var(--text-color) l c h / 45%); + background: var(--color-neutral-200); + margin-right: 5px; + vertical-align: middle; } -/* Override some Prism.js styles */ -code[class*="language-"], pre[class*="language-"] { - white-space: pre-wrap; + +img[src$=".svg"] { + max-width: 100%; } -pre[class*="language-"] > code { - z-index: 0; +.screenshot, +.genericimage { + border: .5px solid rgb(0 0 0 / 10%); + border-radius: 3px; + margin: 2em auto; + display: block; + box-shadow: rgb(0 0 0 / 8%) 0 1px 5px 0; + background-color: var(--image-bg); } -/* Table related classes */ +/* ============================================================ + * TABELAS + * ============================================================ */ + +table { + background: var(--table-background); + box-shadow: rgb(0 0 0 / 8%) 0 1px 5px 0; + border-collapse: collapse; + margin: 0px auto; +} -/* Special case of table with one cell */ .onecell { box-shadow: rgb(0 0 0 / 10%) 0 1px 3px 0; - border-bottom: 1px solid #E8E8E8; + border-bottom: 1px solid var(--table-border-color); } -/* Special case of icon table */ + .icontable { display: flex; align-items: center; } + .iconcell { padding: 0.3em; - /* background: var(--heading-color); */ } + .iconcell img { min-width: 38px; min-height: 38px; } -table { - background: var(--background-color); - box-shadow: rgb(0 0 0 / 8%) 0 1px 5px 0; - border-collapse: collapse; - margin: 0px auto;/* center tables in divs */ -} -table, th, td { - border-top: 0; - border-bottom: 1px solid #E8E8E8; - border-left: 0; - border-right: 0; +table, +th, +td { + border: 1px solid var(--table-border-color); padding: 0.3em; } + tr:nth-of-type(even) { - background-color: #e3e3e3; + background-color: var(--table-stripe-bg); } + html[dir="ltr"] th { text-align: left; } + .tablehead, .tableheadintable { font-weight: bold; margin-top: 0; } + .tableheadcell { - background: green; - color: white; + background: var(--table-head-bg); + color: var(--table-head-color); vertical-align: top; + border-style: var(--table-head-border-style); + border-color: var(--table-head-border-color); + border-width: var(--table-head-border-width); } .table_font_small { font-size: 0.98rem; } -p.tablecontentintable, p.tableheadintable{ - margin-left: 5px; -} + /* ScriptForge service tables */ .sf_table { min-width: 100%; + background-color: var(--sf-table-bg); } + .sf_table tr, .sf_table td { display: block; @@ -302,47 +944,36 @@ p.tablecontentintable, p.tableheadintable{ display: none; } -h1, -h2, -h3, -h4, -h5, -h6 { - margin-bottom: 0.67rem; - color: var(--heading-color); - border-bottom-color: var(--heading-color); -} +/* ============================================================ + * TÍTULOS E PARÁGRAFOS + * ============================================================ */ p, ol, -ul, td { - font-size: 1.15rem; - margin-left:30px; - margin-top:2px; - margin-bottom:10px; -} -li p { - font-size: 1.15rem; - margin-left:0px; - margin-top:2px; - margin-bottom:10px; + font-size: inherit; + margin: 2px 0 10px; } + h1 { font-size: 1.83rem; font-weight: bold; border-bottom: 2px solid; margin-bottom: 1.67rem; } + h1 a, .pagination a { text-decoration: none; } + h2 { font-size: 1.55rem; } + h3 { font-size: 1.33rem; } + h4, h5, h6 { @@ -352,46 +983,54 @@ h6 { .relatedtopics { font-weight: normal; } -.relatedtopics p{ - margin-left: 0px; -} + +/* ============================================================ + * HOWTOGET + * ============================================================ */ .howtoget { - background: #EBE7E9; - border-left: 2px solid #4E4B55; + background: var(--howtoget-bg); + border-left: 2px solid var(--howtoget-border-color); border-radius: 2px; box-shadow: 0 2px 5px -3px rgb(0 0 0 / 10%); padding: 0.2em; display: flex; flex-direction: column; } + .howtogetheader { - background: #FFF; + background: var(--howtoget-header-bg); border-radius: 2px; box-shadow: 0 2px 2px -2px rgb(0 0 0 / 20%); display: inline-block; font-weight: bold; padding: 0.1em 0.3em; } + .howtogetbody { padding: 0 0.3em; } -/*.samplefilesection{}*/ +/* ============================================================ + * MISCELÂNEA + * ============================================================ */ .wide, #search-bar { width: 100%; } + .bug { - color: red; + color: var(--color-red-600); } + .debug { border: 1px solid black; padding: 3px; display: none; - background-color: #222; - color: red; + background-color: var(--color-neutral-900); + color: var(--color-red-500); text-align: left; } + .sqlcode, .pycode, .bascode { @@ -399,307 +1038,297 @@ h6 { margin-top: 15px; margin-bottom: 15px; } + #DisplayArea { background-color: var(--background-color); overflow: auto; - padding: 10px 10px 40px; + padding: .8rem .8rem 2.5rem; grid-area: main; } + +#DisplayArea h3, +#DisplayArea h3~p { + margin-inline-start: .8rem; +} + + +#DisplayArea h3:not(h2 ~ h3), +#DisplayArea p:not(h2 ~ p) { + margin-inline-start: 0; +} + #omega-autofocus { - width: 274px; + flex: 1; + min-width: 200px; } + .mediabutton { - background-color: cyan; + background-color: var(--color-blue-400); } + .mediadiv { padding-bottom: 5%; height: 0; display: inline-block; border: none; } -.screenshot, .genericimage, .mathml { - border: .5px solid rgb(0 0 0 / 10%); - border-radius: 3px; - margin: 2em auto; - display: block; - box-shadow: rgb(0 0 0 / 8%) 0 1px 5px 0; -} -/* .iconimage{} */ -/* .switch, */ -/* .switchinline {} */ -/* .embedded {} */ -#TopLeftHeader { - background: var(--heading-color); - grid-area: header; - position: sticky; - top: 0; - color: #fff; - display: flex; - flex-wrap: wrap; - justify-content: flex-start; - z-index: 100; -} -.dropdowns { - /* allow for scrolling */ - overflow: auto hidden; - /* make it smooth on iOS */ - -webkit-overflow-scrolling: touch; - grid-area: dropdowns; - display: flex; - justify-content: space-between; - flex-direction: column; - width: 100%; -} -.symbol, .logo, .logo:hover, .logo:visited { - color: #fff; - text-decoration: none; -} -.logo p { - font-size: 24px; -} -.logo { - grid-area: logo; -} -.symbol { - grid-area: symbol; - padding: 8px 8px 8px 20px; -} -.symbol div { - background-image: url("media/navigation/libo-symbol-white.svg"); - background-repeat: no-repeat; - background-size: contain; - width: 52px; - height: 60px; -} - -/* YouTube matters */ +/* ============================================================ + * YOUTUBE + * ============================================================ */ .youtube_placeholder { - border: 1px dashed #eee; - max-width: 700px; - padding: 10px; - background-color: var(--background-color); + border: 1px dashed var(--text-color); + max-width: 100%; + padding: 1rem; + background-color: var(--youtube-placeholder-bg); text-align: center; } + .youtube_button { - appearance: none; - backface-visibility: hidden; - background-color: #27ae60; - border-radius: 8px; - border-style: none; - box-shadow: rgb(39 174 96 / 15%) 0 4px 9px; - box-sizing: border-box; - color: #fff; - cursor: pointer; - display: inline-block; - font-size: 16px; - font-weight: 600; - letter-spacing: normal; - line-height: 1.5; - outline: none; - overflow: hidden; - padding: 13px 20px; - position: relative; - text-align: center; - text-decoration: none; - transform: translate3d(0, 0, 0); - transition: all .3s; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; - vertical-align: top; - white-space: nowrap; + appearance: none; + backface-visibility: hidden; + background-color: var(--color-brand-600); + border-radius: 8px; + border-style: none; + box-shadow: rgb(39 174 96 / 15%) 0 4px 9px; + box-sizing: border-box; + color: var(--color-neutral-50); + cursor: pointer; + display: inline-block; + font-size: 1rem; + font-weight: 600; + letter-spacing: normal; + line-height: 1.5; + outline: none; + overflow: hidden; + padding: 13px 20px; + position: relative; + text-align: center; + text-decoration: none; + transform: translate3d(0, 0, 0); + transition: all .3s; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + vertical-align: top; + white-space: nowrap; } + .youtube_button:hover { - background-color: #1e8449; - opacity: 1; - transform: translateY(0); - transition-duration: .35s; - box-shadow: rgb(39 174 96 / 20%) 0 6px 12px; + background-color: var(--color-brand-700); + opacity: 1; + transform: translateY(0); + transition-duration: .35s; + box-shadow: rgb(39 174 96 / 20%) 0 6px 12px; } + .youtube_button:active { - transform: translateY(2px); - transition-duration: .35s; + transform: translateY(2px); + transition-duration: .35s; } -#langs-nav, #modules-nav { +/* ============================================================ + * NAVEGAÇÃO (langs / modules) + * ============================================================ */ +#langs-nav, +#modules-nav { z-index: 100; - /* line them up horizontally */ display: flex; flex-direction: row; - /* allow for scrolling */ overflow: auto hidden; - /* make it smooth on iOS */ -webkit-overflow-scrolling: touch; } -#langs-nav a, #modules-nav a { - color: #fff; - background-color: #233336; - display: block; + +#langs-nav a, +#modules-nav a { + color: var(--text-color); + background-color: var(--background-color); + display: flex; + align-items: end; line-height: 1.5; padding: 3px 6px; text-decoration: none; - font-size: 24px; + font-size: 1.6rem; flex-shrink: 0; z-index: 100; white-space: nowrap; } -footer { - padding: 30px 20px; -} -footer p { - font-size: 0.98rem; -} -.contents-treeview input[type="checkbox"], aside input[type="checkbox"] { - /* from .visuallyhidden class of html5-boilerplate */ - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - white-space: nowrap; -} -label[for="accordion-1"] { - color: #233336; - display: block; - margin: 0 0 10px 10px; - font-size: 22px; + +.modules { + border-bottom: 2px solid var(--color-neutral-100); + background-color: var(--heading-color); } -label[for="accordion-1"]::after { - font-size: 44px; + +#modules::after, +#langs::after { + font-size: 30px; content: "⌄"; } -aside input[type="checkbox"] ~ .contents-treeview { - display: none; -} -aside input[type="checkbox"]:checked ~ .contents-treeview { - color: #333; - z-index: 6; - display: block; - margin: 0 20px 20px; -} -.index-label { - font-size: 22px; - color: #233336; - padding-left: 20px; - margin: 20px 0 0; -} -.index { - margin-top: 10px; - padding-left: 15px; -} -.index a { - font-size: 15px; - display: block; + +.lang { + background-color: var(--heading-color); } -#Bookmarks { - width: 300px; - margin-left: 10px; + +#modules-nav div { + background-repeat: no-repeat; + background-size: contain; + display: none; } -#Bookmarks p { - font-size: 22px; - font-weight: bold; - color: #148603; + +/* ============================================================ + * ÍCONES DOS PRODUTOS + * ============================================================ */ +.office-icon, +.calc-icon, +.chart-icon, +.writer-icon, +.impress-icon, +.draw-icon, +.math-icon, +.basic-icon, +.base-icon { + width: 21.5px; + height: 26px; + position: relative; + margin-right: 5px; } -#WRITER::before { - content: "Writer"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.office-icon { + background-image: url("media/navigation/libo-symbol-black.svg"); } -#CALC::before { - content: "Calc"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.calc-icon { + background-image: url("media/navigation/libo-calc.svg"); } -#IMPRESS::before { - content: "Impress"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.writer-icon { + background-image: url("media/navigation/libo-writer.svg"); } -#DRAW::before { - content: "Draw"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.impress-icon { + background-image: url("media/navigation/libo-impress.svg"); } -#BASE::before { - content: "Base"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.draw-icon { + background-image: url("media/navigation/libo-draw.svg"); } -#MATH::before { - content: "Math"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.math-icon { + background-image: url("media/navigation/libo-math.svg"); } -#CHART::before { - content: "Chart"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.base-icon { + background-image: url("media/navigation/libo-base.svg"); } -#BASIC::before { - content: "Basic"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color);; + +.chart-icon { + background-image: url("media/navigation/libo-chart.svg"); } -#SHARED::before { - content: "%PRODUCTNAME"; - display: block; - font-size: 22px; - font-weight: bold; - color: var(--heading-color); + +.basic-icon { + background-image: url("media/navigation/libo-basic.svg"); } + +/* ============================================================ + * PAGINAÇÃO + * ============================================================ */ .pagination-container { text-align: center; - margin-left: -40px; /* The normalizer fails to account for this */ + margin-left: -40px; + color: var(--pagination-color); } + .pagination li { display: inline-block; padding: 0 5px; } + +.pagination a { + color: var(--pagination-link-color); +} + li.active { - background-color: #023a86; + background-color: var(--pagination-active-bg); } + li.active a { - color: #fff; + color: var(--pagination-active-color); } + li.disabled a { + color: var(--pagination-disabled-color); opacity: 0.4; pointer-events: none; } -#search-bar, input { - border: 1px solid #CCC; - box-shadow: inset 0 1px 1px rgb(0 0 0 / 10%); + +/* ============================================================ + * INPUTS & SEARCH + * ============================================================ */ +.input { + background-color: oklch(from var(--text-color) l c h / 15%); + transition-property: background-color; + transition-duration: 150ms; + border-bottom: 1px dashed oklch(from var(--text-color) l c h / 25%); + font-family: var(--font-mono); + padding: .2rem .4rem; + border-radius: .4rem; +} + +#search-bar, +input[type="text"], +input[type="search"]:not(#omega-autofocus) { + font-weight: 500; + height: 42px; + padding: 0.6rem 1rem 0.6rem 2.5rem; + font-size: 1rem; + font-family: var(--font-body); box-sizing: border-box; - line-height: 1.5em; + border: 1.5px solid var(--widget-border-color); + border-radius: 5rem; + background-color: var(--background-color); + color: var(--widget-color); outline: none; - padding: 0 .25em; - transition: all 0.30s ease-in-out; + transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); + + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 2a9 9 0 1 1 0 18 9 9 0 0 1 0-18zm0 2a7 7 0 1 0 0 14A7 7 0 0 0 11 4zm6.707 12.707L21 21l-1.414 1.414-3.293-3.293 1.414-1.414z' fill='currentColor'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: 14px center; + background-size: 22px 22px; +} + +[data-theme="dark"] #search-bar, +html.dark-mode #search-bar { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 2a9 9 0 1 1 0 18 9 9 0 0 1 0-18zm0 2a7 7 0 1 0 0 14A7 7 0 0 0 11 4zm6.707 12.707L21 21l-1.414 1.414-3.293-3.293 1.414-1.414z' fill='%23ddd'/%3E%3C/svg%3E"); } -#search-bar:focus, input:focus { - border: 1px solid #0EA5FB; + +#search-bar:focus, +input[type="text"]:focus, +input[type="search"]:not(#omega-autofocus):focus { + border-color: var(--widget-border-color); + box-shadow: 0 0 0 3px rgb(128 128 128 / 15%), 0 2px 4px rgba(0, 0, 0, 0.05); } -#search-bar::placeholder { + +#search-bar::placeholder, +input::placeholder { + color: var(--widget-color); + opacity: 0.85; font-style: italic; } + +input:not([type="submit"]):not([type="search"]):not([type="text"]):not([type="checkbox"]) { + border: 1.5px solid var(--widget-border-color); + border-radius: 4px; + padding: 0.4rem 0.8rem; + background-color: var(--background-color); + color: var(--widget-color); + outline: none; + transition: border-color 0.2s ease-in-out; +} + +input:not([type="submit"]):not([type="search"]):not([type="text"]):not([type="checkbox"]):focus { + border-color: var(--text-accent-color); +} + #SearchFrame .nav-container { display: none; position: absolute; @@ -709,251 +1338,390 @@ li.disabled a { max-height: 80svh; width: 300px; } + #SearchFrame:focus-within .nav-container { display: block; } + +/* ============================================================ + * TOOLTIP + * ============================================================ */ +[data-tooltip] { + position: relative; +} + +[data-tooltip]::before { + content: ""; + position: absolute; + top: -6px; + left: 50%; + transform: translateX(-50%); + border-width: 4px 6px 0; + border-style: solid; + border-color: oklch(from var(--text-color) l c h / 70%) transparent transparent; + z-index: 100; + opacity: 0; + pointer-events: none; +} + +[data-tooltip]::after { + content: attr(data-tooltip); + position: absolute; + left: 50%; + top: -6px; + transform: translateX(-50%) translateY(-100%); + background: oklch(from var(--text-color) l c h / 80%); + text-align: center; + color: var(--background-color); + padding: 4px 2px; + font-size: .9rem; + min-width: 80px; + border-radius: 5px; + opacity: 0; + pointer-events: none; +} + +[data-tooltip]:hover::before, +[data-tooltip]:hover::after { + opacity: 1; + pointer-events: auto; +} + +/* ============================================================ + * DOAÇÃO / XAPIAN + * ============================================================ */ .xapian-donation { - border-top: 2px solid #148603; - background-color: #FCFCFC; + border-top: 2px solid var(--color-brand-700); + background-color: var(--xapian-search-color); box-shadow: 0 2px 8px 0 rgb(0 0 0 / 5%); } -#DonationFrame { - background: var(--background-color); - position: sticky; - top: 0; -} + .donation { - border: 1px solid #f1c62a; + border: 1px solid var(--color-amber-500); border-radius: 2px; padding: 5px 10px; margin: 5px 10px; max-width: 200px; - color: white; - align-items:center; + color: var(--color-neutral-50); + align-items: center; } + .donation:hover { - background: linear-gradient(90deg, #1c71d8 0%, #30c877 100%); + background: var(--donation-hover-bg); } + .donation a { - color: white; + color: var(--color-neutral-50); text-decoration: none; } + .donation p { font-size: 1rem; text-align: center; } -#SearchFrame { - top: 0; - position: sticky; - z-index: 1; -} + .xapian-omega-search { - margin: auto; + width: 100%; + max-width: 520px; + margin: 24px auto; } -.modules { - border-bottom: 2px solid #f3f3f3; - background-color: #233336; + +.xapian-omega-search form { + display: flex; + gap: 8px; + align-items: center; + justify-content: center; + background-color: var(--background-color); + border: 1.5px solid var(--widget-border-color); + border-radius: 5rem; + padding: 0.2rem; + box-sizing: border-box; + transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); + width: 100%; } -#modules::after, #langs::after { - font-size: 30px; - color: #fff; - content: "⌄"; + +.xapian-omega-search form:focus-within { + border-color: var(--text-accent-color); + box-shadow: 0 0 0 3px rgb(128 128 128 / 15%), 0 2px 4px rgba(0, 0, 0, 0.05); } -.lang { - background-color: #233336; + +#omega-autofocus { + flex: 1; + min-width: 200px; + height: 36px; + padding-left: .5rem; + font-size: 1rem; + font-weight: 500; + font-family: var(--font-body); + background: transparent !important; + border: none !important; + box-shadow: none !important; + color: var(--text-color); + outline: none !important; + background-image: none !important; } -#modules-nav div { - background-repeat: no-repeat; - background-size: contain; - float: left; + +.xapian-omega-search-button { + height: 36px; + width: 36px; + min-width: 36px; + display: flex; + justify-content: center; + align-items: center; + background-color: var(--link-color); + border: none; + border-radius: 5rem; + cursor: pointer; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + /* color: var(--text-color); */ + padding: 0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); +} + +.xapian-omega-search-button i { + font-family: "remixicon"; + font-size: 1.4rem; + color: var(--xapian-search-color); + display: flex; + align-items: center; + justify-content: center; +} + +.xapian-omega-search-button:hover { + transform: scale(1.08); + filter: brightness(1.1); +} + +.xapian-omega-search-button:active { + transform: scale(0.92); +} + +/* ============================================================ + * CONTENTS / BOOKMARKS / INDEX + * ============================================================ */ +.contents-treeview input[type="checkbox"], +aside input[type="checkbox"] { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + white-space: nowrap; +} + +label[for="accordion-1"] { + display: block; + margin: 0 0 10px 10px; + font-size: 22px; + background-color: transparent; + text-decoration: none; + font-weight: bold; +} + +aside input[type="checkbox"]~.contents-treeview { display: none; } -.office-icon, -.calc-icon, -.chart-icon, -.writer-icon, -.impress-icon, -.draw-icon, -.math-icon, -.basic-icon, -.base-icon { - width: 21.5px; - height: 26px; - position: relative; - margin-right: 5px; +aside input[type="checkbox"]:checked~.contents-treeview { + color: var(--color-neutral-700); + z-index: 6; + display: block; + margin: 0 20px 20px; +} + +.index-label { + font-size: 22px; + color: var(--color-neutral-800); + padding-left: 20px; + margin: 20px 0 0; +} + +.index { + margin-top: 10px; + padding-left: 15px; +} + +.index a { + font-size: 15px; + display: block; +} + +#Bookmarks { + width: 100%; + max-width: 100%; + margin-left: 0; + background-color: var(--background-color); + border-radius: 5rem; +} + +#Bookmarks p { + font-size: 22px; + font-weight: bold; + color: var(--color-brand-700); } -.office-icon { - background-image: url("media/navigation/libo-symbol-black.svg"); + +/* ============================================================ + * PRODUCT HEADERS (pseudo-elements) + * ============================================================ */ +#WRITER::before, +#CALC::before, +#IMPRESS::before, +#DRAW::before, +#BASE::before, +#MATH::before, +#CHART::before, +#BASIC::before, +#SHARED::before { + display: block; + font-size: 22px; + font-weight: bold; + color: var(--text-color); } -.calc-icon { - background-image: url("media/navigation/libo-calc.svg"); + +#WRITER::before { + content: "Writer"; } -.writer-icon { - background-image: url("media/navigation/libo-writer.svg"); + +#CALC::before { + content: "Calc"; } -.impress-icon { - background-image: url("media/navigation/libo-impress.svg"); + +#IMPRESS::before { + content: "Impress"; } -.draw-icon { - background-image: url("media/navigation/libo-draw.svg"); + +#DRAW::before { + content: "Draw"; } -.math-icon { - background-image: url("media/navigation/libo-math.svg"); + +#BASE::before { + content: "Base"; } -.base-icon { - background-image: url("media/navigation/libo-base.svg"); + +#MATH::before { + content: "Math"; } -.chart-icon { - background-image: url("media/navigation/libo-chart.svg"); + +#CHART::before { + content: "Chart"; } -.basic-icon { - background-image: url("media/navigation/libo-basic.svg"); + +#BASIC::before { + content: "Basic"; +} + +#SHARED::before { + content: "LibreOffice"; } -/* tree view */ +/* ============================================================ + * CONTENTS TREE VIEW + * ============================================================ */ .contents-treeview ul, .contents-treeview li { padding: 0; margin: 0; list-style: none; - font-size: 15px; } + .contents-treeview { -webkit-user-select: none; user-select: none; } -.contents-treeview a, .index a { + +.contents-treeview a, +.index a { text-decoration: none; line-height: 1.4; } -.contents-treeview a:hover, .index a:hover { - border-left: 2px solid rgb(0 0 0 / 5%); + +.contents-treeview a:hover, +.index a:hover { + border-left: 2px solid var(--treeview-hover-border-color); margin-left: -12px; padding-left: 10px; } -.contents-treeview input + label + ul { + +.contents-treeview input+label+ul { margin: 0 0 0 22px; } -.contents-treeview input ~ ul { + +.contents-treeview input~ul { display: none; } -.contents-treeview label, -.contents-treeview label::before { - cursor: pointer; - color: #111; -} -.contents-treeview input:disabled + label { + +.contents-treeview input:disabled+label { cursor: default; opacity: .6; } -.contents-treeview input:checked:not(:disabled) ~ ul { + +.contents-treeview input:checked:not(:disabled)~ul { display: block; } + .contents-treeview label, .contents-treeview a, .contents-treeview label::before { display: block; - vertical-align: middle; + line-height: 1.5; } + .contents-treeview label::before { content: "⊞"; - color: #0461e0; width: 16px; margin: 0 5px 0 0; display: inline-block; } -.contents-treeview input:checked + label::before { + +.contents-treeview input:checked+label::before { content: "⊟"; } + .contents-current { - background: rgb(0 0 0 / 10%); - border-left: 2px solid #6E7487; + background: var(--contents-current-bg); + border-left: 2px solid var(--contents-current-border-color); margin-left: -12px; padding-left: 10px; } -/* webkit adjacent element selector bugfix */ -@media screen and (-webkit-min-device-pixel-ratio: 0) { - .contents-treeview { - -webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s; - } - @-webkit-keyframes webkit-adjacent-element-selector-bugfix { - from { - padding: 0; - } - to { - padding: 0; - } - } +/* ============================================================ + * JAVASCRIPT WARNING + * ============================================================ */ +#WarnJS { + margin: 20px; + display: block; } -@media screen and (width >= 960px) { - html { - scroll-padding-top: 64px; - } - body { - display: grid; - grid-template-columns: 320px 100px 300px 1fr; - grid-template-rows: minmax(1em, auto) minmax(1em, auto) 1fr minmax(1em, auto); - grid-template-areas: "header header search donation" - "leftside main main main" - "leftside main main main" - ". footer footer footer"; - } - #TopLeftHeader { - display: grid; - align-items: end; - grid-template-columns: auto auto; - grid-template-rows: auto auto; - grid-template-areas: "symbol logo" - "symbol dropdowns"; - } - #SearchFrame { - grid-area: search; - display: flex; - justify-content: space-between; - align-items: center; - background: var(--heading-color); - } - .index-label { - color: #fff; - } - #DonationFrame { - grid-area: donation; - display: flex; - justify-content: space-between; - align-items: center; - background-color: var(--heading-color); - } - #Contents { - color: #333; - z-index: 6; - display: block; - margin: 0 20px; - } - label[for="accordion-1"] { - margin: 0; - } - label[for="accordion-1"]::after { - content: ""; - font-size: unset; - } - #Bookmarks { - margin-left: 0; - } + +#WarnJS h1 { + color: var(--color-red-600); + font-weight: bold; + text-align: center; +} + +/* ============================================================ + * BREAKPOINTS + * ============================================================ */ + +/* --- ≥600px (Tablets) --- */ +@media screen and (width >=600px) { .dropdowns { flex-direction: row; overflow: hidden auto; + justify-content: flex-start; + gap: 1.5rem; } + #langs-nav a { - font-size: 19px; white-space: normal; } - /* these are buttons, so also reset some default stylings */ - #langs, #modules { + + #langs, + #modules { cursor: pointer; - color: #fff; - font-size: 19px; + font-size: 1.4rem; display: block; background: transparent; border: none; @@ -962,258 +1730,195 @@ li.disabled a { line-height: normal; } - /* change the menu direction to stacked */ - #langs-nav, #modules-nav { + #langs-nav, + #modules-nav { display: flex; flex-direction: column; overflow-y: auto; max-height: 480px; position: absolute; } + #modules-nav { - background-color: #101820; text-align: left; } + #modules-nav div { display: block; } - #modules-nav a { - font-size: 19px; - } - aside { - float: left; - width: 320px; - } - .leftside { - grid-area: leftside; - padding: 40px 10px 0; - } - footer { - grid-area: footer; - } - .lang { - background-color: transparent; - } - .modules { - border: none; - background-color: transparent; - } - #DisplayArea { - box-shadow: 0 2px 8px 0 rgb(0 0 0 / 5%); - padding: 40px 20px; - } - .xapian-omega-search { - width: 100%; - } - .xapian-omega-search form { - display: flex; - justify-content: flex-end; - } - /* ScriptForge service tables */ - .sf_table { - min-width: auto; - } - .sf_table thead { - display: table-header-group; - } - .sf_table tr { - display: table-row; - } - .sf_table td { - display: table-cell; - } -} -@media screen and (width >= 1440px) { - body { - display: grid; - grid-template-columns: 1fr 360px 100px 400px 400px 1fr; - grid-template-rows: 1fr minmax(1em, auto) minmax(1em, auto); - grid-template-areas: "header header search search donation donation" - ". leftside main main main ." - ". footer footer footer footer ."; + + .header { + grid-template-columns: 2fr 1fr 40px; + grid-template-areas: + "TopLeftHeader search theme-toggle" + "TopLeftHeader donationFrame theme-toggle"; + padding: 10px 1rem; + align-items: center; } + #TopLeftHeader { - grid-template-columns: 1fr auto auto; - grid-template-areas: ". symbol logo" - ". symbol dropdowns"; - } - #SearchFrame { - justify-content: center; - } - #DonationFrame { display: grid; - grid-template-columns: subgrid; + align-items: end; + grid-template-columns: auto 1fr; + grid-template-rows: auto auto; + grid-template-areas: + "symbol logo" + "dropdowns dropdowns"; } - .donation { - max-width: 300px; + + .logo { + align-self: baseline; } - label[for="accordion-1"] { - background-color: transparent; - text-decoration: none; - color: var(--heading-color); - font-weight: bold; + + #DonationFrame { + justify-content: flex-start; } - label[for="accordion-1"]:hover { - background-color: transparent; + + #theme-toggle { + margin-top: 0; + align-self: center; } } -@media (prefers-color-scheme: dark) { - :root { - --background-color: #002a1a; - --heading-color: #ddffee; - --hover-color: #60ec93; - --link-color: #BB86FC; - --visited-color: #CF6679; - --table-background:#2e2e2e; + +/* --- ≥960px (Small monitor Desktops) --- */ +@media screen and (width >=960px) { + html { + scroll-padding-top: 64px; } body { - background-color: var(--background-color); - color: #e0e0e0; - } - h1, - h2, - h3, - h4, - h5, - h6 { - color: var(--heading-color); - border-bottom-color: var(--heading-color); - } - a { - color: var(--link-color); + display: grid; + grid-template-columns: 1fr 3fr; + grid-template-rows: minmax(1em, auto) minmax(1em, auto) 1fr minmax(1em, auto); + grid-template-areas: + "header header" + "leftside main" + "footer footer"; } - a:hover { - color: var(--hover-color); + .header { + grid-template-columns: 1fr 1fr 1fr 40px; + grid-template-areas: + "TopLeftHeader search donationFrame theme-toggle"; + padding: 0 1rem; } - a:visited { - color: var(--visited-color);; + #TopLeftHeader { + display: grid; + align-items: end; + grid-template-columns: auto 1fr; + grid-template-areas: + "symbol logo" + "dropdowns dropdowns"; } - .code, - .codeintable{ - background-color:black; + .dropdowns { + justify-content: start; + gap: 0; } - .note { - background-color: #2E2E2E; - border-left-color: #03DAC6; + #SearchFrame { + grid-area: search; + display: flex; + justify-content: space-between; + align-items: center; + background: var(--heading-color); } - .tip { - background-color: #2E2E2E; - border-left-color: #BB86FC; + #Bookmarks { + width: 20rem; + margin-left: 0; } - - .warning { - background-color: #2E2E2E; - border-left-color: #CF6679; + .index-label { + color: var(--color-neutral-50); } - .widget { - background: #808080; - border-color: #eee; - color: #eee; - font-weight: bold; - } - .iconimage { - background: var(--heading-color); - margin-right: 5px; - vertical-align: middle; + #Contents { + color: var(--color-neutral-700); + z-index: 6; + display: block; + margin: 0 20px; } - .howtoget { - background: #1E1E1E; - border-left-color: #BB86FC; + aside { + float: left; + width: 320px; } - .howtogetheader { - background: #333; + .leftside { + grid-area: leftside; + padding: 2.5rem .8rem 0; } - .youtube_placeholder { - background-color: #1E1E1E; + footer { + grid-area: footer; } - .pagination-container { - color: #e0e0e0; + .lang { + background-color: transparent; } - .pagination a { - color: #BB86FC; + .modules { + border: none; + background-color: transparent; } - .pagination li.active { - background-color: #3700B3; + #DisplayArea { + box-shadow: 0 2px 8px 0 rgb(0 0 0 / 5%); + padding: 2.5rem 1.5rem; } - .pagination li.active a { - color: #e0e0e0; + .xapian-omega-search { + width: 100%; } - .pagination li.disabled a { - color: #666; + .sf_table { + min-width: auto; } - footer, - #TopLeftHeader, - #DonationFrame, - .dropdowns, - #langs-nav a, #modules-nav a, - #SearchFrame, - .donation { - background-color: var(--background-color); + .sf_table thead { + display: table-header-group; } - .contents-treeview a:hover, .index a:hover { - border-left-color: #BB86FC; + .sf_table tr { + display: table-row; } - .contents-current { - background: #333; - border-left-color: #BB86FC; - } - .contents-treeview label, - .contents-treeview label::before { - cursor: pointer; - color: var(--heading-color); - } - #DisplayArea { - background-color: var(--background-color); - color: #efefef; - } - .xapian-donation, - .sf_table { - background-color: #1e1e1e; - } - .donation:hover { - background: linear-gradient(90deg, #3700B3 0%, #03DAC6 100%); - } .sf_table td { - border-color: #333; - } - .screenshot, .genericimage { - background-color: whitesmoke; + display: table-cell; } - .tableheadcell { - background: var(--background-color); - color: var(--heading-color); - vertical-align: top; - border-style: solid; - border-color: #888; - border-width: thin; +} + +/* --- ≥1440px (Big monitor Desktops) --- */ +@media screen and (width >=1440px) { + details.products { + position: relative; + display: inline-block; } - table { - background: var(--table-background); + + body { + display: grid; + grid-template-columns: 1fr 1fr 7fr 1fr; + grid-template-rows: 1fr minmax(1em, auto) minmax(1em, auto); + grid-template-areas: + "header header header header" + ". leftside main ." + ". footer footer ."; } - tr:nth-of-type(even) { - background-color: #1A1A1A; + + .header { + grid-template-columns: 1fr 1fr 1fr 40px; + grid-template-areas: + "TopLeftHeader search donationFrame theme-toggle"; + padding: 0 10vw; } - ::selection { - color: black; + + #TopLeftHeader { + grid-template-columns: auto 1fr; + grid-template-areas: + "symbol logo" + "symbol dropdowns"; } -} +} \ No newline at end of file diff --git a/help3xsl/help2.js b/help3xsl/help2.js index 66b6398347..21a80d9873 100644 --- a/help3xsl/help2.js +++ b/help3xsl/help2.js @@ -4,8 +4,9 @@ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * file, You can obtain one at http://www.mozilla.org/MPL/2.0/. */ + // Used to set Application in caseinline=APP function setApplSpan(spanZ) { let module = getParameterByName("DbPAR"); @@ -36,6 +37,7 @@ function setApplSpan(spanZ) { } } } + // Used to set system in case, caseinline=SYSTEM function setSystemSpan(spanZ) { // if no System in URL, get browser system @@ -80,9 +82,11 @@ function fixURL(module, system) { for (var i = 0; i < n; i++) { if (itemlink[i].getAttribute("class") != "objectfiles") { setURLParam(itemlink[i], pSystem, pAppl); + appendThemeParam(itemlink[i]); } } } + //Set the params inside URL function setURLParam(itemlink, pSystem, pAppl) { var href = itemlink.getAttribute("href"); @@ -101,6 +105,48 @@ function setURLParam(itemlink, pSystem, pAppl) { } } +// Append Theme parameter to a link if the user has an explicit preference. +// The fragment (#bookmark) must stay at the very end of the URL. +function appendThemeParam(itemlink) { + var theme = getExplicitTheme(); + if (!theme) return; + + var href = itemlink.getAttribute("href"); + if (href === null || href.startsWith("http")) return; + if (href.indexOf("Theme=") !== -1) return; + + var hash = ''; + var idx = href.indexOf('#'); + if (idx !== -1) { + hash = href.substring(idx); + href = href.substring(0, idx); + } + + var separator = href.indexOf("?") !== -1 ? "&" : "?"; + itemlink.setAttribute("href", href + separator + "Theme=" + theme + hash); +} + +// fixURL() only walks #DisplayArea. Header, treeview, pagination and +// module links need the Theme parameter as well, otherwise the choice +// is lost as soon as the user leaves the article area. +function propagateThemeGlobally() { + var links = document.querySelectorAll('a[href]'); + for (var i = 0; i < links.length; i++) { + appendThemeParam(links[i]); + } +} + +// Rewrite links that already carry an outdated Theme value +function refreshThemeParams(newTheme) { + var links = document.querySelectorAll('a[href*="Theme="]'); + for (var i = 0; i < links.length; i++) { + links[i].setAttribute('href', + links[i].getAttribute('href') + .replace(/([?&])Theme=(dark|light)/, '$1Theme=' + newTheme)); + } + propagateThemeGlobally(); +} + function getSystem() { var system = "Unknown OS"; if (navigator.appVersion.indexOf("Win") != -1) system = "WIN"; @@ -149,6 +195,7 @@ function existingLang(lang) { function setupModules(lang) { var modulesNav = document.getElementById('modules-nav'); + if (!modulesNav) return; if (!modulesNav.classList.contains('loaded')) { let html = '<a href="' + lang + '/text/shared/05/new_help.html?DbPAR=SHARED"><div class="office-icon"></div>%PRODUCTNAME</a>' + @@ -204,6 +251,111 @@ function impl_Switches(){ } } } + +/* ============================================================ + * THEME MANAGEMENT + * Priority: URL param > localStorage > prefers-color-scheme + * + * Under file:// Chromium treats every document as an opaque + * origin, so localStorage is not shared between help pages. + * The Theme URL parameter is therefore the primary carrier and + * localStorage is only an extra layer (works on Firefox and + * whenever the help is served over http://). + * ============================================================ */ + +var THEME_STORAGE_KEY = 'theme'; +var themeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + +function getStoredTheme() { + try { return localStorage.getItem(THEME_STORAGE_KEY); } + catch(e) { return null; } +} + +function saveTheme(theme) { + try { localStorage.setItem(THEME_STORAGE_KEY, theme); } + catch(e) {} +} + +function clearStoredTheme() { + try { localStorage.removeItem(THEME_STORAGE_KEY); } + catch(e) {} +} + +// Theme explicitly chosen by the user, or null when the page is +// still following the operating system preference. Only explicit +// choices are propagated to other pages. +function getExplicitTheme() { + var urlTheme = getParameterByName("Theme"); + if (urlTheme === 'dark' || urlTheme === 'light') { + return urlTheme; + } + var saved = getStoredTheme(); + if (saved === 'dark' || saved === 'light') { + return saved; + } + return null; +} + +// The theme class lives on <html>: it exists before <body> is parsed, +// so the script can run from <head> without a flash of the wrong theme. +function applyTheme(theme) { + var root = document.documentElement; + root.classList.remove('dark-mode', 'light-mode'); + root.classList.add(theme + '-mode'); +} + + +// Determine effective theme from all sources +function resolveTheme() { + var explicit = getExplicitTheme(); + if (explicit) { + return explicit; + } + // Fall back to the OS preference + return themeMediaQuery.matches ? 'dark' : 'light'; +} + +function bindThemeToggle() { + var toggleBtn = document.getElementById('theme-toggle'); + if (!toggleBtn || toggleBtn.dataset.themeBound) return; + toggleBtn.dataset.themeBound = '1'; + + toggleBtn.addEventListener('click', function() { + var isDark = document.documentElement.classList.contains('dark-mode'); + var newTheme = isDark ? 'light' : 'dark'; + applyTheme(newTheme); + saveTheme(newTheme); + // Update URL without reload so links on this page reflect the change + var url = new URL(window.location.href); + url.searchParams.set('Theme', newTheme); + window.history.replaceState({}, '', url); + // Keep every link on this page in sync with the new choice + refreshThemeParams(newTheme); + }); +} + +function initTheme() { + applyTheme(resolveTheme()); + + // React to OS preference changes only when user has no explicit preference + themeMediaQuery.addEventListener('change', function() { + if (!getExplicitTheme()) { + applyTheme(themeMediaQuery.matches ? 'dark' : 'light'); + } + }); + + // The toggle button may not exist yet when this file is parsed + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', bindThemeToggle); + } else { + bindThemeToggle(); + } +} + + +// Apply theme early to avoid flash of wrong theme +initTheme(); + // Main let module = getParameterByName("DbPAR"); let system = getParameterByName("System"); @@ -220,7 +372,9 @@ debugInfo(getParameterByName("Debug")); if (Math.max(document.documentElement.clientWidth, window.innerWidth || 0) < 960) { let modules = document.getElementById('modules-nav'); let langs = document.getElementById('langs-nav'); - modules.removeAttribute('hidden'); + if (modules) { + modules.removeAttribute('hidden'); + } if (langs) { langs.removeAttribute('hidden'); } @@ -231,4 +385,15 @@ const lang = getParameterByName("Language", href) || document.querySelector("htm setupModules(lang); setupLanguages(href); +// Must run after the innerHTML injections above, so the freshly +// created module and language links also carry the Theme parameter. +propagateThemeGlobally(); + +// Late safety net: links created after page load (bookmark search, +// Xapian results) get the parameter at click time. +document.addEventListener('click', function(e) { + var link = e.target.closest ? e.target.closest('a[href]') : null; + if (link) appendThemeParam(link); +}, true); + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/help3xsl/online_transform.xsl b/help3xsl/online_transform.xsl index 0a3e4ca64d..013166d7a8 100644 --- a/help3xsl/online_transform.xsl +++ b/help3xsl/online_transform.xsl @@ -18,1535 +18,1540 @@ --> <xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:m="http://www.w3.org/1998/Math/MathML" - exclude-result-prefixes="m"> -<xsl:output indent="yes" method="html" doctype-system= "about:legacy-compat"/> - -<xsl:include href="links.txt.xsl"/> -<!-- -############################ -# Variables and Parameters # -############################ -//--> - -<xsl:param name="local" /> -<xsl:param name="root"/> -<xsl:param name="Language"/> -<xsl:param name="productname"/> -<xsl:param name="productversion"/> -<xsl:param name="xapian"/> - -<xsl:param name="System" select="'WIN'"/> -<xsl:param name="imgtheme" select="''"/> -<xsl:param name="Id" /> - -<!-- General Usage --> -<xsl:variable name="am" select="'&'"/> -<xsl:variable name="sl" select="'/'"/> -<xsl:variable name="qt" select="'"'"/> - -<!-- For calculating pixel sizes --> -<xsl:variable name="dpi" select="'96'"/> -<xsl:variable name="dpcm" select="'38'"/> -<xsl:variable name="dpmm" select="'3.8'"/> - -<!-- Product brand variables used in the help files --> -<xsl:variable name="brand1" select="'$[officename]'"/> -<xsl:variable name="brand2" select="'$[officeversion]'"/> -<xsl:variable name="brand3" select="'%PRODUCTNAME'"/> -<xsl:variable name="brand4" select="'%PRODUCTVERSION'"/> - -<!-- Installation --> -<xsl:variable name="online" select="$local!='yes'"/> - -<!-- meta data variables from the help file --> -<xsl:variable name="filename" select="/helpdocument/meta/topic/filename"/> -<xsl:variable name="title" select="/helpdocument/meta/topic/title"/> - -<!-- the other parameters given by the help caller --> - -<xsl:variable name="pversion"> - <xsl:value-of select="translate($productversion,' ','')"/> -</xsl:variable> -<!-- this is were the images are --> - -<xsl:variable name="lang" select="$Language"/> -<xsl:variable name="urlpre" select="$root"/> - - -<!-- generic Icon alt text --> -<xsl:variable name="alttext" select="concat($root,'text/shared/00/icon_alt.xhp')"/> - - <!-- parts of help and image urls --> - -<xsl:variable name="img_url_prefix" select="concat('media',$imgtheme,'/')"/> - -<xsl:variable name="urlpost" select="concat('?Language=',$lang,$am,'System=',$System,$am,'UseDB=no')"/> - -<xsl:variable name="linkprefix" select="concat($lang,'/')"/> - -<!--<xsl:variable name="linkpostfix" select="$urlpost"/>--> -<xsl:variable name="linkpostfix" select="''"/> - -<!-- images for notes, tips and warnings --> -<xsl:variable name="iconsizestyle" select="'width:40px;height:40px;'"/> -<xsl:variable name="note_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/note.svg')"/> -<xsl:variable name="tip_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/tip.svg')"/> -<xsl:variable name="warning_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/warning.svg')"/> -<xsl:variable name="donate_img" select="concat($img_url_prefix,'helpimg/donate.png')"/> - -<!-- Strings for the help UI page --> -<xsl:variable name="url_canonical" select="'https://help.libreoffice.org/'"/> -<xsl:variable name="tmp_href_ui"><xsl:value-of select="concat($urlpre,'text/shared/help/browserhelp.xhp')"/></xsl:variable> -<xsl:variable name="tmp_doc_ui" select="document($tmp_href_ui)"/> -<xsl:variable name="ui_contents"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='contents']"/></xsl:variable> -<xsl:variable name="ui_index"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='index']"/></xsl:variable> -<xsl:variable name="ui_pholderbmarksall"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderbmarksall']"/></xsl:variable> -<xsl:variable name="ui_pholderbmarkschosen"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderbmarkschosen']"/></xsl:variable> -<xsl:variable name="ui_pholderfullsearch"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderfullsearch']"/></xsl:variable> -<xsl:variable name="ui_module"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='module']"/></xsl:variable> -<xsl:variable name="ui_language"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='language']"/></xsl:variable> -<xsl:variable name="ui_donate"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='donate']"/></xsl:variable> -<xsl:variable name="ui_logo"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='LibreOfficeHelp']"/></xsl:variable> -<xsl:variable name="ui_selectmodule"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='selectmodule']"/></xsl:variable> -<xsl:variable name="ui_selectlang"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='selectlanguage']"/></xsl:variable> -<xsl:variable name="ui_search"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='searchhelpcontents']"/></xsl:variable> -<xsl:variable name="ui_copyclip"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='copyclip']"/></xsl:variable> -<xsl:variable name="ytvideobutton"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='ytbutton']"/></xsl:variable> -<xsl:variable name="ytaccept"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='ytaccept']"/></xsl:variable> -<xsl:variable name="ytpromovideoH2"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='externalvideo']"/></xsl:variable> -<xsl:variable name="ytprivacy"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='ytprivacy']"/></xsl:variable> -<xsl:variable name="ui_books"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='books']"/></xsl:variable> -<!-- -############# -# Templates # -############# -//--> - -<!-- Create the document skeleton --> -<xsl:template match="/"> - <xsl:variable name="htmlpage"> - <xsl:value-of select="concat(substring-before($filename,'.xhp'),'.html')"/> - </xsl:variable> - <xsl:variable name="titleL10N"> - <xsl:call-template name="brand"><xsl:with-param name="string"><xsl:value-of select="$title"/></xsl:with-param></xsl:call-template> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:m="http://www.w3.org/1998/Math/MathML" + exclude-result-prefixes="m"> + <xsl:output indent="yes" method="html" doctype-system= "about:legacy-compat"/> + + <xsl:include href="links.txt.xsl"/> + <!-- + ############################ + # Variables and Parameters # + ############################ + //--> + + <xsl:param name="local" /> + <xsl:param name="root"/> + <xsl:param name="Language"/> + <xsl:param name="productname"/> + <xsl:param name="productversion"/> + <xsl:param name="xapian"/> + + <xsl:param name="System" select="'WIN'"/> + <xsl:param name="imgtheme" select="''"/> + <xsl:param name="Id" /> + + <!-- General Usage --> + <xsl:variable name="am" select="'&'"/> + <xsl:variable name="sl" select="'/'"/> + <xsl:variable name="qt" select="'"'"/> + + <!-- For calculating pixel sizes --> + <xsl:variable name="dpi" select="'96'"/> + <xsl:variable name="dpcm" select="'38'"/> + <xsl:variable name="dpmm" select="'3.8'"/> + + <!-- Product brand variables used in the help files --> + <xsl:variable name="brand1" select="'$[officename]'"/> + <xsl:variable name="brand2" select="'$[officeversion]'"/> + <xsl:variable name="brand3" select="'%PRODUCTNAME'"/> + <xsl:variable name="brand4" select="'%PRODUCTVERSION'"/> + + <!-- Installation --> + <xsl:variable name="online" select="$local!='yes'"/> + + <!-- meta data variables from the help file --> + <xsl:variable name="filename" select="/helpdocument/meta/topic/filename"/> + <xsl:variable name="title" select="/helpdocument/meta/topic/title"/> + + <!-- the other parameters given by the help caller --> + + <xsl:variable name="pversion"> + <xsl:value-of select="translate($productversion,' ','')"/> </xsl:variable> - <xsl:variable name="install"> - <xsl:call-template name="tokenize"> - <xsl:with-param name="str" select="$filename"/> - </xsl:call-template> - </xsl:variable> - <xsl:variable name="logoprodversion"> + <!-- this is were the images are --> + + <xsl:variable name="lang" select="$Language"/> + <xsl:variable name="urlpre" select="$root"/> + + + <!-- generic Icon alt text --> + <xsl:variable name="alttext" select="concat($root,'text/shared/00/icon_alt.xhp')"/> + + <!-- parts of help and image urls --> + + <xsl:variable name="img_url_prefix" select="concat('media',$imgtheme,'/')"/> + + <xsl:variable name="urlpost" select="concat('?Language=',$lang,$am,'System=',$System,$am,'UseDB=no')"/> + + <xsl:variable name="linkprefix" select="concat($lang,'/')"/> + + <!--<xsl:variable name="linkpostfix" select="$urlpost"/>--> + <xsl:variable name="linkpostfix" select="''"/> + + <!-- images for notes, tips and warnings --> + <xsl:variable name="iconsizestyle" select="'width:40px;height:40px;'"/> + <xsl:variable name="note_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/note.svg')"/> + <xsl:variable name="tip_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/tip.svg')"/> + <xsl:variable name="warning_img" select="concat($img_url_prefix,'icon-themes/res/helpimg/warning.svg')"/> + <xsl:variable name="donate_img" select="concat($img_url_prefix,'helpimg/donate.png')"/> + + <!-- Strings for the help UI page --> + <xsl:variable name="url_canonical" select="'https://help.libreoffice.org/'"/> + <xsl:variable name="tmp_href_ui"><xsl:value-of select="concat($urlpre,'text/shared/help/browserhelp.xhp')"/></xsl:variable> + <xsl:variable name="tmp_doc_ui" select="document($tmp_href_ui)"/> + <xsl:variable name="ui_contents"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='contents']"/></xsl:variable> + <xsl:variable name="ui_index"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='index']"/></xsl:variable> + <xsl:variable name="ui_pholderbmarksall"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderbmarksall']"/></xsl:variable> + <xsl:variable name="ui_pholderbmarkschosen"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderbmarkschosen']"/></xsl:variable> + <xsl:variable name="ui_pholderfullsearch"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='pholderfullsearch']"/></xsl:variable> + <xsl:variable name="ui_module"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='module']"/></xsl:variable> + <xsl:variable name="ui_language"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='language']"/></xsl:variable> + <xsl:variable name="ui_donate"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='donate']"/></xsl:variable> + <xsl:variable name="ui_logo"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='LibreOfficeHelp']"/></xsl:variable> + <xsl:variable name="ui_selectmodule"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='selectmodule']"/></xsl:variable> + <xsl:variable name="ui_selectlang"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='selectlanguage']"/></xsl:variable> + <xsl:variable name="ui_search"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='searchhelpcontents']"/></xsl:variable> + <xsl:variable name="ui_copyclip"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='copyclip']"/></xsl:variable> + <xsl:variable name="ytvideobutton"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='ytbutton']"/></xsl:variable> + <xsl:variable name="ytaccept"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='ytaccept']"/></xsl:variable> + <xsl:variable name="ytpromovideoH2"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='externalvideo']"/></xsl:variable> + <xsl:variable name="ytprivacy"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='ytprivacy']"/></xsl:variable> + <xsl:variable name="ui_books"><xsl:apply-templates select="$tmp_doc_ui//variable[@id='books']"/></xsl:variable> + <!-- + ############# + # Templates # + ############# + //--> + + <!-- Create the document skeleton --> + <xsl:template match="/"> + <xsl:variable name="htmlpage"> + <xsl:value-of select="concat(substring-before($filename,'.xhp'),'.html')"/> + </xsl:variable> + <xsl:variable name="titleL10N"> + <xsl:call-template name="brand"><xsl:with-param name="string"><xsl:value-of select="$title"/></xsl:with-param></xsl:call-template> + </xsl:variable> + <xsl:variable name="install"> + <xsl:call-template name="tokenize"> + <xsl:with-param name="str" select="$filename"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="logoprodversion"> + <xsl:choose> + <xsl:when test="$productversion='latest'"><xsl:value-of select="''"/></xsl:when> + <xsl:otherwise><xsl:value-of select="$productversion"/></xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="direction"> + <xsl:choose> + <xsl:when test="$lang='ar' or $lang='fa' or $lang='he' or $lang='sd' or $lang='ur'"> + <xsl:value-of select="'rtl'"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="'ltr'"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="meta_description"> + <xsl:call-template name="brand"> + <xsl:with-param name="string"> + <xsl:value-of select="substring(concat($productname,': ',//description),1,170)"/> + </xsl:with-param> + </xsl:call-template> + </xsl:variable> + <html lang="{$lang}" dir="{$direction}"> + <head> + <base href="{$install}"/> + <title><xsl:value-of disable-output-escaping="yes" select="$titleL10N"/></title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <xsl:if test="//description"> + <meta name="description" contents="{$meta_description}"/> + </xsl:if> + <xsl:if test="$online"> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' piwik.documentfoundation.org"/> + </xsl:if> + <link rel="shortcut icon" href="media/navigation/favicon.ico"/> + <link type="text/css" href="normalize.css" rel="Stylesheet"/> + <link type="text/css" href="prism.css" rel="Stylesheet"/> + <link type="text/css" href="default.css" rel="Stylesheet"/> + <script type="text/javascript" src="polyfills.js"></script> + <script type="text/javascript" src="languages.js"></script> + <script type="text/javascript" src="{$lang}/langnames.js"></script> + <script type="text/javascript" src="flexsearch.compact.debug.js"></script> + <script type="text/javascript" src="prism.js"></script> + <script type="text/javascript" src="help2.js" defer=""></script> + <xsl:if test="$online"> + <script type="text/javascript" src="tdf_matomo.js" defer=""></script> + </xsl:if> + <script type="text/javascript" src="a11y-toggle.js" defer=""></script> + <script type="text/javascript" src="paginathing.js" defer=""></script> + <script type="text/javascript" src="{$lang}/bookmarks.js" defer=""></script> + <script type="text/javascript" src="{$lang}/contents.js" defer=""></script> + <script type="text/javascript" src="help.js" defer=""></script> + <meta name="viewport" content="width=device-width,initial-scale=1"/> + <!--tdf#155193 - do not index when indexer="excluded", see omindex on HTML indexing--> + <xsl:if test="//topic[@indexer='exclude']"> + <meta name="robots" content="noindex"/> + </xsl:if> + <link rel="canonical" href="{$url_canonical}{$productversion}/{$lang}{$htmlpage}"/> + </head> + <body> + <header class="header"> + <div id="TopLeftHeader"> + <a class="symbol" href="{$lang}/text/shared/05/new_help.html"> + <img class="moon" src="media/navigation/libo-symbol-white.svg" alt="LibreOffice Symbol" /> + <img class="sun" src="media/navigation/libo-symbol-black-alt.svg" alt="LibreOffice Symbol" /> + </a> + <a class="logo" href="{$lang}/text/shared/05/new_help.html"> + <p dir="auto"><xsl:value-of disable-output-escaping="yes" select="$ui_logo"/></p> + </a> + <div class="dropdowns"> + <div class="modules"> + <button type="button" data-a11y-toggle="modules-nav" id="modules" aria-haspopup="true" aria-expanded="false" aria-controls="modules-nav"> + <xsl:value-of select="$ui_module"/> + </button> -e ... etc. - the rest is truncated
