diff --git a/package.json b/package.json index 2ca073a6..c40c6d20 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "bits-ui": "^2.9.6", "fluid-dnd": "^2.6.2", "modern-normalize": "^3.0.1", + "wx-grid-data-provider": "^2.2.0", "wx-svelte-grid": "^2.0.0", "zod": "^4.1.5" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23c104a1..044d3d2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: modern-normalize: specifier: ^3.0.1 version: 3.0.1 + wx-grid-data-provider: + specifier: ^2.2.0 + version: 2.2.0 wx-svelte-grid: specifier: ^2.0.0 version: 2.2.0 diff --git a/src/app.scss b/src/app.scss index abc81431..4968e36e 100644 --- a/src/app.scss +++ b/src/app.scss @@ -43,6 +43,11 @@ main { @media (max-width: 768px) { padding: 0 spacing.$unit; } + + // Wider layout for database pages + &.database-layout { + max-width: 1400px; + } } // Utility classes for different container widths diff --git a/src/lib/api/resources/search.ts b/src/lib/api/resources/search.ts index bc0fe803..0cf1909e 100644 --- a/src/lib/api/resources/search.ts +++ b/src/lib/api/resources/search.ts @@ -18,6 +18,7 @@ export interface SearchParams { locale?: 'en' | 'ja' exclude?: string[] page?: number + per?: number filters?: { element?: number[] rarity?: number[] @@ -43,9 +44,15 @@ export interface SearchResult { export interface SearchResponse { results: SearchResult[] - total: number - page: number - total_pages: number + total?: number + page?: number + total_pages?: number + meta?: { + count: number + page: number + per_page: number + total_pages: number + } } export function searchAll( @@ -72,7 +79,8 @@ export function searchWeapons( ): Promise { const body: any = { locale: params.locale || 'en', - page: params.page || 1 + page: params.page || 1, + per: params.per || undefined } // Only include query if it's provided and not empty @@ -92,7 +100,13 @@ export function searchWeapons( } const url = `${API_BASE}/search/weapons` - return searchJson(fetchFn, url, body) + console.log('[searchWeapons] Making request to:', url) + console.log('[searchWeapons] Request body:', body) + + return searchJson(fetchFn, url, body).then(response => { + console.log('[searchWeapons] Response received:', response) + return response + }) } export function searchCharacters( @@ -102,7 +116,8 @@ export function searchCharacters( ): Promise { const body: any = { locale: params.locale || 'en', - page: params.page || 1 + page: params.page || 1, + per: params.per || undefined } // Only include query if it's provided and not empty @@ -132,7 +147,8 @@ export function searchSummons( ): Promise { const body: any = { locale: params.locale || 'en', - page: params.page || 1 + page: params.page || 1, + per: params.per || undefined } // Only include query if it's provided and not empty @@ -152,4 +168,4 @@ export function searchSummons( const url = `${API_BASE}/search/summons` return searchJson(fetchFn, url, body) -} \ No newline at end of file +} diff --git a/src/lib/components/Navigation.svelte b/src/lib/components/Navigation.svelte index 98107c31..3f333d95 100644 --- a/src/lib/components/Navigation.svelte +++ b/src/lib/components/Navigation.svelte @@ -5,6 +5,7 @@ import { m } from '$lib/paraglide/messages' import Button from './ui/button/Button.svelte' import Icon from './Icon.svelte' + import DropdownItem from './ui/dropdown/DropdownItem.svelte' import { DropdownMenu } from 'bits-ui' // Props from layout data @@ -53,20 +54,21 @@ - + {m.nav_settings()} - + {#if role !== null && role >= 7} - + Database - + {/if} {#if isAuth} - + +
-
+ {/if}
@@ -214,43 +216,10 @@ } } - :global(.dropdown-item) { - display: flex; - align-items: center; - padding: spacing.$unit (spacing.$unit * 1.5); - border-radius: 6px; - font-size: typography.$font-small; - font-weight: typography.$medium; - color: var(--menu-text); - cursor: pointer; - outline: none; - transition: background-color 0.15s ease; - user-select: none; - text-decoration: none; - - &:hover { - background-color: var(--menu-bg-item-hover); - } - - &:focus-visible { - background-color: var(--menu-bg-item-hover); - outline: 2px solid var(--accent-blue-focus); - outline-offset: -2px; - } - - form { - width: 100%; - } - - button { - width: 100%; - text-align: left; - background: none; - border: none; - color: inherit; - font: inherit; - cursor: inherit; - padding: 0; - } + // Dropdown separator styles + :global(.dropdown-separator) { + height: 1px; + background-color: var(--menu-border, rgba(0, 0, 0, 0.1)); + margin: spacing.$unit-half 0; } diff --git a/src/lib/components/database/cells/ProficiencyCell.svelte b/src/lib/components/database/cells/ProficiencyCell.svelte index 00564b19..f4d92d5d 100644 --- a/src/lib/components/database/cells/ProficiencyCell.svelte +++ b/src/lib/components/database/cells/ProficiencyCell.svelte @@ -14,7 +14,7 @@
- +
\ No newline at end of file + diff --git a/src/lib/components/labels/ElementLabel.svelte b/src/lib/components/labels/ElementLabel.svelte index 2c4ab9c3..1b3a33c7 100644 --- a/src/lib/components/labels/ElementLabel.svelte +++ b/src/lib/components/labels/ElementLabel.svelte @@ -26,12 +26,6 @@ vertical-align: middle; object-fit: contain; - &.natural { - // Display at natural size (34px height) - height: 34px; - width: auto; - } - &.small { height: 20px; width: auto; diff --git a/src/lib/components/labels/ProficiencyLabel.svelte b/src/lib/components/labels/ProficiencyLabel.svelte index 5593e292..9239f3a5 100644 --- a/src/lib/components/labels/ProficiencyLabel.svelte +++ b/src/lib/components/labels/ProficiencyLabel.svelte @@ -31,20 +31,12 @@ vertical-align: middle; object-fit: contain; - &.natural { - // Display at natural size (34px height) - height: 34px; - width: auto; - } - &.small { - // Half of natural size - height: 17px; + height: 20px; width: auto; } &.medium { - // ~75% of natural size height: 25px; width: auto; } @@ -56,9 +48,8 @@ } &.xlarge { - // 1.5x natural size height: 51px; width: auto; } } - \ No newline at end of file + diff --git a/src/lib/types/api/entities.ts b/src/lib/types/api/entities.ts index 062cecef..f0ac6ded 100644 --- a/src/lib/types/api/entities.ts +++ b/src/lib/types/api/entities.ts @@ -47,9 +47,10 @@ export interface Character { element: number rarity: number maxLevel: number - flb: boolean - ulb: boolean - transcendence: boolean + uncap: { + flb: boolean + ulb: boolean + } special: boolean recruits: string | null } @@ -62,9 +63,11 @@ export interface Summon { element: number rarity: number maxLevel: number - flb: boolean - ulb: boolean - transcendence: boolean + uncap: { + flb: boolean + ulb: boolean + transcendence: boolean + } subaura: boolean hp: { minHp: number diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 05e5e67a..d4c24a4c 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -20,7 +20,7 @@
- + {@render children?.()}
diff --git a/src/routes/test-ui/+page.svelte b/src/routes/test-ui/+page.svelte index be619a72..1c5d4c34 100644 --- a/src/routes/test-ui/+page.svelte +++ b/src/routes/test-ui/+page.svelte @@ -5,7 +5,6 @@ import Switch from '$lib/components/ui/switch/Switch.svelte'; import Checkbox from '$lib/components/ui/checkbox/Checkbox.svelte'; import { SegmentedControl, Segment } from '$lib/components/ui/segmented-control'; - import { Heart, Save, Settings, ChevronRight, Search, User } from 'lucide-svelte'; let inputValue = $state(''); let selectValue = $state('option1'); @@ -40,16 +39,16 @@ - +

Button with Icons

- - - + + +
@@ -92,14 +91,12 @@ /> diff --git a/src/stories/Button.stories.svelte b/src/stories/Button.stories.svelte index 71870899..6d61d2b5 100644 --- a/src/stories/Button.stories.svelte +++ b/src/stories/Button.stories.svelte @@ -1,24 +1,24 @@ diff --git a/src/stories/Header.svelte b/src/stories/Header.svelte index d6b7b216..5e0fe9f6 100644 --- a/src/stories/Header.svelte +++ b/src/stories/Header.svelte @@ -1,45 +1,45 @@
-
-
- - - - - - - -

Acme

-
-
- {#if user} - - Welcome, {user.name}! - -
-
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
diff --git a/src/themes/_colors.scss b/src/themes/_colors.scss index 2644b0f0..9ac884d9 100644 --- a/src/themes/_colors.scss +++ b/src/themes/_colors.scss @@ -616,3 +616,10 @@ $light--shadow--dark: color.adjust($light-text-20, $alpha: -0.3); $light--shadow--light--hover: color.adjust($light-text-00, $alpha: -0.3); $light--shadow--dark--hover: color.adjust($light-text-00, $alpha: -0.3); + +// Focus ring styles (commonly used with $blue) +@mixin focus-ring($color: $blue, $width: 2px) { + outline: none; + border: $width solid $color; + box-shadow: 0 0 0 2px rgba($color, 0.2); +} diff --git a/src/themes/_effects.scss b/src/themes/_effects.scss index 8fa3e1fd..ac21af7a 100644 --- a/src/themes/_effects.scss +++ b/src/themes/_effects.scss @@ -1,3 +1,5 @@ +@use 'sass:list'; + // Shadows $hover-stroke: 1px solid rgba(0, 0, 0, 0.1); $hover-shadow: rgba(0, 0, 0, 0.08) 0px 0px 14px; @@ -7,6 +9,9 @@ $duration-modal-open: 0.48s; $duration-color-fade: 0.24s; $duration-zoom: 0.18s; $duration-opacity-fade: 0.12s; +$duration-instant: 100ms; // For immediate feedback (switch toggle) +$duration-quick: 0.15s; // For quick transitions (dropdowns, menus) +$duration-standard: 0.2s; // For standard animations (modals, segments) // Gradients $hero--gradient--light: @@ -67,3 +72,16 @@ $hero--gradient--dark--overlay: rgba(25, 25, 25, 0) 78%, rgba(25, 25, 25, 1) 95% ); + +// Smooth transition helper mixin +@mixin smooth-transition($duration: $duration-zoom, $properties...) { + @if list.length($properties) == 0 { + transition: $duration all ease-out; + } @else { + $transitions: (); + @each $prop in $properties { + $transitions: list.append($transitions, $duration #{$prop} ease-out, comma); + } + transition: $transitions; + } +} diff --git a/src/themes/_spacing.scss b/src/themes/_spacing.scss index e1f2c0c0..16695fbf 100644 --- a/src/themes/_spacing.scss +++ b/src/themes/_spacing.scss @@ -23,13 +23,16 @@ $unit: 8px; $unit-fourth: calc($unit / 4); $unit-half: calc($unit / 2); +$unit-three-quarter: calc($unit * 0.75); // 6px - common gap/small spacing $unit-three-fourth: calc($unit / 4) * 3; $unit-2x: $unit * 2; $unit-3x: $unit * 3; $unit-4x: $unit * 4; $unit-5x: $unit * 5; $unit-6x: $unit * 6; +$unit-7x: $unit * 7; // 56px $unit-8x: $unit * 8; +$unit-9x: $unit * 9; // 72px $unit-10x: $unit * 10; $unit-12x: $unit * 12; $unit-14x: $unit * 14;