2026-07-10 12:51:17 -04:00
|
|
|
<script lang="ts">
|
2026-07-21 13:41:10 -04:00
|
|
|
import { base } from '$app/paths'
|
2026-07-10 12:51:17 -04:00
|
|
|
import DifficultyBadge from './DifficultyBadge.svelte'
|
2026-07-10 13:38:43 -04:00
|
|
|
import { isAdopted } from '$lib/adopted.svelte'
|
2026-07-10 12:51:17 -04:00
|
|
|
import { t } from '$lib/i18n/index.svelte'
|
|
|
|
|
|
|
|
|
|
interface CardTool {
|
|
|
|
|
name: string
|
|
|
|
|
slug: string
|
|
|
|
|
difficulty: 'beginner' | 'intermediate' | 'advanced'
|
|
|
|
|
license?: string
|
|
|
|
|
color?: string
|
|
|
|
|
monogram?: string
|
|
|
|
|
tags: string[]
|
|
|
|
|
excerpt: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let { tool }: { tool: CardTool } = $props()
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<article class="card">
|
|
|
|
|
<header class="cluster">
|
|
|
|
|
<span class="monogram" style:--tool-color={tool.color} aria-hidden="true">
|
|
|
|
|
{tool.monogram ?? tool.name.slice(0, 2)}
|
|
|
|
|
</span>
|
2026-07-21 13:41:10 -04:00
|
|
|
<h3><a href="{base}/outils/{tool.slug}">{tool.name}</a></h3>
|
2026-07-10 13:38:43 -04:00
|
|
|
{#if isAdopted(tool.slug)}
|
|
|
|
|
<!-- information périphérique (doctrine §3.5) : discret, jamais bloquant -->
|
|
|
|
|
<span class="adopted" title={t('adopted.marked')}>
|
|
|
|
|
<span aria-hidden="true">✓</span>
|
|
|
|
|
<span class="visually-hidden">{t('adopted.marked')}</span>
|
|
|
|
|
</span>
|
|
|
|
|
{/if}
|
2026-07-10 12:51:17 -04:00
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="excerpt"><span class="visually-hidden">{t('tool.why')} : </span>{tool.excerpt}</p>
|
|
|
|
|
|
|
|
|
|
<footer class="cluster">
|
|
|
|
|
<DifficultyBadge difficulty={tool.difficulty} />
|
|
|
|
|
{#if tool.license}
|
|
|
|
|
<span class="meta">{tool.license}</span>
|
|
|
|
|
{/if}
|
|
|
|
|
{#each tool.tags as tag (tag)}
|
|
|
|
|
<span class="meta">{tag}</span>
|
|
|
|
|
{/each}
|
|
|
|
|
</footer>
|
|
|
|
|
</article>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.card {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: var(--space-2);
|
|
|
|
|
padding: var(--space-3);
|
|
|
|
|
border: 1px solid var(--oki-line);
|
|
|
|
|
border-left: 4px solid var(--oki-jaune);
|
|
|
|
|
border-radius: var(--radius-2);
|
|
|
|
|
background: var(--oki-surface);
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-10 13:38:43 -04:00
|
|
|
/* la couleur de marque en anneau, jamais en fond de texte :
|
|
|
|
|
contraste AA garanti quel que soit l'outil (doctrine §4.3) */
|
2026-07-10 12:51:17 -04:00
|
|
|
.monogram {
|
|
|
|
|
display: grid;
|
|
|
|
|
place-items: center;
|
|
|
|
|
inline-size: 2.5rem;
|
|
|
|
|
block-size: 2.5rem;
|
|
|
|
|
border-radius: var(--radius-2);
|
2026-07-10 13:38:43 -04:00
|
|
|
background: var(--oki-surface-2);
|
|
|
|
|
border: 3px solid var(--tool-color, var(--oki-line));
|
|
|
|
|
color: var(--oki-ink);
|
2026-07-10 12:51:17 -04:00
|
|
|
font-weight: 700;
|
|
|
|
|
font-size: var(--text-0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
|
font-size: var(--text-2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* toute la carte est cliquable via le pseudo-élément du lien —
|
|
|
|
|
un vrai <a>, pas de div cliquable (doctrine §4.3) */
|
|
|
|
|
h3 a {
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
h3 a::after {
|
|
|
|
|
content: '';
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
}
|
|
|
|
|
h3 a:focus-visible::after {
|
|
|
|
|
outline: var(--focus-ring);
|
|
|
|
|
outline-offset: -3px;
|
|
|
|
|
border-radius: var(--radius-2);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-10 13:38:43 -04:00
|
|
|
.adopted {
|
|
|
|
|
display: grid;
|
|
|
|
|
place-items: center;
|
|
|
|
|
inline-size: 1.4rem;
|
|
|
|
|
block-size: 1.4rem;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background: var(--oki-vert);
|
|
|
|
|
color: oklch(98% 0 0);
|
|
|
|
|
font-size: var(--text-0);
|
|
|
|
|
margin-inline-start: auto;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-10 12:51:17 -04:00
|
|
|
.excerpt {
|
|
|
|
|
color: var(--oki-ink-2);
|
|
|
|
|
font-size: var(--text-0);
|
|
|
|
|
flex-grow: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.meta {
|
|
|
|
|
font-size: var(--text-0);
|
|
|
|
|
color: var(--oki-ink-2);
|
|
|
|
|
border: 1px solid var(--oki-line);
|
|
|
|
|
border-radius: var(--radius-2);
|
|
|
|
|
padding: 0.1em 0.6em;
|
|
|
|
|
}
|
|
|
|
|
</style>
|