From 5f6ac1a9163e9b066f6d94e33ca2ab026268c95f Mon Sep 17 00:00:00 2001 From: Matthias Metelka <62722460+kleinerpirat@users.noreply.github.com> Date: Fri, 19 Aug 2022 02:02:28 +0200 Subject: [PATCH] Field redesign (#2002) * Adjust size of legacy buttons * Revert "Adjust size of legacy buttons" This reverts commit fb888fe1db9050c34b1a7b0820e6da5ac91ccee6. * Remove unused function from #1476 * Use outline version for tag icon * Add chevron icons * Remove code icons, keep one pin icon version * Add code-bg color * Redesign fields * Remove unused import * Fix imports * Move PlainTextBadge between editing inputs where it belongs :) * Make whole separator line clickable * Fix transition and format * Don't show toggle when field is collapsed * Show toggle only on hover for mobile I'd like to implement a swipe mechanism. * Use tweened SVG for triangle instead of CSS hack * Implement more obvious HTML toggle on bottom right * Reduce field height by a few pixels * Reduce field height by two pixels * Show HTML toggle when PlainTextInput is active, regardless of hover/focus * Remove RichTextBadge.svelte * Create separate collapsed field state this means users can collapse fields with the HTML editor open and it will stay open when the field is expanded again. * Add slide out animation to EditingArea, RichTextInput and PlainTextInput only for collapsing, because it is choppy on expansion (common issue with Svelte transitions). * Fix aliasing issue on focused field corners * Make StickyBadge feel more responsive * Move StickyBadge closer to field border * Adjust field gutter/margins * Make LabelContainer sticky to make field operations accessible on fields with a lot of content. * Add back html icons, remove visual editor icons * Revert "Add code-bg color" This reverts commit 4200f354193710b3acd9bcf84b67958e200ddcdb. * Add rich text icon, remove strikethrough code icon * Revert PlainTextBadge to original position * Adjust margins in FieldState * Rename PlainTextBadge to SecondaryInputBadge in preparation for #1987 * Run eslint and prettier * Make whole LabelContainer clickable area for collapse/expand * Revert "Add slide out animation to EditingArea, RichTextInput and PlainTextInput" This reverts commit 9a2b3410d0ead37ae1da408d68e14507a058a613. * Fix error on collapse/expansion this was caused by the {#if} blocks, which resulted in the deletion of original EditingAreas. * Refocus when toggling chevron and secondary input badge * Revert "Revert "Add code-bg color"" This reverts commit 1cfd3bda65354ab90c1ab4cbbef47596a1be8754. * Use single rotating chevron icon and make it RTL-compatible * Remove redundant CSS transition rule * Introduce animated Collapsible component and fix refocus on toggle * Do not try to force repaint, as it is not required * Remove RTL store from LabelContainer the direction is already applied globally. * Collapse secondary input with field * Add focusedField to NoteEditorAPI * Replace :global CSS selector with class .visible thus removing the assumption that the component is used inside an EditorField. https://github.com/ankitects/anki/pull/2002#discussion_r944876448 * Use named function syntax instead of function expressions * Add explanation comment * Remove unnecessary :bind directive * Create CollapseBadge component * Move :global selector into .plain-text-input * Add comment explaining box-shadow pseudo-element * Move Collapsible from EditingArea, PlainTextInput and RichTextInput into user components * Rename SecondaryInputBadge to PlainTextBadge and remove generalization logic I kept the rich text icon inside icons.ts for future use. * Sort imports * Fix background-color for duplicates not showing with yet another pseudo-element :) The pseudo-element that covers up field borders on scroll caused this issue. Fighting fire with fire here. * Increase size of plain text toggle to original value again This makes the clickable area a bit bigger and looks slightly more consistent with StickyBadge. * Scrap pseudo-element mess in LabelContainer and tackle the actual issue * Add class .visible to StickyBadge too This introduces a peculiar bug: The active prop of StickyBadge resets to false when the mouse leaves the field - regardless of the actual back-end value. * Fix sticky badge resetting on mouseleave/blur * Apply overflow: hidden only during transition fixes MathJax handle getting cut off by fields * Remove unused variable * Fix visual bug caused by overflow:hidden not applying in time I tried several asynchronous approaches, but they all caused issues: either they prevented the CSS transition or they made field inputs lose focus. In the end I resorted to direct, synchronous DOM-manipulation and added an explanatory comment. * Decrease Collapsible load time by blocking first transition I noticed the sliding animation has a hefty performance impact when a large number of fields is loaded simultaneously. Blocking the first transition (which isn't even visible) results in a big boost in load time. * Replace usages of gap with margins for children * Revert unnecessary removal of grid-gap definition * Correct comments about flex-gap property mistook that for grid-gap. * Resolve style issues * Add minimum targets to gap comment Co-authored-by: Henrik Giesel --- ftl/core/editing.ftl | 3 +- sass/_vars.scss | 2 + ts/components/Collapsible.svelte | 100 +++++++++++++ ts/editor/CollapseBadge.svelte | 35 +++++ ts/editor/EditingArea.svelte | 22 ++- ts/editor/EditorField.svelte | 53 +++---- ts/editor/FieldState.svelte | 23 ++- ts/editor/Fields.svelte | 4 +- ts/editor/FieldsEditor.svelte | 6 + ts/editor/LabelContainer.svelte | 56 +++++--- ts/editor/NoteCreator.svelte | 4 +- ts/editor/NoteEditor.svelte | 136 +++++++++++------- ts/editor/PlainTextBadge.svelte | 21 +-- ts/editor/RichTextBadge.svelte | 42 ------ ts/editor/StickyBadge.svelte | 24 ++-- ts/editor/icons.ts | 11 +- .../plain-text-input/PlainTextInput.svelte | 14 +- .../rich-text-input/RichTextInput.svelte | 3 +- ts/lib/context-keys.ts | 1 + ts/tag-editor/tag-options-button/icons.ts | 4 +- 20 files changed, 375 insertions(+), 189 deletions(-) create mode 100644 ts/components/Collapsible.svelte create mode 100644 ts/editor/CollapseBadge.svelte delete mode 100644 ts/editor/RichTextBadge.svelte diff --git a/ftl/core/editing.ftl b/ftl/core/editing.ftl index 96e5af0e5..244872282 100644 --- a/ftl/core/editing.ftl +++ b/ftl/core/editing.ftl @@ -54,7 +54,8 @@ editing-text-highlight-color = Text highlight color editing-to-make-a-cloze-deletion-on = To make a cloze deletion on an existing note, you need to change it to a cloze type first, via 'Notes>Change Note Type' editing-toggle-html-editor = Toggle HTML Editor editing-toggle-sticky = Toggle sticky -editing-toggle-visual-editor = Toggle Visual Editor +editing-expand-field = Expand field +editing-collapse-field = Collapse field editing-underline-text = Underline text editing-unordered-list = Unordered list editing-warning-cloze-deletions-will-not-work = Warning, cloze deletions will not work until you switch the type at the top to Cloze. diff --git a/sass/_vars.scss b/sass/_vars.scss index 2e584d1da..1a2efce62 100644 --- a/sass/_vars.scss +++ b/sass/_vars.scss @@ -38,6 +38,7 @@ --tooltip-bg: #fcfcfc; --focus-border: #0969da; --focus-shadow: rgba(9 105 218 / 0.3); + --code-bg: white; } :root[class*="night-mode"] { @@ -77,5 +78,6 @@ --tooltip-bg: #272727; --focus-border: #316dca; --focus-shadow: #194380; + --code-bg: #272822; color-scheme: dark; } diff --git a/ts/components/Collapsible.svelte b/ts/components/Collapsible.svelte new file mode 100644 index 000000000..3a116aa53 --- /dev/null +++ b/ts/components/Collapsible.svelte @@ -0,0 +1,100 @@ + + + +
+
+ +
+
+ + diff --git a/ts/editor/CollapseBadge.svelte b/ts/editor/CollapseBadge.svelte new file mode 100644 index 000000000..42f7e1b17 --- /dev/null +++ b/ts/editor/CollapseBadge.svelte @@ -0,0 +1,35 @@ + + + +
+ {@html chevronDown} +
+ + diff --git a/ts/editor/EditingArea.svelte b/ts/editor/EditingArea.svelte index 8aa156bed..da5dfd0f9 100644 --- a/ts/editor/EditingArea.svelte +++ b/ts/editor/EditingArea.svelte @@ -189,10 +189,28 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html position: relative; background: var(--frame-bg); - border-radius: 0 0 5px 5px; + border-radius: 5px; + border: 1px solid var(--border); - &:focus { + box-shadow: 0px 0px 2px 0px var(--border); + transition: box-shadow 80ms cubic-bezier(0.33, 1, 0.68, 1); + + &:focus-within { outline: none; + + /* This pseudo-element is required to display + the inset box-shadow above field contents */ + &::after { + content: ""; + position: absolute; + top: -1px; + right: -1px; + bottom: -1px; + left: -1px; + pointer-events: none; + border-radius: 5px; + box-shadow: inset 0 0 0 2px var(--focus-border); + } } } diff --git a/ts/editor/EditorField.svelte b/ts/editor/EditorField.svelte index 23588ffb6..bd3f1983d 100644 --- a/ts/editor/EditorField.svelte +++ b/ts/editor/EditorField.svelte @@ -45,22 +45,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import type { Writable } from "svelte/store"; import { writable } from "svelte/store"; - import { directionKey } from "../lib/context-keys"; + import Collapsible from "../components/Collapsible.svelte"; + import { collapsedKey, directionKey } from "../lib/context-keys"; import { promiseWithResolver } from "../lib/promise"; import type { Destroyable } from "./destroyable"; import EditingArea from "./EditingArea.svelte"; - import FieldState from "./FieldState.svelte"; - import LabelContainer from "./LabelContainer.svelte"; - import LabelName from "./LabelName.svelte"; export let content: Writable; export let field: FieldData; + export let collapsed = false; const directionStore = writable<"ltr" | "rtl">(); setContext(directionKey, directionStore); $: $directionStore = field.direction; + const collapsedStore = writable(); + setContext(collapsedKey, collapsedStore); + + $: $collapsedStore = collapsed; + const editingArea: Partial = {}; const [element, elementResolve] = promiseWithResolver(); @@ -85,37 +89,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html on:focusin on:focusout on:click={() => editingArea.focus?.()} + on:mouseenter + on:mouseleave > - - - - {field.name} - - - - - - - + + + + + + + diff --git a/ts/editor/FieldState.svelte b/ts/editor/FieldState.svelte index f41ed793a..d0cc34444 100644 --- a/ts/editor/FieldState.svelte +++ b/ts/editor/FieldState.svelte @@ -12,8 +12,27 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html justify-content: flex; flex-grow: 1; - & > :global(*) { - margin-left: 2px; + /* replace with "gap: 5px" once it's available + - required: Chromium 84 (Qt6 only) and iOS 14.1 */ + > :global(*) { + margin: 0 3px; + + &:first-child { + margin-left: 0; + } + &:last-child { + margin-right: 0; + } + } + } + :global([dir="rtl"]) .field-state > :global(*) { + margin: 0 3px; + + &:last-child { + margin-left: 0; + } + &:first-child { + margin-right: 0; } } diff --git a/ts/editor/Fields.svelte b/ts/editor/Fields.svelte index d63350031..b4fcffaad 100644 --- a/ts/editor/Fields.svelte +++ b/ts/editor/Fields.svelte @@ -10,9 +10,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html .fields { display: grid; grid-auto-rows: min-content; - grid-gap: 4px; + grid-gap: 6px; - padding: 5px 3px 0; + padding: 0 3px; /* set height to 100% for rich text widgets */ height: 100%; diff --git a/ts/editor/FieldsEditor.svelte b/ts/editor/FieldsEditor.svelte index b71ee9e79..f38dd6785 100644 --- a/ts/editor/FieldsEditor.svelte +++ b/ts/editor/FieldsEditor.svelte @@ -13,5 +13,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html flex-direction: column; flex-grow: 1; overflow-x: hidden; + + /* replace with "gap: 5px" once it's available + - required: Chromium 84 (Qt6 only) and iOS 14.1 */ + > :global(*) { + margin: 5px 0; + } } diff --git a/ts/editor/LabelContainer.svelte b/ts/editor/LabelContainer.svelte index 770e0a9fc..ad546461a 100644 --- a/ts/editor/LabelContainer.svelte +++ b/ts/editor/LabelContainer.svelte @@ -3,38 +3,54 @@ Copyright: Ankitects Pty Ltd and contributors License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> -
+
+ (hovered = true)} + on:mouseleave={() => (hovered = false)} + > + + +
diff --git a/ts/editor/NoteCreator.svelte b/ts/editor/NoteCreator.svelte index 3ada91086..064c78180 100644 --- a/ts/editor/NoteCreator.svelte +++ b/ts/editor/NoteCreator.svelte @@ -45,7 +45,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - - + + diff --git a/ts/editor/NoteEditor.svelte b/ts/editor/NoteEditor.svelte index 29ea40f07..9f942f3ba 100644 --- a/ts/editor/NoteEditor.svelte +++ b/ts/editor/NoteEditor.svelte @@ -5,12 +5,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - - - {@html icon} - - - diff --git a/ts/editor/StickyBadge.svelte b/ts/editor/StickyBadge.svelte index 0b264c6c8..a8f038aea 100644 --- a/ts/editor/StickyBadge.svelte +++ b/ts/editor/StickyBadge.svelte @@ -10,11 +10,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import * as tr from "../lib/ftl"; import { getPlatformString, registerShortcut } from "../lib/shortcuts"; import { context as editorFieldContext } from "./EditorField.svelte"; - import { stickyOff, stickyOn } from "./icons"; + import { stickyIcon } from "./icons"; export let active: boolean; - - $: icon = active ? stickyOn : stickyOff; + export let visible: boolean; const editorField = editorFieldContext.get(); const keyCombination = "F9"; @@ -34,23 +33,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html onMount(() => editorField.element.then(shortcut)); - + {@html icon}{@html stickyIcon} diff --git a/ts/editor/icons.ts b/ts/editor/icons.ts index 701483237..018bb7071 100644 --- a/ts/editor/icons.ts +++ b/ts/editor/icons.ts @@ -5,10 +5,9 @@ export { default as incrementClozeIcon } from "../icons/contain-plus.svg"; export { default as alertIcon } from "@mdi/svg/svg/alert.svg"; -export { default as htmlOn } from "@mdi/svg/svg/code-tags.svg"; +export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg"; +export { default as chevronUp } from "@mdi/svg/svg/chevron-up.svg"; +export { default as plainTextIcon } from "@mdi/svg/svg/code-tags.svg"; export { default as clozeIcon } from "@mdi/svg/svg/contain.svg"; -export { default as richTextOff } from "@mdi/svg/svg/eye-off-outline.svg"; -export { default as richTextOn } from "@mdi/svg/svg/eye-outline.svg"; -export { default as stickyOff } from "@mdi/svg/svg/pin-off-outline.svg"; -export { default as stickyOn } from "@mdi/svg/svg/pin-outline.svg"; -export { default as htmlOff } from "@mdi/svg/svg/xml.svg"; +export { default as richTextIcon } from "@mdi/svg/svg/format-font.svg"; +export { default as stickyIcon } from "@mdi/svg/svg/pin-outline.svg"; diff --git a/ts/editor/plain-text-input/PlainTextInput.svelte b/ts/editor/plain-text-input/PlainTextInput.svelte index 4a28b7185..67d4f8049 100644 --- a/ts/editor/plain-text-input/PlainTextInput.svelte +++ b/ts/editor/plain-text-input/PlainTextInput.svelte @@ -143,7 +143,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
($focusedInput = api)} > diff --git a/ts/editor/rich-text-input/RichTextInput.svelte b/ts/editor/rich-text-input/RichTextInput.svelte index 35b952b94..c04813c95 100644 --- a/ts/editor/rich-text-input/RichTextInput.svelte +++ b/ts/editor/rich-text-input/RichTextInput.svelte @@ -211,7 +211,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html setupLifecycleHooks(api); -
+
{/await} +