mirror of
https://codeberg.org/pronounscc/pronouns.cc.git
synced 2024-11-20 12:39:51 +01:00
feat: improve icon picker
This commit is contained in:
parent
48b41c7135
commit
6decfab248
3 changed files with 78 additions and 31 deletions
|
@ -8,6 +8,8 @@
|
|||
export let disabled = false;
|
||||
export let type: string | undefined = undefined;
|
||||
export let id: string | undefined = undefined;
|
||||
export let outline: boolean | undefined = undefined;
|
||||
export let border = true;
|
||||
|
||||
export let click: ((e: MouseEvent) => void) | undefined = undefined;
|
||||
export let href: string | undefined = undefined;
|
||||
|
@ -23,6 +25,8 @@
|
|||
{active}
|
||||
{disabled}
|
||||
{href}
|
||||
{outline}
|
||||
class={border ? undefined : "border-0"}
|
||||
aria-label={tooltip}
|
||||
on:click={click}
|
||||
bind:inner={button}
|
||||
|
|
|
@ -7,51 +7,22 @@
|
|||
DropdownMenu,
|
||||
DropdownToggle,
|
||||
Icon,
|
||||
Input,
|
||||
InputGroup,
|
||||
Tooltip,
|
||||
} from "sveltestrap";
|
||||
import icons from "../../../icons";
|
||||
import IconPicker from "./IconPicker.svelte";
|
||||
|
||||
export let preference: CustomPreference;
|
||||
export let remove: () => void;
|
||||
|
||||
let iconButton: HTMLElement;
|
||||
let sizeButton: HTMLElement;
|
||||
|
||||
const toggleMuted = () => (preference.muted = !preference.muted);
|
||||
const toggleFavourite = () => (preference.favourite = !preference.favourite);
|
||||
|
||||
let searchBox = "";
|
||||
let filteredIcons: string[] = [];
|
||||
$: filteredIcons = searchBox
|
||||
? icons
|
||||
.filter((icon) => icon.startsWith(searchBox))
|
||||
.sort()
|
||||
.slice(0, 15)
|
||||
: [];
|
||||
</script>
|
||||
|
||||
<InputGroup class="m-1">
|
||||
<ButtonDropdown>
|
||||
<Tooltip target={iconButton} placement="top">Change icon</Tooltip>
|
||||
<DropdownToggle color="secondary" caret bind:inner={iconButton}>
|
||||
<Icon name={preference.icon} alt="Current icon" />
|
||||
</DropdownToggle>
|
||||
<DropdownMenu>
|
||||
<p class="px-2">
|
||||
<Input type="text" placeholder="Search for icons" bind:value={searchBox} />
|
||||
</p>
|
||||
<DropdownItem divider />
|
||||
{#each filteredIcons as icon}
|
||||
<DropdownItem active={preference.icon === icon} on:click={() => (preference.icon = icon)}
|
||||
><Icon name={icon} alt="Icon: {icon}" /> {icon}</DropdownItem
|
||||
>
|
||||
{:else}
|
||||
<p class="px-2">Start typing to filter</p>
|
||||
{/each}
|
||||
</DropdownMenu>
|
||||
</ButtonDropdown>
|
||||
<IconPicker bind:icon={preference.icon} />
|
||||
<input type="text" class="form-control" bind:value={preference.tooltip} />
|
||||
<Tooltip target={sizeButton} placement="top">Change text size</Tooltip>
|
||||
<ButtonDropdown>
|
||||
|
|
72
frontend/src/routes/edit/profile/IconPicker.svelte
Normal file
72
frontend/src/routes/edit/profile/IconPicker.svelte
Normal file
|
@ -0,0 +1,72 @@
|
|||
<script lang="ts">
|
||||
import {
|
||||
Button,
|
||||
ButtonDropdown,
|
||||
DropdownItem,
|
||||
DropdownMenu,
|
||||
DropdownToggle,
|
||||
Icon,
|
||||
Input,
|
||||
Tooltip,
|
||||
} from "sveltestrap";
|
||||
import icons from "../../../icons";
|
||||
import IconButton from "$lib/components/IconButton.svelte";
|
||||
|
||||
export let icon = "";
|
||||
|
||||
const MAX_VISIBLE_ITEMS = 21;
|
||||
|
||||
let searchBox = "";
|
||||
let showAll = false;
|
||||
let filteredIcons: string[] = [];
|
||||
$: filteredIcons = icons
|
||||
.filter((icon) => icon.toLowerCase().includes(searchBox.toLowerCase()))
|
||||
.sort()
|
||||
.slice(0, showAll ? undefined : MAX_VISIBLE_ITEMS);
|
||||
|
||||
let iconCount = 0;
|
||||
$: iconCount = icons.filter((icon) =>
|
||||
icon.toLowerCase().includes(searchBox.toLowerCase()),
|
||||
).length;
|
||||
|
||||
let iconButton: HTMLElement;
|
||||
</script>
|
||||
|
||||
<ButtonDropdown autoClose={false}>
|
||||
<Tooltip target={iconButton} placement="top">Change icon</Tooltip>
|
||||
<DropdownToggle color="secondary" caret bind:inner={iconButton}>
|
||||
<Icon name={icon} alt="Current icon" />
|
||||
</DropdownToggle>
|
||||
<DropdownMenu>
|
||||
<p class="px-2">
|
||||
<Input type="text" placeholder="Search for icons" bind:value={searchBox} />
|
||||
</p>
|
||||
<ul class="list-unstyled icon-list text-center">
|
||||
{#each filteredIcons as iconOption}
|
||||
<li class="list-inline-item">
|
||||
<IconButton
|
||||
icon={iconOption}
|
||||
tooltip={iconOption}
|
||||
outline
|
||||
border={false}
|
||||
color="secondary"
|
||||
click={() => (icon = iconOption)}
|
||||
/>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{#if iconCount > MAX_VISIBLE_ITEMS || showAll}
|
||||
<DropdownItem divider />
|
||||
<DropdownItem toggle={true} on:click={() => (showAll = !showAll)}
|
||||
>{showAll ? "Stop showing all results" : `Show all results (${iconCount})`}</DropdownItem
|
||||
>
|
||||
{/if}
|
||||
</DropdownMenu>
|
||||
</ButtonDropdown>
|
||||
|
||||
<style>
|
||||
.icon-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
Loading…
Reference in a new issue