Platform Foundationsv1.3.2

Changelog

A CTA + modal showing implemented issues from a bundled JSON source.

## What's new

You can now **export quotes** as PDF directly from the quote editor.

- Supports custom branding
- Includes line-item totals
- Works in light and dark mode

When to use

When a Platform app needs to surface recently implemented issues to its users in a non-intrusive way: a button in the sidebar or topbar that opens a modal listing the latest changes, grouped by date with type badges.

How it works

The package ships a data.json file bundled at build time, so there is no runtime fetch, server endpoint, or public/ setup. Each entry has a title, type (feature / bugfix / improvement), date, and a markdown body.

To add a new entry, edit packages/ui-components/src/changelog/data.json, publish a new version of the package, and consuming apps pick it up on their next pnpm update.

Platform notes

Like DataTable, this component is slot-based: it carries no hard dependency on shadcn, lucide, or any i18n library. The consuming app passes its own Dialog, Button, and icon components as slots, along with localised strings, a markdown renderer, and a date formatter. This means it works identically across apps that use different UI primitives (e.g. one app uses @tabler/icons-react while the docs app uses lucide-react).

The renderMarkdown slot lets each app decide how rich the entry bodies are: react-markdown, a custom MDX pipeline, or a lightweight inline parser. The formatDate slot lets each app format dates per its locale and i18n settings.

State is controllable: pass open + onOpenChange for full control (e.g. when wiring to a sidebar button), or leave them unset for uncontrolled internal state driven by the trigger button.

Install

pnpm add @plainconceptsplatform/ui-components

Import from the sub-path:

import { Changelog } from "@plainconceptsplatform/ui-components/changelog";
import type { ChangelogEntry } from "@plainconceptsplatform/ui-components/changelog";

Slot contract

<Changelog
  entries={entries}        // optional: override the bundled data.json
  slots={{
    Dialog,                 // Radix Dialog root
    DialogContent,          // shadcn DialogContent (supports showCloseButton)
    DialogHeader,
    DialogTitle,
    DialogDescription,
    Button,                 // shadcn Button (variant, size, asChild)
    ScrollArea,             // optional: shadcn ScrollArea; falls back to a div
  }}
  texts={{
    trigger: "What's new",
    title: "Latest changes",
    description: "Recently implemented issues and improvements.",
    noEntries: "No entries yet.",
    typeLabels: {
      feature: "Feature",
      bugfix: "Bugfix",
      improvement: "Improvement",
    },
  }}
  icons={{ IconSparkles }}
  renderMarkdown={(md) => <MyMarkdownRenderer source={md} />}
  formatDate={(d) => format(new Date(d), "MMM d, yyyy")}
  open={open}
  onOpenChange={setOpen}
/>

Entry schema

[
  {
    "id": "42",
    "title": "Export quotes to PDF",
    "type": "feature",
    "date": "2025-01-15",
    "text": "## What's new\n\nMarkdown **supported** here."
  }
]
FieldTypeRequiredNotes
idstringyesStable identifier (GitHub issue number)
titlestringyesShort one-liner shown in the card header
type"feature" | "bugfix" | "improvement"yesControls the badge colour
datestringyesISO 8601 date (YYYY-MM-DD)
textstringyesMarkdown body rendered via the renderMarkdown slot

Full API

packages/ui-components README