refactor: migrate templates to tailwind utilities
This commit is contained in:
@@ -15,37 +15,37 @@ type AnimeCardProps struct {
|
||||
|
||||
templ AnimeCard(props AnimeCardProps) {
|
||||
if props.CurrentNode {
|
||||
<div class={ defaultString(props.Class, "catalog-item") }>
|
||||
<div class={ defaultString(props.Class, "min-w-0") }>
|
||||
if props.ImageURL != "" {
|
||||
<img src={ props.ImageURL } alt={ props.Title } class={ defaultString(props.ImgClass, "catalog-thumb") } loading="lazy"/>
|
||||
<img src={ props.ImageURL } alt={ props.Title } class={ defaultString(props.ImgClass, "block aspect-[2/3] max-h-[var(--poster-max-height)] w-full object-cover object-center") } loading="lazy"/>
|
||||
} else {
|
||||
<div class="no-image">No image</div>
|
||||
<div class="flex aspect-[2/3] max-h-[var(--poster-max-height)] w-full items-end justify-center overflow-hidden text-[0] text-transparent">No image</div>
|
||||
}
|
||||
<div class={ defaultString(props.TitleClass, "catalog-title") }>
|
||||
<div class={ defaultString(props.TitleClass, "mt-2 line-clamp-2 text-[0.86rem] leading-[1.3] text-[var(--text)]") }>
|
||||
{ props.Title }
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
} else {
|
||||
<a href={ templ.URL(fmt.Sprintf("/anime/%d", props.ID)) } class={ props.Class }>
|
||||
<a href={ templ.URL(fmt.Sprintf("/anime/%d", props.ID)) } class={ defaultString(props.Class, "flex flex-col bg-transparent text-inherit no-underline") }>
|
||||
if props.Class == "notification-card" || props.Class == "schedule-card" {
|
||||
<div class={ defaultString(props.ImgClass, "schedule-card-image") }>
|
||||
<div class={ defaultString(props.ImgClass, "flex aspect-[2/3] max-h-[var(--poster-max-height)] w-full items-end justify-center overflow-hidden") }>
|
||||
if props.ImageURL != "" {
|
||||
<img src={ props.ImageURL } alt={ props.Title } loading="lazy"/>
|
||||
<img src={ props.ImageURL } alt={ props.Title } class="block h-full w-full object-cover object-center" loading="lazy"/>
|
||||
} else {
|
||||
<div class="no-image">No image</div>
|
||||
<div class="flex aspect-[2/3] max-h-[var(--poster-max-height)] w-full items-end justify-center overflow-hidden text-[0] text-transparent">No image</div>
|
||||
}
|
||||
</div>
|
||||
} else {
|
||||
if props.ImageURL != "" {
|
||||
<img src={ props.ImageURL } alt={ props.Title } class={ defaultString(props.ImgClass, "catalog-thumb") } loading="lazy"/>
|
||||
<img src={ props.ImageURL } alt={ props.Title } class={ defaultString(props.ImgClass, "block aspect-[2/3] max-h-[var(--poster-max-height)] w-full object-cover object-center") } loading="lazy"/>
|
||||
} else {
|
||||
<div class="no-image">No image</div>
|
||||
<div class="flex aspect-[2/3] max-h-[var(--poster-max-height)] w-full items-end justify-center overflow-hidden text-[0] text-transparent">No image</div>
|
||||
}
|
||||
}
|
||||
|
||||
if props.Class != "notification-card" && props.Class != "schedule-card" {
|
||||
<div class={ defaultString(props.TitleClass, "catalog-title") }>
|
||||
<div class={ defaultString(props.TitleClass, "mt-2 line-clamp-2 text-[0.86rem] leading-[1.3] text-[var(--text)]") }>
|
||||
{ props.Title }
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
|
||||
templ InfiniteAnimeList(animes []jikan.Anime, hasNext bool, nextURL string, containerID string) {
|
||||
for _, anime := range animes {
|
||||
<div class="catalog-item" data-id={ fmt.Sprintf("%d", anime.MalID) }>
|
||||
<div class="min-w-0" data-id={ fmt.Sprintf("%d", anime.MalID) }>
|
||||
@CatalogItem(anime)
|
||||
</div>
|
||||
}
|
||||
if hasNext {
|
||||
<div class="scroll-trigger full-span-trigger" hx-get={ nextURL } hx-trigger="revealed" hx-swap="outerHTML"></div>
|
||||
<div class="col-span-full h-px w-full" hx-get={ nextURL } hx-trigger="revealed" hx-swap="outerHTML"></div>
|
||||
}
|
||||
<script data-container={ containerID }>
|
||||
(function() {
|
||||
@@ -20,7 +20,7 @@ templ InfiniteAnimeList(animes []jikan.Anime, hasNext bool, nextURL string, cont
|
||||
const currentScript = scripts[scripts.length - 1];
|
||||
const actualID = currentScript.getAttribute('data-container');
|
||||
const container = document.getElementById(actualID) || document;
|
||||
const items = container.querySelectorAll('.catalog-item[data-id]');
|
||||
const items = container.querySelectorAll('[data-id]');
|
||||
const seen = new Set();
|
||||
items.forEach(item => {
|
||||
const id = item.getAttribute('data-id');
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package ui
|
||||
|
||||
templ EmptyState(title string) {
|
||||
<div class="empty-state py-4">
|
||||
<div class="empty-state-title mb-2 text-base">{ title }</div>
|
||||
<div class="empty-state-text text-sm text-[var(--color-text-muted)]">
|
||||
<div class="py-4">
|
||||
<div class="mb-2 text-base">{ title }</div>
|
||||
<div class="text-sm text-[var(--text-muted)]">
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package ui
|
||||
|
||||
templ LoadingIndicator(text string) {
|
||||
<div class="loading-indicator inline-flex items-center gap-2 text-sm text-[var(--color-text-muted)]">
|
||||
<div class="loading-dot h-1.5 w-1.5 rounded-full bg-[var(--color-text-faint)]"></div>
|
||||
<div class="loading-dot h-1.5 w-1.5 rounded-full bg-[var(--color-text-faint)]"></div>
|
||||
<div class="loading-dot h-1.5 w-1.5 rounded-full bg-[var(--color-text-faint)]"></div>
|
||||
<div class="inline-flex items-center gap-2 text-sm text-[var(--text-muted)]">
|
||||
<div class="h-1.5 w-1.5 rounded-full bg-[var(--text-faint)]"></div>
|
||||
<div class="h-1.5 w-1.5 rounded-full bg-[var(--text-faint)]"></div>
|
||||
<div class="h-1.5 w-1.5 rounded-full bg-[var(--text-faint)]"></div>
|
||||
<span>{ text }</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -8,23 +8,23 @@ type SortFilterOptions struct {
|
||||
}
|
||||
|
||||
templ SortFilter(opts SortFilterOptions) {
|
||||
<div class="sort-filter">
|
||||
<div class="sort-filter-group">
|
||||
<label for="sort-select">Sort by</label>
|
||||
<select id="sort-select" class="sort-filter-select" onchange="document.getElementById('sort-input').value = this.value; document.getElementById('sort-form').submit()">
|
||||
<div class="mb-4 flex flex-wrap items-center gap-3 bg-[var(--panel)] p-3 max-[860px]:flex-col max-[860px]:items-start max-[860px]:gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<label for="sort-select" class="text-[0.78rem] text-[var(--text-muted)]">Sort by</label>
|
||||
<select id="sort-select" class="h-[30px] bg-[var(--surface-select)] px-2 text-[0.78rem] text-[var(--text)]" onchange="document.getElementById('sort-input').value = this.value; document.getElementById('sort-form').submit()">
|
||||
<option value="date" selected?={ opts.Sort == "date" }>Date added</option>
|
||||
<option value="title" selected?={ opts.Sort == "title" }>Title</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="sort-filter-group">
|
||||
<label for="order-select">Order</label>
|
||||
<select id="order-select" class="sort-filter-select" onchange="document.getElementById('order-input').value = this.value; document.getElementById('sort-form').submit()">
|
||||
<div class="flex items-center gap-2">
|
||||
<label for="order-select" class="text-[0.78rem] text-[var(--text-muted)]">Order</label>
|
||||
<select id="order-select" class="h-[30px] bg-[var(--surface-select)] px-2 text-[0.78rem] text-[var(--text)]" onchange="document.getElementById('order-input').value = this.value; document.getElementById('sort-form').submit()">
|
||||
<option value="desc" selected?={ opts.Order == "desc" }>Descending</option>
|
||||
<option value="asc" selected?={ opts.Order == "asc" }>Ascending</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<form id="sort-form" method="get" class="is-hidden">
|
||||
<form id="sort-form" method="get" class="hidden">
|
||||
<input type="hidden" name="sort" id="sort-input" value={ opts.Sort }/>
|
||||
<input type="hidden" name="order" id="order-input" value={ opts.Order }/>
|
||||
if opts.View != "" {
|
||||
|
||||
Reference in New Issue
Block a user