feat(storefront): render product description as markdown
Some checks failed
Deploy — Staging / Detect changed apps (push) Successful in 16s
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m29s
Deploy — Staging / Build & push — ${{ matrix.app }} (push) Failing after 49s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
Some checks failed
Deploy — Staging / Detect changed apps (push) Successful in 16s
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m29s
Deploy — Staging / Build & push — ${{ matrix.app }} (push) Failing after 49s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
- Add react-markdown dependency to storefront - Use ReactMarkdown in ProductDetailDescriptionSection for formatted descriptions Made-with: Cursor
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
"@stripe/react-stripe-js": "^5.6.0",
|
||||
"@stripe/stripe-js": "^8.8.0",
|
||||
"framer-motion": "^11.0.0",
|
||||
"lucide-react": "^0.400.0"
|
||||
"lucide-react": "^0.400.0",
|
||||
"react-markdown": "^10.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
type ProductDetailDescriptionSectionProps = {
|
||||
/** Product description (HTML or plain text); server-rendered in initial HTML per SEO. */
|
||||
/** Product description (Markdown); server-rendered in initial HTML per SEO. */
|
||||
description?: string | null;
|
||||
};
|
||||
|
||||
const descriptionClasses =
|
||||
"max-w-3xl text-sm leading-relaxed text-[var(--foreground)]/80 [&_ol]:mb-3 [&_ol]:list-inside [&_ol]:list-decimal [&_p:last-child]:mb-0 [&_p]:mb-3 [&_ul]:mb-3 [&_ul]:list-inside [&_ul]:list-disc";
|
||||
|
||||
/**
|
||||
* Description content for the PDP tabs section.
|
||||
* Renders inside a parent <section> provided by ProductDetailTabsSection.
|
||||
* Renders Markdown as HTML inside a parent <section> provided by ProductDetailTabsSection.
|
||||
* If empty, shows a short fallback message.
|
||||
*/
|
||||
export function ProductDetailDescriptionSection({
|
||||
@@ -15,10 +20,9 @@ export function ProductDetailDescriptionSection({
|
||||
typeof description === "string" && description.trim().length > 0;
|
||||
|
||||
return hasContent ? (
|
||||
<div
|
||||
className="max-w-3xl text-sm leading-relaxed text-[var(--foreground)]/80 [&_ol]:mb-3 [&_ol]:list-inside [&_ol]:list-decimal [&_p:last-child]:mb-0 [&_p]:mb-3 [&_ul]:mb-3 [&_ul]:list-inside [&_ul]:list-disc"
|
||||
dangerouslySetInnerHTML={{ __html: description!.trim() }}
|
||||
/>
|
||||
<div className={descriptionClasses}>
|
||||
<ReactMarkdown>{description!.trim()}</ReactMarkdown>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-[var(--muted)]">No description available.</p>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user