# Petal Components: shadcn-style HEEx components for Phoenix LiveView

> Petal Components is a Hex package of Tailwind v4 HEEx components for Phoenix, paired with a hosted MCP server so AI coding tools read the real schema. The manual install is short; the interesting part is what happens when you leave the component list to the agent.

**petalframework/petal_components** — Phoenix + Live View HEEX Components. Petal Components Shadcn-style Phoenix components that AI assistants can actually use.

- Repository: https://github.com/petalframework/petal_components
- Website: https://petal.build/components
- Stars: 1,055 · Forks: 101
- Language: Elixir
- License: MIT
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/petalframework-petal-components

## What Petal Components is for

Phoenix ships with function components and HEEx, but nothing resembling a design system. Teams either write their own button, modal and table markup or copy patterns between projects. Petal Components fills that gap with a Hex package of roughly thirty components, described in the README as "shadcn-style Phoenix components that AI assistants can actually use."

The audience is narrower than "any Phoenix developer." The README targets people who already know the shadcn workflow in React: composable primitives, patterns you own, no monolithic theme to fight. The second audience is less usual. Petal ships a hosted MCP server at mcp.petal.build whose stated purpose is to stop Claude Code, Cursor, Codex and Windsurf from generating raw Tailwind markup out of training data. That is a bet that the component library's real competition is not another Elixir package but an assistant's memory of what Tailwind classes look like.

The catalogue spans layout and content (container, card, accordion, tabs, stepper, skeleton), forms (field, text_input, select, checkbox, radio_group, switch, textarea, date_input, file_input), actions, feedback and data display (table, pagination, breadcrumbs, badge, avatar, marquee, icon, link). The README states the MCP server is the canonical list, not the README, which is an honest admission that a prose catalogue drifts.

## How the components and the MCP server fit together

The runtime is ordinary Phoenix. Components are HEEx function components built with Tailwind v4, and the README says they work in both live and dead views. Most of the library is CSS plus LiveView.JS, so it adds no client-side framework. The exceptions are the bundled JS hooks, which the README lists as powering the password, copyable and clearable inputs plus the chat components.

The MCP server is a separate, hosted piece. It exposes each component's schema to an AI tool, so the agent can call list_components and then get_component before writing markup. The repository also carries a rules.md file described as the canonical instruction set, covering the component naming map (HEEx tag form, module path, CSS class prefix), how to discover components through the MCP, and common patterns such as form-in-card, modal-with-form and table-with-actions. That file is the part you can read without running anything, and it is where the real conventions live.

The distribution model differs from shadcn in a way worth stating plainly. Petal is a Hex dependency, not a CLI that copies source files into your repository. The README frames this as an advantage (update with mix deps.update) and it is, until you want to change a component's internals. With copied files you edit them. With a dependency you either wrap it, override the CSS, or fork.

## Installing petal_components manually and rendering a first table

The README recommends a two-step path where an AI agent applies the install for you, and a manual path for people who would rather do it themselves. The manual path is the one you can verify without trusting an agent.

Start with the dependency in mix.exs. The README's example pins "~> 4.0", while the latest release listed in the repository metadata is v3.2.2 from 2026-05-15. Check Hex for the constraint that matches the version you actually intend to run before copying this.

```elixir
def deps do
  [
    {:petal_components, "~> 4.0"},
    # optional — only needed for the chat markdown components (<Chat.markdown>, <Chat.rich_text>)
    {:mdex, "~> 0.12"}
  ]
end
```

Next, Tailwind needs to see the component source. The README patches assets/css/app.css with an @source directive pointing at the dependency and an import of the default stylesheet.

```css
@import "tailwindcss";
@source "../deps/petal_components/**/*.*ex";
@import "../deps/petal_components/assets/default.css";
```

Then bring the components into your web module so the tags are available in your templates.

```elixir
def html do
  quote do
    use PetalComponents
    # ... your other imports
  end
end
```

If you need the password, copyable, clearable or chat components, register the bundled hooks in assets/js/app.js. The README shows them merged into the LiveSocket hooks map alongside your own.

