Skip to content

Commit

Permalink
Merge pull request #18 from xyhomi3/dev
Browse files Browse the repository at this point in the history
Enhancement(site, ui): accessibility
  • Loading branch information
lucien-loua authored Sep 14, 2024
2 parents fe961b9 + 94dc9be commit 3a6c386
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 88 deletions.
11 changes: 11 additions & 0 deletions .changeset/pretty-chefs-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@omi3/ui': patch
'@omi3/site': patch
---

This changeset includes minor updates and improvements to `@omi3/ui` package and `@omi3/site`:

- `@omi3/ui`: Minor enhancements and bug fixes to UI components.
- `@omi3/site`: Small improvements to the site's functionality and user interface.

These patch updates aim to enhance stability and user experience without introducing major new features or breaking changes.
65 changes: 47 additions & 18 deletions apps/site/app/_components/audio/player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,45 +53,74 @@ export function AudioPlayer() {
const getPlayPauseIcon = useCallback(() => {
switch (playbackState) {
case AudioChannel.PlaybackState.PLAYING:
return <Icons.Pause className='fill-text' />;
return <Icons.Pause className="fill-text" />;
case AudioChannel.PlaybackState.LOADING:
return <Icons.Loader2 className="animate-spin" />;
default:
return <Icons.Play className='fill-text' />;
return <Icons.Play className="fill-text" />;
}
}, [playbackState]);

const getThumbProps = useCallback((value: number) => ({
'aria-label': `Current value: ${value}`,
title: `Current value: ${value}`,
}), []);

return (
<Card className="w-full">
<CardHeader className="flex flex-row justify-between items-center">
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle>
Omi<span className="text-[#f50000]">3</span> Player
Omi<span className="text-[#ff6b6b]">3</span> Player
</CardTitle>
<ThemeWidget/>
<ThemeWidget />
</CardHeader>
<CardContent>
<div className="w-full">
<Visualizer analyser={analyser} width={300} height={150} className="border-2 border-border dark:border-darkBorder rounded-md" />
<Visualizer
analyser={analyser}
width={300}
height={150}
className="border-border dark:border-darkBorder rounded-base border-2"
aria-label="Visualiseur audio"
/>
</div>
<div className="relative mt-4">
<Slider
className="mt-4"
value={[currentTime]}
max={duration}
step={0.1}
onValueChange={audioHandlers.onValueChange}
onValueCommit={audioHandlers.onValueCommit}
aria-label={`Playback progress: ${playtime(currentTime)} of ${playtime(duration)}`}
thumbProps={getThumbProps(currentTime)}
/>
</div>
<Slider
className="mt-4"
value={[currentTime]}
max={duration}
step={0.1}
onValueChange={audioHandlers.onValueChange}
onValueCommit={audioHandlers.onValueCommit}
/>
<div className="text-text dark:text-darkText mt-2 flex w-full justify-between text-sm">
<div className="mt-2 flex w-full justify-between text-sm">
<span>{playtime(currentTime)}</span>
<span>{playtime(duration)}</span>
</div>
<div className="mt-4 flex items-center justify-between">
<Button size="icon" onClick={handlePlay} disabled={playbackState === AudioChannel.PlaybackState.LOADING}>
<Button
size="icon"
onClick={handlePlay}
disabled={playbackState === AudioChannel.PlaybackState.LOADING}
aria-label={playbackState === AudioChannel.PlaybackState.PLAYING ? 'Pause' : 'Lecture'}
>
{getPlayPauseIcon()}
</Button>
<div className="flex items-center gap-2">
{getVolumeIcon()}
<Slider className="w-32" value={[localVolume]} max={100} step={1} {...volumeHandlers} />
<span aria-hidden="true">{getVolumeIcon()}</span>
<div className="relative w-32">
<Slider
value={[localVolume]}
max={100}
step={1}
{...volumeHandlers}
aria-label={`Volume control: ${localVolume}%`}
thumbProps={getThumbProps(localVolume)}
/>
</div>
</div>
</div>
</CardContent>
Expand Down
4 changes: 2 additions & 2 deletions apps/site/app/_components/layout/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export function Footer() {
return (
<footer className="z-50 flex items-center justify-center gap-1 p-5">
<footer className="z-50 flex items-center justify-center gap-1 p-5" tabIndex={-1}>
© {new Date().getFullYear()}
<a href="https://github.com/xyhomi3" className="text-main">
<a href="https://github.com/xyhomi3" className="hover:underline">
Omi3
</a>
</footer>
Expand Down
19 changes: 4 additions & 15 deletions apps/site/app/_components/theme/widgets/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
Icons,
} from '@omi3/ui';
import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, Icons } from '@omi3/ui';

import { ThemeToggler } from '../_toggler';
import { memo } from 'react';
import { ThemeToggler } from '../_toggler';
import { useThemeLogic } from '../logic';

export const ThemeWidget = memo(function ThemeWidget() {
Expand All @@ -16,12 +10,7 @@ export const ThemeWidget = memo(function ThemeWidget() {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
variant="neutral"
data-umami-event="theme-toggle"
aria-label="Toggle theme"
>
<Button size="icon" variant="noShadow" data-umami-event="theme-toggle" aria-label="Toggle theme">
{!isMounted ? (
<Icons.Loader2 className="h-4 w-4 animate-spin" />
) : (
Expand All @@ -34,7 +23,7 @@ export const ThemeWidget = memo(function ThemeWidget() {
<span className="sr-only">Theme Widget</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[200px] p-3 bg-bg" align="center">
<DropdownMenuContent align="center">
<ThemeToggler />
</DropdownMenuContent>
</DropdownMenu>
Expand Down
9 changes: 7 additions & 2 deletions apps/site/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ export default function RootLayout({
}>) {
return (
<html lang="en" className="h-full" suppressHydrationWarning>
<body className={cn(silk.variable, 'font-silk flex min-h-full flex-col antialiased')}>
<body
className={cn(
silk.variable,
'font-silk bg-bg dark:bg-darkBg text-text dark:text-darkText flex min-h-full flex-col antialiased',
)}
>
<Providers>
<main className="flex flex-grow items-center justify-center p-5">{children}</main>
{children}
<Footer />
</Providers>
</body>
Expand Down
8 changes: 5 additions & 3 deletions apps/site/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ export const metadata: Metadata = {

export default function Home() {
return (
<div className="w-full max-w-md">
<AudioPlayer />
</div>
<main className="flex flex-grow items-center justify-center p-5" role="main">
<div className="w-full max-w-md">
<AudioPlayer />
</div>
</main>
);
}
28 changes: 6 additions & 22 deletions packages/ui/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';

import { cn } from '@omi3/utils';
import { Slot } from '@radix-ui/react-slot';
import type { VariantProps } from 'class-variance-authority';
import { cn } from '@omi3/utils';
import { cva } from 'class-variance-authority';

const buttonVariants = cva(
Expand All @@ -12,13 +12,13 @@ const buttonVariants = cva(
variant: {
default:
'bg-main border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark data-[state=pressed]:translate-x-boxShadowX data-[state=pressed]:translate-y-boxShadowY data-[state=pressed]:shadow-none dark:data-[state=pressed]:shadow-none',
noShadow: 'bg-white border-2 border-border dark:border-darkBorder',
noShadow: 'border-2 border-border dark:border-darkBorder bg-bg dark:bg-secondaryBlack',
link: 'underline-offset-4 text-text dark:text-darkText hover:underline',
neutral:
'bg-white dark:bg-darkBg dark:text-darkText border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark data-[state=pressed]:translate-x-boxShadowX data-[state=pressed]:translate-y-boxShadowY data-[state=pressed]:shadow-none dark:data-[state=pressed]:shadow-none',
outline: 'bg-transparent border-2 text-white border-main',
ghost: 'border-none text-white',
second: 'bg-main border-2 text-black border-black',
reverse:
'bg-main border-2 border-border dark:border-darkBorder hover:translate-x-reverseBoxShadowX hover:translate-y-reverseBoxShadowY hover:shadow-light dark:hover:shadow-dark',

destructive:
'bg-[#ff6b6b] text-white border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark data-[state=pressed]:translate-x-boxShadowX data-[state=pressed]:translate-y-boxShadowY data-[state=pressed]:shadow-none dark:data-[state=pressed]:shadow-none',
},
Expand All @@ -40,32 +40,16 @@ export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
loading?: boolean;
label?: string | null;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(
{
className,
variant,
size,
asChild = false,
loading,
children,
label,

...props
},
ref,
) => {
({ className, variant, size, asChild = false, children, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
const [pressed, setPressed] = React.useState(false);

return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
disabled={loading}
ref={ref}
data-state={pressed ? 'pressed' : 'unpressed'}
onMouseDown={() => setPressed(true)}
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/components/ui/dropdown-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const DropdownMenuContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
'z-50 min-w-[8rem] overflow-hidden rounded-base border-2 border-border bg-white p-1 font-base text-black 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 dark:border-darkBorder dark:bg-darkBg',
'z-50 min-w-[11rem] overflow-hidden rounded-base border-2 border-border bg-bg p-3 font-base text-black 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 dark:border-darkBorder dark:bg-darkBg',
className,
)}
{...props}
Expand Down Expand Up @@ -203,5 +203,6 @@ export {
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
DropdownMenuTrigger
};

54 changes: 30 additions & 24 deletions packages/ui/src/components/ui/slider.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
'use client'
'use client';

import * as React from 'react'
import * as SliderPrimitive from '@radix-ui/react-slider'
import * as React from 'react';
import * as SliderPrimitive from '@radix-ui/react-slider';

import { cn } from '@omi3/utils'
import { cn } from '@omi3/utils';

const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
'relative flex w-full touch-none select-none items-center',
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-3 w-full grow overflow-hidden rounded-full border-2 border-border dark:border-darkBorder bg-bg dark:bg-darkBg">
<SliderPrimitive.Range className="absolute h-full bg-main" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-border dark:border-darkBorder bg-bg dark:bg-darkBg ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
))
Slider.displayName = SliderPrimitive.Root.displayName
interface SliderProps extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {
thumbProps?: React.ComponentPropsWithoutRef<typeof SliderPrimitive.Thumb>;
}

export { Slider }
const Slider = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, SliderProps>(
({ className, thumbProps, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn('relative flex w-full touch-none select-none items-center', className)}
{...props}
>
<SliderPrimitive.Track className="border-border dark:border-darkBorder bg-bg dark:bg-secondaryBlack relative h-3 w-full grow overflow-hidden rounded-full border-2">
<SliderPrimitive.Range className="bg-main absolute h-full" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb
className={cn(
'border-border dark:border-darkBorder bg-bg dark:bg-darkBg block h-5 w-5 rounded-full border-2 ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
thumbProps?.className,
)}
{...thumbProps}
/>
</SliderPrimitive.Root>
),
);
Slider.displayName = SliderPrimitive.Root.displayName;

export { Slider };

0 comments on commit 3a6c386

Please sign in to comment.