diff --git a/project/Build.scala b/project/Build.scala index b32eb094cc59..dc20ee2d3e2a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1313,10 +1313,12 @@ object Build { Seq(jsDestinationFile) }.taskValue, Compile / resourceGenerators += Def.task { - val cssDesitnationFile = (Compile / resourceManaged).value / "dotty_res" / "styles" / "scaladoc-searchbar.css" - val cssSourceFile = (`scaladoc-js` / Compile / resourceDirectory).value / "scaladoc-searchbar.css" - sbt.IO.copyFile(cssSourceFile, cssDesitnationFile) - Seq(cssDesitnationFile) + Seq("code-snippets.css", "searchbar.css", "social-links.css", "ux.css", "versions-dropdown.css").map { file => + val cssDesitnationFile = (Compile / resourceManaged).value / "dotty_res" / "styles" / file + val cssSourceFile = (`scaladoc-js` / Compile / resourceDirectory).value / file + sbt.IO.copyFile(cssSourceFile, cssDesitnationFile) + cssDesitnationFile + } }.taskValue, Compile / resourceGenerators += Def.task { import _root_.scala.sys.process._ diff --git a/scaladoc-js/resources/code-snippets.css b/scaladoc-js/resources/code-snippets.css new file mode 100644 index 000000000000..29a7670ebe2f --- /dev/null +++ b/scaladoc-js/resources/code-snippets.css @@ -0,0 +1,232 @@ +/* Snippets */ + +.snippet { + padding: 12px 8px 10px 12px; + background: var(--code-bg); + margin: 1em 0px; + border-radius: 2px; + box-shadow: 0 0 2px #888; + cursor: default; +} +.snippet-error { + border-bottom: 2px dotted red; +} +.snippet-warn { + border-bottom: 2px dotted orange; +} +.snippet-info { + border-bottom: 2px dotted teal; +} +.snippet-debug { + border-bottom: 2px dotted pink; +} + +.snippet .snippet-meta { + border-top: 2px solid var(--inactive-bg); + color: var(--inactive-fg); + margin-top: 10px; + padding-top: 10px; + font-size: 0.75em; +} + +.snippet-meta .snippet-label { + font-weight: bold; +} + +.snippet .buttons { + --icon-size: 16px; +} + +.snippet-showhide { + display: flex; + flex-direction: row; + align-items: center; + --slider-width: 40px; + --slider-height: 16px; + --slider-diameter: calc(var(--slider-height) - 4px); +} + +.snippet-showhide p { + margin-left: 4px; + margin-bottom: 0; + margin-top: 0; + color: var(--inactive-fg); +} + +.snippet-showhide-button { + display: inline-block; + position: relative; + width: var(--slider-width); + height: var(--slider-height); + margin-bottom: 0; +} + +.snippet-showhide-button input { + opacity: 0; + width: 0; + height: 0; +} + +.snippet-showhide-button .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--inactive-bg); + -webkit-transition: .4s; + transition: .4s; + border-radius: var(--slider-height); +} + +.snippet-showhide-button .slider:before { + position: absolute; + content: ""; + height: var(--slider-diameter); + width: var(--slider-diameter); + left: 2px; + bottom: 2px; + background-color: var(--inactive-fg); + -webkit-transition: .4s; + transition: .4s; + border-radius: 50%; +} + +.snippet-showhide-button .slider:hover::before { + background-color: var(--active-fg); +} + +input:checked + .slider { + background-color: var(--active-bg); +} + +input:focus + .slider { + box-shadow: 0 0 1px var(--active-bg-shadow); +} + +input:checked + .slider:before { + --translation-size: calc(var(--slider-width) - var(--slider-diameter) - 4px); + -webkit-transform: translateX(var(--translation-size)); + -ms-transform: translateX(var(--translation-size)); + transform: translateX(var(--translation-size)); +} + +.tooltip { + position: relative; +} +.tooltip:hover:after { + content: attr(label); + padding: 4px 8px; + color: white; + background-color:black; + position: absolute; + left: 0; + z-index:10; + box-shadow:0 0 3px #444; + opacity: 0.8; +} + +.snippet .buttons .tooltip::after { + top: 32px; +} + +.snippet .buttons { + display: flex; + flex-direction: row-reverse; + justify-content: flex-start; +} + +.snippet .buttons button { + outline: none; + background: none; + border: none; + font-size: var(--icon-size); + color: var(--inactive-fg); + cursor: pointer; +} + +.snippet .buttons button:hover:not(:disabled) { + color: var(--inactive-fg-shadow) +} + +.snippet .buttons button:active:not(:disabled) { + transform: translateY(2px); + color: var(--active-fg) +} + +.snippet .buttons button:disabled { + color: var(--inactive-bg) +} + + +.snippet .buttons>:not(:last-child) { + border-left: 2px solid var(--inactive-bg); +} + +.snippet .buttons>* { + padding-left: 5px; + padding-right: 5px; +} + +.unselectable { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.included-section { + display: flex; + flex-direction: column; +} + +.included-section a { + color: var(--inactive-fg) !important; + font-size: 0.75em; +} + +.included-section b { + font-weight: bold; +} + +.hideable.hidden { + display: none; +} + +@media(max-width: 576px) { + .snippet-showhide { + --slider-width: 32px; + --slider-height: 16px; + } + + .snippet .buttons { + --icon-size: 16px; + font-size: 16px; + } + +} + +@media(max-width: 360px) { + .snippet-showhide { + --slider-width: 32px; + --slider-height: 16px; + } + + .snippet .buttons { + --icon-size: 16px; + font-size: 0px; + } +} + +@media(max-width: 240px) { + .snippet-showhide { + --slider-width: 24px; + --slider-height: 10px; + } + + .snippet .buttons { + --icon-size: 16px; + font-size: 0px; + } +} diff --git a/scaladoc-js/resources/scaladoc-searchbar.css b/scaladoc-js/resources/scaladoc-searchbar.css deleted file mode 100644 index 66c847d5778a..000000000000 --- a/scaladoc-js/resources/scaladoc-searchbar.css +++ /dev/null @@ -1,329 +0,0 @@ -/* button */ -.search span { - background: var(--red500); - fill: var(--white); - cursor: pointer; - border: none; - padding: 9px; - border-radius: 24px; - box-shadow: 0 0 16px var(--code-bg); -} -.search span:hover { - background: var(--red600); -} - -@media(max-width: 576px) { - .search span { - background: none; - fill: var(--icon-color); - cursor: pointer; - border: none; - padding: 0; - box-shadow: none; - margin-top: 2px; - } - - .search span:hover { - fill: var(--link-hover-fg); - } -} - -#scaladoc-search { - margin-top: 16px; - cursor: pointer; - position: fixed; - top: 0; - right: 20px; - z-index: 5; -} - -#scaladoc-searchbar.hidden { - display: none; -} - -#scaladoc-searchbar { - position: fixed; - top: 50px; - left: calc(5% + var(--side-width)); - z-index: 5; - width: calc(90% - var(--side-width)); - box-shadow: 0 2px 16px 0 rgba(0, 42, 76, 0.15); - font-size: 13px; - font-family: system-ui, -apple-system, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, Arial, sans-serif; - background-color: var(--leftbar-bg); - color: var(--leftbar-fg); - box-shadow: 0 0 2px var(--shadow); -} - -#scaladoc-searchbar-input { - width: 100%; - min-height: 32px; - border: none; - border-bottom: 1px solid #bbb; - padding: 10px; - background-color: var(--leftbar-bg); - color: var(--leftbar-fg); -} - -#scaladoc-searchbar-input:focus { - outline: none; -} - -#scaladoc-searchbar-results { - display: flex; - flex-direction: column; - max-height: 500px; - overflow: auto; -} - -.scaladoc-searchbar-result { - background-color: var(--leftbar-bg); - color: var(--leftbar-fg); - line-height: 24px; - padding: 4px 10px 4px 10px; -} - -.scaladoc-searchbar-result-row { - display: flex; -} - -.scaladoc-searchbar-result .micon { - height: 16px; - width: 16px; - margin: 4px 8px 0px 0px; -} - -.scaladoc-searchbar-result:first-of-type { - margin-top: 10px; -} - -.scaladoc-searchbar-result[selected] { - background-color: var(--leftbar-hover-bg); - color: var(--leftbar-hover-fg); -} - -.scaladoc-searchbar-result a { - /* for some reason, with display:block if there's a wrap between the - * search result text and the location span, the dead space to the - * left of the location span doesn't get treated as part of the block, - * which defeats the purpose of making the a block element. - * But inline-block with width:100% works as desired. - */ - display: inline-block; - width: 100%; - text-indent: -20px; - padding-left: 20px; -} - -#searchBar { - display: inline-flex; -} - -.pull-right { - float: right; - margin-left: auto; -} - -/* Snippets */ - -.snippet { - cursor: default; -} - -.snippet .snippet-meta { - border-top: 2px solid var(--inactive-bg); - color: var(--inactive-fg); - margin-top: 10px; - padding-top: 10px; - font-size: 0.75em; -} - -.snippet-meta .snippet-label { - font-weight: bold; -} - -.snippet .buttons { - --icon-size: 16px; -} - -.snippet-showhide { - display: flex; - flex-direction: row; - align-items: center; - --slider-width: 40px; - --slider-height: 16px; - --slider-diameter: calc(var(--slider-height) - 4px); -} - -.snippet-showhide p { - margin-left: 4px; - margin-bottom: 0; - margin-top: 0; - color: var(--inactive-fg); -} - -.snippet-showhide-button { - display: inline-block; - position: relative; - width: var(--slider-width); - height: var(--slider-height); - margin-bottom: 0; -} - -.snippet-showhide-button input { - opacity: 0; - width: 0; - height: 0; -} - -.snippet-showhide-button .slider { - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: var(--inactive-bg); - -webkit-transition: .4s; - transition: .4s; - border-radius: var(--slider-height); -} - -.snippet-showhide-button .slider:before { - position: absolute; - content: ""; - height: var(--slider-diameter); - width: var(--slider-diameter); - left: 2px; - bottom: 2px; - background-color: var(--inactive-fg); - -webkit-transition: .4s; - transition: .4s; - border-radius: 50%; -} - -.snippet-showhide-button .slider:hover::before { - background-color: var(--active-fg); -} - -input:checked + .slider { - background-color: var(--active-bg); -} - -input:focus + .slider { - box-shadow: 0 0 1px var(--active-bg-shadow); -} - -input:checked + .slider:before { - --translation-size: calc(var(--slider-width) - var(--slider-diameter) - 4px); - -webkit-transform: translateX(var(--translation-size)); - -ms-transform: translateX(var(--translation-size)); - transform: translateX(var(--translation-size)); -} - -.snippet .buttons .tooltip::after { - top: 32px; -} - -.snippet .buttons { - display: flex; - flex-direction: row-reverse; - justify-content: flex-start; -} - -.snippet .buttons button { - outline: none; - background: none; - border: none; - font-size: var(--icon-size); - color: var(--inactive-fg); - cursor: pointer; -} - -.snippet .buttons button:hover:not(:disabled) { - color: var(--inactive-fg-shadow) -} - -.snippet .buttons button:active:not(:disabled) { - transform: translateY(2px); - color: var(--active-fg) -} - -.snippet .buttons button:disabled { - color: var(--inactive-bg) -} - - -.snippet .buttons>:not(:last-child) { - border-left: 2px solid var(--inactive-bg); -} - -.snippet .buttons>* { - padding-left: 5px; - padding-right: 5px; -} - -.unselectable { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.included-section { - display: flex; - flex-direction: column; -} - -.included-section a { - color: var(--inactive-fg) !important; - font-size: 0.75em; -} - -.included-section b { - font-weight: bold; -} - -.hideable.hidden { - display: none; -} - -@media(max-width: 576px) { - .snippet-showhide { - --slider-width: 32px; - --slider-height: 16px; - } - - .snippet .buttons { - --icon-size: 16px; - font-size: 16px; - } - -} - -@media(max-width: 360px) { - .snippet-showhide { - --slider-width: 32px; - --slider-height: 16px; - } - - .snippet .buttons { - --icon-size: 16px; - font-size: 0px; - } - -} - -@media(max-width: 240px) { - .snippet-showhide { - --slider-width: 24px; - --slider-height: 10px; - } - - .snippet .buttons { - --icon-size: 16px; - font-size: 0px; - } - -} - diff --git a/scaladoc/resources/dotty_res/styles/search-bar.css b/scaladoc-js/resources/searchbar.css similarity index 50% rename from scaladoc/resources/dotty_res/styles/search-bar.css rename to scaladoc-js/resources/searchbar.css index 9662db3f90e7..103b830e0ca4 100644 --- a/scaladoc/resources/dotty_res/styles/search-bar.css +++ b/scaladoc-js/resources/searchbar.css @@ -127,3 +127,129 @@ div[selected] > .scaladoc-searchbar-inkuire-package { float: right; margin-left: auto !important; } + +/* button */ +.search span { + background: var(--red500); + fill: var(--white); + cursor: pointer; + border: none; + padding: 9px; + border-radius: 24px; + box-shadow: 0 0 16px var(--code-bg); +} +.search span:hover { + background: var(--red600); +} + +@media(max-width: 576px) { + .search span { + background: none; + fill: var(--icon-color); + cursor: pointer; + border: none; + padding: 0; + box-shadow: none; + margin-top: 2px; + } + + .search span:hover { + fill: var(--link-hover-fg); + } +} + +#scaladoc-search { + margin-top: 16px; + cursor: pointer; + position: fixed; + top: 0; + right: 20px; + z-index: 5; +} + +#scaladoc-searchbar.hidden { + display: none; +} + +#scaladoc-searchbar { + position: fixed; + top: 50px; + left: calc(5% + var(--side-width)); + z-index: 5; + width: calc(90% - var(--side-width)); + box-shadow: 0 2px 16px 0 rgba(0, 42, 76, 0.15); + font-size: 13px; + font-family: system-ui, -apple-system, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, Arial, sans-serif; + background-color: var(--leftbar-bg); + color: var(--leftbar-fg); + box-shadow: 0 0 2px var(--shadow); +} + +#scaladoc-searchbar-input { + width: 100%; + min-height: 32px; + border: none; + border-bottom: 1px solid #bbb; + padding: 10px; + background-color: var(--leftbar-bg); + color: var(--leftbar-fg); +} + +#scaladoc-searchbar-input:focus { + outline: none; +} + +#scaladoc-searchbar-results { + display: flex; + flex-direction: column; + max-height: 500px; + overflow: auto; +} + +.scaladoc-searchbar-result { + background-color: var(--leftbar-bg); + color: var(--leftbar-fg); + line-height: 24px; + padding: 4px 10px 4px 10px; +} + +.scaladoc-searchbar-result-row { + display: flex; +} + +.scaladoc-searchbar-result .micon { + height: 16px; + width: 16px; + margin: 4px 8px 0px 0px; +} + +.scaladoc-searchbar-result:first-of-type { + margin-top: 10px; +} + +.scaladoc-searchbar-result[selected] { + background-color: var(--leftbar-hover-bg); + color: var(--leftbar-hover-fg); +} + +.scaladoc-searchbar-result a { + /* for some reason, with display:block if there's a wrap between the + * search result text and the location span, the dead space to the + * left of the location span doesn't get treated as part of the block, + * which defeats the purpose of making the a block element. + * But inline-block with width:100% works as desired. + */ + display: inline-block; + width: 100%; + text-indent: -20px; + padding-left: 20px; +} + +#searchBar { + display: inline-flex; +} + +.pull-right { + float: right; + margin-left: auto; +} diff --git a/scaladoc-js/resources/social-links.css b/scaladoc-js/resources/social-links.css new file mode 100644 index 000000000000..f0edfafa7d6d --- /dev/null +++ b/scaladoc-js/resources/social-links.css @@ -0,0 +1,17 @@ +.theme-dark footer .social-icon { + /* "Poor man's dark mode" for images. + * This works great with black images, + * and just-okay with colored images. + */ + filter: invert(100%) hue-rotate(180deg); +} + +.social-icon { + padding-right: 5px; + padding-left: 5px; +} + +.social-icon img { + height: 20px; + width: 20px; +} diff --git a/scaladoc-js/resources/ux.css b/scaladoc-js/resources/ux.css new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/scaladoc-js/resources/versions-dropdown.css b/scaladoc-js/resources/versions-dropdown.css new file mode 100644 index 000000000000..94f0359b4108 --- /dev/null +++ b/scaladoc-js/resources/versions-dropdown.css @@ -0,0 +1,66 @@ +/* The container
- needed to position the dropdown content */ +.versions-dropdown { + position: relative; +} + +/* Dropdown Button */ +.dropdownbtn { + background-color: var(--leftbar-bg); + color: white; + padding: 4px 12px; + border: none; +} + +/* Dropdown button on hover & focus */ +.dropdownbtnactive:hover, .dropdownbtnactive:focus { + background-color: var(--leftbar-hover-bg); + cursor: pointer; +} + +/* The search field */ +#dropdown-input { + box-sizing: border-box; + background-image: url('searchicon.png'); + background-position: 14px 12px; + background-repeat: no-repeat; + font-size: 16px; + padding: 14px 20px 12px 45px; + border: none; + border-bottom: 1px solid #ddd; +} + + +/* The search field when it gets focus/clicked on */ +#dropdown-input:focus {outline: 3px solid #ddd;} + + +/* Dropdown Content (Hidden by Default) */ +.dropdown-content { + display: none; + position: absolute; + background-color: #f6f6f6; + min-width: 230px; + border: 1px solid #ddd; + z-index: 1; +} + +/* Links inside the dropdown */ +.dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; +} + +/* Change color of dropdown links on hover */ +.dropdown-content a:hover {background-color: #f1f1f1} + +/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ +.show { + display:block; +} + +/* Filtered entries in dropdown menu */ +.dropdown-content a.filtered { + display: none; +} diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index 4657d59b0673..4a9c6fadd91c 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -78,39 +78,7 @@ pre code, pre code.hljs { font-size: 1em; padding: 0; } -.snippet { - padding: 12px 8px 10px 12px; - background: var(--code-bg); - margin: 1em 0px; - border-radius: 2px; - box-shadow: 0 0 2px #888; -} -.snippet-error { - border-bottom: 2px dotted red; -} -.snippet-warn { - border-bottom: 2px dotted orange; -} -.snippet-info { - border-bottom: 2px dotted teal; -} -.snippet-debug { - border-bottom: 2px dotted pink; -} -.tooltip { - position: relative; -} -.tooltip:hover:after { - content: attr(label); - padding: 4px 8px; - color: white; - background-color:black; - position: absolute; - left: 0; - z-index:10; - box-shadow:0 0 3px #444; - opacity: 0.8; -} + pre, .symbol.monospace { font-weight: 500; font-size: 12px; @@ -506,13 +474,6 @@ footer { border-top: 1px solid var(--border-light); font-size: 14px; } -.theme-dark footer .social-icon { - /* "Poor man's dark mode" for images. - * This works great with black images, - * and just-okay with colored images. - */ - filter: invert(100%) hue-rotate(180deg); -} footer .padded-icon { padding-left: 0.5em; @@ -526,6 +487,12 @@ footer .mode { align-items: center; } +@media(max-height:640px) { + footer { + position: unset; + } +} + /* Theme Toggle */ .switch { /* The switch - the box around the slider */ @@ -851,16 +818,6 @@ footer .socials { margin-right: 8px; } -.social-icon { - padding-right: 5px; - padding-left: 5px; -} - -.social-icon img { - height: 20px; - width: 20px; -} - #generated-by { display: flex; align-items: center; @@ -957,77 +914,8 @@ footer .socials { } } -/* The container
- needed to position the dropdown content */ -.versions-dropdown { - position: relative; -} - /* Dropdown Button */ -.dropdownbtn { - background-color: var(--leftbar-bg); - color: white; - padding: 4px 12px; - border: none; -} -/* Dropdown button on hover & focus */ -.dropdownbtnactive:hover, .dropdownbtnactive:focus { - background-color: var(--leftbar-hover-bg); - cursor: pointer; -} - -/* The search field */ -#dropdown-input { - box-sizing: border-box; - background-image: url('searchicon.png'); - background-position: 14px 12px; - background-repeat: no-repeat; - font-size: 16px; - padding: 14px 20px 12px 45px; - border: none; - border-bottom: 1px solid #ddd; -} - -/* The search field when it gets focus/clicked on */ -#dropdown-input:focus {outline: 3px solid #ddd;} - - -/* Dropdown Content (Hidden by Default) */ -.dropdown-content { - display: none; - position: absolute; - background-color: #f6f6f6; - min-width: 230px; - border: 1px solid #ddd; - z-index: 1; -} - -/* Links inside the dropdown */ -.dropdown-content a { - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; -} - -/* Change color of dropdown links on hover */ -.dropdown-content a:hover {background-color: #f1f1f1} - -/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ -.show { - display:block; -} - -/* Filtered entries in dropdown menu */ -.dropdown-content a.filtered { - display: none; -} - -@media(max-height:640px) { - footer { - position: unset; - } -} /* Breadcrumbs */ @@ -1038,3 +926,5 @@ footer .socials { .breadcrumbs a:first-child { margin: 0 8px 0 0; } + + diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala index 8a4696ec38c0..26e715fc5b69 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala @@ -73,8 +73,11 @@ trait Resources(using ctx: DocContext) extends Locations, Writer: "styles/dotty-icons.css", "styles/diagram.css", "styles/filter-bar.css", - "styles/search-bar.css", - "styles/scaladoc-searchbar.css", + "styles/code-snippets.css", + "styles/searchbar.css", + "styles/social-links.css", + "styles/ux.css", + "styles/versions-dropdown.css", "hljs/highlight.pack.js", "hljs/LICENSE", "scripts/hljs-scala3.js",