Fix field description (#1923)

* Remove most of the original description placeholder implementation

* Move description showing logic to RichTextInput

- there is no need to propagate it to ContentEditable

* Remove the @html from field-description

This actually worked - however I removed it in case we'd rather offer
markdown support or something else in the future.

* Do not remove placeholder already on focus

- Other editors do not do it either

* Hide via hidden attribute instead of unmounting

* Do not pass content to ContentEditable

* Sort imports

* Change placeholder text color (dae)

In day mode, slightly-grey is almost indistinguishable from black
(at least on the monitor I'm using here)
This commit is contained in:
Henrik Giesel 2022-06-22 01:53:10 +02:00 committed by GitHub
parent cd3f9ff646
commit c1e54e6842
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 38 deletions

View file

@ -7,11 +7,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import { getContext } from "svelte"; import type { Writable } from "svelte/store";
import type { Readable, Writable } from "svelte/store";
import { updateAllState } from "../components/WithState.svelte"; import { updateAllState } from "../components/WithState.svelte";
import { descriptionKey } from "../lib/context-keys";
import actionList from "../sveltelib/action-list"; import actionList from "../sveltelib/action-list";
import type { MirrorAction } from "../sveltelib/dom-mirror"; import type { MirrorAction } from "../sveltelib/dom-mirror";
import type { SetupInputHandlerAction } from "../sveltelib/input-handler"; import type { SetupInputHandlerAction } from "../sveltelib/input-handler";
@ -35,15 +33,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const [focusHandler, setupFocusHandling] = useFocusHandler(); const [focusHandler, setupFocusHandling] = useFocusHandler();
Object.assign(api, { focusHandler }); Object.assign(api, { focusHandler });
const description = getContext<Readable<string>>(descriptionKey);
$: descriptionCSSValue = `"${$description}"`;
export let content: string;
</script> </script>
<anki-editable <anki-editable
class:empty={!content}
contenteditable="true" contenteditable="true"
use:resolve use:resolve
use:setupFocusHandling use:setupFocusHandling
@ -54,14 +46,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
on:blur on:blur
on:click={updateAllState} on:click={updateAllState}
on:keyup={updateAllState} on:keyup={updateAllState}
style="--description: {descriptionCSSValue}"
/> />
<style lang="scss"> <style lang="scss">
anki-editable { anki-editable {
display: block; display: block;
position: relative; position: relative;
padding: 6px;
overflow: auto; overflow: auto;
overflow-wrap: anywhere; overflow-wrap: anywhere;
/* fallback for iOS */ /* fallback for iOS */
@ -70,17 +61,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
&:focus { &:focus {
outline: none; outline: none;
} }
&.empty::before {
content: var(--description);
opacity: 0.4;
cursor: text;
/* stay on single line */
position: absolute;
max-width: 95%;
overflow-x: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
} }
/* editable-base.scss contains styling targeting user HTML */ /* editable-base.scss contains styling targeting user HTML */

View file

@ -47,10 +47,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import { getAllContexts, onMount } from "svelte"; import { getAllContexts, getContext, onMount } from "svelte";
import type { Readable } from "svelte/store";
import { placeCaretAfterContent } from "../../domlib/place-caret"; import { placeCaretAfterContent } from "../../domlib/place-caret";
import ContentEditable from "../../editable/ContentEditable.svelte"; import ContentEditable from "../../editable/ContentEditable.svelte";
import {
descriptionKey,
directionKey,
fontFamilyKey,
fontSizeKey,
} from "../../lib/context-keys";
import { promiseWithResolver } from "../../lib/promise"; import { promiseWithResolver } from "../../lib/promise";
import { singleCallback } from "../../lib/typing"; import { singleCallback } from "../../lib/typing";
import useDOMMirror from "../../sveltelib/dom-mirror"; import useDOMMirror from "../../sveltelib/dom-mirror";
@ -68,6 +75,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const { focusedInput } = noteEditorContext.get(); const { focusedInput } = noteEditorContext.get();
const { content, editingInputs } = editingAreaContext.get(); const { content, editingInputs } = editingAreaContext.get();
const description = getContext<Readable<string>>(descriptionKey);
const fontFamily = getContext<Readable<string>>(fontFamilyKey);
const fontSize = getContext<Readable<number>>(fontSizeKey);
const direction = getContext<Readable<"ltr" | "rtl">>(directionKey);
const nodes = getNormalizingNodeStore(); const nodes = getNormalizingNodeStore();
const [richTextPromise, resolve] = useRichTextResolve(); const [richTextPromise, resolve] = useRichTextResolve();
const { mirror, preventResubscription } = useDOMMirror(); const { mirror, preventResubscription } = useDOMMirror();
@ -148,7 +160,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
mirrors: [mirror], mirrors: [mirror],
inputHandlers: [setupInputHandler, setupGlobalInputHandler], inputHandlers: [setupInputHandler, setupGlobalInputHandler],
api: api.editable, api: api.editable,
content: $content,
}, },
context: allContexts, context: allContexts,
}); });
@ -160,6 +171,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$editingInputs = $editingInputs; $editingInputs = $editingInputs;
} }
function setFocus(): void {
$focusedInput = api;
// We do not unset focusedInput here.
// If we did, UI components for the input would react the store
// being unset, even though most likely it will be set to some other
// field right away.
}
$: pushUpdate(!hidden); $: pushUpdate(!hidden);
onMount(() => { onMount(() => {
@ -180,9 +200,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
setupLifecycleHooks(api); setupLifecycleHooks(api);
</script> </script>
<div class="rich-text-input" on:focusin={() => ($focusedInput = api)}> <div class="rich-text-input" on:focusin={setFocus} {hidden}>
{#if $content.length === 0}
<div
class="rich-text-placeholder"
style:font-family={$fontFamily}
style:font-size={$fontSize + "px"}
style:direction={$direction}
>
{$description}
</div>
{/if}
<RichTextStyles <RichTextStyles
color={$pageTheme.isDark ? "white" : "black"} color={$pageTheme.isDark ? "white" : "black"}
fontFamily={$fontFamily}
fontSize={$fontSize}
direction={$direction}
callback={stylesResolve} callback={stylesResolve}
let:attachToShadow={attachStyles} let:attachToShadow={attachStyles}
let:stylesDidLoad let:stylesDidLoad
@ -190,7 +224,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<div <div
bind:this={richTextDiv} bind:this={richTextDiv}
class={className} class={className}
class:hidden
class:night-mode={$pageTheme.isDark} class:night-mode={$pageTheme.isDark}
use:attachShadow use:attachShadow
use:attachStyles use:attachStyles
@ -208,7 +241,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</div> </div>
<style lang="scss"> <style lang="scss">
.hidden { .rich-text-input {
display: none; position: relative;
margin: 6px;
}
.rich-text-placeholder {
position: absolute;
color: var(--disabled);
/* Adopts same size as the content editable element */
width: 100%;
height: 100%;
} }
</style> </style>

View file

@ -3,10 +3,6 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import { getContext } from "svelte";
import type { Readable } from "svelte/store";
import { directionKey, fontFamilyKey, fontSizeKey } from "../../lib/context-keys";
import { promiseWithResolver } from "../../lib/promise"; import { promiseWithResolver } from "../../lib/promise";
import type { StyleLinkType, StyleObject } from "./CustomStyles.svelte"; import type { StyleLinkType, StyleObject } from "./CustomStyles.svelte";
import CustomStyles from "./CustomStyles.svelte"; import CustomStyles from "./CustomStyles.svelte";
@ -25,9 +21,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}); });
export let color: string; export let color: string;
const fontFamily = getContext<Readable<string>>(fontFamilyKey); export let fontFamily: string;
const fontSize = getContext<Readable<number>>(fontSizeKey); export let fontSize: number;
const direction = getContext<Readable<"ltr" | "rtl">>(directionKey); export let direction: "ltr" | "rtl";
async function setStyling(property: string, value: unknown): Promise<void> { async function setStyling(property: string, value: unknown): Promise<void> {
const rule = await userBaseRule; const rule = await userBaseRule;
@ -35,9 +31,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} }
$: setStyling("color", color); $: setStyling("color", color);
$: setStyling("fontFamily", $fontFamily); $: setStyling("fontFamily", fontFamily);
$: setStyling("fontSize", $fontSize + "px"); $: setStyling("fontSize", fontSize + "px");
$: setStyling("direction", $direction); $: setStyling("direction", direction);
const styles = [ const styles = [
{ {