# CourseCard

> Componentes / Cursos e matrícula · Estado: **Em andamento** — Implementado e utilizável, mas ainda sem a validação completa de acessibilidade.

Cartão de curso do catálogo: imagem, categoria e selos ("Em breve", "Lista de espera", destaque), modalidade e carga horária, título, descrição, preço opcional (com o cheio riscado) e a chamada "Ver detalhes do curso". Sobre o Card: o link é o título, estendido sobre o cartão inteiro (E68).

- Função: Cursos e matrícula
- Também chamado de: cartão de curso, card de curso, vitrine de curso
- Mora em: `app/components/molecules/CourseCard.tsx`
- Página: [https://phorte-design-system.vercel.app/styleguide/peca/CourseCard](https://phorte-design-system.vercel.app/styleguide/peca/CourseCard)
- Ficha no Storybook: [components-complex-coursecard](https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-coursecard--docs)
- Prévia ao vivo, sozinha: [https://phorte-design-system.vercel.app/previa/CourseCard/0](https://phorte-design-system.vercel.app/previa/CourseCard/0)
- Todas as peças: [https://phorte-design-system.vercel.app/llms.txt](https://phorte-design-system.vercel.app/llms.txt)

## Como usar no código

```tsx
import CourseCard from '@/app/components/molecules/CourseCard';

<CourseCard course={…}>…</CourseCard>
```

O `…` marca as props obrigatórias — ver *Propriedades*.

## Uso

### Variantes na ficha

1. [Padrão](https://phorte-design-system.vercel.app/previa/CourseCard/0)
2. [Proporcoes](https://phorte-design-system.vercel.app/previa/CourseCard/1)
3. [Sem Turma](https://phorte-design-system.vercel.app/previa/CourseCard/2)
4. [Com preço](https://phorte-design-system.vercel.app/previa/CourseCard/3)
5. [Com preço promocional](https://phorte-design-system.vercel.app/previa/CourseCard/4)
6. [Texto Longo](https://phorte-design-system.vercel.app/previa/CourseCard/5)
7. [Esqueleto](https://phorte-design-system.vercel.app/previa/CourseCard/6)

Em grades e listas do catálogo de cursos, com os dados de um `CatalogCourseDTO`.

### Quando não usar

Para a vitrine de destaque da página inicial, com setas, use o TopCourses. Para as turmas de um curso, o TurmaCard. Para um cartão genérico, o Card.

### Faça

- Enquanto os dados chegam, mostre o `CourseCardEsqueleto` (E157) — um por cartão esperado, dentro de um `EsqueletoGrupo rotulo="Carregando cursos"` —, e troque o grupo inteiro pelos cartões quando chegarem.
- Passe o curso como vem do serviço (`CatalogCourseDTO`): a opção principal, a categoria e o estado saem dele.
- Use `preco` só quando o valor for real; com `original`, o cheio aparece riscado e o leitor ouve "Preço original" e "Preço com desconto".
- Mantenha a mesma `imageAspectRatio` em todos os cartões de uma grade.
- Troque o `href` quando o site clonado tiver outras rotas (padrão `/curso/<slug>`, E68).

### Evite

- Envolver o cartão em outro link: o título já leva ao curso, e o cartão inteiro é a área dele.
- Pôr outro controle dentro do cartão sem `relative z-(--z-elevado)`: a área do link o cobre.

### Nota de uso

Curso inativo **deixa de ser link**. Antes virava `<Link href="#">`: recebia foco, anunciava-se como link e não levava a lugar nenhum — uma parada morta repetida a cada cartão inativo da grade.

### Anatomia

1. **Cartão** — O Card `interactive` como `<article>` (E68): `--card`, cantos `rounded-superficie`, borda e sombra do sistema.
2. **Imagem** — O `CardMedia`, decorativo (`alt=""`), na proporção escolhida; aproxima no hover, só com movimento liberado.
3. **Selos sobre a foto** — A categoria (Tag `vidro`, cortada no limite do cartão), "Em breve" (`indisponivel`), "Lista de espera" (`aviso`) e o destaque (`destaque`) — a Tag do sistema desde a E64.
4. **Informações** — Modalidade com ícone e carga horária, em Tag `neutro` (E64).
5. **Título** — `h3` de até duas linhas, com o `CardLink` dentro — o único link do cartão.
6. **Descrição** — Até três linhas.
7. **Preço** — Com `preco`: rótulo ("Investimento"), o cheio riscado, o atual e as parcelas.
8. **Chamada** — "Ver detalhes do curso" (ou "Avise-me", na lista de espera): texto com aparência de botão verde, `aria-hidden` — quem leva é o link do título.

### Estados

| Estado | O que muda |
| --- | --- |
| Carregando | O `CourseCardEsqueleto` (E157): a mesma superfície e proporção, com as linhas e a imagem em esqueleto, decorativo (`aria-hidden`); o grupo diz "Carregando cursos" uma vez. Medido na ficha: a mesma largura e menos de 20% de diferença de altura. |
| Aberto | Link para o `href`; no hover, sobe 4px (com movimento liberado), a sombra cresce e o título fica vermelho. |
| Lista de espera | `aggregateStatus="closed"`: selo "Lista de espera" e chamada "Avise-me". |
| Em breve | `aggregateStatus="inactive"`: selo "Em breve", 80% de opacidade, sem hover, sem preço nem chamada — e **sem link**. |
| Foco | O anel de foco do cartão inteiro, só no teclado (`has-focus-visible`, E68). |

### Comportamento

| Situação | O que acontece |
| --- | --- |
| Clique em qualquer lugar do cartão | Leva ao curso: a área do link do título cobre o cartão. |
| Curso inativo | Sem link: não recebe foco nem se anuncia como link — antes era um `href="#"` morto. O `ref` chega à raiz nos dois casos (E68). |
| Várias opções no curso | A principal é a primeira ativa ou em espera; sem nenhuma, a primeira. |

### Relacionados

- [Card](https://phorte-design-system.vercel.app/styleguide/md/Card.md) — A superfície e o `CardLink`.
- [TopCourses](https://phorte-design-system.vercel.app/styleguide/md/TopCourses.md) — Vitrine de cursos em destaque, com setas.
- [TurmaCard](https://phorte-design-system.vercel.app/styleguide/md/TurmaCard.md) — As turmas de um curso.

## Especificação

### Propriedades

| Prop | Tipo | Padrão | Obrigatória | Descrição |
| --- | --- | --- | --- | --- |
| `course` | `CatalogCourseDTO` | — | sim |  |
| `imageAspectRatio` | `'1:1' \| '4:3' \| '3:4' \| '16:9' \| '9:16'` | `'16:9'` | não |  |
| `preco` | `PrecoDoCurso` | — | não |  |
| `href` | `string` | — | não | Destino do cartão (E68). Padrão `/curso/<slug>` — troque se o site clonado tiver outras rotas. |

Aceita também: `Omit<React.HTMLAttributes<HTMLElement>, 'title'>`.

### Tokens de cor

| Token | Valor | Usado como |
| --- | --- | --- |
| `--border` | #E5E5E5 | `border-border` |
| `--foreground` | #1A1A1A | `text-ink` |
| `--muted-foreground` | #595959 | `text-muted-foreground` |
| `--primary` | #D42B2B | `text-primary` |
| `--secondary` | #0B8434 | `bg-secondary` |
| `--secondary-dark` | #0D6B2E | `bg-secondary-dark` |
| `--secondary-foreground` | #FFFFFF | `text-secondary-foreground` |

## Acessibilidade

### Teclado

| Tecla | Faz |
| --- | --- |
| Tab | Uma parada por cartão aberto: o link do título — conferido no teste da ficha (E68; eram duas, o link e o botão de dentro). O cartão "Em breve" não recebe foco. |
| Enter | No link, abre a página do curso. |

### Leitor de tela

- O nome do link é o título do curso — conferido no teste da ficha. Antes era o texto inteiro do cartão.
- O preço riscado diz, por escrito, "Preço original" e "Preço com desconto": o traço não é anunciado.

### O que sustenta o estado

Usa os padrões: estatico. Falta ouvir com leitor de tela: estatico.

## Status e recursos

| Tipo | Recurso | Status |
| --- | --- | --- |
| Código | `app/components/molecules/CourseCard.tsx` | Disponível |
| Ficha | https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-coursecard--docs | Disponível |
| Teste de acessibilidade | axe em `npm run test` | No gate de todo commit |
| Leitor de tela | Passada da E33 | Falta ouvir |
| Design | Figma | Desativado até a Fase 2 |

### Histórico

- `251416b` 2026-10-01 — E159: Testimonials — o vídeo toca dentro do cartão, YouTube e Vimeo
- Histórico completo no GitHub: https://github.com/srbunnie/Pos-Phorte-Design-System/commits/main/app/components/molecules/CourseCard.tsx
