diff --git a/package.json b/package.json index 13d07a3..a72ca83 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@avocadi/ui", "type": "module", - "version": "0.2.18", + "version": "0.3.0", "description": "ui elements for avocadi", "private": false, "files": [ diff --git a/src/assets/sounds/762132__ienba__ui-buttons.wav b/src/assets/sounds/762132__ienba__ui-buttons.wav deleted file mode 100644 index 36e13f7..0000000 Binary files a/src/assets/sounds/762132__ienba__ui-buttons.wav and /dev/null differ diff --git a/src/assets/sounds/842498__newlocknew__uimvmt_game-user-interface-sound-set.mp3 b/src/assets/sounds/842498__newlocknew__uimvmt_game-user-interface-sound-set.mp3 deleted file mode 100644 index 0c4efd4..0000000 Binary files a/src/assets/sounds/842498__newlocknew__uimvmt_game-user-interface-sound-set.mp3 and /dev/null differ diff --git a/src/assets/sounds/clickSmall.wav b/src/assets/sounds/clickSmall.wav new file mode 100644 index 0000000..1fe6317 Binary files /dev/null and b/src/assets/sounds/clickSmall.wav differ diff --git a/src/assets/sounds/hover.wav b/src/assets/sounds/hover.wav new file mode 100644 index 0000000..384e7c8 Binary files /dev/null and b/src/assets/sounds/hover.wav differ diff --git a/src/assets/sounds/uploadSuccess.wav b/src/assets/sounds/uploadSuccess.wav new file mode 100644 index 0000000..65559ec Binary files /dev/null and b/src/assets/sounds/uploadSuccess.wav differ diff --git a/src/button.tsx b/src/button.tsx index eb35826..5f75d90 100644 --- a/src/button.tsx +++ b/src/button.tsx @@ -64,10 +64,15 @@ function Button({ className={cn(buttonVariants({ variant, size, className }))} onClick={(e) => { onClick?.(e); - play({ id: "click1" }); + }} + onMouseUp={() => { + play({ id: "clickSmall" }); + }} + onMouseDown={() => { + play({ id: "clickSmall" }); }} onMouseEnter={(e) => { - play({ id: "click2" }); + play({ id: "hover" }); onMouseEnter?.(e); }} {...props} diff --git a/src/card.tsx b/src/card.tsx index 4563b3c..dde06be 100644 --- a/src/card.tsx +++ b/src/card.tsx @@ -5,6 +5,7 @@ import { type HTMLMotionProps, motion } from "motion/react"; import { forwardRef, type HTMLAttributes, type ReactNode } from "react"; import { cn } from "@/lib/utils"; import { CardDepthProvider, useCardDepth } from "./card-context"; +import useInterfaceSound from "./hooks/useInterfaceSound"; import { defaultTransitionCard, defaultVariantsCard, @@ -51,9 +52,26 @@ const Card = forwardRef( const Comp = asChild ? Slot : "div"; + const { play } = useInterfaceSound(); + return ( { + if (interactive) { + play({ id: "hover" }); + } + }} + onMouseDown={() => { + if (interactive) { + play({ id: "clickSmall" }); + } + }} + onMouseUp={() => { + if (interactive) { + play({ id: "clickSmall" }); + } + }} ref={ref} style={{ borderRadius: `${radius}rem`, ...style }} className={cn(cardVariants({ interactive, className, padding }))} @@ -70,11 +88,20 @@ const MCard = motion.create(Card); export const AnimatedCard: React.FC< CommonCardProps & HTMLMotionProps<"div"> -> = (props) => { +> = ({ interactive, ...props }) => { return ( ); diff --git a/src/form/checkbox.tsx b/src/form/checkbox.tsx index 11f23f9..924ab01 100644 --- a/src/form/checkbox.tsx +++ b/src/form/checkbox.tsx @@ -16,7 +16,7 @@ function Checkbox({ { if (onCheckedChange) onCheckedChange(checked); - play({ id: "click2" }); + play({ id: "clickSmall" }); }} data-slot="checkbox" className={cn( diff --git a/src/form/input-number.tsx b/src/form/input-number.tsx index 3ac1ca8..945f8c4 100644 --- a/src/form/input-number.tsx +++ b/src/form/input-number.tsx @@ -45,7 +45,7 @@ const InputNumber = React.forwardRef( value={draft} onFocus={(e) => { setFocused(true); - play({ id: "click2" }); + play({ id: "clickSmall" }); onFocus?.(e); }} onChange={(e) => { diff --git a/src/form/input-text.tsx b/src/form/input-text.tsx index 8fab3fe..c71b6c1 100644 --- a/src/form/input-text.tsx +++ b/src/form/input-text.tsx @@ -11,11 +11,11 @@ const InputText = React.forwardRef< return ( { - play({ id: "click2" }); + play({ id: "clickSmall" }); }} type={type} 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, )} ref={ref} diff --git a/src/form/select.tsx b/src/form/select.tsx index 6646d6d..36b3008 100644 --- a/src/form/select.tsx +++ b/src/form/select.tsx @@ -15,9 +15,9 @@ function Select({ { if (open) { - play({ id: "click3" }); + play({ id: "clickSmall" }); } else { - play({ id: "click4" }); + play({ id: "clickSmall" }); } }} data-slot="select" @@ -53,7 +53,7 @@ function SelectTrigger({ className={cn( "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", - "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", "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", @@ -133,7 +133,7 @@ function SelectItem({ return ( play({ id: "click2" })} + onMouseEnter={() => play({ id: "hover" })} data-slot="select-item" className={cn( "focus:bg-main/25 text-main/75 focus:text-main [&_svg:not([class*='text-'])]:text-main transition-colors", diff --git a/src/hooks/useInterfaceSound.ts b/src/hooks/useInterfaceSound.ts index e5e13ad..dbd7a5c 100644 --- a/src/hooks/useInterfaceSound.ts +++ b/src/hooks/useInterfaceSound.ts @@ -1,41 +1,32 @@ import { useSound } from "use-sound"; 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([ - "smooth1", - "smooth2", - "lobbyCreated", - "gameStart", -]); +import clickSmallSound from "../assets/sounds/clickSmall.wav"; +import hoverSound from "../assets/sounds/hover.wav"; +import uploadSuccessSound from "../assets/sounds/uploadSuccess.wav"; -const UiButtonSprites = z.enum(["click1", "click2", "click3", "click4"]); +export const InterfaceSounds = z.enum(["clickSmall", "hover", "uploadSuccess"]); export default function useInterfaceSound() { - const [playSprite1] = useSound(soundSprite, { - sprite: { - smooth1: [0, 1200], - smooth2: [7800, 1400], - lobbyCreated: [53800, 3500], - gameStart: [62000, 4000], - }, - }); + const [playHover] = useSound(hoverSound); - const [playSprite2] = useSound(soundSpriteButtons, { - sprite: { - click1: [0, 1000], - click2: [2750, 1000], - click3: [5200, 1000], - click4: [7700, 1000], - }, - }); + const [playClickSmall] = useSound(clickSmallSound); - const play = ({ id }: { id: string }) => { - if (UiSoundSetSprites.safeParse(id).success) { - playSprite1({ id }); - } else if (UiButtonSprites.safeParse(id).success) { - playSprite2({ id }); + const [playUploadSuccess] = useSound(uploadSuccessSound); + + const play = ({ id }: { id: z.output }) => { + switch (id) { + case "clickSmall": + playClickSmall(); + break; + case "hover": + playHover(); + break; + case "uploadSuccess": + playUploadSuccess(); + break; + default: + break; } }; diff --git a/src/logo/text.tsx b/src/logo/text.tsx index a848f05..7160ec1 100644 --- a/src/logo/text.tsx +++ b/src/logo/text.tsx @@ -3,6 +3,7 @@ import { stagger, type Transition } from "motion"; import { motion, type Variants } from "motion/react"; import type { FC } from "react"; +import useInterfaceSound from "@/hooks/useInterfaceSound"; import { cn, getRandomInt } from "@/lib/utils"; const variants: { @@ -46,6 +47,8 @@ export const LogoText: FC<{ "transition-colors", ); + const { play } = useInterfaceSound(); + return ( { + play({ id: "clickSmall" }); + }} {...(animateOnGestures && { whileHover: "hover", whileTap: "active" })} className="overflow-visible" width="100%" diff --git a/src/styles/globals.css b/src/styles/globals.css index 5450c21..ac75274 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -49,6 +49,8 @@ --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); --radius-2xl: calc(var(--radius) + 12px); + + --radius-input: calc(var(--radius) + 4px); } @theme {