From fec826b106031083550fd125bc0c0496a4185911 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 9 Dec 2020 11:47:23 +0000 Subject: [PATCH] (Almost the) rest of the redesign (#880) * Load demo img * two-up styles * Back button * Button size tweak * Move back btn * Move options and back button into a single grid * Simpler max height * Responsive grid * Feed index into options * Option heading themes * More option styles * Changing checkbox position * Theme range input & use transforms * Range input underline theme * Checkbox color * Add toggle * Reorder * Arrow revealer * Round two-up thumb * Don't bundle CSS urls starting # * Results in progress * Fix Safari bugs * Download blobs * Loading spinner * Hook up download button * Different style for original image * Mobile design for results * Remove demo auto-loader * Remove redundant colors * Sticky headings --- lib/css-plugin.js | 2 +- package-lock.json | 6 - package.json | 1 - .../Compress/Options/Checkbox/style.css | 2 +- .../Range/custom-els/RangeInput/index.ts | 32 +- .../Range/custom-els/RangeInput/style.css | 31 +- .../lazy-app/Compress/Options/Range/style.css | 1 + .../Compress/Options/Revealer/index.tsx | 21 + .../Compress/Options/Revealer/style.css | 29 ++ .../Compress/Options/Select/index.tsx | 7 +- .../Compress/Options/Select/style.css | 9 +- .../Compress/Options/Toggle/index.tsx | 22 + .../Compress/Options/Toggle/style.css | 55 +++ .../lazy-app/Compress/Options/index.tsx | 37 +- .../lazy-app/Compress/Options/style.css | 71 ++-- .../Compress/Output/custom-els/TwoUp/index.ts | 11 +- .../Output/custom-els/TwoUp/styles.css | 22 +- src/client/lazy-app/Compress/Output/index.tsx | 10 +- src/client/lazy-app/Compress/Output/style.css | 29 +- .../lazy-app/Compress/Results/FileSize.tsx | 43 -- .../lazy-app/Compress/Results/index.tsx | 147 +++---- .../lazy-app/Compress/Results/pretty-bytes.ts | 27 ++ .../lazy-app/Compress/Results/style.css | 388 ++++++++++++++---- .../Compress/custom-els/MultiPanel/styles.css | 2 +- src/client/lazy-app/Compress/index.tsx | 87 ++-- src/client/lazy-app/Compress/style.css | 93 ++++- src/client/lazy-app/icons/index.tsx | 52 +-- src/features/encoders/avif/client/index.tsx | 23 +- src/features/encoders/jxl/client/index.tsx | 16 +- .../encoders/mozJPEG/client/index.tsx | 39 +- src/features/encoders/webP/client/index.tsx | 35 +- src/features/encoders/wp2/client/index.tsx | 19 +- .../processors/resize/client/index.tsx | 12 +- src/shared/prerendered-app/Intro/index.tsx | 2 +- src/shared/prerendered-app/Intro/style.css | 2 +- src/shared/prerendered-app/colors.css | 15 +- 36 files changed, 903 insertions(+), 497 deletions(-) create mode 100644 src/client/lazy-app/Compress/Options/Revealer/index.tsx create mode 100644 src/client/lazy-app/Compress/Options/Revealer/style.css create mode 100644 src/client/lazy-app/Compress/Options/Toggle/index.tsx create mode 100644 src/client/lazy-app/Compress/Options/Toggle/style.css delete mode 100644 src/client/lazy-app/Compress/Results/FileSize.tsx create mode 100644 src/client/lazy-app/Compress/Results/pretty-bytes.ts diff --git a/lib/css-plugin.js b/lib/css-plugin.js index b97bc1f9..43e040b3 100644 --- a/lib/css-plugin.js +++ b/lib/css-plugin.js @@ -90,7 +90,7 @@ export default function (resolveFileUrl) { }), postCSSUrl({ url: ({ relativePath, url }) => { - if (/^(https?|data):/.test(url)) return url; + if (/^((https?|data):|#)/.test(url)) return url; const parsedPath = parsePath(relativePath); const source = readFileSync( resolvePath(dirname(path), relativePath), diff --git a/package-lock.json b/package-lock.json index 2ddde372..1a69b7ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6056,12 +6056,6 @@ "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", "dev": true }, - "pretty-bytes": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.4.1.tgz", - "integrity": "sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA==", - "dev": true - }, "pretty-format": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", diff --git a/package.json b/package.json index 44bc7fac..a42a91d5 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "preact": "^10.5.5", "preact-render-to-string": "^5.1.11", "prettier": "^2.1.2", - "pretty-bytes": "^5.4.1", "rollup": "^2.33.1", "rollup-plugin-terser": "^7.0.2", "serve": "^11.3.2", diff --git a/src/client/lazy-app/Compress/Options/Checkbox/style.css b/src/client/lazy-app/Compress/Options/Checkbox/style.css index c68bd895..46a6828d 100644 --- a/src/client/lazy-app/Compress/Options/Checkbox/style.css +++ b/src/client/lazy-app/Compress/Options/Checkbox/style.css @@ -18,5 +18,5 @@ } .checked { - fill: #34b9eb; + fill: var(--main-theme-color); } diff --git a/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/index.ts b/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/index.ts index 49b8c58b..2a41f13b 100644 --- a/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/index.ts +++ b/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/index.ts @@ -1,4 +1,3 @@ -import PointerTracker from 'pointer-tracker'; import * as style from './style.css'; import 'add-css:./style.css'; @@ -28,7 +27,7 @@ function getPrescision(value: string): number { class RangeInputElement extends HTMLElement { private _input: HTMLInputElement; - private _valueDisplay?: HTMLDivElement; + private _valueDisplay?: HTMLSpanElement; private _ignoreChange = false; static get observedAttributes() { @@ -41,15 +40,22 @@ class RangeInputElement extends HTMLElement { this._input.type = 'range'; this._input.className = style.input; - const tracker = new PointerTracker(this._input, { - start: (): boolean => { - if (tracker.currentPointers.length !== 0) return false; - this._input.classList.add(style.touchActive); - return true; - }, - end: () => { + let activePointer: number | undefined; + + // Not using pointer-tracker here due to https://bugs.webkit.org/show_bug.cgi?id=219636. + this.addEventListener('pointerdown', (event) => { + if (activePointer) return; + activePointer = event.pointerId; + this._input.classList.add(style.touchActive); + const pointerUp = (event: PointerEvent) => { + if (event.pointerId !== activePointer) return; + activePointer = undefined; this._input.classList.remove(style.touchActive); - }, + window.removeEventListener('pointerup', pointerUp); + window.removeEventListener('pointercancel', pointerUp); + }; + window.addEventListener('pointerup', pointerUp); + window.addEventListener('pointercancel', pointerUp); }); for (const event of RETARGETED_EVENTS) { @@ -66,13 +72,13 @@ class RangeInputElement extends HTMLElement { this.innerHTML = `
` + `
` + - `
` + + `
` + '
'; this.insertBefore(this._input, this.firstChild); this._valueDisplay = this.querySelector( - '.' + style.valueDisplay, - ) as HTMLDivElement; + '.' + style.valueDisplay + ' > span', + ) as HTMLSpanElement; // Set inline styles (this is useful when used with frameworks which might clear inline styles) this._update(); } diff --git a/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/style.css b/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/style.css index 0b18ea33..c65acb8a 100644 --- a/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/style.css +++ b/src/client/lazy-app/Compress/Options/Range/custom-els/RangeInput/style.css @@ -23,10 +23,8 @@ range-input::before { width: 100%; height: 2px; border-radius: 1px; - box-shadow: 0 -0.5px 0 rgba(0, 0, 0, 0.3), - inset 0 0.5px 0 rgba(255, 255, 255, 0.2), 0 0.5px 0 rgba(255, 255, 255, 0.3); - background: linear-gradient(#34b9eb, #218ab1) 0 / var(--value-percent, 0%) - 100% no-repeat #eee; + background: linear-gradient(var(--main-theme-color), var(--main-theme-color)) + 0 / var(--value-percent, 0%) 100% no-repeat var(--medium-light-gray); } .input { @@ -41,14 +39,12 @@ range-input::before { pointer-events: none; position: absolute; bottom: 3px; - left: var(--value-percent, 0%); + left: 0; margin-left: -6px; - background: url('data:image/svg+xml,') - center no-repeat #34b9eb; + background: var(--main-theme-color); border-radius: 50%; width: 12px; height: 12px; - box-shadow: 0 0.5px 2px rgba(0, 0, 0, 0.3); } .thumb-wrapper { @@ -58,21 +54,19 @@ range-input::before { bottom: 0; height: 0; overflow: visible; + transform: translate(var(--value-percent, 0%), 0); } .value-display { - background: url('data:image/svg+xml,') - top center no-repeat; position: absolute; box-sizing: border-box; - left: var(--value-percent, 0%); + left: 0; bottom: 3px; width: 32px; height: 62px; text-align: center; padding: 8px 3px 0; margin: 0 0 0 -16px; - filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3)); transform-origin: 50% 90%; opacity: 0.0001; transform: scale(0.2); @@ -86,6 +80,19 @@ range-input::before { will-change: transform; pointer-events: none; overflow: hidden; + + > svg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + fill: var(--main-theme-color); + } + + > span { + position: relative; + } } .touch-active + .thumb-wrapper .value-display { diff --git a/src/client/lazy-app/Compress/Options/Range/style.css b/src/client/lazy-app/Compress/Options/Range/style.css index b8ed2b69..e1bb92a6 100644 --- a/src/client/lazy-app/Compress/Options/Range/style.css +++ b/src/client/lazy-app/Compress/Options/Range/style.css @@ -33,6 +33,7 @@ box-sizing: border-box; text-decoration: underline; text-decoration-style: dotted; + text-decoration-color: var(--main-theme-color); text-underline-position: under; width: 48px; position: relative; diff --git a/src/client/lazy-app/Compress/Options/Revealer/index.tsx b/src/client/lazy-app/Compress/Options/Revealer/index.tsx new file mode 100644 index 00000000..a28dd5fb --- /dev/null +++ b/src/client/lazy-app/Compress/Options/Revealer/index.tsx @@ -0,0 +1,21 @@ +import { h, Component } from 'preact'; +import * as style from './style.css'; +import 'add-css:./style.css'; +import { Arrow } from '../../../icons'; + +interface Props extends preact.JSX.HTMLAttributes {} +interface State {} + +export default class Revealer extends Component { + render(props: Props) { + return ( +
+ {/* @ts-ignore - TS bug https://github.com/microsoft/TypeScript/issues/16019 */} + +
+ +
+
+ ); + } +} diff --git a/src/client/lazy-app/Compress/Options/Revealer/style.css b/src/client/lazy-app/Compress/Options/Revealer/style.css new file mode 100644 index 00000000..a1c250bd --- /dev/null +++ b/src/client/lazy-app/Compress/Options/Revealer/style.css @@ -0,0 +1,29 @@ +.checkbox { + display: inline-block; + position: relative; +} + +.arrow { + width: 10px; + height: 10px; + fill: var(--white); + transition: transform 200ms ease; + transform: rotate(-90deg); + + svg { + width: 100%; + height: 100%; + display: block; + } +} + +.real-checkbox { + top: 0; + position: absolute; + opacity: 0; + pointer-events: none; + + &:checked + .arrow { + transform: none; + } +} diff --git a/src/client/lazy-app/Compress/Options/Select/index.tsx b/src/client/lazy-app/Compress/Options/Select/index.tsx index d6cbb6d0..44f9936b 100644 --- a/src/client/lazy-app/Compress/Options/Select/index.tsx +++ b/src/client/lazy-app/Compress/Options/Select/index.tsx @@ -1,6 +1,7 @@ import { h, Component } from 'preact'; import * as style from './style.css'; import 'add-css:./style.css'; +import { Arrow } from 'client/lazy-app/icons'; interface Props extends preact.JSX.HTMLAttributes { large?: boolean; @@ -18,9 +19,9 @@ export default class Select extends Component { class={`${style.builtinSelect} ${large ? style.large : ''}`} {...otherProps} /> - - - +
+ +
); } diff --git a/src/client/lazy-app/Compress/Options/Select/style.css b/src/client/lazy-app/Compress/Options/Select/style.css index 82f21a02..fc6514b1 100644 --- a/src/client/lazy-app/Compress/Options/Select/style.css +++ b/src/client/lazy-app/Compress/Options/Select/style.css @@ -3,10 +3,12 @@ } .builtin-select { - background: #2f2f2f; + background: var(--black); border-radius: 4px; font: inherit; - padding: 4px 25px 4px 10px; + padding: 7px 0; + padding-right: 25px; + padding-left: 10px; -webkit-appearance: none; -moz-appearance: none; border: none; @@ -21,11 +23,12 @@ transform: translateY(-50%); fill: #fff; width: 10px; + pointer-events: none; } .large { padding: 10px 35px 10px 10px; - background: #151515; + background: var(--dark-gray); & .arrow { right: 13px; diff --git a/src/client/lazy-app/Compress/Options/Toggle/index.tsx b/src/client/lazy-app/Compress/Options/Toggle/index.tsx new file mode 100644 index 00000000..48411cb6 --- /dev/null +++ b/src/client/lazy-app/Compress/Options/Toggle/index.tsx @@ -0,0 +1,22 @@ +import { h, Component } from 'preact'; +import * as style from './style.css'; +import 'add-css:./style.css'; + +interface Props extends preact.JSX.HTMLAttributes {} +interface State {} + +export default class Toggle extends Component { + render(props: Props) { + return ( +
+ {/* @ts-ignore - TS bug https://github.com/microsoft/TypeScript/issues/16019 */} + +
+
+
+
+
+
+ ); + } +} diff --git a/src/client/lazy-app/Compress/Options/Toggle/style.css b/src/client/lazy-app/Compress/Options/Toggle/style.css new file mode 100644 index 00000000..c3b1a356 --- /dev/null +++ b/src/client/lazy-app/Compress/Options/Toggle/style.css @@ -0,0 +1,55 @@ +.checkbox { + display: inline-block; + position: relative; +} + +.track { + --thumb-size: 14px; + background: var(--black); + border-radius: 1000px; + width: 24px; + padding: 3px calc(var(--thumb-size) / 2 + 3px); +} + +.thumb { + position: relative; + width: var(--thumb-size); + height: var(--thumb-size); + background: var(--less-light-gray); + border-radius: 100%; + transform: translateX(calc(var(--thumb-size) / -2)); + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--main-theme-color); + opacity: 0; + transition: opacity 200ms ease; + } +} + +.thumb-track { + transition: transform 200ms ease; +} + +.real-checkbox { + top: 0; + position: absolute; + opacity: 0; + pointer-events: none; + + &:checked + .track { + .thumb-track { + transform: translateX(100%); + } + + .thumb::before { + opacity: 1; + } + } +} diff --git a/src/client/lazy-app/Compress/Options/index.tsx b/src/client/lazy-app/Compress/Options/index.tsx index ede3b056..5208775d 100644 --- a/src/client/lazy-app/Compress/Options/index.tsx +++ b/src/client/lazy-app/Compress/Options/index.tsx @@ -14,18 +14,20 @@ import { } from '../../feature-meta'; import Expander from './Expander'; import Checkbox from './Checkbox'; +import Toggle from './Toggle'; import Select from './Select'; import { Options as QuantOptionsComponent } from 'features/processors/quantize/client'; import { Options as ResizeOptionsComponent } from 'features/processors/resize/client'; interface Props { + index: 0 | 1; mobileView: boolean; source?: SourceImage; encoderState?: EncoderState; processorState: ProcessorState; - onEncoderTypeChange(newType: OutputType): void; - onEncoderOptionsChange(newOptions: EncoderOptions): void; - onProcessorOptionsChange(newOptions: ProcessorState): void; + onEncoderTypeChange(index: 0 | 1, newType: OutputType): void; + onEncoderOptionsChange(index: 0 | 1, newOptions: EncoderOptions): void; + onProcessorOptionsChange(index: 0 | 1, newOptions: ProcessorState): void; } interface State { @@ -73,7 +75,7 @@ export default class Options extends Component { // The select element only has values matching encoder types, // so 'as' is safe here. const type = el.value as OutputType; - this.props.onEncoderTypeChange(type); + this.props.onEncoderTypeChange(this.props.index, type); }; private onProcessorEnabledChange = (event: Event) => { @@ -81,24 +83,31 @@ export default class Options extends Component { const processor = el.name.split('.')[0] as keyof ProcessorState; this.props.onProcessorOptionsChange( + this.props.index, cleanSet(this.props.processorState, `${processor}.enabled`, el.checked), ); }; private onQuantizerOptionsChange = (opts: ProcessorOptions['quantize']) => { this.props.onProcessorOptionsChange( + this.props.index, cleanMerge(this.props.processorState, 'quantize', opts), ); }; private onResizeOptionsChange = (opts: ProcessorOptions['resize']) => { this.props.onProcessorOptionsChange( + this.props.index, cleanMerge(this.props.processorState, 'resize', opts), ); }; + private onEncoderOptionsChange = (newOptions: EncoderOptions) => { + this.props.onEncoderOptionsChange(this.props.index, newOptions); + }; + render( - { source, encoderState, processorState, onEncoderOptionsChange }: Props, + { source, encoderState, processorState }: Props, { supportedEncoderMap }: State, ) { const encoder = encoderState && encoderMap[encoderState.type]; @@ -106,18 +115,24 @@ export default class Options extends Component { encoder && 'Options' in encoder ? encoder.Options : undefined; return ( -
+
{!encoderState ? null : (

Edit

{processorState.resize.enabled ? ( @@ -132,12 +147,12 @@ export default class Options extends Component { {processorState.quantize.enabled ? ( @@ -180,7 +195,7 @@ export default class Options extends Component { // the correct type, but typescript isn't smart enough. encoderState!.options as any } - onChange={onEncoderOptionsChange} + onChange={this.onEncoderOptionsChange} /> )} diff --git a/src/client/lazy-app/Compress/Options/style.css b/src/client/lazy-app/Compress/Options/style.css index ac0efca4..7f1d1590 100644 --- a/src/client/lazy-app/Compress/Options/style.css +++ b/src/client/lazy-app/Compress/Options/style.css @@ -1,58 +1,83 @@ .options-scroller { - overflow-x: hidden; - overflow-y: auto; - -webkit-overflow-scrolling: touch; --horizontal-padding: 15px; + border-radius: var(--scroller-radius); + + /* At smaller widths, the multi-panel handles the scrolling */ + @media (min-width: 600px) { + overflow-x: hidden; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + } } .options-title { - background: rgba(0, 0, 0, 0.9); + background-color: var(--main-theme-color); + color: var(--header-text-color); margin: 0; padding: 10px var(--horizontal-padding); - font-weight: normal; + font-weight: bold; font-size: 1.4rem; - border-bottom: 1px solid #000; + border-bottom: 1px solid var(--off-black); + transition: all 300ms ease-in-out; + transition-property: background-color, color; + + position: sticky; + top: 0; + z-index: 1; +} + +.original-image .options-title { + background-color: var(--black); + color: var(--white); } .option-text-first { display: grid; align-items: center; grid-template-columns: 87px 1fr; - grid-gap: 0.7em; + gap: 0.7em; padding: 10px var(--horizontal-padding); } +.option-toggle { + cursor: pointer; + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + gap: 0.7em; + padding: 10px var(--horizontal-padding); +} + +.option-reveal { + composes: option-toggle; + grid-template-columns: auto 1fr; + gap: 1em; +} + .option-one-cell { display: grid; grid-template-columns: 1fr; padding: 10px var(--horizontal-padding); } -.option-input-first, .section-enabler { - cursor: pointer; - display: grid; - align-items: center; - grid-template-columns: auto 1fr; - grid-gap: 0.7em; - padding: 10px var(--horizontal-padding); -} - -.section-enabler { - background: rgba(0, 0, 0, 0.8); + composes: option-toggle; + background: var(--dark-gray); + padding: 15px var(--horizontal-padding); + border-bottom: 1px solid var(--off-black); } .options-section { - background: rgba(0, 0, 0, 0.7); + background: var(--off-black); } .text-field { - background: #fff; - color: #000; + background: var(--white); + color: var(--black); font: inherit; border: none; - padding: 2px 0 2px 10px; + padding: 6px 0 6px 10px; width: 100%; box-sizing: border-box; - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5); + border-radius: 4px; } diff --git a/src/client/lazy-app/Compress/Output/custom-els/TwoUp/index.ts b/src/client/lazy-app/Compress/Output/custom-els/TwoUp/index.ts index e003be25..35b51831 100644 --- a/src/client/lazy-app/Compress/Output/custom-els/TwoUp/index.ts +++ b/src/client/lazy-app/Compress/Output/custom-els/TwoUp/index.ts @@ -73,9 +73,14 @@ export default class TwoUp extends HTMLElement { connectedCallback() { this._childrenChange(); - this._handle.innerHTML = `
${`${''}`}
`; + // prettier-ignore + this._handle.innerHTML = + `
${ + `${ + `` + + `` + } + `}
`; if (!this._everConnected) { this._resetPosition(); diff --git a/src/client/lazy-app/Compress/Output/custom-els/TwoUp/styles.css b/src/client/lazy-app/Compress/Output/custom-els/TwoUp/styles.css index a823c7e0..ac853377 100644 --- a/src/client/lazy-app/Compress/Output/custom-els/TwoUp/styles.css +++ b/src/client/lazy-app/Compress/Output/custom-els/TwoUp/styles.css @@ -2,12 +2,11 @@ two-up { display: grid; position: relative; --split-point: 0; - --accent-color: #777; - --track-color: var(--accent-color); - --thumb-background: #fff; + --track-color: rgb(0 0 0 / 0.6); + --thumb-background: var(--black); --thumb-color: var(--accent-color); --thumb-size: 62px; - --bar-size: 6px; + --bar-size: 9px; --bar-touch-size: 30px; } @@ -37,8 +36,6 @@ two-up[legacy-clip-compat] > :not(.two-up-handle) { height: 100%; width: var(--bar-size); margin: 0 auto; - box-shadow: inset calc(var(--bar-size) / 2) 0 0 rgba(0, 0, 0, 0.1), - 0 1px 4px rgba(0, 0, 0, 0.4); background: var(--track-color); } @@ -47,14 +44,11 @@ two-up[legacy-clip-compat] > :not(.two-up-handle) { position: absolute; top: 50%; left: 50%; - transform-origin: 50% 50%; transform: translate(-50%, -50%); width: var(--thumb-size); - height: calc(var(--thumb-size) * 0.9); + height: var(--thumb-size); background: var(--thumb-background); - border: 1px solid rgba(0, 0, 0, 0.2); border-radius: var(--thumb-size); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); color: var(--thumb-color); box-sizing: border-box; padding: 0 calc(var(--thumb-size) * 0.24); @@ -64,6 +58,14 @@ two-up[legacy-clip-compat] > :not(.two-up-handle) { flex: 1; } +.arrow-left { + fill: var(--pink); +} + +.arrow-right { + fill: var(--blue); +} + two-up[orientation='vertical'] .two-up-handle { width: auto; height: var(--bar-touch-size); diff --git a/src/client/lazy-app/Compress/Output/index.tsx b/src/client/lazy-app/Compress/Output/index.tsx index c459c2b3..562445c3 100644 --- a/src/client/lazy-app/Compress/Output/index.tsx +++ b/src/client/lazy-app/Compress/Output/index.tsx @@ -10,7 +10,6 @@ import { ToggleBackgroundIcon, AddIcon, RemoveIcon, - BackIcon, ToggleBackgroundActiveIcon, RotateIcon, } from '../../icons'; @@ -28,7 +27,6 @@ interface Props { rightCompressed?: ImageData; leftImgContain: boolean; rightImgContain: boolean; - onBack: () => void; onPreprocessorChange: (newState: PreprocessorState) => void; } @@ -255,7 +253,7 @@ export default class Output extends Component { }; render( - { mobileView, leftImgContain, rightImgContain, source, onBack }: Props, + { mobileView, leftImgContain, rightImgContain, source }: Props, { scale, editingScale, altBackground }: State, ) { const leftDraw = this.leftDrawable(); @@ -314,12 +312,6 @@ export default class Output extends Component { -
- -
-
+ - - - -
- {downloadUrl && imageFile && ( - - - - )} - {showLoadingState && } -
+ + Download + + + +
+ +
+ {showLoadingState && } +
); } diff --git a/src/client/lazy-app/Compress/Results/pretty-bytes.ts b/src/client/lazy-app/Compress/Results/pretty-bytes.ts new file mode 100644 index 00000000..acdec300 --- /dev/null +++ b/src/client/lazy-app/Compress/Results/pretty-bytes.ts @@ -0,0 +1,27 @@ +// Based on https://www.npmjs.com/package/pretty-bytes +// Modified so the units are returned separately. + +const UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + +interface PrettyBytesResult { + value: string; + unit: string; +} + +export default function prettyBytes(number: number): PrettyBytesResult { + const isNegative = number < 0; + const prefix = isNegative ? '-' : ''; + + if (isNegative) number = -number; + if (number < 1) return { value: prefix + number, unit: UNITS[0] }; + + const exponent = Math.min( + Math.floor(Math.log10(number) / 3), + UNITS.length - 1, + ); + + return { + unit: UNITS[exponent], + value: prefix + (number / Math.pow(1000, exponent)).toPrecision(3), + }; +} diff --git a/src/client/lazy-app/Compress/Results/style.css b/src/client/lazy-app/Compress/Results/style.css index 8d56f36f..82971b31 100644 --- a/src/client/lazy-app/Compress/Results/style.css +++ b/src/client/lazy-app/Compress/Results/style.css @@ -1,3 +1,12 @@ +@font-face { + font-family: 'Roboto Mono Numbers'; + font-style: normal; + font-weight: 700; + /* Just 0132456789. https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@700&text=0123456789 */ + src: url('data:font/woff;base64,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') + format('woff'); +} + @keyframes action-enter { from { transform: rotate(-90deg); @@ -15,117 +24,336 @@ } .results { + --download-overflow-size: 9px; + background: rgba(0, 0, 0, 0.67); + border-radius: 5px; display: grid; - grid-template-columns: [text] 1fr [copy-button] auto [download-button] auto; - background: rgba(0, 0, 0, 0.9); - font-size: 1rem; - - @media (min-width: 400px) { - font-size: 1.2rem; - } + grid-template-columns: max-content [bubble] 1fr [download] max-content; @media (min-width: 600px) { - font-size: 1.4rem; - } - - &:focus { - outline: none; + --download-overflow-size: 30px; + background: none; + border-radius: none; + grid-template-columns: [download] auto [bubble] 1fr; + align-items: center; + margin-bottom: calc(var(--download-overflow-size) / 2); } } -.result-data { +.expand-arrow { + fill: var(--white); + transform: rotate(180deg); + margin: 0 1rem; + align-self: center; + + @media (min-width: 600px) { + display: none; + } + + :focus & { + fill: var(--main-theme-color); + } + + [content-expanded] & { + transform: none; + } + + svg { + display: block; + --size: 15px; + width: var(--size); + height: var(--size); + } +} + +.file-size { +} + +.bubble { + align-self: center; + + @media (min-width: 600px) { + position: relative; + width: max-content; + grid-row: 1; + grid-column: bubble; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-image-source: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='186.5' height='280.3' viewBox='0 0 186.5 280.3'%3E%3Cpath fill='rgba(30,31,29,0.69)' d='M181.5 0H16.4a5 5 0 00-5 5v134L0 146.5h11.4v128.8a5 5 0 005 5h165.1a5 5 0 005-5V5a5 5 0 00-5-5z'/%3E%3Cpath fill='rgba(0,0,0,0.23)' d='M16.4 1a4 4 0 00-4 4v134.5l-.5.3-8.6 5.7h9v129.8a4 4 0 004 4h165.2a4 4 0 004-4V5a4 4 0 00-4-4H16.4m0-1h165.1a5 5 0 015 5v270.3a5 5 0 01-5 5H16.4a5 5 0 01-5-5V146.5H0l11.4-7.5V5a5 5 0 015-5z'/%3E%3C/svg%3E"); + border-image-slice: 12 12 12 17 fill; + border-image-width: 12px 12px 12px 17px; + border-image-repeat: repeat; + } + } +} + +.bubble-inner { + display: grid; + grid-template-columns: [size-info] 1fr [percent-info] auto; + + @media (min-width: 600px) { + position: relative; + --main-padding: 1px; + --speech-padding: 2.1rem; + padding: var(--main-padding) var(--main-padding) var(--main-padding) + var(--speech-padding); + gap: 0.9rem; + } +} + +.unit { + color: var(--main-theme-color); +} + +.type-label { + @media (min-width: 600px) { + display: none; + } +} + +.size-info { + background: var(--dark-gray); + border-radius: 19px; + align-self: center; + justify-self: start; + grid-column: size-info; grid-row: 1; - grid-column: text; - display: flex; - align-items: center; - padding: 0 10px; - white-space: nowrap; - overflow: hidden; -} + justify-self: start; + padding: 0.6rem 1.2rem; + margin: 0.4rem 0; -.download-right { - grid-template-columns: [copy-button] auto [text] 1fr [download-button] auto; -} - -.download-left { - grid-template-columns: [download-button] auto [text] 1fr [copy-button] auto; -} - -.stack-right { - & .result-data { - padding: 0 15px; + @media (min-width: 600px) { + border-radius: none; + background: none; + padding: 0; + margin: 0; } } -.result-title { - display: flex; - align-items: center; - margin-right: 0.4em; +.percent-info { + align-self: center; + margin-left: 1rem; + margin-right: 0.3rem; + + @media (min-width: 600px) { + margin: 0; + display: grid; + --arrow-width: 16px; + grid-template-columns: [arrow] var(--arrow-width) [data] auto; + grid-column: percent-info; + grid-row: 1; + --shadow-direction: -1px; + filter: drop-shadow(var(--shadow-direction) 0 0 rgba(0, 0, 0, 0.67)); + } } -.size-delta { - font-size: 0.8em; - font-style: italic; +.big-arrow { + display: none; + + @media (min-width: 600px) { + display: block; + width: 100%; + fill: var(--main-theme-color); + grid-column: arrow; + grid-row: 1; + align-self: stretch; + } +} + +.percent-output { + grid-column: data; + grid-row: 1; + display: grid; + grid-template-columns: auto auto auto; + line-height: 1; + + @media (min-width: 600px) { + background: var(--main-theme-color); + --radius: 4px; + border-radius: 0 var(--radius) var(--radius) 0; + --padding-arrow-side: 0.6rem; + --padding-other-side: 1.1rem; + padding: 0.7rem var(--padding-other-side); + padding-left: var(--padding-arrow-side); + } +} + +.size-direction { + font-weight: 700; + align-self: center; + font-family: sans-serif; + opacity: 0.76; + text-shadow: 0 2px rgba(0, 0, 0, 0.3); + font-size: 1.5rem; position: relative; - top: -1px; - margin-left: 0.3em; + top: 3px; } -.size-increase { - color: #e35050; +.size-value { + font-family: 'Roboto Mono Numbers'; + font-size: 2.6rem; + text-shadow: 0 2px rgba(0, 0, 0, 0.3); } -.size-decrease { - color: #50e3c2; +.percent-char { + align-self: start; + position: relative; + top: 4px; + opacity: 0.76; + margin-left: 0.2rem; } .download { + --size: 59px; + width: calc(var(--size) + var(--download-overflow-size)); + height: calc(var(--size) + var(--download-overflow-size)); + position: relative; grid-row: 1; - grid-column: download-button; - background: #34b9eb; - --size: 38px; - width: var(--size); - height: var(--size); + grid-column: download; + margin: calc(var(--download-overflow-size) / -2) 0; + margin-right: calc(var(--download-overflow-size) / -3); display: grid; align-items: center; justify-items: center; + align-self: center; + + @media (min-width: 600px) { + --size: 63px; + } + + loading-spinner { + grid-area: 1 / 1; + position: relative; + --color: var(--white); + --size: 21px; + top: 0px; + left: 1px; + + @media (min-width: 600px) { + top: -1px; + left: 2px; + --size: 28px; + } + } } -.download-link { - animation: action-enter 0.2s; - grid-area: 1/1; +.download-blobs { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + path { + fill: var(--hot-theme-color); + opacity: 0.7; + } } -.download-link-disable { - pointer-events: none; - opacity: 0; - transform: rotate(90deg); - animation: action-leave 0.2s; +.download-icon { + grid-area: 1 / 1; + + svg { + --size: 19px; + width: var(--size); + height: var(--size); + fill: var(--white); + position: relative; + top: 3px; + left: 1px; + animation: action-enter 0.2s; + + @media (min-width: 600px) { + --size: 27px; + top: 2px; + left: 2px; + } + } } -.download-icon, -.copy-icon { - color: #fff; - display: block; - --size: 24px; - width: var(--size); - height: var(--size); - padding: 7px; - filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.7)); -} - -.spinner { - --color: #fff; - --delay: 0; - --size: 22px; - grid-area: 1/1; -} - -.copy-to-other { - grid-row: 1; - grid-column: copy-button; - composes: unbutton from global; +.download-disable { composes: download; - background: #656565; + pointer-events: none; + + .download-icon svg { + opacity: 0; + transform: rotate(90deg); + animation: action-leave 0.2s; + } +} + +.results-left { + composes: results; +} + +.results-right { + composes: results; + + @media (min-width: 600px) { + grid-template-columns: [bubble] 1fr [download] auto; + } + + .bubble { + @media (min-width: 600px) { + justify-self: end; + + &::before { + transform: scaleX(-1); + } + } + } + + .download { + margin-left: calc(var(--download-overflow-size) / -3); + margin-right: 0; + } + + .bubble-inner { + @media (min-width: 600px) { + padding: var(--main-padding) var(--speech-padding) var(--main-padding) + var(--main-padding); + grid-template-columns: [percent-info] auto [size-info] 1fr; + } + } + + .percent-info { + @media (min-width: 600px) { + grid-template-columns: [data] auto [arrow] var(--arrow-width); + --shadow-direction: 1px; + } + } + + .percent-output { + @media (min-width: 600px) { + border-radius: var(--radius) 0 0 var(--radius); + padding-left: var(--padding-other-side); + padding-right: var(--padding-arrow-side); + } + } + + .big-arrow { + transform: scaleX(-1); + } +} + +.is-original { + .big-arrow { + fill: transparent; + } + .percent-output { + background: none; + } + .download-blobs path { + fill: var(--black); + } + .unit { + color: var(--white); + opacity: 0.76; + } } diff --git a/src/client/lazy-app/Compress/custom-els/MultiPanel/styles.css b/src/client/lazy-app/Compress/custom-els/MultiPanel/styles.css index 0efe86ce..641839de 100644 --- a/src/client/lazy-app/Compress/custom-els/MultiPanel/styles.css +++ b/src/client/lazy-app/Compress/custom-els/MultiPanel/styles.css @@ -1,6 +1,6 @@ .panel-heading { - background: gray; } + .panel-content { height: 0px; overflow: auto; diff --git a/src/client/lazy-app/Compress/index.tsx b/src/client/lazy-app/Compress/index.tsx index 0b56d8fb..d97f5fde 100644 --- a/src/client/lazy-app/Compress/index.tsx +++ b/src/client/lazy-app/Compress/index.tsx @@ -31,7 +31,7 @@ import Results from './Results'; import WorkerBridge from '../worker-bridge'; import { resize } from 'features/processors/resize/client'; import type SnackBarElement from 'shared/custom-els/snack-bar'; -import { CopyAcrossIconProps, ExpandIcon } from '../icons'; +import { Arrow, ExpandIcon } from '../icons'; export type OutputType = EncoderType | 'identity'; @@ -319,7 +319,7 @@ export default class Compress extends Component { this.setState({ mobileView: this.widthQuery.matches }); }; - private onEncoderTypeChange(index: 0 | 1, newType: OutputType): void { + private onEncoderTypeChange = (index: 0 | 1, newType: OutputType): void => { this.setState({ sides: cleanSet( this.state.sides, @@ -332,12 +332,12 @@ export default class Compress extends Component { }, ), }); - } + }; - private onProcessorOptionsChange( + private onProcessorOptionsChange = ( index: 0 | 1, options: ProcessorState, - ): void { + ): void => { this.setState({ sides: cleanSet( this.state.sides, @@ -345,9 +345,12 @@ export default class Compress extends Component { options, ), }); - } + }; - private onEncoderOptionsChange(index: 0 | 1, options: EncoderOptions): void { + private onEncoderOptionsChange = ( + index: 0 | 1, + options: EncoderOptions, + ): void => { this.setState({ sides: cleanSet( this.state.sides, @@ -355,7 +358,7 @@ export default class Compress extends Component { options, ), }); - } + }; componentWillReceiveProps(nextProps: Props): void { if (nextProps.file !== this.props.file) { @@ -794,50 +797,30 @@ export default class Compress extends Component { const options = sides.map((side, index) => ( )); - const copyDirections = (mobileView - ? ['down', 'up'] - : ['right', 'left']) as CopyAcrossIconProps['copyDirection'][]; - const results = sides.map((side, index) => ( - {!mobileView - ? null - : [ - , - `${resultTitles[index]} (${ - side.latestSettings.encoderState - ? encoderMap[side.latestSettings.encoderState.type].meta.label - : 'Original Image' - })`, - ]} - + flipSide={mobileView || index === 1} + typeLabel={ + side.latestSettings.encoderState + ? encoderMap[side.latestSettings.encoderState.type].meta.label + : 'Original Image' + } + /> )); // For rendering, we ideally want the settings that were used to create the @@ -862,26 +845,38 @@ export default class Compress extends Component { rightCompressed={rightImageData} leftImgContain={leftImgContain} rightImgContain={rightImgContain} - onBack={onBack} preprocessorState={preprocessorState} onPreprocessorChange={this.onPreprocessorChange} /> + {mobileView ? (
- {results[0]} - {options[0]} - {results[1]} - {options[1]} +
{results[0]}
+
{options[0]}
+
{results[1]}
+
{options[1]}
) : ( [ -
+
{options[0]} {results[0]}
, -
+
{options[1]} {results[1]}
, diff --git a/src/client/lazy-app/Compress/style.css b/src/client/lazy-app/Compress/style.css index 545a91eb..b40d6fff 100644 --- a/src/client/lazy-app/Compress/style.css +++ b/src/client/lazy-app/Compress/style.css @@ -3,39 +3,77 @@ height: 100%; contain: strict; display: grid; - align-items: end; - align-content: end; - grid-template-rows: 1fr auto; + grid-template-rows: max-content 1fr; + grid-template-areas: + 'header' + 'opts'; + + --options-radius: 7px; @media (min-width: 600px) { - grid-template-columns: 1fr auto; - grid-template-rows: 100%; + grid-template-rows: max-content 1fr; + grid-template-columns: max-content 1fr max-content; + grid-template-areas: + 'header header header' + 'optsLeft viewportOpts optsRight'; } } .options { + position: relative; color: #fff; - opacity: 0.9; font-size: 1.2rem; - display: flex; - flex-flow: column; max-width: 400px; margin: 0 auto; width: calc(100% - 60px); - max-height: calc(100% - 104px); + max-height: 100%; overflow: hidden; + grid-area: opts; + display: grid; + grid-template-rows: 1fr max-content; + align-content: end; + align-self: end; @media (min-width: 600px) { - max-height: calc(100% - 75px); width: 300px; margin: 0; } +} - @media (min-width: 860px) { - max-height: calc(100% - 40px); +.options-1-theme { + --main-theme-color: var(--pink); + --hot-theme-color: var(--hot-pink); + --header-text-color: var(--white); + --scroller-radius: var(--options-radius) var(--options-radius) 0 0; + + @media (min-width: 600px) { + --scroller-radius: 0 var(--options-radius) var(--options-radius) 0; } } +.options-2-theme { + --main-theme-color: var(--blue); + --hot-theme-color: var(--deep-blue); + --header-text-color: var(--dark-text); + --scroller-radius: var(--options-radius) var(--options-radius) 0 0; + + @media (min-width: 600px) { + --scroller-radius: var(--options-radius) 0 0 var(--options-radius); + } +} + +.options-1 { + composes: options; + composes: options-1-theme; + grid-area: optsLeft; +} + +.options-2 { + composes: options; + composes: options-2-theme; + grid-area: optsRight; +} + .multi-panel { position: relative; display: flex; @@ -61,15 +99,32 @@ } } -.expand-icon { - transform: rotate(180deg); - margin-left: -12px; +.back { + composes: unbutton from global; + position: relative; + grid-area: header; + margin: 9px; + justify-self: start; + align-self: start; + + & > svg { + width: 47px; + } + + @media (min-width: 600px) { + margin: 14px; + + & > svg { + width: 58px; + } + } } -[content-expanded] .expand-icon { - transform: none; +.back-blob { + fill: var(--hot-pink); + opacity: 0.77; } -:focus .expand-icon { - fill: #34b9eb; +.back-x { + fill: var(--white); } diff --git a/src/client/lazy-app/icons/index.tsx b/src/client/lazy-app/icons/index.tsx index 7b1f19fb..9b3a0e6a 100644 --- a/src/client/lazy-app/icons/index.tsx +++ b/src/client/lazy-app/icons/index.tsx @@ -11,12 +11,6 @@ const Icon = (props: preact.JSX.HTMLAttributes) => ( /> ); -export const DownloadIcon = (props: preact.JSX.HTMLAttributes) => ( - - - -); - export const ToggleBackgroundIcon = (props: preact.JSX.HTMLAttributes) => ( @@ -67,42 +61,14 @@ export const ExpandIcon = (props: preact.JSX.HTMLAttributes) => ( ); -export const BackIcon = (props: preact.JSX.HTMLAttributes) => ( - - - +export const Arrow = () => ( + + + ); -const copyAcrossRotations = { - up: 90, - right: 180, - down: -90, - left: 0, -}; - -export interface CopyAcrossIconProps extends preact.JSX.HTMLAttributes { - copyDirection: keyof typeof copyAcrossRotations; -} - -export const CopyAcrossIcon = (props: CopyAcrossIconProps) => { - const { copyDirection, ...otherProps } = props; - const id = 'point-' + copyDirection; - const rotation = copyAcrossRotations[copyDirection]; - - return ( - - - - - - - - - ); -}; +export const DownloadIcon = () => ( + + + +); diff --git a/src/features/encoders/avif/client/index.tsx b/src/features/encoders/avif/client/index.tsx index 892c1248..f7d0316b 100644 --- a/src/features/encoders/avif/client/index.tsx +++ b/src/features/encoders/avif/client/index.tsx @@ -8,6 +8,7 @@ import Expander from 'client/lazy-app/Compress/Options/Expander'; import Select from 'client/lazy-app/Compress/Options/Select'; import Range from 'client/lazy-app/Compress/Options/Range'; import linkState from 'linkstate'; +import Revealer from 'client/lazy-app/Compress/Options/Revealer'; export const encode = ( signal: AbortSignal, @@ -209,12 +210,12 @@ export class Options extends Component { ) { return (
-
)} -
)} -
) : null}
- -
); @@ -224,23 +225,23 @@ export class Options extends Component { Quality:
- {showAdvanced ? (
-
)}
-