diff options
Diffstat (limited to 'design/toolbar.html')
-rw-r--r-- | design/toolbar.html | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/design/toolbar.html b/design/toolbar.html new file mode 100644 index 0000000..34270f6 --- /dev/null +++ b/design/toolbar.html @@ -0,0 +1,201 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <title>Toolbar</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="mobile-web-app-capable" content="yes"> + <meta name="theme-color" content="#FFFFFF"> + <link rel="manifest" href="manifest.json"> + + <link rel="preconnect" href="https://fonts.gstatic.com"> + <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,700&display=swap"> + <style> + :root { + --bg-color: #FFF; + --page-bg-color: #EEE; + --text-color: rgba(0,0,0,.87); + --error-triple: 176, 0, 32; + --error-color: rgb(var(--error-triple)); + --icon-opacity-active: .87; + --icon-opacity-inactive: .6; + --icon-opacity-disabled: .38; + --icon-inactive-filter: brightness(0); + --icon-add-hover-filter: brightness(1); + --icon-menu-hover-filter: brightness(1); + --icon-search-hover-filter: brightness(1); + --icon-window-hover-filter: brightness(1); + --menu-button-hover-bg-color: #FBBC04; + --button-hover-bg-color: #FFF; + --button-hover-shadow: 0 2px 16px rgba(0,0,0,.1), 0 2px 4px rgba(0,0,0,.2); + --fab-bg: #FFF; + --fab-shadow: 0 2px 12px rgba(0,0,0,.15), 0 2px 6px rgba(0,0,0,.2); + --fab-shadow-hover: 0 4px 16px rgba(0,0,0,.2), 0 3px 6px rgba(0,0,0,.3); + --toolbar-shadow-mobile: 0 8px 8px 8px rgba(0,0,0,.2); + --toolbar-hide-distance-mobile: calc(-56px - 8px); + --toolbar-button-hover-bg-mobile: rgba(0,0,0,.1); + } + + @media (prefers-color-scheme: dark) { :root { + --bg-color: #000; + --page-bg-color: #000; + --text-color: rgba(255,255,255,.87); + --error-triple: 245, 0, 45; + --error-color: rgb(var(--error-triple)); + --icon-opacity-active: .87; + --icon-opacity-inactive: .6; + --icon-opacity-disabled: .38; + --icon-inactive-filter: brightness(0) invert(1) hue-rotate(180deg); + --icon-add-hover-filter: brightness(1.4) invert(.1) hue-rotate(0); + --icon-menu-hover-filter: brightness(1) invert(1) hue-rotate(180deg); + --icon-search-hover-filter: brightness(1) invert(1) hue-rotate(180deg); + --icon-window-hover-filter: brightness(.75) invert(1) hue-rotate(180deg); + --menu-button-hover-bg-color: #FBBC04; + --button-hover-bg-color: #181818; + --button-hover-shadow: 0 0 0 transparent; + --fab-bg: #333; + --fab-shadow: 0 2px 12px rgba(0,0,0,.2), 0 2px 6px rgba(0,0,0,.24); + --fab-shadow-hover: 0 2px 12px rgba(0,0,0,.2), 0 2px 6px rgba(0,0,0,.24); + --toolbar-shadow-mobile: 0 8px 8px 8px #000, 0 56px 56px -56px rgba(255,255,255,.25) inset; + --toolbar-hide-distance-mobile: calc(-56px - 8px); + --toolbar-button-hover-bg-mobile: rgba(255,255,255,.1); + }} + + * { box-sizing: border-box; margin: 0; padding: 0; font-family: "Roboto", sans-serif; transition-timing-function: cubic-bezier(.4,0,.2,1); } + html { background: var(--page-bg-color); color: var(--text-color); } + + #toolbar { position: fixed; font-size: 0; } + #toolbar > * { font-size: 16px; text-align: center; } + .toolbar-btn, .toolbar-fab { position: relative; border-radius: 100%; } + .toolbar-btn { height: 48px; width: 48px; } + + .toolbar-btn:not(#conflict-btn)::after, .toolbar-fab::after { content: ""; display: block; height: 24px; width: 24px; background-image: url("icons.svg"); filter: var(--icon-inactive-filter); opacity: var(--icon-opacity-active); position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); } + #menu-btn::after { background-position: 0 0; } + #window-btn::after { background-position: -24px 0; } + #search-btn::after { background-position: -48px 0; } + #add-btn::after { background-position: -72px 0; } + + #conflict-btn { display: none; vertical-align: bottom; } + #conflict-btn::after { content: ""; position: absolute; top: 50%; left: 50%; display: block; height: 8px; width: 8px; border-radius: 4px; background: rgba(var(--error-triple), .8); transform: translate(-50%,-50%); } + + @media (hover:hover) { + .toolbar-btn, .toolbar-fab { cursor: pointer; transition: background-color .2s, box-shadow .2s; } + .toolbar-btn:not(#conflict-btn)::after, .toolbar-fab::after { transition: opacity .1s, filter .1s; filter: var(--icon-inactive-filter); } + .toolbar-btn:not(#conflict-btn):hover::after, .toolbar-fab:hover::after { opacity: 1; } + + #menu-btn:hover::after { filter: var(--icon-menu-hover-filter); } + #window-btn:hover::after { filter: var(--icon-window-hover-filter); } + #search-btn:hover::after { filter: var(--icon-search-hover-filter); } + #add-btn:hover::after { filter: var(--icon-add-hover-filter); } + + #conflict-btn::after { transition: box-shadow .1s; } + #conflict-btn:hover::after { box-shadow: 0 0 0 4px rgba(var(--error-triple),.25); } + } + + @media (hover:hover) and (min-width:481px) { + body { padding: 0 80px 16px; } + #toolbar { top: 16px; left: 50%; transform: translate(-50%,0); width: 100%; max-width: calc(7in + 16px); pointer-events: none; } + #toolbar > * { pointer-events: auto; } + .toolbar-fab { height: 48px; width: 48px; } + .toolbar-btn, .toolbar-fab { display: block; margin: 0 16px; } + .toolbar-btn:not(#conflict-btn):hover, .toolbar-fab:hover { background-color: var(--button-hover-bg-color); box-shadow: var(--button-hover-shadow); } + .toolbar-btn:not(#conflict-btn)::after, .toolbar-fab::after { opacity: var(--icon-opacity-inactive) } + .toolbar-btn:not(#conflict-btn):hover::after, .toolbar-fab:hover::after { opacity: var(--icon-opacity-active) } + + #menu-btn:hover { background-color: var(--menu-button-hover-bg-color) !important; } + #search-btn { position: absolute; top: 0; right: 0; } + #add-btn { position: absolute; top: 48px; right: 0; } + #conflict-btn { height: 42px; } + #conflict-btn.show { display: block; } + } + + @media (hover:none), (max-width:480px) { + body { padding: 0 16px 16px; } + #toolbar { bottom: 0; left: 0; right: 0; width: 100%; box-shadow: var(--toolbar-shadow-mobile); padding: 0 4px; background: var(--bg-color); transition: bottom .25s; /* reentrance speed */ } + .toolbar-btn { display: inline-block; } + .toolbar-fab { position: absolute; display: block; right: 16px; top: -28px; width: 56px; height: 56px; box-shadow: var(--fab-shadow); background: var(--fab-bg); transition: top .25s; } + #conflict-btn { width: 36px; } + #conflict-btn.show { display: inline-block; } + + #toolbar.hide { bottom: var(--toolbar-hide-distance-mobile); transition: bottom .2s; /* exit speed */ } + #toolbar.hide .toolbar-fab { top: calc(var(--toolbar-hide-distance-mobile) - 16px); transition: top .2s; } + + @media (orientation:portrait) { + .toolbar-btn { margin: 4px 0; } + } + + @media (orientation:landscape) { + .toolbar-btn { margin: 0; } + } + } + + @media (hover:hover) and (max-width:480px) { + .toolbar-btn:not(#conflict-btn)::before { content: ""; display: block; position: absolute; top: 50%; left: 50%; height: 40px; width: 40px; border-radius: 20px; transform: translate(-50%,-50%); transition: background-color .2s; } + .toolbar-btn:not(#conflict-btn):hover::before { background-color: var(--toolbar-button-hover-bg-mobile); } + #menu-btn:hover::before { background-color: var(--menu-button-hover-bg-color) !important; } + .toolbar-fab { transition: top .25s, box-shadow .2s; } + #toolbar.hide .toolbar-fab { transition: top .2s, box-shadow .2s; } + .toolbar-fab:hover { box-shadow: var(--fab-shadow-hover); } + #add-btn::after { transition: opacity .15s, filter .15s, transform .2s; } + #add-btn:hover::after { filter: var(--icon-add-hover-filter); transform: translate(-50%,-50%) scale(1.25); } + } + + a { display: block; margin: 16px auto; padding: 24px; max-width: 5.5in; background-color: var(--bg-color); border-radius: 16px; box-shadow: 0 2px 16px rgba(0,0,0,.05), 0 2px 4px rgba(0,0,0,.1), 0 0 0 1px rgba(255,255,255,.2) inset; transition: box-shadow .2s; } + a:hover { box-shadow: 0 2px 16px rgba(0,0,0,.15), 0 2px 4px rgba(0,0,0,.15), 0 0 0 2px rgba(255,255,255,.25) inset; } + </style> + </head> + <body> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <a href="#">Hello!</a> + <div id="toolbar"> + <div class="toolbar-btn" id="menu-btn"></div> + <div class="toolbar-btn" id="window-btn"></div> + <div class="toolbar-btn" id="search-btn"></div> + <div class="toolbar-btn" id="conflict-btn"></div> + <div class="toolbar-fab" id="add-btn"></div> + </div> + <script> + function changeThemeColor(color) { + document.querySelector("meta[name=theme-color]") + .setAttribute("content", color); + } + + //changeThemeColor("#eee"); + + function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; + }; + + document.addEventListener("DOMContentLoaded", debounce(() => { + let prevScroll = 0; + window.addEventListener("scroll", function() { + if (this.scrollY && this.scrollY > prevScroll) { + document.querySelector("#toolbar").classList.add("hide"); + } else { + document.querySelector("#toolbar").classList.remove("hide"); + } + prevScroll = this.scrollY; + }); + }, 250, true)); + </script> + </body> +</html> |