selection mode ui tweaks: element-ghost buttons, clear button, fixed nav height

This commit is contained in:
Justin Edmund 2025-12-19 12:26:38 -08:00
parent 2ebe9ec086
commit 1bac7fc846
2 changed files with 78 additions and 45 deletions

View file

@ -508,6 +508,7 @@
color: var(--wind-button-bg); color: var(--wind-button-bg);
&:hover:not(:disabled) { &:hover:not(:disabled) {
background-color: var(--wind-nav-selected-bg); background-color: var(--wind-nav-selected-bg);
color: var(--wind-nav-selected-text);
} }
} }
@ -515,6 +516,7 @@
color: var(--fire-button-bg); color: var(--fire-button-bg);
&:hover:not(:disabled) { &:hover:not(:disabled) {
background-color: var(--fire-nav-selected-bg); background-color: var(--fire-nav-selected-bg);
color: var(--fire-nav-selected-text);
} }
} }
@ -522,6 +524,7 @@
color: var(--water-button-bg); color: var(--water-button-bg);
&:hover:not(:disabled) { &:hover:not(:disabled) {
background-color: var(--water-nav-selected-bg); background-color: var(--water-nav-selected-bg);
color: var(--water-nav-selected-text);
} }
} }
@ -529,6 +532,7 @@
color: var(--earth-button-bg); color: var(--earth-button-bg);
&:hover:not(:disabled) { &:hover:not(:disabled) {
background-color: var(--earth-nav-selected-bg); background-color: var(--earth-nav-selected-bg);
color: var(--earth-nav-selected-text);
} }
} }
@ -536,6 +540,7 @@
color: var(--dark-button-bg); color: var(--dark-button-bg);
&:hover:not(:disabled) { &:hover:not(:disabled) {
background-color: var(--dark-nav-selected-bg); background-color: var(--dark-nav-selected-bg);
color: var(--dark-nav-selected-text);
} }
} }
@ -543,6 +548,7 @@
color: var(--light-button-bg); color: var(--light-button-bg);
&:hover:not(:disabled) { &:hover:not(:disabled) {
background-color: var(--light-nav-selected-bg); background-color: var(--light-nav-selected-bg);
color: var(--light-nav-selected-text);
} }
} }

View file

