fix menu
This commit is contained in:
parent
80a4b9f1d1
commit
f7d23174a5
@ -22,7 +22,7 @@
|
|||||||
"@tauri-apps/plugin-shell": "^2",
|
"@tauri-apps/plugin-shell": "^2",
|
||||||
"@tauri-apps/plugin-sql": "^2.2.0",
|
"@tauri-apps/plugin-sql": "^2.2.0",
|
||||||
"ky": "^1.7.3",
|
"ky": "^1.7.3",
|
||||||
"lucide-svelte": "^0.468.0",
|
"lucide-svelte": "^0.469.0",
|
||||||
"osu-classes": "^3.1.0",
|
"osu-classes": "^3.1.0",
|
||||||
"osu-parsers": "^4.1.7",
|
"osu-parsers": "^4.1.7",
|
||||||
"radix-icons-svelte": "^1.2.1"
|
"radix-icons-svelte": "^1.2.1"
|
||||||
@ -33,7 +33,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||||
"@tauri-apps/cli": "^2",
|
"@tauri-apps/cli": "^2",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"bits-ui": "^1.0.0-next.70",
|
"bits-ui": "^1.0.0-next.74",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"sass-embedded": "^1.82.0",
|
"sass-embedded": "^1.82.0",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
|
@ -5,8 +5,13 @@
|
|||||||
<div
|
<div
|
||||||
class="absolute w-screen h-screen overflow-hidden pointer-events-none rounded"
|
class="absolute w-screen h-screen overflow-hidden pointer-events-none rounded"
|
||||||
>
|
>
|
||||||
<div
|
<img
|
||||||
|
src={background}
|
||||||
|
alt="background"
|
||||||
|
class="absolute top-0 left-0 w-full h-full !bg-cover -z-10 pointer-events-none blur opacity-10 rounded"
|
||||||
|
/>
|
||||||
|
<!-- <div
|
||||||
style="background: url(https://osu.direct/api/media/background/2226722)"
|
style="background: url(https://osu.direct/api/media/background/2226722)"
|
||||||
class="absolute top-0 left-0 w-full h-full !bg-cover -z-10 pointer-events-none blur opacity-10 rounded"
|
class="absolute top-0 left-0 w-full h-full !bg-cover -z-10 pointer-events-none blur opacity-10 rounded"
|
||||||
></div>
|
></div> -->
|
||||||
</div>
|
</div>
|
||||||
|
50
src/lib/components/ui/badge/badge.svelte
Normal file
50
src/lib/components/ui/badge/badge.svelte
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<script lang="ts" module>
|
||||||
|
import { type VariantProps, tv } from "tailwind-variants";
|
||||||
|
|
||||||
|
export const badgeVariants = tv({
|
||||||
|
base: "focus:ring-ring inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default:
|
||||||
|
"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent",
|
||||||
|
secondary:
|
||||||
|
"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
|
||||||
|
destructive:
|
||||||
|
"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent",
|
||||||
|
outline: "text-foreground",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import type { WithElementRef } from "bits-ui";
|
||||||
|
import type { HTMLAnchorAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
href,
|
||||||
|
class: className,
|
||||||
|
variant = "default",
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||||
|
variant?: BadgeVariant;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:element
|
||||||
|
this={href ? "a" : "span"}
|
||||||
|
bind:this={ref}
|
||||||
|
{href}
|
||||||
|
class={cn(badgeVariants({ variant, className }))}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</svelte:element>
|
2
src/lib/components/ui/badge/index.ts
Normal file
2
src/lib/components/ui/badge/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { default as Badge } from "./badge.svelte";
|
||||||
|
export { badgeVariants, type BadgeVariant } from "./badge.svelte";
|
@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChildrenOrChild } from "bits-ui";
|
||||||
|
import Check from "lucide-svelte/icons/check";
|
||||||
|
import Minus from "lucide-svelte/icons/minus";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
checked = $bindable(false),
|
||||||
|
indeterminate = $bindable(false),
|
||||||
|
class: className,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<DropdownMenuPrimitive.CheckboxItemProps> & {
|
||||||
|
children?: Snippet;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
|
bind:ref
|
||||||
|
bind:checked
|
||||||
|
bind:indeterminate
|
||||||
|
class={cn(
|
||||||
|
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked, indeterminate })}
|
||||||
|
<span class="absolute left-2 flex size-3.5 items-center justify-center">
|
||||||
|
{#if indeterminate}
|
||||||
|
<Minus class="size-4" />
|
||||||
|
{:else}
|
||||||
|
<Check class={cn("size-4", !checked && "text-transparent")} />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{@render childrenProp?.()}
|
||||||
|
{/snippet}
|
||||||
|
</DropdownMenuPrimitive.CheckboxItem>
|
@ -0,0 +1,26 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
sideOffset = 4,
|
||||||
|
portalProps,
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.ContentProps & {
|
||||||
|
portalProps?: DropdownMenuPrimitive.PortalProps;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Portal {...portalProps}>
|
||||||
|
<DropdownMenuPrimitive.Content
|
||||||
|
bind:ref
|
||||||
|
{sideOffset}
|
||||||
|
class={cn(
|
||||||
|
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md outline-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
</DropdownMenuPrimitive.Portal>
|
@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.GroupHeadingProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.GroupHeading
|
||||||
|
bind:ref
|
||||||
|
class={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.ItemProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Item
|
||||||
|
bind:ref
|
||||||
|
class={cn(
|
||||||
|
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
import { type WithElementRef } from "bits-ui";
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
class={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
@ -0,0 +1,30 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChild } from "bits-ui";
|
||||||
|
import Circle from "lucide-svelte/icons/circle";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChild<DropdownMenuPrimitive.RadioItemProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.RadioItem
|
||||||
|
bind:ref
|
||||||
|
class={cn(
|
||||||
|
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked })}
|
||||||
|
<span class="absolute left-2 flex size-3.5 items-center justify-center">
|
||||||
|
{#if checked}
|
||||||
|
<Circle class="size-2 fill-current" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{@render childrenProp?.({ checked })}
|
||||||
|
{/snippet}
|
||||||
|
</DropdownMenuPrimitive.RadioItem>
|
@ -0,0 +1,16 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.SeparatorProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Separator
|
||||||
|
bind:ref
|
||||||
|
class={cn("bg-muted -mx-1 my-1 h-px", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { type WithElementRef } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={ref}
|
||||||
|
class={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</span>
|
@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.SubContentProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.SubContent
|
||||||
|
bind:ref
|
||||||
|
class={cn(
|
||||||
|
"bg-popover text-popover-foreground z-50 min-w-[8rem] rounded-md border p-1 shadow-lg focus:outline-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
import ChevronRight from "lucide-svelte/icons/chevron-right";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.SubTriggerProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
|
bind:ref
|
||||||
|
class={cn(
|
||||||
|
"data-[highlighted]:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||||
|
inset && "pl-8",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
<ChevronRight class="ml-auto" />
|
||||||
|
</DropdownMenuPrimitive.SubTrigger>
|
50
src/lib/components/ui/dropdown-menu/index.ts
Normal file
50
src/lib/components/ui/dropdown-menu/index.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||||
|
import CheckboxItem from "./dropdown-menu-checkbox-item.svelte";
|
||||||
|
import Content from "./dropdown-menu-content.svelte";
|
||||||
|
import GroupHeading from "./dropdown-menu-group-heading.svelte";
|
||||||
|
import Item from "./dropdown-menu-item.svelte";
|
||||||
|
import Label from "./dropdown-menu-label.svelte";
|
||||||
|
import RadioItem from "./dropdown-menu-radio-item.svelte";
|
||||||
|
import Separator from "./dropdown-menu-separator.svelte";
|
||||||
|
import Shortcut from "./dropdown-menu-shortcut.svelte";
|
||||||
|
import SubContent from "./dropdown-menu-sub-content.svelte";
|
||||||
|
import SubTrigger from "./dropdown-menu-sub-trigger.svelte";
|
||||||
|
|
||||||
|
const Sub = DropdownMenuPrimitive.Sub;
|
||||||
|
const Root = DropdownMenuPrimitive.Root;
|
||||||
|
const Trigger = DropdownMenuPrimitive.Trigger;
|
||||||
|
const Group = DropdownMenuPrimitive.Group;
|
||||||
|
const RadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||||
|
|
||||||
|
export {
|
||||||
|
CheckboxItem,
|
||||||
|
Content,
|
||||||
|
Root as DropdownMenu,
|
||||||
|
CheckboxItem as DropdownMenuCheckboxItem,
|
||||||
|
Content as DropdownMenuContent,
|
||||||
|
Group as DropdownMenuGroup,
|
||||||
|
GroupHeading as DropdownMenuGroupHeading,
|
||||||
|
Item as DropdownMenuItem,
|
||||||
|
Label as DropdownMenuLabel,
|
||||||
|
RadioGroup as DropdownMenuRadioGroup,
|
||||||
|
RadioItem as DropdownMenuRadioItem,
|
||||||
|
Separator as DropdownMenuSeparator,
|
||||||
|
Shortcut as DropdownMenuShortcut,
|
||||||
|
Sub as DropdownMenuSub,
|
||||||
|
SubContent as DropdownMenuSubContent,
|
||||||
|
SubTrigger as DropdownMenuSubTrigger,
|
||||||
|
Trigger as DropdownMenuTrigger,
|
||||||
|
Group,
|
||||||
|
GroupHeading,
|
||||||
|
Item,
|
||||||
|
Label,
|
||||||
|
RadioGroup,
|
||||||
|
RadioItem,
|
||||||
|
Root,
|
||||||
|
Separator,
|
||||||
|
Shortcut,
|
||||||
|
Sub,
|
||||||
|
SubContent,
|
||||||
|
SubTrigger,
|
||||||
|
Trigger,
|
||||||
|
};
|
@ -1,9 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
|
||||||
import ezppLogo from "../../../../assets/logo.png";
|
import ezppLogo from "../../../../assets/logo.png";
|
||||||
import { osudirect } from "@/api/osudirect";
|
|
||||||
import { playAudio } from "@/utils";
|
import { playAudio } from "@/utils";
|
||||||
import { BeatmapDecoder } from "osu-parsers";
|
|
||||||
|
|
||||||
type logoProps = {
|
type logoProps = {
|
||||||
extended: boolean;
|
extended: boolean;
|
||||||
@ -13,57 +10,7 @@
|
|||||||
let { extended, onclick }: logoProps = $props();
|
let { extended, onclick }: logoProps = $props();
|
||||||
|
|
||||||
let hovered = $state(false);
|
let hovered = $state(false);
|
||||||
let bpm = $state(150); // 1000 * 60 / bpm
|
const bpm = $state(130);
|
||||||
let lastTimeout: number | undefined = undefined;
|
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
const beatmapId = 2226722;
|
|
||||||
const beatmapData = await osudirect.osu(beatmapId);
|
|
||||||
if (beatmapData) {
|
|
||||||
const decoder = new BeatmapDecoder();
|
|
||||||
const beatmap = decoder.decodeFromString(beatmapData);
|
|
||||||
console.log(beatmap);
|
|
||||||
|
|
||||||
const audio = new Audio(
|
|
||||||
`https://osu.direct/api/media/audio/${beatmapId}`
|
|
||||||
);
|
|
||||||
audio.volume = 0.3;
|
|
||||||
|
|
||||||
// Function to play the heartbeat sound
|
|
||||||
const playHeartbeat = () => {
|
|
||||||
playAudio("/audio/menuHeartbeat.mp3", hovered ? 1 : 0.3);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to synchronize the heartbeat with the song
|
|
||||||
const syncHeartbeat = () => {
|
|
||||||
const currentTime = audio.currentTime * 1000; // Convert to milliseconds
|
|
||||||
const timingPoint = beatmap.controlPoints.timingPointAt(currentTime);
|
|
||||||
if (timingPoint && bpm !== timingPoint.bpm) {
|
|
||||||
bpm = timingPoint.bpm;
|
|
||||||
|
|
||||||
if (lastTimeout) {
|
|
||||||
clearTimeout(lastTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
const interval = (1000 * 60) / bpm; // Interval in milliseconds
|
|
||||||
const nextBeat = interval - (currentTime % interval); // Time to the next beat
|
|
||||||
setTimeout(() => {
|
|
||||||
playHeartbeat();
|
|
||||||
lastTimeout = setInterval(playHeartbeat, interval);
|
|
||||||
}, nextBeat);
|
|
||||||
}
|
|
||||||
// Continue syncing
|
|
||||||
requestAnimationFrame(syncHeartbeat);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start playback and syncing
|
|
||||||
audio.addEventListener("play", () => {
|
|
||||||
syncHeartbeat();
|
|
||||||
});
|
|
||||||
|
|
||||||
await audio.play();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -83,9 +30,9 @@
|
|||||||
onmouseleave={() => (hovered = false)}
|
onmouseleave={() => (hovered = false)}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if (extended) {
|
if (extended) {
|
||||||
playAudio("/audio/menuBack.wav", 1);
|
playAudio("/audio/menuBack.wav", 0.35);
|
||||||
} else {
|
} else {
|
||||||
playAudio("/audio/menuHit.wav", 1);
|
playAudio("/audio/menuHit.wav", 0.35);
|
||||||
}
|
}
|
||||||
onclick();
|
onclick();
|
||||||
}}
|
}}
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
||||||
export const prerender = true;
|
export const prerender = true;
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
|
|
||||||
|
@ -3,18 +3,56 @@
|
|||||||
import Button from "@/components/ui/button/button.svelte";
|
import Button from "@/components/ui/button/button.svelte";
|
||||||
import Logo from "@/components/ui/logo/logo.svelte";
|
import Logo from "@/components/ui/logo/logo.svelte";
|
||||||
import * as Avatar from "@/components/ui/avatar";
|
import * as Avatar from "@/components/ui/avatar";
|
||||||
|
import * as DropdownMenu from "@/components/ui/dropdown-menu";
|
||||||
import Progressbar from "@/components/ui/progressbar/progressbar.svelte";
|
import Progressbar from "@/components/ui/progressbar/progressbar.svelte";
|
||||||
|
import Settings from "lucide-svelte/icons/settings";
|
||||||
|
import LogOut from "lucide-svelte/icons/log-out";
|
||||||
|
import Heart from "lucide-svelte/icons/heart";
|
||||||
|
import { badgeVariants } from "@/components/ui/badge";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
let progress = $state(0);
|
let progress = $state(0);
|
||||||
let extended = $state(false);
|
let extended = $state(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative h-screen w-screen">
|
<div class="relative h-screen w-screen">
|
||||||
<Background />
|
<Background />
|
||||||
<div class="absolute top-2 right-2 py-7">
|
<div class="absolute z-20 top-2 right-2 py-7">
|
||||||
<Avatar.Root>
|
<DropdownMenu.Root>
|
||||||
<Avatar.AvatarFallback>U</Avatar.AvatarFallback>
|
<DropdownMenu.Trigger>
|
||||||
<Avatar.AvatarImage src="https://a.ez-pp.farm/1001"></Avatar.AvatarImage>
|
<div class="relative">
|
||||||
</Avatar.Root>
|
<p
|
||||||
|
class={twMerge(
|
||||||
|
badgeVariants(),
|
||||||
|
"p-0 h-5 w-5 absolute -right-0.5 -top-0.5 z-50 !bg-pink-600 border-2 border-pink-800 text-white"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Heart class="h-3 w-3 m-auto p-0" />
|
||||||
|
</p>
|
||||||
|
<Avatar.Root class="border-[3px] z-40">
|
||||||
|
<Avatar.AvatarFallback>U</Avatar.AvatarFallback>
|
||||||
|
<Avatar.AvatarImage src="https://a.ez-pp.farm/1001"
|
||||||
|
></Avatar.AvatarImage>
|
||||||
|
</Avatar.Root>
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
<DropdownMenu.Content class="w-48 max-w-48 mx-2" side="bottom">
|
||||||
|
<DropdownMenu.Group>
|
||||||
|
<DropdownMenu.GroupHeading class="truncate">Hello, Quetzalcoatl!</DropdownMenu.GroupHeading>
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
<DropdownMenu.Group>
|
||||||
|
<DropdownMenu.Item class="cursor-pointer">
|
||||||
|
<Settings class="mr-2 size-4" />
|
||||||
|
<span>Settings</span>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</DropdownMenu.Group>
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
<DropdownMenu.Item class="cursor-pointer">
|
||||||
|
<LogOut class="mr-2 size-4" />
|
||||||
|
<span>Log out</span>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</DropdownMenu.Group>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
Loading…
Reference in New Issue
Block a user