Skip to main content
The WordCard component displays a word entry as an interactive card with category badge, title, meaning preview, and a “learn more” link. Used for related words sections and word listings.

Import

import WordCard from "../components/WordCard.astro";
import type { CollectionEntry } from "astro:content";

Usage

src/components/RelatedWordsSection.astro
---
import WordCard from "./WordCard.astro";
import { getCollection } from "astro:content";

const words = await getCollection("words-es");
const featuredWords = words.slice(0, 3);
const lang = "es";
---

<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
  {featuredWords.map((entry) => (
    <WordCard entry={entry} lang={lang} />
  ))}
</div>

With Custom Title Level

<WordCard 
  entry={wordEntry} 
  lang="en" 
  titleLevel="h3" 
/>

Props

entry
CollectionEntry<'words-es' | 'words-en'>
required
The word entry from Astro’s content collection. Contains word data including:
  • slug - URL-safe identifier
  • data.word - The word itself
  • data.meaning - Definition/meaning
  • data.category - Word category (sustantivo, verbo, etc.)
lang
string
required
The current language code. Used for generating the correct URL path.Values: "es" or "en"
titleLevel
'h3' | 'h4'
default:"h4"
The HTML heading level to use for the word title. Use "h3" for primary sections and "h4" for nested sections to maintain proper heading hierarchy.

Word Data Structure

The entry.data object should contain:
interface WordData {
  word: string;           // The word/phrase
  meaning: string;        // Definition
  category?: string;      // Category badge (sustantivo, verbo, etc.)
  // ... other properties
}

Structure

<a href="/{lang}/palabras/{slug}/" class="word-related-card">
  {category && (
    <span class="category-badge">{category}</span>
  )}
  <h4>{word}</h4>
  <p>{meaning}</p>
  <span class="learn-more-link">
    Learn more
    <ArrowRight size={12} />
  </span>
</a>

Features

Category Badge

Displays a colored badge in the top-right corner based on the word’s category:
<span
  class="absolute top-3 right-3 inline-block rounded-full px-2 py-0.5 text-xs font-medium text-white"
  style={`background-color: ${getCategoryColor(entry.data.category)};`}
>
  {entry.data.category}
</span>
Category colors are determined by the getCategoryColor() utility function.

Semantic Heading Levels

Choose the appropriate heading level based on your document structure:
{titleLevel === "h3" ? (
  <h3 class="text-text m-0 mb-2 font-semibold">{entry.data.word}</h3>
) : (
  <h4 class="text-text m-0 mb-2 font-semibold">{entry.data.word}</h4>
)}

Text Truncation

The meaning text is limited to 2 lines using CSS line clamping:
.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

Hover Effects

Interactive hover states include:
  • Slight upward translation (hover:-translate-y-1)
  • Border color changes to primary
  • Background color changes to card-hover
  • Shadow enhancement

Styling

Base Styles

.word-related-card {
  text-decoration: none;
  color: inherit;
  display: block;
  border-radius: 0.5rem;
  border: 1px solid var(--border-theme);
  background: var(--card);
  padding: 1rem;
  transition: all 200ms;
}

Hover State

.word-related-card:hover {
  border-color: var(--primary);
  background-color: var(--card-hover);
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
}

Internationalization

The “learn more” text is automatically translated:
const t = useTranslations(lang);

<span>
  {t("word.learn_more")}
  <ArrowRight size={12} />
</span>

Accessibility

  • Semantic HTML with proper heading hierarchy
  • Full card is clickable (entire area is the link)
  • Visible focus states
  • Descriptive link text with icon
  • Color contrast meets WCAG standards

Layout Examples

Grid Layout

<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  {words.map((entry) => (
    <WordCard entry={entry} lang={lang} />
  ))}
</div>

Flex Layout

<div class="flex flex-wrap gap-4">
  {words.map((entry) => (
    <WordCard entry={entry} lang={lang} />
  ))}
</div>

Category Colors

Category colors are defined in the getCategoryColor() utility:
  • sustantivo/noun: Blue
  • verbo/verb: Green
  • adjetivo/adjective: Orange
  • adverbio/adverb: Purple
  • expresion/expression: Pink
  • interjección/interjection: Red
  • getCategoryColor() - Returns color for a given category
  • useTranslations() - Translation helper

Build docs developers (and LLMs) love