```js
import PetalComponents from "../../deps/petal_components/assets/js/petal_components"

const liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: { ...PetalComponents }, // merge with your own hooks if you have any
})
```

Run mix deps.get and then mix compile. A first real use is the table example from the README, which shows the slot-based API: named :col slots with a :let binding for each row.

```heex
<.table rows={@users}>
  <:col :let={user} label="Name">{user.name}</:col>
  <:col :let={user} label="Email">{user.email}</:col>
  <:col :let={user} label="">
    <.button size="xs" variant="outline" phx-click="edit" phx-value-id={user.id}>
      Edit
    </.button>
  </:col>
</.table>
```

If you want the agent-driven route instead, the README's first command registers the MCP server with Claude Code over HTTP, after which you tell the assistant to install petal_components and it edits mix.exs, runs mix deps.get, patches the CSS and adds the use line itself.

```sh
claude mcp add petal --transport http https://mcp.petal.build/mcp
```

Cursor, Windsurf, Continue, Codex and Cline have their own MCP install commands, which the README points to at petal.build/petal-components rather than reproducing.

## What the AI-first install path asks you to trust

The agent-driven install is the project's distinctive claim and also its weakest point for a cautious team. The README says the agent calls get_install_instructions, applies changes to mix.exs, runs mix deps.get, patches assets/css/app.css and adds use PetalComponents to your web module, and that this approach handles umbrella and standard project shapes without the install code special-casing them.

That is a reasonable division of labour. Project shape variance is exactly the kind of thing a human-written installer gets wrong, and an agent reading your files can adapt. But it means the install is non-deterministic. Two engineers on the same repository can get different diffs, and there is no installer version to pin. The README does not document a rollback path for a bad agent edit, and it does not describe what the agent does when your app.css already imports Tailwind with custom layers. Review the diff before you commit it.

The second trust question is the hosted MCP endpoint itself. mcp.petal.build is a remote service, not a local process. Nothing in the README says component schemas are transmitted anywhere beyond the tool call, but the endpoint is the mechanism, and a team with restrictions on outbound developer tooling will need to weigh that. The manual install path exists precisely so you can skip the MCP entirely, at the cost of losing the schema lookup.

A smaller constraint: the README notes the MCP server is the canonical component list, so the README catalogue is illustrative. If you are writing your own tooling against the component set, read rules.md rather than parsing the README.

## Petal Components compared with shadcn and SaladUI

The README's own comparison is with shadcn, and it is fair as far as it goes: same philosophy of composable primitives, same MCP-style integration for AI tools, different runtime (HEEx rather than JSX), different styling baseline (Tailwind v4 rather than Tailwind 3 with CSS variables), and different distribution (a Hex package rather than a CLI that copies files). The distribution difference is the one that changes daily work. mix deps.update is a one-line upgrade; it is also a one-line way to inherit a breaking change across every view at once. The repository carries an UPGRADE_GUIDE.md, which suggests the maintainers expect those jumps to need reading.

SaladUI is the other Phoenix component library that comes up in the same searches, and the approaches differ in a way that matters. SaladUI is built around copying component source into your application, the shadcn model taken literally: you get the code, you own it, you edit it in place. Petal keeps components in a dependency and gives you a naming map and a rules file so tools and humans can call them consistently. If your team expects to restyle a modal's internals rather than wrap it, copy-in is the easier model. If you want a versioned dependency you can bump and a schema an agent can read, Petal is the one built for that.

Neither choice fixes your design system. Both give you a starting vocabulary and leave the composition patterns to you, which is what the README means by "you own the patterns."

## Running the component playground locally

The repository includes a standalone dev server so you can inspect every component without wiring Petal into an application first. The README gives the sequence directly: clone the repository, fetch dependencies, install the Tailwind binary, and start it under IEx with dev.exs.

```sh
# 1. Install the MCP server once
git clone https://github.com/petalframework/petal_components.git
cd petal_components
mix deps.get
mix tailwind.install
iex -S mix run dev.exs
```

