KKiotaPay UI
Browse documentation

Sanitized HTML

Renders HTML you did not write — rich-text fields, imported descriptions, API copy — through DOMPurify with a conservative tag and attribute allowlist.

Installation

pnpm dlx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/sanitized-html.json

Adds dompurify to your dependencies.

Usage

import { SanitizedHtml } from '@/components/custom/sanitized-html'

export function PolicyBody({ policy }) {
  return <SanitizedHtml dirtyHtml={policy.body} className="prose text-sm" />
}

Props

PropTypeDefaultDescription
dirtyHtmlstring—Required. Untrusted markup.
classNamestring''Merged with sanitized-html-content.
allowedTagsstring[]see belowTags that survive sanitising.
allowedAttributesstring[]['href', 'title', 'target', 'rel', 'class']Attributes that survive.

The default tag list is inline formatting, links, paragraphs, lists, headings, span and div. No img, no script, no style, no event handlers.

Widen allowedTags deliberately. Every tag added is one an attacker can reach for, and the list is the whole of the defence — dangerouslySetInnerHTML does exactly what it says once something gets past it.

Behaviour notes

The first paint is empty. Sanitising needs a real DOM, so it runs in an effect: doing it during a server render would throw or require jsdom, and doing it inline on the client only would make the server and client markup disagree and fail hydration. The cleaned markup lands immediately after mount.

Pass stable arrays. allowedTags and allowedAttributes are effect dependencies, so a fresh array literal on every render re-sanitises every render. Hoist them to module scope, or leave them at their defaults.