Files
Toju/toju-app/src/app/domains/custom-emoji/feature/custom-emoji-picker/custom-emoji-picker.component.html
Myx 85eef74bf7
Some checks failed
Build Android APK / build-android-apk (push) Has been cancelled
Deploy Web Apps / deploy (push) Has been cancelled
Queue Release Build / prepare (push) Has been cancelled
Queue Release Build / build-linux (push) Has been cancelled
Queue Release Build / build-windows (push) Has been cancelled
Queue Release Build / finalize (push) Has been cancelled
feat: Rename to Toju and add translation
2026-06-05 17:13:03 +02:00

149 lines
5.2 KiB
HTML

<div class="relative">
@if (compact()) {
<div class="flex gap-1 rounded-lg border border-border bg-card p-2 shadow-lg">
@for (entry of shortcuts(); track entry.key) {
<button
type="button"
class="grid h-10 w-10 place-items-center rounded transition-colors hover:bg-secondary"
[attr.aria-label]="entry.label"
[title]="entry.label"
(click)="selectShortcut(entry)"
>
@if (entry.kind === 'custom') {
<img
[src]="entry.emoji.dataUrl"
[alt]="entry.emoji.name"
class="h-10 w-10 object-contain"
/>
} @else {
<span class="text-[2rem] leading-none">{{ entry.emoji }}</span>
}
</button>
}
<button
type="button"
class="grid h-10 w-10 place-items-center rounded text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
aria-label="{{ 'emoji.picker.openAria' | translate }}"
title="{{ 'emoji.picker.openAria' | translate }}"
(click)="openModal()"
>
<ng-icon
name="lucideSmile"
class="h-5 w-5"
/>
</button>
</div>
}
@if (!compact() || modalOpen()) {
<div
class="rounded-lg border border-border bg-card p-3 shadow-xl"
[class.absolute]="!inline()"
[class.bottom-full]="!inline()"
[class.right-0]="!inline()"
[class.z-20]="!inline()"
[class.mb-2]="!inline()"
[class.w-72]="!inline()"
[class.w-full]="inline()"
>
@if (!inline()) {
<div class="mb-2 flex items-center justify-between gap-2">
<p class="text-sm font-semibold text-foreground">{{ 'emoji.picker.title' | translate }}</p>
@if (compact()) {
<button
type="button"
class="grid h-7 w-7 place-items-center rounded hover:bg-secondary"
aria-label="Close emoji selector"
(click)="closeModal()"
>
<ng-icon
name="lucideX"
class="h-4 w-4 text-muted-foreground"
/>
</button>
}
</div>
}
<label class="relative mb-3 block">
<ng-icon
name="lucideSearch"
class="pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"
/>
<input
type="search"
class="w-full rounded-md border border-border bg-background py-2 pl-8 pr-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary"
placeholder="{{ 'emoji.picker.searchPlaceholder' | translate }}"
aria-label="{{ 'emoji.picker.searchAria' | translate }}"
[value]="searchQuery()"
(input)="onSearchInput($event)"
/>
</label>
<label
class="mb-3 flex cursor-pointer items-center justify-center gap-2 rounded-md border border-dashed border-border px-3 py-2 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/50 hover:text-foreground"
>
<ng-icon
name="lucideUpload"
class="h-4 w-4"
/>
<span>{{ uploading() ? ('emoji.picker.uploading' | translate) : ('emoji.picker.upload' | translate) }}</span>
<input
type="file"
class="hidden"
[accept]="acceptAttribute"
[disabled]="uploading()"
(change)="uploadEmoji($event)"
/>
</label>
@if (uploadError()) {
<div class="mb-3 rounded-md border border-destructive/30 bg-destructive/10 px-2 py-1.5 text-xs text-destructive">
{{ uploadError() }}
</div>
}
@if (showEmptySearchState()) {
<div class="mb-3 rounded-md border border-border/70 bg-secondary/20 px-3 py-4 text-center text-xs text-muted-foreground">
{{ 'emoji.picker.emptySearch' | translate }}
</div>
}
@if (filteredUnicodeEntries().length > 0) {
<div class="mb-3 grid grid-cols-6 gap-1">
@for (entry of filteredUnicodeEntries(); track entry.emoji) {
<button
type="button"
class="grid h-10 w-10 place-items-center rounded transition-colors hover:bg-secondary"
(click)="selectUnicode(entry.emoji)"
>
<span class="text-[2rem] leading-none">{{ entry.emoji }}</span>
</button>
}
</div>
}
@if (filteredCustomEmojis().length > 0) {
<div class="grid max-h-44 grid-cols-6 gap-1 overflow-y-auto pr-1">
@for (emoji of filteredCustomEmojis(); track emoji.id) {
<button
type="button"
class="grid h-10 w-10 place-items-center rounded transition-colors hover:bg-secondary"
[title]="emoji.name"
data-custom-emoji-library
[attr.data-custom-emoji-id]="emoji.id"
(click)="selectCustom(emoji)"
>
<img
[src]="emoji.dataUrl"
[alt]="emoji.name"
class="h-10 w-10 object-contain"
/>
</button>
}
</div>
}
</div>
}
</div>