fix(badges): fix search-result layout shift + unify empty/loading states
Scrollbar shift: - Add [scrollbar-gutter:stable] to #ae_main_content in events layout so a scrollbar appearing on first results load no longer reflows the centered search form (was shifting ~8px left on Linux) Empty/loading state consistency: - Move search_status prop into ae_comp__badge_obj_li so it can swap its own empty state: spinner + "Searching..." while a search is in progress, UserSearch icon + prompt text otherwise - Unify p-16 / size-3em / mb-2 / text-xl across all three states (initial load, searching, no results) so height never jumps between transitions - Pass search_status from +page.svelte to the component Transitions: - transition:fade on initial-load spinner div - transition:slide on Create/Upload badge button row (appears with edit mode) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -210,7 +210,7 @@ function clear_sess() {
|
|||||||
container m-auto flex h-full min-h-full
|
container m-auto flex h-full min-h-full
|
||||||
w-full max-w-7xl
|
w-full max-w-7xl
|
||||||
min-w-full flex-col gap-1
|
min-w-full flex-col gap-1
|
||||||
overflow-auto
|
overflow-auto [scrollbar-gutter:stable]
|
||||||
|
|
||||||
bg-gray-50 text-gray-800
|
bg-gray-50 text-gray-800
|
||||||
dark:bg-gray-900 dark:text-gray-200
|
dark:bg-gray-900 dark:text-gray-200
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
|
import { slide, fade } from 'svelte/transition';
|
||||||
interface Props {
|
interface Props {
|
||||||
/** @type {import('./$types').PageData} */
|
/** @type {import('./$types').PageData} */
|
||||||
data: any;
|
data: any;
|
||||||
@@ -472,7 +473,7 @@ async function handle_search_refresh(params: any) {
|
|||||||
></Comp_badge_search>
|
></Comp_badge_search>
|
||||||
|
|
||||||
{#if $ae_loc.trusted_access && $ae_loc.edit_mode}
|
{#if $ae_loc.trusted_access && $ae_loc.edit_mode}
|
||||||
<div class="flex flex-row gap-1 items-center justify-center">
|
<div transition:slide={{ duration: 200 }} class="flex flex-row gap-1 items-center justify-center">
|
||||||
{#if badges_loc.current.enable_add_badge_btn ?? true}
|
{#if badges_loc.current.enable_add_badge_btn ?? true}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -593,12 +594,16 @@ async function handle_search_refresh(params: any) {
|
|||||||
|
|
||||||
{#if $events_sess?.badges?.search_status === 'loading' && event_badge_id_li.length === 0}
|
{#if $events_sess?.badges?.search_status === 'loading' && event_badge_id_li.length === 0}
|
||||||
<div
|
<div
|
||||||
class="flex flex-col items-center justify-center p-10 text-center opacity-50">
|
transition:fade={{ duration: 200 }}
|
||||||
<LoaderCircle size="3em" class="mx-auto mb-4 animate-spin" />
|
class="flex w-full flex-col items-center justify-center p-16 text-center opacity-50">
|
||||||
|
<LoaderCircle size="3em" class="mx-auto mb-2 animate-spin" />
|
||||||
<p class="text-xl">Loading badges...</p>
|
<p class="text-xl">Loading badges...</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Comp_badge_obj_li {lq__event_badge_obj_li} log_lvl={1}></Comp_badge_obj_li>
|
<Comp_badge_obj_li
|
||||||
|
{lq__event_badge_obj_li}
|
||||||
|
search_status={$events_sess?.badges?.search_status ?? null}
|
||||||
|
log_lvl={1} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
container_class_li?: string | Array<string>;
|
container_class_li?: string | Array<string>;
|
||||||
lq__event_badge_obj_li: any;
|
lq__event_badge_obj_li: any;
|
||||||
|
search_status?: string | null;
|
||||||
log_lvl?: number;
|
log_lvl?: number;
|
||||||
show_sensitive_fields?: boolean;
|
show_sensitive_fields?: boolean;
|
||||||
hide_affiliations?: boolean;
|
hide_affiliations?: boolean;
|
||||||
@@ -12,6 +13,7 @@ interface Props {
|
|||||||
let {
|
let {
|
||||||
container_class_li = [],
|
container_class_li = [],
|
||||||
lq__event_badge_obj_li,
|
lq__event_badge_obj_li,
|
||||||
|
search_status = null,
|
||||||
log_lvl = $bindable(0),
|
log_lvl = $bindable(0),
|
||||||
show_sensitive_fields = true,
|
show_sensitive_fields = true,
|
||||||
hide_affiliations = false,
|
hide_affiliations = false,
|
||||||
@@ -408,12 +410,16 @@ let visible_badge_obj_li = $derived(
|
|||||||
</ul>
|
</ul>
|
||||||
{:else}
|
{:else}
|
||||||
<div
|
<div
|
||||||
class="flex w-full flex-col items-center justify-center p-20 text-center opacity-50">
|
class="flex w-full flex-col items-center justify-center p-16 text-center opacity-50">
|
||||||
<UserSearch size="3em" class="mx-auto mb-2 opacity-20" />
|
{#if search_status === 'loading'}
|
||||||
{#if !is_trusted && !(badges_loc.current.fulltext_search_qry_str ?? '').trim()}
|
<LoaderCircle size="3em" class="mx-auto mb-2 animate-spin" />
|
||||||
<p>Enter your name above to find your badge.</p>
|
<p class="text-xl">Searching...</p>
|
||||||
|
{:else if !is_trusted && !(badges_loc.current.fulltext_search_qry_str ?? '').trim()}
|
||||||
|
<UserSearch size="3em" class="mx-auto mb-2 opacity-20" />
|
||||||
|
<p class="text-xl">Enter your name above to find your badge.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p>No badges found matching your criteria. Try adjusting your filters.</p>
|
<UserSearch size="3em" class="mx-auto mb-2 opacity-20" />
|
||||||
|
<p class="text-xl">No badges found matching your criteria.</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user