update sound design

update form design
This commit is contained in:
2026-05-09 14:05:32 +02:00
parent b2891feea4
commit e909095495
15 changed files with 73 additions and 42 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "@avocadi/ui", "name": "@avocadi/ui",
"type": "module", "type": "module",
"version": "0.2.18", "version": "0.3.0",
"description": "ui elements for avocadi", "description": "ui elements for avocadi",
"private": false, "private": false,
"files": [ "files": [
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+7 -2
View File
@@ -64,10 +64,15 @@ function Button({
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}
onClick={(e) => { onClick={(e) => {
onClick?.(e); onClick?.(e);
play({ id: "click1" }); }}
onMouseUp={() => {
play({ id: "clickSmall" });
}}
onMouseDown={() => {
play({ id: "clickSmall" });
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
play({ id: "click2" }); play({ id: "hover" });
onMouseEnter?.(e); onMouseEnter?.(e);
}} }}
{...props} {...props}
+28 -1
View File
@@ -5,6 +5,7 @@ import { type HTMLMotionProps, motion } from "motion/react";
import { forwardRef, type HTMLAttributes, type ReactNode } from "react"; import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { CardDepthProvider, useCardDepth } from "./card-context"; import { CardDepthProvider, useCardDepth } from "./card-context";
import useInterfaceSound from "./hooks/useInterfaceSound";
import { import {
defaultTransitionCard, defaultTransitionCard,
defaultVariantsCard, defaultVariantsCard,
@@ -51,9 +52,26 @@ const Card = forwardRef<HTMLDivElement, CommonCardProps>(
const Comp = asChild ? Slot : "div"; const Comp = asChild ? Slot : "div";
const { play } = useInterfaceSound();
return ( return (
<CardDepthProvider> <CardDepthProvider>
<Comp <Comp
onMouseEnter={() => {
if (interactive) {
play({ id: "hover" });
}
}}
onMouseDown={() => {
if (interactive) {
play({ id: "clickSmall" });
}
}}
onMouseUp={() => {
if (interactive) {
play({ id: "clickSmall" });
}
}}
ref={ref} ref={ref}
style={{ borderRadius: `${radius}rem`, ...style }} style={{ borderRadius: `${radius}rem`, ...style }}
className={cn(cardVariants({ interactive, className, padding }))} className={cn(cardVariants({ interactive, className, padding }))}
@@ -70,11 +88,20 @@ const MCard = motion.create(Card);
export const AnimatedCard: React.FC< export const AnimatedCard: React.FC<
CommonCardProps & HTMLMotionProps<"div"> CommonCardProps & HTMLMotionProps<"div">
> = (props) => { > = ({ interactive, ...props }) => {
return ( return (
<MCard <MCard
variants={defaultVariantsCard} variants={defaultVariantsCard}
transition={defaultTransitionCard} transition={defaultTransitionCard}
{...(interactive && {
whileHover: {
scale: 1.05,
},
whileTap: {
scale: 0.95,
},
})}
interactive={interactive}
{...props} {...props}
/> />
); );
+1 -1
View File
@@ -16,7 +16,7 @@ function Checkbox({
<CheckboxPrimitive.Root <CheckboxPrimitive.Root
onCheckedChange={(checked) => { onCheckedChange={(checked) => {
if (onCheckedChange) onCheckedChange(checked); if (onCheckedChange) onCheckedChange(checked);
play({ id: "click2" }); play({ id: "clickSmall" });
}} }}
data-slot="checkbox" data-slot="checkbox"
className={cn( className={cn(
+1 -1
View File
@@ -45,7 +45,7 @@ const InputNumber = React.forwardRef<HTMLInputElement, Props>(
value={draft} value={draft}
onFocus={(e) => { onFocus={(e) => {
setFocused(true); setFocused(true);
play({ id: "click2" }); play({ id: "clickSmall" });
onFocus?.(e); onFocus?.(e);
}} }}
onChange={(e) => { onChange={(e) => {
+2 -2
View File
@@ -11,11 +11,11 @@ const InputText = React.forwardRef<
return ( return (
<input <input
onFocus={() => { onFocus={() => {
play({ id: "click2" }); play({ id: "clickSmall" });
}} }}
type={type} type={type}
className={cn( className={cn(
"flex h-input-height w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "flex h-input-height w-full rounded-input border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className, className,
)} )}
ref={ref} ref={ref}
+4 -4
View File
@@ -15,9 +15,9 @@ function Select({
<SelectPrimitive.Root <SelectPrimitive.Root
onOpenChange={(open) => { onOpenChange={(open) => {
if (open) { if (open) {
play({ id: "click3" }); play({ id: "clickSmall" });
} else { } else {
play({ id: "click4" }); play({ id: "clickSmall" });
} }
}} }}
data-slot="select" data-slot="select"
@@ -53,7 +53,7 @@ function SelectTrigger({
className={cn( className={cn(
"border-main data-placeholder:text-secondary [&_svg:not([class*='text-'])]:text-secondary focus-visible:border-ring", "border-main data-placeholder:text-secondary [&_svg:not([class*='text-'])]:text-secondary focus-visible:border-ring",
"focus-visible:ring-main/50 aria-invalid:ring-error/20 dark:aria-invalid:ring-error/40 aria-invalid:border-error", "focus-visible:ring-main/50 aria-invalid:ring-error/20 dark:aria-invalid:ring-error/40 aria-invalid:border-error",
"dark:bg-neutral-accent/30 dark:hover:bg-neutral-accent/50 flex w-fit items-center justify-between gap-2 rounded-full", "dark:bg-neutral-accent/30 dark:hover:bg-neutral-accent/50 flex w-fit items-center justify-between gap-2 rounded-input",
"border bg-transparent px-4 py-2 text-sm text-main whitespace-nowrap shadow-xs transition-[color,box-shadow,background-color] outline-none", "border bg-transparent px-4 py-2 text-sm text-main whitespace-nowrap shadow-xs transition-[color,box-shadow,background-color] outline-none",
"focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-input-height data-[size=sm]:h-8", "focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-input-height data-[size=sm]:h-8",
"*:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center", "*:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center",
@@ -133,7 +133,7 @@ function SelectItem({
return ( return (
<SelectPrimitive.Item <SelectPrimitive.Item
onMouseEnter={() => play({ id: "click2" })} onMouseEnter={() => play({ id: "hover" })}
data-slot="select-item" data-slot="select-item"
className={cn( className={cn(
"focus:bg-main/25 text-main/75 focus:text-main [&_svg:not([class*='text-'])]:text-main transition-colors", "focus:bg-main/25 text-main/75 focus:text-main [&_svg:not([class*='text-'])]:text-main transition-colors",
+21 -30
View File
@@ -1,41 +1,32 @@
import { useSound } from "use-sound"; import { useSound } from "use-sound";
import z from "zod"; import z from "zod";
import soundSpriteButtons from "../assets/sounds/762132__ienba__ui-buttons.wav";
import soundSprite from "../assets/sounds/842498__newlocknew__uimvmt_game-user-interface-sound-set.mp3";
const UiSoundSetSprites = z.enum([ import clickSmallSound from "../assets/sounds/clickSmall.wav";
"smooth1", import hoverSound from "../assets/sounds/hover.wav";
"smooth2", import uploadSuccessSound from "../assets/sounds/uploadSuccess.wav";
"lobbyCreated",
"gameStart",
]);
const UiButtonSprites = z.enum(["click1", "click2", "click3", "click4"]); export const InterfaceSounds = z.enum(["clickSmall", "hover", "uploadSuccess"]);
export default function useInterfaceSound() { export default function useInterfaceSound() {
const [playSprite1] = useSound(soundSprite, { const [playHover] = useSound(hoverSound);
sprite: {
smooth1: [0, 1200],
smooth2: [7800, 1400],
lobbyCreated: [53800, 3500],
gameStart: [62000, 4000],
},
});
const [playSprite2] = useSound(soundSpriteButtons, { const [playClickSmall] = useSound(clickSmallSound);
sprite: {
click1: [0, 1000],
click2: [2750, 1000],
click3: [5200, 1000],
click4: [7700, 1000],
},
});
const play = ({ id }: { id: string }) => { const [playUploadSuccess] = useSound(uploadSuccessSound);
if (UiSoundSetSprites.safeParse(id).success) {
playSprite1({ id }); const play = ({ id }: { id: z.output<typeof InterfaceSounds> }) => {
} else if (UiButtonSprites.safeParse(id).success) { switch (id) {
playSprite2({ id }); case "clickSmall":
playClickSmall();
break;
case "hover":
playHover();
break;
case "uploadSuccess":
playUploadSuccess();
break;
default:
break;
} }
}; };
+6
View File
@@ -3,6 +3,7 @@
import { stagger, type Transition } from "motion"; import { stagger, type Transition } from "motion";
import { motion, type Variants } from "motion/react"; import { motion, type Variants } from "motion/react";
import type { FC } from "react"; import type { FC } from "react";
import useInterfaceSound from "@/hooks/useInterfaceSound";
import { cn, getRandomInt } from "@/lib/utils"; import { cn, getRandomInt } from "@/lib/utils";
const variants: { const variants: {
@@ -46,6 +47,8 @@ export const LogoText: FC<{
"transition-colors", "transition-colors",
); );
const { play } = useInterfaceSound();
return ( return (
<motion.svg <motion.svg
variants={variants.container} variants={variants.container}
@@ -53,6 +56,9 @@ export const LogoText: FC<{
transition={{ transition={{
delayChildren: stagger(0.1, { from: "center" }), delayChildren: stagger(0.1, { from: "center" }),
}} }}
onClick={() => {
play({ id: "clickSmall" });
}}
{...(animateOnGestures && { whileHover: "hover", whileTap: "active" })} {...(animateOnGestures && { whileHover: "hover", whileTap: "active" })}
className="overflow-visible" className="overflow-visible"
width="100%" width="100%"
+2
View File
@@ -49,6 +49,8 @@
--radius-lg: var(--radius); --radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px); --radius-xl: calc(var(--radius) + 4px);
--radius-2xl: calc(var(--radius) + 12px); --radius-2xl: calc(var(--radius) + 12px);
--radius-input: calc(var(--radius) + 4px);
} }
@theme { @theme {