UI Library

Principles grid

A two-column grid of bordered term-and-description cards, with a section header above it. Built on a real <dl>, so each term is announced together with its description.

Featuresgriddefinition-listaccessible
Preview
How we work

A few principles that constrain what we build.

Not slogans: actual limits on what we will and will not ship.

Amanah
User data is held in trust. Collect only what a feature needs, never sell it, and deletion is real deletion.
Sidq
Marketing claims match the implementation. No dark patterns. AI outputs are disclosed.
Adl
Transparent, proportionate pricing. Safety features are never paywalled. Cancellation is frictionless.
Ihsan
Quality over feature count. Performance and reliability come first.
apps/site/blocks/components/principles-grid.tsx
interface Principle {
  term: string;
  description: string;
}

const DEFAULT_PRINCIPLES: Principle[] = [
  {
    term: 'Amanah',
    description:
      'User data is held in trust. Collect only what a feature needs, never sell it, and deletion is real deletion.',
  },
  {
    term: 'Sidq',
    description:
      'Marketing claims match the implementation. No dark patterns. AI outputs are disclosed.',
  },
  {
    term: 'Adl',
    description:
      'Transparent, proportionate pricing. Safety features are never paywalled. Cancellation is frictionless.',
  },
  {
    term: 'Ihsan',
    description: 'Quality over feature count. Performance and reliability come first.',
  },
];

export function PrinciplesGrid({
  eyebrow = 'How we work',
  title = 'A few principles that constrain what we build.',
  intro = 'Not slogans: actual limits on what we will and will not ship.',
  principles = DEFAULT_PRINCIPLES,
}: {
  eyebrow?: string;
  title?: string;
  intro?: string;
  principles?: Principle[];
}) {
  return (
    <section className="border-b border-border/60">
      <div className="mx-auto max-w-6xl px-4 py-20 sm:px-6">
        <div className="mb-12 max-w-2xl space-y-3">
          <div className="text-xs font-medium uppercase tracking-widest text-primary">{eyebrow}</div>
          <h2 className="text-2xl font-semibold tracking-tight sm:text-3xl">{title}</h2>
          <p className="text-sm text-muted-foreground sm:text-base">{intro}</p>
        </div>

        {/* A definition list, not a div soup: each card is genuinely a term and
            its description, so screen readers announce the pairing. */}
        <dl className="grid gap-6 sm:grid-cols-2">
          {principles.map((principle) => (
            <div key={principle.term} className="rounded-lg border border-border/70 bg-card p-5">
              <dt className="text-sm font-semibold">{principle.term}</dt>
              <dd className="mt-1.5 text-sm text-muted-foreground">{principle.description}</dd>
            </div>
          ))}
        </dl>
      </div>
    </section>
  );
}

Dependencies

None. This block is self-contained — plain React and Tailwind utility classes. Paste the file and it renders.

Colours come from CSS variables (--background, --primary, --border) using the shadcn/ui token names, so the block adopts your palette rather than importing ours.