@ -3,13 +3,12 @@
import { page } from '$app/stores' import { page } from '$app/stores'
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { setContext } from 'svelte' import { setContext } from 'svelte'
import { DropdownMenu } from 'bits-ui' import { createQuery } from '@tanstack/svelte-query'
import ProfileHeader from '$lib/components/profile/ProfileHeader.svelte' import ProfileHeader from '$lib/components/profile/ProfileHeader.svelte'
import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte' import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte'
import Segment from '$lib/components/ui/segmented-control/Segment.svelte' import Segment from '$lib/components/ui/segmented-control/Segment.svelte'
import Button from '$lib/components/ui/Button.svelte' import Button from '$lib/components/ui/Button.svelte'
import Icon from '$lib/components/Icon.svelte' import DropdownMenu from '$lib/components/ui/DropdownMenu.svelte'
import DropdownItem from '$lib/components/ui/dropdown/DropdownItem.svelte'
import AddToCollectionModal from '$lib/components/collection/AddToCollectionModal.svelte' import AddToCollectionModal from '$lib/components/collection/AddToCollectionModal.svelte'
import BulkDeleteConfirmModal from '$lib/components/collection/BulkDeleteConfirmModal.svelte' import BulkDeleteConfirmModal from '$lib/components/collection/BulkDeleteConfirmModal.svelte'
import { openAddArtifactSidebar } from '$lib/features/collection/openAddArtifactSidebar' import { openAddArtifactSidebar } from '$lib/features/collection/openAddArtifactSidebar'
@ -25,9 +24,18 @@
useBulkRemoveSummonsFromCollection useBulkRemoveSummonsFromCollection
} from '$lib/api/mutations/collection.mutations' } from '$lib/api/mutations/collection.mutations'
import { useBulkDeleteCollectionArtifacts } from '$lib/api/mutations/artifact.mutations' import { useBulkDeleteCollectionArtifacts } from '$lib/api/mutations/artifact.mutations'
import { collectionQueries } from '$lib/api/queries/collection.queries'
let { data, children }: { data: LayoutData; children: any } = $props() let { data, children }: { data: LayoutData; children: any } = $props()
// Query for collection counts
const countsQuery = createQuery(() => collectionQueries.counts(data.user?.id ?? ''))
// User's element for elemental styling
const userElement = $derived(
data.user?.avatar?.element as 'wind' | 'fire' | 'water' | 'earth' | 'dark' | 'light' | undefined
)
// Bulk delete mutations // Bulk delete mutations
const bulkDeleteCharacters = useBulkRemoveCharactersFromCollection() const bulkDeleteCharacters = useBulkRemoveCharactersFromCollection()
const bulkDeleteWeapons = useBulkRemoveWeaponsFromCollection() const bulkDeleteWeapons = useBulkRemoveWeaponsFromCollection()
@ -102,6 +110,10 @@
selectionMode.selectAll(loadedIds) selectionMode.selectAll(loadedIds)
} }
function handleClearSelection() {
selectionMode.clearSelection()
}
function handleDeleteClick() { function handleDeleteClick() {
if (selectionMode.selectedCount > 0) { if (selectionMode.selectedCount > 0) {
confirmDeleteOpen = true confirmDeleteOpen = true
@ -169,7 +181,16 @@
<!-- Selection mode UI --> <!-- Selection mode UI -->
<div class="selection-controls-left"> <div class="selection-controls-left">
<span class="selection-count">{selectionMode.selectedCount} selected</span> <span class="selection-count">{selectionMode.selectedCount} selected</span>
<button class="select-all-link" onclick={handleSelectAll}>Select all</button> <div class="selection-buttons">
<Button variant="element-ghost" size="small" element={userElement} onclick={handleSelectAll}>
Select all
</Button>
{#if selectionMode.selectedCount > 0}
<Button variant="element-ghost" size="small" element={userElement} onclick={handleClearSelection}>
Clear
</Button>
{/if}
</div>
</div> </div>
<div class="selection-controls-right"> <div class="selection-controls-right">
<Button <Button
@ -191,11 +212,32 @@
onValueChange={handleTabChange} onValueChange={handleTabChange}
variant="blended" variant="blended"
size="small" size="small"
element={userElement}
> >
<Segment value="characters">Characters</Segment> <Segment value="characters">
<Segment value="weapons">Weapons</Segment> Characters
<Segment value="summons">Summons</Segment> {#if countsQuery.data?.characters != null}
<Segment value="artifacts">Artifacts</Segment> <span class="count">{countsQuery.data.characters}</span>
{/if}
</Segment>
<Segment value="weapons">
Weapons
{#if countsQuery.data?.weapons != null}
<span class="count">{countsQuery.data.weapons}</span>
{/if}
</Segment>
<Segment value="summons">
Summons
{#if countsQuery.data?.summons != null}
<span class="count">{countsQuery.data.summons}</span>
{/if}
</Segment>
<Segment value="artifacts">
Artifacts
{#if countsQuery.data?.artifacts != null}
<span class="count">{countsQuery.data.artifacts}</span>
{/if}
</Segment>
</SegmentedControl> </SegmentedControl>
{#if data.isOwner} {#if data.isOwner}
@ -222,24 +264,16 @@
</Button> </Button>
{/if} {/if}
<DropdownMenu.Root> <DropdownMenu>
<DropdownMenu.Trigger> {#snippet trigger({ props })}
{#snippet child({ props })} <Button {...props} variant="ghost" size="small" iconOnly icon="ellipsis" />
<Button {...props} variant="ghost" size="icon" icon="ellipsis" /> {/snippet}
{/snippet} {#snippet menu()}
</DropdownMenu.Trigger> <button type="button" class="dropdown-menu-item" onclick={handleEnterSelectionMode}>
Select {activeEntityType}...
<DropdownMenu.Portal> </button>
<DropdownMenu.Content class="collection-dropdown-menu" sideOffset={5} align="end"> {/snippet}
<DropdownItem> </DropdownMenu>
<button onclick={handleEnterSelectionMode}>
<Icon name="check" size={14} />
<span>Select...</span>
</button>
</DropdownItem>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
</div> </div>
{/if} {/if}
{/if} {/if}
@ -288,6 +322,7 @@
justify-content: space-between; justify-content: space-between;
gap: $unit-2x; gap: $unit-2x;
padding: $unit-2x; padding: $unit-2x;
min-height: 74px;
} }
.content { .content {
@ -302,11 +337,6 @@
gap: $unit; gap: $unit;
} }
// Dropdown menu z-index fix
:global(.collection-dropdown-menu) {
z-index: 200;
}
// Selection mode controls // Selection mode controls
.selection-controls-left { .selection-controls-left {
display: flex; display: flex;
@ -315,24 +345,14 @@
} }
.selection-count { .selection-count {
font-size: $font-regular; font-size: $font-small;
font-weight: $medium; font-weight: $medium;
color: var(--text-primary); color: var(--text-primary);
} }
.select-all-link { .selection-buttons {
background: none; display: flex;
border: none; gap: $unit;
padding: 0;
font-size: $font-small;
font-weight: $medium;
color: var(--accent-color);
cursor: pointer;
text-decoration: none;
&:hover {
text-decoration: underline;
}
} }
.selection-controls-right { .selection-controls-right {
@ -340,4 +360,11 @@
align-items: center; align-items: center;
gap: $unit; gap: $unit;
} }
// Count badge in segment tabs
.count {
margin-left: $unit-half;
color: inherit;
opacity: 0.7;
}
</style> </style>