Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

### 🎨 변경 사항 (UX / 접근성)

- 로그인·관리자 로그인·비밀번호 재설정의 제출 대기 상태에 기존 상태 문구를 보조하는 장식 로딩 아이콘을 추가했습니다. 아이콘은 접근성 트리에서 숨기고, 운영체제의 reduced-motion 선호가 켜진 경우 회전 애니메이션을 중지합니다.
- 세션 활동 리본은 시각적으로 현재인 이벤트를 토글 버튼으로 오인시키지 않고 `aria-current`로 노출하며, 병합된 도구 실행은 `Expand … group` 다음 행동과 포함 이벤트 수를 명확히 안내합니다.
- 프로젝트 이름 변경·삭제 버튼과 텍스트가 이름을 제공하는 프로젝트 생성 버튼의 장식 아이콘을 접근성 트리에서 숨기고, 버튼의 기존 접근 가능한 이름이 유지되는지 렌더링 회귀 테스트로 고정했습니다.
- 웹 대시보드의 각종 로그아웃 버튼(`org-sidebar.tsx`, `org-header.tsx`, `no-organization-state.tsx`)에 스크린 리더용 `aria-label="Log out of your account"` (또는 `Sign out of your account`) 속성을 추가하여 접근성을 개선했습니다.
8 changes: 6 additions & 2 deletions packages/web/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState } from 'react'
import { signIn } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import { Button } from '@/components/ui/button'
import { Button, ButtonLoadingContent } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
Expand Down Expand Up @@ -75,7 +75,11 @@ export default function LoginPage() {
<p className="text-sm text-destructive">{error}</p>
)}
<Button type="submit" className="w-full" disabled={loading}>
{loading ? 'Signing in...' : 'Sign in'}
{loading ? (
<ButtonLoadingContent>Signing in...</ButtonLoadingContent>
) : (
'Sign in'
)}
</Button>
</form>
<div className="mt-4 text-center text-sm">
Expand Down
8 changes: 6 additions & 2 deletions packages/web/src/components/admin/admin-login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from 'react'
import { Lock } from 'lucide-react'
import { useRouter } from 'next/navigation'

import { Button } from '@/components/ui/button'
import { Button, ButtonLoadingContent } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
Expand Down Expand Up @@ -76,7 +76,11 @@ export function AdminLoginForm() {
</div>
{error && <p className="text-sm text-destructive">{error}</p>}
<Button type="submit" className="w-full" disabled={loading}>
{loading ? 'Signing in...' : 'Sign in'}
{loading ? (
<ButtonLoadingContent>Signing in...</ButtonLoadingContent>
) : (
'Sign in'
)}
</Button>
</form>
</CardContent>
Expand Down
8 changes: 6 additions & 2 deletions packages/web/src/components/auth/reset-password-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from 'react'
import Link from 'next/link'

import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button, buttonVariants } from '@/components/ui/button'
import { Button, ButtonLoadingContent, buttonVariants } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
Expand Down Expand Up @@ -110,7 +110,11 @@ export function ResetPasswordForm({ token, email }: ResetPasswordFormProps) {
</Alert>
)}
<Button type="submit" className="w-full" disabled={loading}>
{loading ? 'Updating...' : 'Update password'}
{loading ? (
<ButtonLoadingContent>Updating...</ButtonLoadingContent>
) : (
'Update password'
)}
</Button>
</form>
</CardContent>
Expand Down
18 changes: 18 additions & 0 deletions packages/web/src/components/ui/button.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import { describe, expect, it } from 'vitest'

import { ButtonLoadingContent } from './button'

describe('ButtonLoadingContent', () => {
it('keeps loading copy readable while the decorative spinner respects reduced motion', () => {
const markup = renderToStaticMarkup(
<ButtonLoadingContent>Signing in...</ButtonLoadingContent>,
)

expect(markup).toContain('aria-hidden="true"')
expect(markup).toContain('animate-spin')
expect(markup).toContain('motion-reduce:animate-none')
expect(markup).toContain('Signing in...')
})
})
18 changes: 17 additions & 1 deletion packages/web/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import React from 'react'
import { Loader2 } from 'lucide-react'
import type { ReactNode } from 'react'
import { Button as ButtonPrimitive } from "@base-ui/react/button"
import { cva, type VariantProps } from "class-variance-authority"

Expand Down Expand Up @@ -55,4 +58,17 @@ function Button({
)
}

export { Button, buttonVariants }

function ButtonLoadingContent({ children }: { children: ReactNode }) {
return (
<>
<Loader2
className="mr-2 h-4 w-4 animate-spin motion-reduce:animate-none"
aria-hidden="true"
/>
{children}
</>
)
}

export { Button, ButtonLoadingContent, buttonVariants }
Loading