Consolidate listing pages with unified grid cards and modal system#2101
Open
aaronpowell wants to merge 2 commits into
Open
Consolidate listing pages with unified grid cards and modal system#2101aaronpowell wants to merge 2 commits into
aaronpowell wants to merge 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors the website’s resource listing pages to use a shared card-grid renderer and a unified modal system, aiming to remove duplicated HTML/CSS/JS across Extensions, Agents, Instructions, Skills, Hooks, Workflows, and Plugins.
Changes:
- Introduces shared card rendering helpers (
card-render.ts) and shared card data types (card-model.ts) and migrates per-page*-render.tstemplates to use them. - Adds a “card details” mode to the existing modal (
openCardDetailsModal) and updates listing page scripts to open details modals and in-app source views. - Consolidates/extends global styling for card grids and details-mode modal layouts; updates several extension
canvas.jsonmetadata entries.
Show a summary per file
| File | Description |
|---|---|
| website/src/styles/global.css | Adds modal “details-mode” styling and shared listing card grid styles. |
| website/src/scripts/pages/workflows.ts | Switches to card-details modal and native <select multiple> filtering; adds modal actions. |
| website/src/scripts/pages/workflows-render.ts | Migrates workflow card HTML to renderSharedCardHtml() and shared empty-state helper. |
| website/src/scripts/pages/skills.ts | Switches to card-details modal; adds modal actions for install/download/source. |
| website/src/scripts/pages/skills-render.ts | Migrates skill card HTML to renderSharedCardHtml() and shared empty-state helper. |
| website/src/scripts/pages/plugins.ts | Switches to card-details modal; adds included-items tags and install/source/repository actions. |
| website/src/scripts/pages/plugins-render.ts | Migrates plugin card HTML to renderSharedCardHtml() and shared empty-state helper. |
| website/src/scripts/pages/instructions.ts | Switches to card-details modal; replaces Choices-based filtering with native multi-select. |
| website/src/scripts/pages/instructions-render.ts | Migrates instruction card HTML to renderSharedCardHtml() and shared empty-state helper. |
| website/src/scripts/pages/hooks.ts | Switches to card-details modal; replaces Choices-based filtering with native multi-select; adds download action wiring. |
| website/src/scripts/pages/hooks-render.ts | Migrates hook card HTML to renderSharedCardHtml() and shared empty-state helper. |
| website/src/scripts/pages/extensions.ts | Replaces the extensions preview modal with the unified details modal + gallery support. |
| website/src/scripts/pages/extensions-render.ts | Migrates extension cards to renderSharedCardHtml() and adjusts thumbnail wrapper markup. |
| website/src/scripts/pages/card-render.ts | Adds shared empty state HTML + shared “resource card” HTML renderer. |
| website/src/scripts/pages/card-model.ts | Adds shared card/grid TypeScript model types (currently not enforced by renderers). |
| website/src/scripts/pages/agents.ts | Switches to card-details modal and in-app source viewing actions. |
| website/src/scripts/pages/agents-render.ts | Migrates agent card HTML to renderSharedCardHtml() and shared empty-state helper. |
| website/src/scripts/modal.ts | Adds openCardDetailsModal() and a global click handler for data-open-file-path; uses dynamic imports for markdown rendering deps. |
| website/src/pages/workflows.astro | Adds listing-cards-page class and relies on shared modal. |
| website/src/pages/skills.astro | Adds listing-cards-page class and relies on shared modal. |
| website/src/pages/plugins.astro | Adds listing-cards-page class and relies on shared modal. |
| website/src/pages/instructions.astro | Adds listing-cards-page class and relies on shared modal. |
| website/src/pages/hooks.astro | Adds listing-cards-page class and relies on shared modal. |
| website/src/pages/extensions.astro | Removes the custom extensions preview modal and uses the shared modal component. |
| website/src/pages/agents.astro | Keeps agents page container class (but missing listing-cards-page). |
| extensions/gesture-review/canvas.json | Updates description text. |
| extensions/diagram-viewer/canvas.json | Updates description text. |
| extensions/color-orb/canvas.json | Updates description text. |
| extensions/backlog-swipe-triage/canvas.json | Updates description text. |
| extensions/arcade-canvas/canvas.json | Changes extension id (affects anchors/links). |
| extensions/accessibility-kanban/canvas.json | Updates description text. |
Copilot's findings
- Files reviewed: 31/31 changed files
- Comments generated: 8
- Add detail popup modal for extension cards with full metadata and gallery - Implement image gallery with thumbnail strip and main image selection - Add modal styling and positioning in global.css - Connect card click handlers to open modal with extension data Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
46f390c to
31def0b
Compare
- Add missing listing-cards-page class to agents.astro page root - Pass focusable button element to openCardDetailsModal instead of article - Fixes focus restoration for keyboard users when closing modal - Applied fix across all listing pages (agents, instructions, hooks, plugins, skills, workflows) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines
+153
to
+157
| gallery?.querySelectorAll<HTMLButtonElement>(".extension-details-thumbnail-btn").forEach((button) => { | ||
| const isActive = button.dataset.galleryImageUrl === url; | ||
| button.classList.toggle("active", isActive); | ||
| button.toggleAttribute("aria-current", isActive); | ||
| }); |
Comment on lines
+299
to
+309
| const thumbnailButton = target.closest( | ||
| ".resource-thumbnail-btn" | ||
| ) as HTMLButtonElement | null; | ||
| if (thumbnailButton) { | ||
| event.preventDefault(); | ||
| event.stopPropagation(); | ||
| const extensionId = thumbnailButton.dataset.extensionId; | ||
| if (!extensionId) return; | ||
| openDetailsModal(extensionId, undefined, thumbnailButton); | ||
| return; | ||
| } |
Comment on lines
+318
to
+322
| const card = target.closest(".resource-item") as HTMLElement | null; | ||
| const extensionId = card?.dataset.extensionId; | ||
| if (extensionId) { | ||
| openDetailsModal(extensionId, undefined, card || undefined); | ||
| } |
Comment on lines
+47
to
+52
| function getSelectValues(select: HTMLSelectElement | null): string[] { | ||
| if (!select) return []; | ||
| return Array.from(select.selectedOptions).map((option) => option.value); | ||
| } | ||
|
|
||
| function setSelectValues(select: HTMLSelectElement | null, values: string[]): void { |
Comment on lines
+1
to
+5
| export type CardActionKind = "link" | "install" | "copy" | "download" | "share"; | ||
| export type CardActionVariant = "primary" | "secondary" | "icon"; | ||
|
|
||
| export interface CardAction { | ||
| id: string; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR consolidates the listing pages (Extensions, Agents, Instructions, Skills, Hooks, Workflows, Plugins) from a stacked list layout to a unified card grid design, eliminating significant HTML/CSS/JavaScript duplication across pages.
Why
The website had implemented card-grid layouts independently on each listing page, resulting in:
*-render.tsfilesglobal.csswith 5 per-page selector groupsApproach
1. Shared card rendering primitives
card-model.tswith a unifiedSharedCardRenderIteminterface used across all pagescard-render.tswith reusablerenderSharedCardHtml()helper to eliminate per-page template duplication2. Unified modal system
Modal.astrocomponentmodal.tswithopenCardDetailsModal()function supporting both file-view and card-details modesmarkedandfront-matterto avoid Vite "Outdated Optimize Dep" errors3. Consolidated CSS
.listing-cards-pageclass to replace 5 duplicated page-specific selector groups4. In-app source viewing
<a>tags to<button>elements withdata-open-file-pathhandlermodal.tsto open resource files in-app instead of navigating to GitHubgetResourceType(filePath)helper to auto-detect file types from extensions5. Restored plugin items visibility
Files changed
Created:
website/src/scripts/pages/card-model.ts- Shared card/grid data model interfaceswebsite/src/scripts/pages/card-render.ts- Shared HTML card rendering helpersModified:
website/src/scripts/modal.ts- Unified modal system with in-app file open handlerwebsite/src/styles/global.css- Added.listing-cards-pageclass, consolidated CSS, fixed keyword tag clippingwebsite/src/pages/{agents,instructions,extensions,skills,hooks,workflows,plugins}.astro- Added shared class, removed per-page modalswebsite/src/scripts/pages/{agents,instructions,skills,hooks,workflows,plugins}.ts- Use unified modal and in-app file handlerwebsite/src/scripts/pages/{*}-render.ts- All migrated to sharedrenderSharedCardHtml()website/src/scripts/pages/extensions-render.ts- Fixed nested button markup (thumbnail button → div)Testing notes
Non-obvious decisions
<button>to<div class="resource-thumbnail-btn">to fix browser DOM rewriting of invalid nested buttons (fixes Coffilot card rendering).Type of Contribution
By submitting this pull request, I confirm that my contribution abides by the Code of Conduct and will be licensed under the MIT License.