← Corpus / lost-in-public / other
Refactor Reference Lists into Reference Grid
Refactor reference lists into a grid-based component
- Path
- refactors/Refactor-Reference-Lists-into-Reference-Grid.md
- Authors
- Michael Staton
- Augmented with
- Windsurf Cascade on Claude 3.5 Sonnet
- Tags
- Render-Logic · Astro · Component-Architecture · Content-Display · Refactoring · CSS
Goal
Refactor the existing reference item listing logic and styling from site/src/pages/more-about/index.astro into a reusable Astro component located at site/src/components/reference/ReferenceGrid.astro. The new component must use the project’s established CSS framework (@/styles) and CSS variables, completely replacing the current Tailwind CSS implementation for the grid.
Starting Point Files
- Source Logic & Styling:
site/src/pages/more-about/index.astro - Target Component:
site/src/components/reference/ReferenceGrid.astro(currently empty)
Current Implementation (index.astro)
- Data Fetching: Uses
getCollection('vocabulary')andgetCollection('concepts')to fetch markdown entries. - Data Processing: Iterates through entries to generate titles from filenames if missing, then sorts entries alphabetically by title.
- Rendering: Maps over the
vocabularyEntriesandconceptsEntriesarrays separately. - Grid Structure: Uses Tailwind CSS classes (
grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4) for layout. - Item Rendering: Renders each item using dedicated preview card components (
VocabularyPreviewCard.astroandConceptPreviewCard.astro).
// site/src/pages/more-about/index.astro (Relevant Snippet)
// ... data fetching and processing ...
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{vocabularyEntries.map(entry => (
<VocabularyPreviewCard entry={entry} />
))}
</div>
// ... separator ...
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{conceptsEntries.map(entry => (
<ConceptPreviewCard entry={entry} />
))}
</div>
Target Component (ReferenceGrid.astro)
1. Props Interface
The component should accept a single prop, items, which is an array of objects. Each object should contain the necessary data to render a preview card.
// Define within ReferenceGrid.astro script
interface ReferenceItem {
// Data required by the preview cards
// Example fields - adjust based on actual card needs
slug: string;
collection: 'vocabulary' | 'concepts'; // To determine URL path
data: {
title: string;
// Add other fields used by preview cards (e.g., description, image?)
};
}
interface Props {
items: ReferenceItem[];
}
const { items } = Astro.props;
2. Rendering Logic
- The component should map over the
itemsprop. - Inside the loop, it should render the appropriate preview card (
VocabularyPreviewCardorConceptPreviewCard) based on the item’s collection or some other distinguishing factor if needed. Alternatively, the grid could be made more generic and the parent page passes the specific card component as a prop if necessary, but using the existing cards directly is preferred if possible. - The grid layout itself should be implemented within this component.
3. Styling (CSS)
- No Tailwind: Remove all Tailwind classes.
- Use Project Styles: Implement the grid layout using standard CSS within a
<style>tag inReferenceGrid.astro. - CSS Variables: Leverage variables from
@/stylesfor consistency (e.g.,var(--spacing-4),var(--breakpoint-md)). - Grid Layout: Aim for a responsive grid:
- 1 column on small screens.
- 2 columns on medium screens (
--breakpoint-md). - 3 columns on large screens (
--breakpoint-lg).
- Class Naming: Use a consistent naming convention (e.g., BEM like
reference-grid,reference-grid__item).
Target HTML Structure (Example)
<div class="reference-grid">
<!-- Loop over items -->
<div class="reference-grid__item">
<!-- Render VocabularyPreviewCard or ConceptPreviewCard here -->
<!-- Example: <VocabularyPreviewCard entry={item} /> -->
</div>
<!-- ... more items ... -->
</div>
Example CSS Snippet
/* site/src/components/reference/ReferenceGrid.astro */
.reference-grid {
display: grid;
grid-template-columns: 1fr; /* Default 1 column */
gap: var(--spacing-4); /* Example variable */
}
@media (min-width: var(--breakpoint-md)) { /* Example variable */
.reference-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: var(--breakpoint-lg)) { /* Example variable */
.reference-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* No styling needed for reference-grid__item unless specifically required */
Data Flow
graph TD
A[index.astro] -- Fetches --> B(Vocabulary Collection);
A -- Fetches --> C(Concepts Collection);
A -- Processes & Sorts --> D{Combined/Processed Data Array};
D -- Passed as 'items' prop --> E[ReferenceGrid.astro Component];
E -- Maps over 'items' --> F[Renders Grid Layout];
E -- For each item --> G(VocabularyPreviewCard / ConceptPreviewCard);
F & G --> H(Final HTML Output);
Refactored Usage Example (index.astro)
// site/src/pages/more-about/index.astro (After Refactor)
---
import { getCollection } from 'astro:content';
import Layout from '@layouts/Layout.astro';
import ThinGradientBleedSeparator from '@components/basics/separators/ThinGradientBleedSeparator.astro';
import ReferenceGrid from '@components/reference/ReferenceGrid.astro'; // Import the new component
// ... data fetching and processing logic remains largely the same ...
// Combine or prepare data as needed for the ReferenceItem interface
// Example: prepare items for the grid component
const vocabularyItems = vocabularyEntries.map(entry => ({
slug: entry.slug,
collection: entry.collection,
data: entry.data
}));
const conceptItems = conceptsEntries.map(entry => ({
slug: entry.slug,
collection: entry.collection,
data: entry.data
}));
---
<Layout title="Reference - Vocabulary & Concepts">
<div class="container mx-auto py-8 px-4"> <!-- Keep container styling -->
<h1 class="text-3xl font-bold mb-6">Reference Library</h1> <!-- Keep heading styling -->
<p class="text-lg mb-8">Browse our collection of vocabulary terms and conceptual frameworks.</p> <!-- Keep text styling -->
<!-- Navigation tabs -->
<!-- ... keep tabs ... -->
<!-- Vocabulary Section -->
<section class="mb-12">
<h2 class="text-2xl font-bold mb-4">Vocabulary</h2> <!-- Keep section heading -->
<p class="mb-6">Terms and definitions used throughout our work.</p> <!-- Keep section text -->
<ReferenceGrid items={vocabularyItems} /> <!-- Use the new component -->
</section>
<ThinGradientBleedSeparator height="2px" marginTop="2rem" marginBottom="2rem" />
<!-- Concepts Section -->
<section>
<h2 class="text-2xl font-bold mb-4">Concepts</h2> <!-- Keep section heading -->
<p class="mb-6">Important ideas and frameworks we use in our work.</p> <!-- Keep section text -->
<ReferenceGrid items={conceptItems} /> <!-- Use the new component -->
</section>
</div>
</Layout>
Key Considerations
- Ensure the
ReferenceGridcomponent correctly uses theVocabularyPreviewCardandConceptPreviewCardto render items. The logic withinReferenceGrid.astromight need to check theitem.collectionproperty to decide which card to use. - The existing preview card components (
VocabularyPreviewCard,ConceptPreviewCard) might need minor adjustments if their props change or if they rely on Tailwind context that is no longer present. - Focus on refactoring the grid layout and the looping mechanism into the new component. The styling of the individual cards should ideally remain within their respective components, but ensure they render correctly without Tailwind grid context.