The README says the playground is at http://localhost:4000 with every component rendered, and that edits under lib/ trigger live reload. Tests run with mix test. There is also a deployed copy of the same playground at playground.petal.build, and the Dockerfile in the repository explains why it is unusual: the container runs MIX_ENV=dev on purpose, because the playground is the dev server and every runtime dependency is scoped only: :dev in mix.exs, so a production build would have nothing to run. The Dockerfile sets PLAYGROUND_DEPLOY=true to switch off the code reloader, live reload and the Tailwind watcher, and supplies a real secret_key_base.

That is a coherent design for a documentation site and a poor template for your own deployment. Do not copy that Dockerfile as a starting point for a LiveView app; it exists to serve a dev-mode playground.

## Licence, maintenance and upgrade cost

The licence is MIT, per the repository's LICENSE.md and the badge in the README. MIT is permissive: you can use the components in commercial and closed-source applications, and you carry the attribution requirement that comes with the licence text. That is a summary of the licence identifier, not legal advice; read LICENSE.md if the distinction matters to your organisation.

On maintenance, the facts are concrete. The repository is not archived. The last push was on 2026-05-15, the same day as the v3.2.2 release, roughly four months before today. The release history in the repository metadata shows v3.2.0 on 2026-04-04, v3.2.1 and v3.2.2 both on 2026-05-15. There is no evidence of activity after that date, so treat it as a project whose latest published work is from May 2026 rather than one with a visible current cadence.

Upgrade cost is the practical concern. Because the components live in a dependency, a version bump changes every view at once, and the presence of UPGRADE_GUIDE.md and CHANGELOG.md in the repository root tells you the maintainers document those transitions. The README's own example pins "~> 4.0" while the release list tops out at v3.2.2, so confirm which major line you are on before following the snippet. If you depend on the MCP server, note that the schema it serves and the package version you installed are separate moving parts; the README does not describe a version-negotiation step between them.

## Conclusion

Adopt Petal Components if you are building a Phoenix or LiveView app and want a component vocabulary an AI agent can look up rather than invent. Skip it if your views are mostly dead templates, if you refuse to run a hosted MCP endpoint, or if you want a copy-in CLI the way shadcn ships. Before committing, call list_components on mcp.petal.build to see the live inventory, check the CHANGELOG.md and UPGRADE_GUIDE.md for the 3.x to 4.0 jump, and confirm that the mix.exs constraint you copy matches the version the MCP server is describing.

## FAQ

### What does Petal Components do?

It provides a shadcn-style set of HEEx components for Phoenix LiveView apps, covering buttons, forms, modals, tables, cards and more, built with Tailwind v4 and usable in live or dead views. A companion MCP server at mcp.petal.build exposes each component's schema to AI coding tools so they use the real components instead of generating raw Tailwind markup.

### How do I install Petal Components in a Phoenix project?

Add {:petal_components, "~> 4.0"} to your deps in mix.exs, then patch assets/css/app.css with the @source directive and the default.css import shown in the README. Add use PetalComponents to your web module, run mix deps.get and mix compile, and register the bundled JS hooks in assets/js/app.js if you need the password, copyable, clearable or chat components.

### Can Petal Components be installed from Hex?

Yes. The package is published on Hex as petal_components, and the README's install instructions add it as a mix.exs dependency and update it with mix deps.update. The JavaScript hooks are not published to npm; the repository's package.json says they ship inside the Hex package.

### How does Petal Components work with Claude Code?

You register the hosted MCP server with claude mcp add petal --transport http https://mcp.petal.build/mcp, then ask the assistant to install petal_components. According to the README, the agent calls get_install_instructions, edits mix.exs, runs mix deps.get, patches assets/css/app.css and adds use PetalComponents to your web module.

## Sources

- [Official documentation](https://petal.build/components)
- [Official README](https://github.com/petalframework/petal_components#readme)
- [Project repository](https://github.com/petalframework/petal_components)
- [Release notes](https://github.com/petalframework/petal_components/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/petalframework-petal-components
