mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 01:06:35 -04:00
Redesign fields
This commit is contained in:
parent
4200f35419
commit
3043789960
10 changed files with 176 additions and 83 deletions
|
@ -189,10 +189,26 @@ 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;
|
||||
border-color: var(--focus-border);
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
border-radius: 5px;
|
||||
box-shadow: inset 0 0 0 1px var(--focus-border);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -48,9 +48,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
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<string>;
|
||||
export let field: FieldData;
|
||||
|
@ -90,14 +87,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
on:focusout
|
||||
on:click={() => editingArea.focus?.()}
|
||||
>
|
||||
<LabelContainer>
|
||||
<span>
|
||||
<LabelName>
|
||||
{field.name}
|
||||
</LabelName>
|
||||
</span>
|
||||
<FieldState><slot name="field-state" /></FieldState>
|
||||
</LabelContainer>
|
||||
<slot name="field-label" />
|
||||
|
||||
<EditingArea
|
||||
{content}
|
||||
fontFamily={field.fontFamily}
|
||||
|
@ -110,16 +101,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
<style lang="scss">
|
||||
.editor-field {
|
||||
position: relative;
|
||||
--border-color: var(--border);
|
||||
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--border-color);
|
||||
|
||||
&:focus-within {
|
||||
--border-color: var(--focus-border);
|
||||
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--focus-shadow);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,7 +11,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
display: flex;
|
||||
justify-content: flex;
|
||||
flex-grow: 1;
|
||||
|
||||
& > :global(*) {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
|
|
@ -3,35 +3,67 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
import { createEventDispatcher, getContext } from "svelte";
|
||||
import type { Readable } from "svelte/store";
|
||||
|
||||
import { directionKey } from "../lib/context-keys";
|
||||
|
||||
import * as tr from "../lib/ftl";
|
||||
import Badge from "../components/Badge.svelte";
|
||||
import { chevronRight, chevronDown } from "./icons";
|
||||
|
||||
export let off: boolean;
|
||||
|
||||
const direction = getContext<Readable<"ltr" | "rtl">>(directionKey);
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function toggle() {
|
||||
dispatch("toggle");
|
||||
}
|
||||
|
||||
$: icon = off ? chevronRight : chevronDown;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:collapsed={off}
|
||||
class="label-container"
|
||||
class:rtl={$direction === "rtl"}
|
||||
on:mousedown|preventDefault
|
||||
>
|
||||
<span class="clickable" on:click|stopPropagation={toggle}>
|
||||
<span class="chevron">
|
||||
<Badge
|
||||
tooltip={tr.editingToggleVisualEditor()}
|
||||
iconSize={80}
|
||||
--icon-align="text-bottom"
|
||||
>{@html icon}
|
||||
</Badge>
|
||||
</span>
|
||||
<slot name="field-name" />
|
||||
</span>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.label-container {
|
||||
& .chevron {
|
||||
opacity: 0.4;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
background-color: var(--label-color, transparent);
|
||||
|
||||
border-width: 0 0 1px;
|
||||
border-style: dashed;
|
||||
border-color: var(--border-color);
|
||||
border-radius: 5px 5px 0 0;
|
||||
|
||||
padding: 0px 6px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
&:hover .chevron {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.rtl {
|
||||
|
|
|
@ -9,6 +9,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import type { EditorToolbarAPI } from "./editor-toolbar";
|
||||
import type { EditorFieldAPI } from "./EditorField.svelte";
|
||||
|
||||
import LabelContainer from "./LabelContainer.svelte";
|
||||
import LabelName from "./LabelName.svelte";
|
||||
import FieldState from "./FieldState.svelte";
|
||||
|
||||
export interface NoteEditorAPI {
|
||||
fields: EditorFieldAPI[];
|
||||
focusedField: Writable<EditorFieldAPI | null>;
|
||||
|
@ -322,34 +326,30 @@ the AddCards dialog) should be implemented in the user of this component.
|
|||
? "var(--flag1-bg)"
|
||||
: "transparent"}
|
||||
>
|
||||
<svelte:fragment slot="field-state">
|
||||
{#if cols[index] === "dupe"}
|
||||
<DuplicateLink />
|
||||
{/if}
|
||||
<RichTextBadge
|
||||
<svelte:fragment slot="field-label">
|
||||
<LabelContainer
|
||||
bind:off={richTextsHidden[index]}
|
||||
on:toggle={() => {
|
||||
richTextsHidden[index] = !richTextsHidden[index];
|
||||
|
||||
plainTextsHidden[index] = true;
|
||||
if (!richTextsHidden[index]) {
|
||||
richTextInputs[index].api.refocus();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<PlainTextBadge
|
||||
bind:off={plainTextsHidden[index]}
|
||||
on:toggle={() => {
|
||||
plainTextsHidden[index] = !plainTextsHidden[index];
|
||||
|
||||
if (!plainTextsHidden[index]) {
|
||||
plainTextInputs[index].api.refocus();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<slot name="field-state" {field} {index} />
|
||||
>
|
||||
<svelte:fragment slot="field-name">
|
||||
<LabelName>
|
||||
{field.name}
|
||||
</LabelName>
|
||||
</svelte:fragment>
|
||||
<FieldState>
|
||||
{#if cols[index] === "dupe"}
|
||||
<DuplicateLink />
|
||||
{/if}
|
||||
<slot name="field-state" {field} {index} />
|
||||
</FieldState>
|
||||
</LabelContainer>
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="editing-inputs">
|
||||
<RichTextInput
|
||||
hidden={richTextsHidden[index]}
|
||||
|
@ -361,6 +361,20 @@ the AddCards dialog) should be implemented in the user of this component.
|
|||
>
|
||||
<ImageHandle maxWidth={250} maxHeight={125} />
|
||||
<MathjaxHandle />
|
||||
|
||||
<svelte:fragment slot="plain-text-badge">
|
||||
<PlainTextBadge
|
||||
bind:off={plainTextsHidden[index]}
|
||||
on:toggle={() => {
|
||||
plainTextsHidden[index] =
|
||||
!plainTextsHidden[index];
|
||||
|
||||
if (!plainTextsHidden[index]) {
|
||||
plainTextInputs[index].api.refocus();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
</RichTextInput>
|
||||
|
||||
<PlainTextInput
|
||||
|
|
|
@ -5,11 +5,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
|
||||
import Badge from "../components/Badge.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import { getPlatformString, registerShortcut } from "../lib/shortcuts";
|
||||
import { registerShortcut } from "../lib/shortcuts";
|
||||
import { context as editorFieldContext } from "./EditorField.svelte";
|
||||
import { htmlOff, htmlOn } from "./icons";
|
||||
|
||||
const editorField = editorFieldContext.get();
|
||||
const keyCombination = "Control+Shift+X";
|
||||
|
@ -17,8 +14,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
export let off = false;
|
||||
|
||||
$: icon = off ? htmlOff : htmlOn;
|
||||
|
||||
function toggle() {
|
||||
dispatch("toggle");
|
||||
}
|
||||
|
@ -28,29 +23,72 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
|
||||
onMount(() => editorField.element.then(shortcut));
|
||||
let width = 0;
|
||||
</script>
|
||||
|
||||
<span
|
||||
class="plain-text-badge"
|
||||
class:highlighted={!off}
|
||||
<div
|
||||
class="clickable"
|
||||
style="--width: {width}px"
|
||||
on:click|stopPropagation={toggle}
|
||||
bind:clientWidth={width}
|
||||
>
|
||||
<Badge
|
||||
tooltip="{tr.editingToggleHtmlEditor()} ({getPlatformString(keyCombination)})"
|
||||
iconSize={80}
|
||||
--icon-align="text-top">{@html icon}</Badge
|
||||
>
|
||||
</span>
|
||||
<span class:off class:on={!off} class="plain-text-badge" class:highlighted={!off} />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
span {
|
||||
opacity: 0.4;
|
||||
.clickable {
|
||||
right: calc(50% - var(--width) / 2);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
bottom: -16px;
|
||||
z-index: 3;
|
||||
width: 32px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.plain-text-badge {
|
||||
left: 12px;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
transform: rotate(-45deg);
|
||||
|
||||
&.highlighted {
|
||||
opacity: 1;
|
||||
transition: bottom 0.2s ease-out;
|
||||
&.on {
|
||||
bottom: 0px;
|
||||
background: var(--code-bg);
|
||||
border-right: 1px solid var(--border);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
&.off {
|
||||
bottom: 10px;
|
||||
background: var(--frame-bg);
|
||||
border-left: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
:global(.editor-field) {
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
& .plain-text-badge {
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s ease-in, bottom 0.2s ease-out;
|
||||
&.on,
|
||||
&.off {
|
||||
bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:focus-within .plain-text-badge.off {
|
||||
border-width: 2px;
|
||||
border-color: var(--focus-border);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -24,7 +24,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<Badge
|
||||
tooltip={tr.editingToggleVisualEditor()}
|
||||
iconSize={80}
|
||||
--icon-align="text-top">{@html icon}</Badge
|
||||
--icon-align="text-bottom">{@html icon}</Badge
|
||||
>
|
||||
</span>
|
||||
|
||||
|
|
|
@ -10,12 +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;
|
||||
|
||||
const editorField = editorFieldContext.get();
|
||||
const keyCombination = "F9";
|
||||
|
||||
|
@ -38,19 +36,31 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<Badge
|
||||
tooltip="{tr.editingToggleSticky()} ({getPlatformString(keyCombination)})"
|
||||
widthMultiplier={0.7}
|
||||
--icon-align="text-top">{@html icon}</Badge
|
||||
--icon-align="text-bottom">{@html stickyIcon}</Badge
|
||||
>
|
||||
</span>
|
||||
|
||||
<style lang="scss">
|
||||
span {
|
||||
opacity: 0.4;
|
||||
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease-in;
|
||||
&.highlighted {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
:global(.editor-field) {
|
||||
&:focus-within,
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
& span {
|
||||
opacity: 0.4;
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
&.highlighted {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -164,7 +164,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
|
||||
:global(.CodeMirror-lines) {
|
||||
padding: 6px 0;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
|
@ -172,7 +172,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
}
|
||||
|
||||
.light-theme :global(.CodeMirror) {
|
||||
border-top: 1px solid #ddd;
|
||||
:global(.CodeMirror) {
|
||||
border-top: 1px solid var(--border);
|
||||
background: var(--code-bg);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -238,6 +238,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
</div>
|
||||
{/await}
|
||||
</RichTextStyles>
|
||||
<slot name="plain-text-badge" />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
Loading…
Reference in a new issue