fix(website): catalog cards never collapse; clicking one opens the plugin page

Cards toggled between a 2-line summary and an expanded detail block on click, so the
click users expected to open the plugin page only grew or shrank the card, and the way
to the page (a plain-styled title link) was invisible. Cards now always show the full
detail block, the title underlines on hover, and a click anywhere on the card navigates
to /docs/plugins/<name>; inside the Desktop picker embed it opens the page in a new tab
so the host embed stays put.
This commit is contained in:
teknium1
2026-09-21 00:27:09 -07:00
committed by Teknium
parent dec236b214
commit a782e2ee77
2 changed files with 19 additions and 31 deletions

View File

@@ -71,16 +71,12 @@ function highlightMatch(text: string, query: string): React.ReactNode {
function PluginCard({
plugin,
query,
expanded,
onToggle,
onPick,
onCategoryClick,
style,
}: {
plugin: CatalogPlugin;
query: string;
expanded: boolean;
onToggle: () => void;
/** Picker embed mode: render "+ Add to this Agent" and call this. */
onPick?: (plugin: CatalogPlugin) => void;
onCategoryClick?: (category: string) => void;
@@ -95,14 +91,21 @@ function PluginCard({
const pagePath = pluginPagePath(plugin.name);
const history = useHistory();
const pageHref = useBaseUrl(pagePath); // <Link> adds baseUrl itself; history.push does not
// Outside the Desktop picker a card is a link to the plugin's own page (shareable, indexable);
// inside the picker iframe navigation would leave the host's embed, so the card keeps
// expanding in place there.
const onCardClick = onPick ? onToggle : () => history.push(pageHref);
// A card IS the link to the plugin's own page: nothing expands or collapses in place. Inside
// the Desktop picker iframe an in-frame navigation would leave the host's embed, so the page
// opens in a new tab there instead.
const onCardClick = onPick
? () => window.open(new URL(pageHref, window.location.href).toString(), "_blank", "noopener,noreferrer")
: () => history.push(pageHref);
return (
<div
className={`${styles.card} ${expanded ? styles.cardExpanded : ""}`}
className={styles.card}
role="link"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter") onCardClick();
}}
onClick={onCardClick}
style={style}
>
@@ -159,7 +162,7 @@ function PluginCard({
</div>
</div>
<p className={`${styles.cardDesc} ${expanded ? styles.cardDescFull : ""}`}>
<p className={styles.cardDesc}>
{highlightMatch(plugin.description || "No description available.", query)}
</p>
@@ -239,7 +242,7 @@ function PluginCard({
</a>
)}
{expanded && (
{
<div className={styles.cardDetail}>
{plugin.maintainer && (
<div className={styles.metaRow}>
@@ -320,7 +323,7 @@ function PluginCard({
) : null}
</div>
</div>
)}
}
</div>
</div>
);
@@ -382,7 +385,6 @@ export default function PluginCatalogPage() {
const [tierFilter, setTierFilter] = useState("all");
const [categoryFilter, setCategoryFilter] = useState("all");
const [sort, setSort] = useState<SortKey>("stars");
const [expandedCard, setExpandedCard] = useState<string | null>(null);
const searchRef = useRef<HTMLInputElement>(null);
useEffect(() => {
@@ -418,7 +420,6 @@ export default function PluginCatalogPage() {
}
if (e.key === "Escape") {
searchRef.current?.blur();
setExpandedCard(null);
}
};
window.addEventListener("keydown", handler);
@@ -463,7 +464,6 @@ export default function PluginCatalogPage() {
}, [allPlugins, tierFilter]);
useEffect(() => {
setExpandedCard(null);
}, [search, tierFilter, categoryFilter]);
const clearAll = useCallback(() => {
@@ -486,8 +486,6 @@ export default function PluginCatalogPage() {
key={key}
plugin={plugin}
query={search}
expanded={expandedCard === key}
onToggle={() => setExpandedCard(expandedCard === key ? null : key)}
onPick={pickerMode ? pickPlugin : undefined}
onCategoryClick={pickCategory}
style={{ animationDelay: `${Math.min(i, 20) * 25}ms` }}

View File

@@ -474,10 +474,6 @@
transform: translateY(-1px);
}
.cardExpanded {
border-color: rgba(255, 215, 0, 0.2);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 215, 0, 0.08);
}
.cardAccent {
position: absolute;
@@ -573,15 +569,8 @@
line-height: 1.55;
color: var(--ifm-font-color-secondary, #9a968e);
margin: 0 0 0.6rem;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.cardDescFull {
-webkit-line-clamp: unset;
}
.cardMeta {
display: flex;
@@ -639,7 +628,6 @@
margin-top: 0.75rem;
padding-top: 0.7rem;
border-top: 1px solid rgba(255, 255, 255, 0.04);
animation: cardIn 0.2s ease both;
}
.metaRow {
@@ -962,7 +950,9 @@ a.pickBtn {
text-decoration: none;
}
.cardTitleLink:hover {
.cardTitleLink:hover,
.card:hover .cardTitleLink {
color: var(--ifm-color-primary);
text-decoration: none;
text-decoration: underline;
text-underline-offset: 3px;
}