# petal_components - rules for AI coding assistants petal_components is a shadcn-style component library for Phoenix LiveView. Components live in modules under `PetalComponents.*` and are called as plain HEEx tags (`<.button>`, `<.modal>`, `<.table>`) once you `use PetalComponents`. CSS classes use a `pc-` prefix for styling overrides (`pc-button`, `pc-button--primary`). Use these rules to write idiomatic Phoenix UI instead of inventing raw Tailwind markup. Drop this file into your AI coding tool's rules system (Cursor `.cursorrules`, Claude Code `CLAUDE.md`, Codex `AGENTS.md`, Continue rules, etc.) when working in a Phoenix project that has `petal_components` installed. ## Installing petal_components When the user says "install petal_components" (or you're starting in a Phoenix project that doesn't have it yet), follow these steps. They are idempotent - safe to re-run if any step is partially done. ### 1. Add the dependency Open `mix.exs`. In the `deps/0` function, add this line if it's not already there: ```elixir {:petal_components, "~> 4.0"} ``` If the user wants the chat components (`PetalComponents.Chat` — ``, ``, ``, …), also add the optional `{:mdex, "~> 0.12"}`. The rest of the library needs no extra deps. Note the `Chat` family is not pulled in by `use PetalComponents` — `alias PetalComponents.Chat` and call it namespaced. ### 2. Fetch dependencies ```sh mix deps.get ``` ### 3. Configure Tailwind CSS Open `assets/css/app.css`. Find the `@import "tailwindcss";` line and add the two lines below it: ```css @import "tailwindcss"; @source "../deps/petal_components/**/*.*ex"; @source not "../deps/petal_components/lib/petal_components/showcase"; @import "../deps/petal_components/assets/default.css"; ``` The `@source` line tells Tailwind to scan petal_components source for class usage. The `@source not` line skips the `showcase/` example modules - those power petal.build's own docs, not your app, so scanning them would only add unused utility classes to your CSS. (`@source not` needs Tailwind v4.1+. On v4.0 it's harmless to drop the line; you just get a little extra CSS.) The `@import` line brings in the default component styles (the `pc-*` CSS prefix). If `@import "tailwindcss";` is missing, the project is on Tailwind v3 and petal_components 4.x will not work. Tell the user to upgrade to Tailwind v4, or pin to `petal_components ~> 1.0` for Tailwind v3 support. ### 4. Import the components in your web module Find `lib/_web.ex`. In umbrella apps it lives at `apps/_web/lib/_web.ex`. The file defines macros like `def html`, `def controller`, `def live_view`. Inside `def html`, locate the `quote do` block and add `use PetalComponents`: ```elixir def html do quote do use Phoenix.Component use PetalComponents # ... existing imports end end ``` `use PetalComponents` imports every component so you can call them as `<.button>`, `<.modal>`, etc. without explicit aliases. If a `use PetalComponents` line is already present, skip this step. ### 5. Register the JS hooks petal_components v4 ships a bundled JS hook set - toasts, the command palette and its trigger, the colour-scheme switch, carousel, charts, local time, sliders, OTP input, the chat family, popover, the navigation menu's hover mode, the effects, and the enhanced inputs (everything else is CSS + LiveView.JS only). You never register hooks individually - spread the whole set once. Open `assets/js/app.js`, import the hooks, and merge them into your `LiveSocket`: ```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 existing hooks: { ...MyHooks, ...PetalComponents } }) ``` If the project has no `assets/js/app.js` (an API-only or minimal app), skip this — the hooks are only needed for those interactive components. ### 5b. Charts (only if the app uses `<.chart>`) The `<.chart>` component drives Apache ECharts but does not bundle it — the engine is bring-your-own, exactly like Alpine. Add it ONLY when the app actually renders a `<.chart>`; skip otherwise. Either a script tag in the root layout: ```html ``` or `npm i echarts` plus `import * as echarts from "echarts"; window.echarts = echarts;` in `app.js`. The `PetalChart` hook picks it up from `window.echarts` and warns in the console if it's missing (the chart area renders empty). `<.sparkline>` is pure server-rendered SVG and needs nothing. ### 6. Verify ```sh mix compile ``` Should compile cleanly. To smoke test, drop `<.button>Hello` in any HEEx template. ### 7. Brand colours (optional) Components work out of the box: petal_components ships default colour ramps (blue `primary`, pink `secondary`, semantic hues, zinc `gray`). They are soft defaults (`@theme default`), so a plain `@theme` block in the project's `app.css` wins no matter where it sits relative to the import: ```css @theme inline { --color-primary-50: var(--color-violet-50); --color-primary-100: var(--color-violet-100); /* ...one line per stop, 50-950, for any ramp you want to change... */ --color-primary-950: var(--color-violet-950); } ``` The roles: `primary` is the base action colour and tints every variant of every component (solid fills, outline borders, ghost text); `secondary` is a second brand accent with the same rule; `info`/`success`/`warning`/`danger` carry meaning and should stay recognisable; `gray` is the neutral chrome. Map a role to any Tailwind hue by referencing that hue's variables, or use literal values. One deliberate choice to know about: the `gray` role ships Tailwind's **zinc** values under the gray name, so one coherent neutral runs through every component. Because `--color-gray-*` is a shared namespace, this also sets what the app's own `text-gray-*` / `bg-gray-*` utilities render as. To use a different neutral, remap it like any other role (`--color-gray-50: var(--color-slate-50);` and so on per stop - slate, stone, neutral and zinc all remain available as variables). The one palette a `var()` cannot reach is Tailwind's original gray itself (its values only ever lived under the name petal_components now occupies), so restoring it is a one-line import after the default styles: ```css @import "../deps/petal_components/assets/default.css"; @import "../deps/petal_components/assets/tailwind-gray.css"; ``` ### Installation rules of thumb for AI agents - Read each file before editing. Do not blind-patch. - If the project already uses `petal_components`, skip the steps that are already done. Report what was already in place. - After installing, suggest calling `list_components` to see what's available. ## Hard rules 1. **Prefer a petal_components tag over raw HTML.** If you would reach for a `