Keep the template picker in the create flow, make catalog cards real links, and stop showing a fake community when review has no draft.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilallo
2026-09-10 15:22:46 -06:00
co-authored by Cursor
parent 3f9a8395be
commit 90db213413
31 changed files with 412 additions and 126 deletions
+3 -1
View File
@@ -35,6 +35,7 @@ const RuleContainer = memo<RuleProps>(
backgroundColor = "bg-[var(--color-community-teal-100)]",
className = "",
onClick,
href,
expanded = false,
size: sizeProp,
categories,
@@ -95,8 +96,9 @@ const RuleContainer = memo<RuleProps>(
icon={icon}
backgroundColor={backgroundColor}
className={className}
href={hasBottomLinks ? undefined : href}
onClick={hasBottomLinks ? undefined : handleClick}
onKeyDown={hasBottomLinks ? undefined : handleKeyDown}
onKeyDown={hasBottomLinks || href ? undefined : handleKeyDown}
expanded={expanded}
size={size}
categories={categories}
+6
View File
@@ -50,6 +50,11 @@ export interface RuleProps {
backgroundColor?: string;
className?: string;
onClick?: () => void;
/**
* When set, the card is a real link (focusable, Enter, open in a new tab)
* instead of a click-only `role="button"` surface.
*/
href?: string;
expanded?: boolean;
size?: RuleSizeValue;
categories?: Category[];
@@ -93,6 +98,7 @@ export interface RuleViewProps {
backgroundColor: string;
className: string;
onClick?: () => void;
href?: string;
onKeyDown?: (_event: React.KeyboardEvent<HTMLDivElement>) => void;
expanded: boolean;
size: RuleSizeValue;
+34 -10
View File
@@ -1,6 +1,7 @@
"use client";
import Image from "next/image";
import NextLink from "next/link";
import MultiSelect from "../../controls/MultiSelect";
import InlineTextButton from "../../buttons/InlineTextButton";
import NavigationLink from "../../navigation/Link";
@@ -19,6 +20,7 @@ export function RuleView({
backgroundColor,
className,
onClick,
href,
onKeyDown,
expanded,
size,
@@ -264,16 +266,11 @@ export function RuleView({
);
}
return (
<div
className={`${backgroundColor} ${cardPadding} ${cardGap} ${borderRadiusClass} shadow-[0px_0px_48px_0px_rgba(0,0,0,0.1)] ${interactiveCard ? "hover:shadow-[0px_0px_64px_0px_rgba(0,0,0,0.15)] transition-shadow duration-200" : ""} flex flex-col items-start justify-center relative ${cardWidth || "w-full"} ${className || ""}`}
tabIndex={interactiveCard ? 0 : undefined}
role={interactiveCard ? "button" : "article"}
aria-label={ariaLabel}
aria-expanded={interactiveCard ? expanded : undefined}
onClick={interactiveCard ? onClick : undefined}
onKeyDown={interactiveCard ? onKeyDown : undefined}
>
const cardClassName = `${backgroundColor} ${cardPadding} ${cardGap} ${borderRadiusClass} shadow-[0px_0px_48px_0px_rgba(0,0,0,0.1)] ${interactiveCard ? "hover:shadow-[0px_0px_64px_0px_rgba(0,0,0,0.15)] transition-shadow duration-200" : ""} flex flex-col items-start justify-center relative ${cardWidth || "w-full"} ${href ? "no-underline text-inherit" : ""} ${className || ""}`;
const isLinkCard = Boolean(href) && interactiveCard;
const cardBody = (
<>
{/* Figma: Header = `border-b` row, `gap-px`, icon `pl-1 pr-2 py-2` + `border-l` on title. */}
<div
className="
@@ -483,6 +480,33 @@ export function RuleView({
</div>
)
)}
</>
);
if (isLinkCard && href) {
return (
<NextLink
href={href}
className={cardClassName}
aria-label={ariaLabel}
onClick={onClick}
>
{cardBody}
</NextLink>
);
}
return (
<div
className={cardClassName}
tabIndex={interactiveCard ? 0 : undefined}
role={interactiveCard ? "button" : "article"}
aria-label={ariaLabel}
aria-expanded={interactiveCard ? expanded : undefined}
onClick={interactiveCard ? onClick : undefined}
onKeyDown={interactiveCard ? onKeyDown : undefined}
>
{cardBody}
</div>
);
}