Files
supabase/packages/ui-patterns/src/Markdown/components.tsx
Francesco Sansalvadoreandcoderabbitai[bot] 6470ac9186 chore(studio): marketplace styling (#46574)
- Marketplace index page
  - update order of feature partner integrations in hero
  - fix z-index on MarketplaceFilterBar in "list" view
<img width="275" height="104" alt="Screenshot 2026-06-02 at 17 07 29"
src="https://github.com/user-attachments/assets/5cef64f9-895e-4f8d-8f30-153ddd5c89dd"
/>

- Marketplace detail page
- use "prose" css styling on overview content for better text styling
(heading with top padding, etc)
- refine FilesView in overview tab to only show swipeable and zoomable
previews (so the big image doesn't occupy too much space) + lazy load
FilesView component
  - improve page loading state
- improve overview side rail sticky-top and remove redundant "About"
label

<img width="1333" height="732" alt="Screenshot 2026-06-02 at 17 20 29"
src="https://github.com/user-attachments/assets/8f3dd4a0-c241-4b7f-b8c8-192e1d7a616d"
/>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Interactive carousel with image zoom capability for viewing
integration preview images

* **Bug Fixes**
  * Fixed z-index layering issue with marketplace filter bar

* **Refactor**
  * Redesigned marketplace detail page header with breadcrumb navigation
  * Updated integration image handling structure with enhanced metadata
  * Optimized dynamic loading for integration file viewers
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-06-04 15:38:21 +02:00

140 lines
3.5 KiB
TypeScript

'use client'
import dynamic from 'next/dynamic'
import React, { isValidElement, type HTMLAttributes } from 'react'
import { cn } from 'ui'
import { type CodeBlockLang } from 'ui-patterns/CodeBlock'
const DynamicCodeBlock = dynamic(() =>
import('../CodeBlock').then((m) => ({ default: m.CodeBlock }))
)
export const InlineCode = ({ className, ...props }: HTMLAttributes<HTMLElement>) => (
<code className={cn('text-code-inline', className)} {...props} />
)
export const Blockquote = ({ className, ...props }: HTMLAttributes<HTMLElement>) => (
<blockquote
className={cn('mt-4 border-l-2 pl-6 italic text-foreground-light', className)}
{...props}
/>
)
export const Img = ({
className,
alt = '',
...props
}: HTMLAttributes<HTMLImageElement> & { alt?: string }) => (
// eslint-disable-next-line @next/next/no-img-element
<img className={cn('rounded-md border', className)} alt={alt} {...props} />
)
export const SimplePre = ({ className, ...props }: HTMLAttributes<HTMLPreElement>) => (
<pre
className={cn(
'my-4 overflow-x-auto rounded-lg border bg-surface-75 py-4 px-4 text-sm text-foreground-light',
className
)}
{...props}
/>
)
export const Code = ({
className,
children,
}: {
className?: string
children?: React.ReactNode
}) => {
// Code blocks have language-xxx class, pass through for pre handler to extract
if (className?.startsWith('language-')) {
return <code className={className}>{children}</code>
}
return <InlineCode>{children}</InlineCode>
}
export const DefaultPre = ({ children, ...props }: HTMLAttributes<HTMLPreElement>) => (
<SimplePre {...props}>{children}</SimplePre>
)
export const CodeBlockPre = ({ children, ...props }: HTMLAttributes<HTMLPreElement>) => {
// Find the code element inside pre
const codeElement = React.Children.toArray(children).find(
(child) => isValidElement(child) && child.type === 'code'
)
if (!isValidElement(codeElement)) {
return <SimplePre {...props}>{children}</SimplePre>
}
const { className, children: code } = codeElement.props as {
className?: string
children: string
}
const language = className?.replace('language-', '') as CodeBlockLang
const content = typeof code === 'string' ? code.trimEnd() : ''
if (!language || !content) {
return <SimplePre {...props}>{children}</SimplePre>
}
return (
<DynamicCodeBlock
value={content}
language={language}
hideLineNumbers={false}
className="my-4"
/>
)
}
export const Avatar = ({
src,
alt = 'Avatar',
caption,
}: {
src: string
alt?: string
caption?: string
}) => (
<div className={cn('align-center m-0 flex items-center gap-3')}>
<img src={src} alt={alt} className="h-8 w-8 rounded-full object-cover m-0" />
{caption && (
<figcaption className="text-foreground-lighter font-normal not-italic text-sm m-0">
{caption}
</figcaption>
)}
</div>
)
export const Quote = ({
children,
attribution,
src,
alt,
caption,
className,
...props
}: HTMLAttributes<HTMLQuoteElement> & {
attribution?: string
src?: string
alt?: string
caption?: string
}) => (
<blockquote
className={cn(
'mt-4 border-l-2 pl-6 italic text-foreground-light [&>p]:my-0 [&>p:not(:last-child)]:mb-4',
className
)}
{...props}
>
{children}
{attribution && (
<div className="mt-4 not-italic text-sm text-foreground">
<div className="font-semibold">— {attribution}</div>
{src && caption && <Avatar src={src} alt={alt} caption={caption} />}
</div>
)}
</blockquote>
)