shadimage
contentbit
componentastro-pros-conssource: ok · hit

Pros & Cons Block (Astro)

Paired advantages and disadvantages.

npx shadcn add "https://contentbit.dev/r/astro-pros-cons.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
@contentbit/core@contentbit/blocks@contentbit/astro

Files1 · source cached 10/15/2026, 4:33:48 AM

src/astro/pros-cons.astro
---
import type { ProsConsData } from '@contentbit/blocks'
import type { ValidatedBlockNode } from '@contentbit/core'
import type { AstroBlockContext } from '@contentbit/astro'

import { splitProsCons } from '@contentbit/blocks'

interface Props {
  node: ValidatedBlockNode<unknown>
  ctx: AstroBlockContext
}

const { node, ctx } = Astro.props
const { pros, cons } = splitProsCons(node.data as ProsConsData)
const [renderedPros, renderedCons] = await Promise.all([
  Promise.all(pros.map((item) => ctx.renderMarkdown(item))),
  Promise.all(cons.map((item) => ctx.renderMarkdown(item))),
])

// Inline lucide paths: check, x.
const CHECK = '<path d="M20 6 9 17l-5-5"/>'
const X = '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>'

const columns = [
  {
    heading: 'Pros',
    items: renderedPros,
    path: CHECK,
    head: 'bg-emerald-500/[0.07] text-emerald-700 dark:text-emerald-400',
    mark: 'text-emerald-600 dark:text-emerald-500',
  },
  {
    heading: 'Cons',
    items: renderedCons,
    path: X,
    head: 'bg-rose-500/[0.07] text-rose-700 dark:text-rose-400',
    mark: 'text-rose-600 dark:text-rose-500',
  },
]
---

<div data-cb-styled class="my-6 grid gap-3 sm:grid-cols-2">
  {
    columns.map((col) => (
      <div class="bg-card overflow-hidden rounded-lg border">
        <div class:list={['flex items-center gap-2 border-b px-4 py-2.5', col.head]}>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="3"
            stroke-linecap="round"
            stroke-linejoin="round"
            class="size-3.5"
            aria-hidden="true"
            set:html={col.path}
          />
          <span class="text-xs font-semibold tracking-wider uppercase">{col.heading}</span>
        </div>
        <ul class="list-none space-y-2 p-4 text-sm">
          {col.items.map((html) => (
            <li class="flex gap-2.5">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2.5"
                stroke-linecap="round"
                stroke-linejoin="round"
                class:list={['mt-1 size-3.5 shrink-0', col.mark]}
                aria-hidden="true"
                set:html={col.path}
              />
              <div class="min-w-0 leading-relaxed [&>p]:m-0" set:html={html} />
            </li>
          ))}
        </ul>
      </div>
    ))
  }
</div>

More from contentbit

Browse all components in this library →