View Source
Petal Components
About 🌺
Petal stands for:
Petal is a set of HEEX components that makes it easy for Phoenix developers to start building beautiful web apps.
Docs 📄
Install
For Petal to work you simply need Tailwind CSS and Alpine JS installed along with with some Tailwind configuration.
Existing projects
1 - Follow this guide to install Tailwind and Alpine.
2 - Add Petal to your deps:
mix.exs
defp deps do
[
{:petal_components, "~> 0.3.1"},
]
end
3 - Modify your tailwind.config.js
file to include these settings:
const colors = require("tailwindcss/colors");
module.exports = {
mode: "jit",
purge: [
"../lib/*_web/**/*.*ex",
"./js/**/*.js",
// We need to include the Petal dependency so the classes get picked up by JIT.
"../deps/petal_components/**/*.*ex"
],
darkMode: false,
theme: {
extend: {
// Set these to your brand colors
colors: {
primary: colors.blue,
secondary: colors.pink,
},
},
},
plugins: [require("@tailwindcss/forms")],
};
4 - Alias the components in your <your_project>_web.ex
file
defmodule YourProjectWeb
...
defp view_helpers do
quote do
...
use PetalComponents
end
end
This will import the functions so you can go <.button />
in your templates / live views.
If the function names clash with yours (eg. you already have a .button
function) you can opt to alias the modules instead:
defmodule YourProjectWeb
...
defp view_helpers do
quote do
...
alias PetalComponents.{
Heroicons,
Alert,
Badge,
Button,
Container,
Dropdown,
Form,
Loading,
Typography
}
end
end
New projects
We recommend using Petal boilerplate, which is a fresh Phoenix install with Tailwind + Alpine installed. It comes with a project renaming script so you can still rename your project to whatever you like.
Roadmap
Layout
- [x] container
Form components
- [x] text input
- [x] select dropdown
- [x] textarea
- [x] checkbox
- [ ] multiple select
- [x] radios
- [ ] file upload
- [ ] switch
Buttons
- [x] basic button
- [x] change size
- [x] change color
- [x] loading state (with spinner)
- [x] filled vs outline
- [ ] button group
Misc
- [x] menu dropdown
- [ ] tooltips
- [ ] avatar
- [x] alerts
- [ ] tables
- [ ] cards
- [ ] breadcrumbs
- [ ] modal
- [ ] slide over
- [ ] spinners
- [ ] accordian
- [ ] pagination
- [x] badges
Examples
Containers
<Container.container max_width="full | lg | md | sm">
Buttons
Button types
<.button label="Button">
<.a href="/" label="a">
<.patch href="/" label="Live Patch">
<.redirect href="/" label="Live Redirect">
Button colors
<.button color="primary | secondary | white | success | danger" label="Primary" />
Button colors (outline)
<.button color="primary | secondary | white | success | danger" label="Primary" variant="outline" />
Button sizes
<.button size="sm | md | lg | xl">
Button states
Disabled
<.button disabled type="a" href="/" label="a Disabled" />
<.button disabled color="primary" label="Button Disabled" />
<.patch disabled href="/" label="Live Patch Disabled" />
<.redirect disabled href="/" label="Live Redirect" />
Loading
<.button loading type="a" href="/" label="a Loading" />
<.button loading label="Button Loading" />
<.patch loading href="/" label="Live Patch Loading" />
<.redirect loading href="/" label="Live Redirect Loading" />
Button with icon
<.button icon type="a" href="/">
<Heroicons.Solid.home class="w-5 h-5" />
a with label
</.button>
Typography
<.h1>Heading 1</.h1>
<.h2>Heading 2</.h2>
<.h3>Heading 3</.h3>
<.h4>Heading 4</.h4>
<.h5>Heading 5</.h5>
Heroicons
Heroicons solid
<Heroicons.Solid.home class="w-6 h-6 text-blue-500" />
<Heroicons.Solid.render icon={:home} />
Heroicons outline
<Heroicons.Outline.home class="w-6 h-6 text-blue-500" />
<Heroicons.Outline.render icon={:home} />
Badges
<.badge color="primary | secondary | Info | Success | Warning | Danger | Gray" label="Primary" />
Alerts
Info alert
<.alert state="info">
This is an info state
</.alert>
Success alert
<.alert state="success" label="This is a success state" />
Warning alert
<.alert state="warning" label="This is a warning state" />
Danger alert
<.alert state="danger" label="This is a danger state" />
Optional heading alert
<.alert heading="Optional heading">
This is quite a long paragraph that takes up more than one line.
</.alert>
Forms
Text input
<.text_input form={:user} field={:name} placeholder="eg. John" />
<!-- With a label and bottom margin -->
<div class="mb-6">
<.form_label form={:user} field={:last_name} />
<.text_input form={:user} field={:last_name} placeholder="eg. Smith" />
</div>
<!-- Includes label and bottom margin -->
<.form_field
type="text_input"
form={:user}
field={:first_name}
/>
Text area
<.textarea form={:user} field={:description} />
<!-- With a label and bottom margin -->
<div class="mb-6">
<.form_label form={:user} field={:description} />
<.textarea form={:user} field={:description} />
</div>
<!-- Includes label and bottom margin -->
<.form_field
type="textarea"
form={:user}
field={:description}
/>
Select
<.select
options={["Admin": "admin", "User": "user"]}
form={:user}
field={:role}
/>
<!-- With a label and bottom margin -->
<div class="mb-6">
<.form_label form={:user} field={:role} />
<.select
options={["Admin": "admin", "User": "user"]}
form={:user}
field={:role}
/>
</div>
<!-- Includes label and bottom margin -->
<.form_field
type="select"
form={:user}
field={:first_name}
options={["Admin": "admin", "User": "user"]}
/>
Checkbox
<!-- Includes the label and margin automatically -->
<.checkbox
form={:user}
field={:read_terms}
label="I accept"
/>
Radios
<!-- A collection of radios - provide options like a select dropdown -->
<.radios
form={:user}
field={:eye_color}
options={["Green": "green", "Blue": "blue", "Gray": "gray"]}
/>
Dropdowns
<.dropdown label="Dropdown">
<.dropdown_menu_item type="button">
<Heroicons.Outline.home class="w-5 h-5 text-gray-500" />
Button item with icon
</.dropdown_menu_item>
<.dropdown_menu_item type="a" href="/" label="a item" />
<.dropdown_menu_item type="live_patch" href="/" label="Live Patch item" />
<.dropdown_menu_item type="live_redirect" href="/" label="Live Redirect item" />
</.dropdown>
Loading indicators
<.spinner show={false} />
<.spinner show={true} size="sm" />
<.spinner show={true} size="md" class="text-green-500" />
<.spinner show={true} size="lg" class="text-red-500" />
Breadcrumbs
Slash
<.breadcrumbs links={[
%{ label: "Link 1", to: "#" },
%{ label: "Link 2", to: "#" },
%{ label: "Link 3", to: "#" }
]}/>
Chevron
<.breadcrumbs separator="chevron" links={[
%{ label: "Link 1", to: "#" },
%{ label: "Link 2", to: "#", link_type: "live_patch" },
%{ label: "Link 3", to: "#", link_type: "live_redirect" },
]}/>