Skip to content
Merged
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
10 changes: 7 additions & 3 deletions ui/src/features/decks/components/DeckCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ describe('DeckCard', () => {

expect(screen.getByRole('button', { name: 'Review' })).toHaveClass('bg-card')
expect(screen.getByText('0%')).toBeInTheDocument()
expect(screen.getByText('Due Today').nextElementSibling).toHaveTextContent('0')
expect(screen.getByText(/Due Today:/)).toHaveClass('sr-only')
expect(screen.getByText('0')).toHaveClass('type-metric')
expect(screen.queryByText('-3')).not.toBeInTheDocument()
expect(screen.queryByText(/NaN|Infinity/)).not.toBeInTheDocument()
})
Expand All @@ -251,8 +252,11 @@ describe('DeckCard', () => {

await user.click(screen.getByRole('button', { name: 'Open Biology deck' }))
expect(onOpen).toHaveBeenCalledWith(baseDeck)
const dueMetadata = screen.getByText('Due').closest('div')
expect(dueMetadata).toHaveClass('flex-col')
const dueLabel = screen.getByText(/Due Today:/)
expect(dueLabel).toHaveClass('sr-only')
const dueMetadata = screen.getByText('18').closest('div')
expect(dueMetadata).toHaveClass('items-center', 'gap-1.5')
expect(dueMetadata).not.toHaveClass('flex-col')
expect(dueMetadata).not.toHaveClass('rounded-full')
expect(dueMetadata).not.toHaveClass('bg-muted')
expect(screen.getByText('18')).toHaveClass('text-xs')
Expand Down
81 changes: 44 additions & 37 deletions ui/src/features/decks/components/DeckCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useNavigate } from '@tanstack/react-router'
import { ArrowRight, Pencil, Trash2 } from 'lucide-react'
import { ArrowRight, Clock3, Pencil, Trash2 } from 'lucide-react'
import { useTranslation } from 'react-i18next'

import { LazyIconGlyph } from '@shared/components/icons/IconGlyph'
Expand Down Expand Up @@ -53,6 +53,7 @@ export const DeckCard = ({
const openDeckLabel = t(($) => $.decks.actions.openDeck, { title: deckTitle })
const deckActionsLabel = t(($) => $.decks.actions.actionMenu, { title: deckTitle })
const reviewLabel = t(($) => $.common.actions.review)
const dueTodayA11yLabel = t(($) => $.decks.labels.dueToday)

const openDeck = () => {
onOpen(deck)
Expand Down Expand Up @@ -107,11 +108,14 @@ export const DeckCard = ({
/>
</div>
<div className="pointer-events-none relative z-20 col-start-2 col-end-4 row-start-2 flex min-w-0 flex-wrap items-center gap-2 min-[380px]:gap-x-4 min-[380px]:gap-y-3 sm:col-end-5">
<div className="flex min-w-0 items-center gap-2">
<div className="flex min-w-8 shrink-0 flex-col items-start gap-0.5">
<span className="text-[0.6875rem] font-semibold uppercase leading-none text-muted-foreground">
{t(($) => $.decks.labels.due)}
</span>
<div className="flex min-w-0 items-center gap-3">
<div className="flex min-w-0 shrink-0 items-center gap-1.5">
<Clock3
aria-hidden="true"
className="size-3.5 shrink-0 text-muted-foreground"
strokeWidth={2.3}
/>
<span className="sr-only">{dueTodayA11yLabel}: </span>
<span className="type-technical text-xs font-bold leading-none text-foreground">
{dueTodayLabel}
</span>
Expand Down Expand Up @@ -177,43 +181,46 @@ export const DeckCard = ({
</p>
</div>
</div>
<div className="flex shrink-0 items-center gap-2">
<ProgressRing value={deck.progress} />
<div className="pointer-events-auto">
<ActionMenu
ariaLabel={deckActionsLabel}
items={[
{
icon: <Pencil className="size-4 stroke-[2.4]" />,
label: t(($) => $.common.actions.edit),
onSelect: () => {
onEdit(deck)
},
},
{
icon: <Trash2 className="size-4 stroke-[2.2]" />,
label: t(($) => $.common.actions.delete),
onSelect: () => onDelete(deck),
tone: 'danger',
<div className="pointer-events-auto shrink-0">
<ActionMenu
ariaLabel={deckActionsLabel}
items={[
{
icon: <Pencil className="size-4 stroke-[2.4]" />,
label: t(($) => $.common.actions.edit),
onSelect: () => {
onEdit(deck)
},
]}
triggerFocusSurface="card"
/>
</div>
},
{
icon: <Trash2 className="size-4 stroke-[2.2]" />,
label: t(($) => $.common.actions.delete),
onSelect: () => onDelete(deck),
tone: 'danger',
},
]}
triggerFocusSurface="card"
/>
</div>
</div>
<div className="pointer-events-none relative z-20 flex min-w-0 items-center justify-between">
<div>
<span className="type-label uppercase text-muted-foreground">
{t(($) => $.decks.labels.dueToday)}
</span>
<p className="type-metric text-primary">
{dueTodayLabel}
</p>
<div className="pointer-events-none relative z-20 flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-4">
<div className="flex min-w-0 items-center gap-4">
<div className="flex min-w-0 shrink-0 items-center gap-2">
<Clock3
aria-hidden="true"
className="size-4 shrink-0 text-muted-foreground"
strokeWidth={2.3}
/>
<span className="sr-only">{dueTodayA11yLabel}: </span>
<span className="type-metric text-primary">
{dueTodayLabel}
</span>
</div>
<ProgressRing value={deck.progress} />
</div>
<Button
className={cn(
'type-action pointer-events-auto h-auto rounded-full px-8 py-3.5 transition-[background-color,color,transform] active:scale-95',
'type-action pointer-events-auto ml-auto h-auto rounded-full px-8 py-3.5 transition-[background-color,color,transform] active:scale-95',
hasDueToday
? 'bg-primary text-primary-foreground hover:bg-primary/90'
: 'border border-border bg-card text-foreground hover:bg-muted',
Expand Down
8 changes: 1 addition & 7 deletions ui/src/features/decks/components/DeckDetailPageView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ const DeckDesktopOverview = ({
className="type-action h-12 w-full rounded-full bg-primary text-primary-foreground hover:bg-primary/90"
variant="default"
>
<DeckStudyNowLabel to={studyNowTo} />
<Link to={studyNowTo as never}>{t(($) => $.decks.actions.studyNow)}</Link>
</Button>
</DesktopAsidePanel>
)
Expand All @@ -445,9 +445,3 @@ const DeckMasteryLabel = () => {

return t(($) => $.decks.labels.mastery)
}

const DeckStudyNowLabel = ({ to }: { to: string }) => {
const { t } = useTranslation()

return <Link to={to as never}>{t(($) => $.decks.actions.studyNow)}</Link>
}
8 changes: 8 additions & 0 deletions ui/src/features/decks/pages/DetailPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@ describe('DeckDetailPage', () => {
expect(await screen.findByText(deckDescription)).toBeInTheDocument()
const studyNowLinks = screen.getAllByRole('link', { name: 'Study now' })
expect(studyNowLinks).toHaveLength(1)
expect(studyNowLinks[0]).toHaveClass(
'type-action',
'h-12',
'w-full',
'rounded-full',
'bg-primary',
'text-primary-foreground',
)
const createButton = await screen.findByRole('button', { name: 'Create' })
const deckActions = await screen.findByRole('button', { name: 'World History actions' })

Expand Down