mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 08:22:24 -04:00
Make resizer snap to closest end and improve toggle (#2129)
* Make resizer snap to closest end and improve toggle * Snap on window resize * Remove event parameter * Remove nested ternary expression
This commit is contained in:
parent
0a3d38125d
commit
f5abd3c6af
4 changed files with 79 additions and 29 deletions
|
@ -3,6 +3,9 @@ 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 { createEventDispatcher } from "svelte";
|
||||||
|
import { fly } from "svelte/transition";
|
||||||
|
|
||||||
import { on } from "../lib/events";
|
import { on } from "../lib/events";
|
||||||
import { Callback, singleCallback } from "../lib/typing";
|
import { Callback, singleCallback } from "../lib/typing";
|
||||||
import IconConstrain from "./IconConstrain.svelte";
|
import IconConstrain from "./IconConstrain.svelte";
|
||||||
|
@ -12,8 +15,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export let panes: ResizablePane[];
|
export let panes: ResizablePane[];
|
||||||
export let index = 0;
|
export let index = 0;
|
||||||
export let tip = "";
|
export let tip = "";
|
||||||
|
export let showIndicator = false;
|
||||||
export let clientHeight: number;
|
export let clientHeight: number;
|
||||||
|
|
||||||
|
const rtl = window.getComputedStyle(document.body).direction == "rtl";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
let destroy: Callback;
|
let destroy: Callback;
|
||||||
|
|
||||||
let before: ResizablePane;
|
let before: ResizablePane;
|
||||||
|
@ -77,18 +85,31 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
destroy = singleCallback(
|
destroy = singleCallback(
|
||||||
on(window, "pointermove", onMove),
|
on(window, "pointermove", onMove),
|
||||||
on(window, "pointerup", releasePointer),
|
on(window, "pointerup", () => {
|
||||||
|
releasePointer.call(window);
|
||||||
|
dispatch("release");
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="horizontal-resizer"
|
class="horizontal-resizer"
|
||||||
|
class:rtl
|
||||||
title={tip}
|
title={tip}
|
||||||
bind:clientHeight={resizerHeight}
|
bind:clientHeight={resizerHeight}
|
||||||
on:pointerdown|preventDefault={lockPointer}
|
on:pointerdown|preventDefault={lockPointer}
|
||||||
on:dblclick
|
on:dblclick|preventDefault
|
||||||
>
|
>
|
||||||
|
{#if showIndicator}
|
||||||
|
<div
|
||||||
|
class="resize-indicator"
|
||||||
|
transition:fly={{ x: rtl ? 25 : -25, duration: 200 }}
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="drag-handle">
|
<div class="drag-handle">
|
||||||
<IconConstrain iconSize={80}>{@html horizontalHandle}</IconConstrain>
|
<IconConstrain iconSize={80}>{@html horizontalHandle}</IconConstrain>
|
||||||
</div>
|
</div>
|
||||||
|
@ -99,7 +120,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
width: 100%;
|
width: 100%;
|
||||||
cursor: row-resize;
|
cursor: row-resize;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 10px;
|
height: 25px;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
|
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
|
@ -113,5 +134,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
&:hover .drag-handle {
|
&:hover .drag-handle {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.resize-indicator {
|
||||||
|
position: absolute;
|
||||||
|
font-size: small;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
&.rtl .resize-indicator {
|
||||||
|
padding: 0.5rem 0 0 0.5rem;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -59,5 +59,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
.pane {
|
.pane {
|
||||||
@include panes.resizable(column, true, true);
|
@include panes.resizable(column, true, true);
|
||||||
|
opacity: var(--opacity, 1);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -355,12 +355,28 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
$: tagAmount = $tags.length;
|
$: tagAmount = $tags.length;
|
||||||
|
|
||||||
|
let snapTags = $tagsCollapsed;
|
||||||
|
|
||||||
function collapseTags(): void {
|
function collapseTags(): void {
|
||||||
lowerResizer.move([tagsPane, fieldsPane], tagsPane.minHeight);
|
lowerResizer.move([tagsPane, fieldsPane], tagsPane.minHeight);
|
||||||
|
$tagsCollapsed = snapTags = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function expandTags(): void {
|
function expandTags(): void {
|
||||||
lowerResizer.move([tagsPane, fieldsPane], tagsPane.maxHeight);
|
lowerResizer.move([tagsPane, fieldsPane], tagsPane.maxHeight);
|
||||||
|
$tagsCollapsed = snapTags = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", () => snapResizer(snapTags));
|
||||||
|
|
||||||
|
function snapResizer(collapse: boolean): void {
|
||||||
|
if (collapse) {
|
||||||
|
collapseTags();
|
||||||
|
bridgeCommand("collapseTags");
|
||||||
|
} else {
|
||||||
|
expandTags();
|
||||||
|
bridgeCommand("expandTags");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -390,7 +406,9 @@ the AddCards dialog) should be implemented in the user of this component.
|
||||||
|
|
||||||
<Pane
|
<Pane
|
||||||
bind:this={fieldsPane.resizable}
|
bind:this={fieldsPane.resizable}
|
||||||
on:resize={(e) => (fieldsPane.height = e.detail.height)}
|
on:resize={(e) => {
|
||||||
|
fieldsPane.height = e.detail.height;
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<PaneContent>
|
<PaneContent>
|
||||||
<Fields>
|
<Fields>
|
||||||
|
@ -553,7 +571,17 @@ the AddCards dialog) should be implemented in the user of this component.
|
||||||
</PaneContent>
|
</PaneContent>
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
||||||
{#if $tagsCollapsed}
|
<HorizontalResizer
|
||||||
|
panes={[fieldsPane, tagsPane]}
|
||||||
|
showIndicator={$tagsCollapsed || snapTags}
|
||||||
|
tip={`Double click to ${$tagsCollapsed ? "expand" : "collapse"} tag editor`}
|
||||||
|
{clientHeight}
|
||||||
|
bind:this={lowerResizer}
|
||||||
|
on:dblclick={() => snapResizer(!$tagsCollapsed)}
|
||||||
|
on:release={() => {
|
||||||
|
snapResizer(snapTags);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div class="tags-expander">
|
<div class="tags-expander">
|
||||||
<TagAddButton
|
<TagAddButton
|
||||||
on:tagappend={() => {
|
on:tagappend={() => {
|
||||||
|
@ -564,36 +592,28 @@ the AddCards dialog) should be implemented in the user of this component.
|
||||||
{@html tagAmount > 0 ? `${tagAmount} Tags` : ""}
|
{@html tagAmount > 0 ? `${tagAmount} Tags` : ""}
|
||||||
</TagAddButton>
|
</TagAddButton>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</HorizontalResizer>
|
||||||
|
|
||||||
<HorizontalResizer
|
|
||||||
panes={[fieldsPane, tagsPane]}
|
|
||||||
tip={`Double click to ${$tagsCollapsed ? "expand" : "collapse"} tag editor`}
|
|
||||||
{clientHeight}
|
|
||||||
bind:this={lowerResizer}
|
|
||||||
on:dblclick={() => {
|
|
||||||
if ($tagsCollapsed) {
|
|
||||||
expandTags();
|
|
||||||
bridgeCommand("expandTags");
|
|
||||||
$tagsCollapsed = false;
|
|
||||||
} else {
|
|
||||||
collapseTags();
|
|
||||||
bridgeCommand("collapseTags");
|
|
||||||
$tagsCollapsed = true;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Pane
|
<Pane
|
||||||
bind:this={tagsPane.resizable}
|
bind:this={tagsPane.resizable}
|
||||||
on:resize={(e) => {
|
on:resize={(e) => {
|
||||||
tagsPane.height = e.detail.height;
|
tagsPane.height = e.detail.height;
|
||||||
$tagsCollapsed = tagsPane.height == 0;
|
if (tagsPane.maxHeight > 0) {
|
||||||
|
snapTags = tagsPane.height < tagsPane.maxHeight / 2;
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
--opacity={(() => {
|
||||||
|
if (!$tagsCollapsed) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return snapTags ? tagsPane.height / tagsPane.maxHeight : 1;
|
||||||
|
}
|
||||||
|
})()}
|
||||||
>
|
>
|
||||||
<PaneContent scroll={false}>
|
<PaneContent scroll={false}>
|
||||||
<TagEditor
|
<TagEditor
|
||||||
{tags}
|
{tags}
|
||||||
|
--button-opacity={snapTags ? 0 : 1}
|
||||||
bind:this={tagEditor}
|
bind:this={tagEditor}
|
||||||
on:tagsupdate={saveTags}
|
on:tagsupdate={saveTags}
|
||||||
on:tagsFocused={() => {
|
on:tagsFocused={() => {
|
||||||
|
@ -617,7 +637,4 @@ the AddCards dialog) should be implemented in the user of this component.
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.tags-expander {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -25,6 +25,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.tag-options-button {
|
.tag-options-button {
|
||||||
padding: 6px 3px 0;
|
transition: opacity 0.2s linear;
|
||||||
|
opacity: var(--button-opacity, 1);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue