mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 08:22:24 -04:00
Implement TagWithTooltip
This commit is contained in:
parent
7058d14d25
commit
28b1c09cda
7 changed files with 99 additions and 75 deletions
|
@ -19,15 +19,21 @@
|
||||||
export let tooltip: string;
|
export let tooltip: string;
|
||||||
export let trigger: TriggerType = "hover focus";
|
export let trigger: TriggerType = "hover focus";
|
||||||
|
|
||||||
|
export let placement: "auto" | "top" | "bottom" | "left" | "right" = "top";
|
||||||
|
export let html = true;
|
||||||
|
export let offset: Tooltip.Offset = [0, 0];
|
||||||
|
export let showDelay = 0;
|
||||||
|
export let hideDelay = 0;
|
||||||
|
|
||||||
let tooltipObject: Tooltip;
|
let tooltipObject: Tooltip;
|
||||||
|
|
||||||
function createTooltip(element: HTMLElement): void {
|
function createTooltip(element: HTMLElement): void {
|
||||||
element.title = tooltip;
|
element.title = tooltip;
|
||||||
tooltipObject = new Tooltip(element, {
|
tooltipObject = new Tooltip(element, {
|
||||||
placement: "bottom",
|
placement,
|
||||||
html: true,
|
html,
|
||||||
offset: [0, 20],
|
offset,
|
||||||
delay: { show: 250, hide: 0 },
|
delay: { show: showDelay, hide: hideDelay },
|
||||||
trigger,
|
trigger,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
<Label for={forId}><slot /></Label>
|
<Label for={forId}><slot /></Label>
|
||||||
<WithTooltip tooltip={marked(markdownTooltip)} let:createTooltip>
|
<WithTooltip
|
||||||
|
tooltip={marked(markdownTooltip)}
|
||||||
|
showDelay={250}
|
||||||
|
offset={[0, 20]}
|
||||||
|
placement="bottom"
|
||||||
|
let:createTooltip
|
||||||
|
>
|
||||||
<Badge
|
<Badge
|
||||||
class="opacity-50"
|
class="opacity-50"
|
||||||
on:mount={(event) => createTooltip(event.detail.span)}
|
on:mount={(event) => createTooltip(event.detail.span)}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<!--
|
|
||||||
Copyright: Ankitects Pty Ltd and contributors
|
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
|
||||||
import { onDestroy } from "svelte";
|
|
||||||
import Tooltip from "bootstrap/js/dist/tooltip";
|
|
||||||
|
|
||||||
type TriggerType =
|
|
||||||
| "hover focus"
|
|
||||||
| "click"
|
|
||||||
| "hover"
|
|
||||||
| "focus"
|
|
||||||
| "manual"
|
|
||||||
| "click hover"
|
|
||||||
| "click focus"
|
|
||||||
| "click hover focus";
|
|
||||||
|
|
||||||
export let tooltip: string;
|
|
||||||
export let trigger: TriggerType = "hover focus";
|
|
||||||
|
|
||||||
let tooltipObject: Tooltip;
|
|
||||||
|
|
||||||
function createTooltip(element: HTMLElement): void {
|
|
||||||
element.title = tooltip;
|
|
||||||
tooltipObject = new Tooltip(element, {
|
|
||||||
placement: "bottom",
|
|
||||||
html: true,
|
|
||||||
offset: [0, 20],
|
|
||||||
delay: { show: 250, hide: 0 },
|
|
||||||
trigger,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onDestroy(() => tooltipObject?.dispose());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<slot {createTooltip} {tooltipObject} />
|
|
|
@ -3,7 +3,7 @@ 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="typescript">
|
<script lang="typescript">
|
||||||
import { getContext, createEventDispatcher } from "svelte";
|
import { onMount, getContext, createEventDispatcher } from "svelte";
|
||||||
import { nightModeKey } from "components/context-keys";
|
import { nightModeKey } from "components/context-keys";
|
||||||
import Badge from "components/Badge.svelte";
|
import Badge from "components/Badge.svelte";
|
||||||
import { deleteIcon } from "./icons";
|
import { deleteIcon } from "./icons";
|
||||||
|
@ -50,11 +50,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
|
|
||||||
const nightMode = getContext<boolean>(nightModeKey);
|
const nightMode = getContext<boolean>(nightModeKey);
|
||||||
|
|
||||||
|
let button: HTMLButtonElement;
|
||||||
|
|
||||||
|
onMount(() => dispatch("mount", { button }));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:body on:keydown={setDeleteIcon} on:keyup={setDeleteIcon} />
|
<svelte:body on:keydown={setDeleteIcon} on:keyup={setDeleteIcon} />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
bind:this={button}
|
||||||
class={`tag btn d-inline-flex align-items-center text-nowrap rounded ps-2 pe-1 m-0 ${className}`}
|
class={`tag btn d-inline-flex align-items-center text-nowrap rounded ps-2 pe-1 m-0 ${className}`}
|
||||||
class:selected
|
class:selected
|
||||||
class:flashing
|
class:flashing
|
||||||
|
|
|
@ -10,19 +10,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import StickyBottom from "components/StickyBottom.svelte";
|
import StickyBottom from "components/StickyBottom.svelte";
|
||||||
import AddTagBadge from "./AddTagBadge.svelte";
|
import AddTagBadge from "./AddTagBadge.svelte";
|
||||||
import SelectedTagBadge from "./SelectedTagBadge.svelte";
|
import SelectedTagBadge from "./SelectedTagBadge.svelte";
|
||||||
import Tag from "./Tag.svelte";
|
import TagWithTooltip from "./TagWithTooltip.svelte";
|
||||||
import TagInput from "./TagInput.svelte";
|
import TagInput from "./TagInput.svelte";
|
||||||
import WithAutocomplete from "./WithAutocomplete.svelte";
|
import WithAutocomplete from "./WithAutocomplete.svelte";
|
||||||
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
||||||
import { controlPressed } from "lib/keys";
|
import { controlPressed } from "lib/keys";
|
||||||
import type { Tag as TagType } from "./tags";
|
import type { Tag as TagType } from "./tags";
|
||||||
import {
|
import { attachId, getName, replaceWithDelimChar, replaceWithColon } from "./tags";
|
||||||
attachId,
|
|
||||||
getName,
|
|
||||||
delimChar,
|
|
||||||
replaceWithDelimChar,
|
|
||||||
replaceWithColon,
|
|
||||||
} from "./tags";
|
|
||||||
|
|
||||||
export let size = isApplePlatform() ? 1.6 : 2.0;
|
export let size = isApplePlatform() ? 1.6 : 2.0;
|
||||||
|
|
||||||
|
@ -377,20 +371,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
// typically correct for rows < 7
|
// typically correct for rows < 7
|
||||||
$: assumedRows = Math.floor(height / badgeHeight);
|
$: assumedRows = Math.floor(height / badgeHeight);
|
||||||
$: shortenTags = shortenTags || assumedRows > 2;
|
$: shortenTags = shortenTags || assumedRows > 2;
|
||||||
|
|
||||||
function processTagName(name: string): string {
|
|
||||||
const parts = name.split(delimChar);
|
|
||||||
|
|
||||||
if (parts.length === 1) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `…${delimChar}` + parts[parts.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasMultipleParts(name: string): boolean {
|
|
||||||
return name.split(delimChar).length > 1;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Spacer --height={`${height}px`} />
|
<Spacer --height={`${height}px`} />
|
||||||
|
@ -419,16 +399,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
{#each tags as tag, index (tag.id)}
|
{#each tags as tag, index (tag.id)}
|
||||||
<div class="position-relative gap" class:hide-tag={index === active}>
|
<div class="position-relative gap" class:hide-tag={index === active}>
|
||||||
<Tag
|
<TagWithTooltip
|
||||||
class="me-1"
|
class="me-1"
|
||||||
name={index === active
|
name={index === active ? activeName : tag.name}
|
||||||
? activeName
|
tooltip={tag.name}
|
||||||
: shortenTags
|
active={index === active}
|
||||||
? processTagName(tag.name)
|
shorten={shortenTags}
|
||||||
: tag.name}
|
|
||||||
tooltip={shortenTags && hasMultipleParts(tag.name)
|
|
||||||
? tag.name
|
|
||||||
: undefined}
|
|
||||||
bind:flash={tag.flash}
|
bind:flash={tag.flash}
|
||||||
bind:selected={tag.selected}
|
bind:selected={tag.selected}
|
||||||
on:tagedit={() => {
|
on:tagedit={() => {
|
||||||
|
|
65
ts/editor/TagWithTooltip.svelte
Normal file
65
ts/editor/TagWithTooltip.svelte
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<!--
|
||||||
|
Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
-->
|
||||||
|
<script lang="typescript">
|
||||||
|
import WithTooltip from "components/WithTooltip.svelte";
|
||||||
|
import Tag from "./Tag.svelte";
|
||||||
|
|
||||||
|
import { delimChar } from "./tags";
|
||||||
|
|
||||||
|
export let name: string;
|
||||||
|
let className: string = "";
|
||||||
|
export { className as class };
|
||||||
|
|
||||||
|
export let tooltip: string;
|
||||||
|
|
||||||
|
export let selected: boolean;
|
||||||
|
export let active: boolean;
|
||||||
|
export let shorten: boolean;
|
||||||
|
|
||||||
|
export let flash: () => void;
|
||||||
|
|
||||||
|
function processTagName(name: string): string {
|
||||||
|
const parts = name.split(delimChar);
|
||||||
|
|
||||||
|
if (parts.length === 1) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `…${delimChar}` + parts[parts.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasMultipleParts(name: string): boolean {
|
||||||
|
return name.split(delimChar).length > 1;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if active}
|
||||||
|
<Tag class={className} {name} />
|
||||||
|
{:else if shorten && hasMultipleParts(name)}
|
||||||
|
<WithTooltip {tooltip} placement="auto" let:createTooltip>
|
||||||
|
<Tag
|
||||||
|
class={className}
|
||||||
|
name={processTagName(name)}
|
||||||
|
bind:flash
|
||||||
|
bind:selected
|
||||||
|
on:tagedit
|
||||||
|
on:tagselect
|
||||||
|
on:tagrange
|
||||||
|
on:tagdelete
|
||||||
|
on:mount={(event) => createTooltip(event.detail.button)}
|
||||||
|
/>
|
||||||
|
</WithTooltip>
|
||||||
|
{:else}
|
||||||
|
<Tag
|
||||||
|
class={className}
|
||||||
|
{name}
|
||||||
|
bind:flash
|
||||||
|
bind:selected
|
||||||
|
on:tagedit
|
||||||
|
on:tagselect
|
||||||
|
on:tagrange
|
||||||
|
on:tagdelete
|
||||||
|
/>
|
||||||
|
{/if}
|
4
ts/editor/bootstrap.scss
vendored
4
ts/editor/bootstrap.scss
vendored
|
@ -7,3 +7,7 @@ $btn-disabled-opacity: 0.4;
|
||||||
@import "bootstrap/scss/buttons";
|
@import "bootstrap/scss/buttons";
|
||||||
@import "bootstrap/scss/button-group";
|
@import "bootstrap/scss/button-group";
|
||||||
@import "bootstrap/scss/dropdown";
|
@import "bootstrap/scss/dropdown";
|
||||||
|
|
||||||
|
$tooltip-max-width: 600px;
|
||||||
|
|
||||||
|
@import "bootstrap/scss/tooltip";
|
||||||
|
|
Loading…
Reference in a new issue