Components Petal Framework

Petal Framework

An exciting new private package containing premium components that can be used in any Phoenix project.

While Petal Components provides a great design system for any Phoenix project, Petal Framework takes things one step further with advanced components that often require a lot of custom JavaScript and CSS to get right.

Due to the length of time it takes to develop and maintain, we have decided to make Petal Framework a paid package. This will allow us to continue to develop and maintain it for the long term.


Data table
Local Time
Customizable CSS for all components
More layouts + options
Calendar picker
WYSIWYG Textarea

How to access

See plans

This comes with the Petal Framework private hex package. Purchase a membership to get access to this package. It can be used with any Phoenix project. Post-expiration, you'll retain access but won't be eligible for updates from newer versions.

Installing Petal Framework

Petal Framework is a hex package like any other. The only difference is the repo that you fetch it from. Normally your hex packages are fetched from But Petal Framework is fetched from our private registry.

Petal Framework Repo

Run this command to make your local Hex aware of our registry:

mix hex.repo add petal \
  --fetch-public-key SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs \
  --auth-key please_sign_in_as_a_pro_member_to_view_your_api_token

Then fetch your deps and you should be good to go.

mix deps.get
mix phx.server


You can override the default messages by defining a module that implements the translate/1 function. For example:

# /lib/<your_app>_web/petal_framework_translations.ex

defmodule YourAppWeb.PetalFrameworkTranslations do
  import YourAppWeb.Gettext

  # You can omit any of the following functions if you don't want to override the default message.
  def translate("Showing"), do: gettext("Showing")
  def translate("to"), do: gettext("to")
  def translate("of"), do: gettext("of")
  def translate("rows"), do: gettext("rows")
  def translate("Equals"), do: gettext("Equals")
  def translate("Not equal"), do: gettext("Not equal")
  def translate("Search (case insensitive)"), do: gettext("Search (case insensitive)")
  def translate("Is empty"), do: gettext("Is empty")
  def translate("Not empty"), do: gettext("Not empty")
  def translate("Less than or equals"), do: gettext("Less than or equals")
  def translate("Less than"), do: gettext("Less than")
  def translate("Greater than or equals"), do: gettext("Greater than or equals")
  def translate("Greater than"), do: gettext("Greater than")
  def translate("Search in"), do: gettext("Search in")
  def translate("Contains"), do: gettext("Contains")
  def translate("Search (case sensitive)"), do: gettext("Search (case sensitive)")
  def translate("Search (case sensitive) (and)"), do: gettext("Search (case sensitive) (and)")
  def translate("Search (case sensitive) (or)"), do: gettext("Search (case sensitive) (or)")
  def translate("Search (case insensitive) (and)"), do: gettext("Search (case insensitive) (and)")
  def translate("Search (case insensitive) (or)"), do: gettext("Search (case insensitive) (or)")

Then in your config/config.exs file:

config :petal_framework, :translation_helper_module, YourAppWeb.PetalFrameworkTranslations


Docker images

Building Docker images requires an additional step to add the private hex repo. Passing the fingerprint and password in as build arguments isn’t secure, and you should use buildkit’s secret support instead if possible.

Reference the secrets within in your Dockerfile by mounting it within a RUN command:

RUN --mount=type=secret,id=petal_public_key \
  --mount=type=secret,id=petal_license_key \
  mix hex.repo add petal \
    --fetch-public-key "$(cat /run/secrets/petal_public_key)" \
    --auth-key "$(cat /run/secrets/petal_license_key)"

Then, at build time, pass the fingerprint and license through using the –secret flag:

docker build \
  --secret id=petal_public_key,env=PETAL_PUBLIC_KEY \
  --secret id=petal_license_key,env=PETAL_LICENSE_KEY .

Authorizing on Gigalixir

If your app runs on Gigalixir you can use a buildpack hook to authenticate with the private Petal repo.

First, set your license key on Gigalixir:

gigalixir config:set PETAL_LICENSE_KEY="please_sign_in_as_a_pro_member_to_view_your_api_token"
gigalixir config:set PETAL_PUBLIC_KEY="SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs"

Then add the hook to the end of your elixir_buildpack.config:

hook_pre_fetch_dependencies="mix hex.repo add petal \
  --fetch-public-key ${PETAL_PUBLIC_KEY} \
  --auth-key ${PETAL_LICENSE_KEY}"

Authorizing on Heroku

If your app runs on Heroku using the Elixir Buildpack (rather than Docker) you’ll need to use compilation hook to authorize hex before fetching dependencies.

First, set your license key on Heroku:

heroku config:set PETAL_LICENSE_KEY="please_sign_in_as_a_pro_member_to_view_your_api_token"
heroku config:set PETAL_PUBLIC_KEY="SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs"

Next, add a small shell script to your application in ./bin/predeps:


mix hex.repo add petal \
    --fetch-public-key ${PETAL_PUBLIC_KEY} \
    --auth-key ${PETAL_LICENSE_KEY}

Make sure the prepdeps script is executable:

chmod +x ./bin/prepdeps

Finally, set the predeps script within elixir_buildpack.config:


Authorizing on Fly

Fly uses a Dockerfile to install your application. It also gives you the ability to set build secrets. Firstly, open up your Dockerfile and add this before the mix deps.get step:

RUN --mount=type=secret,id=PETAL_PUBLIC_KEY \
  --mount=type=secret,id=PETAL_LICENSE_KEY \
  mix hex.repo add petal \
    --fetch-public-key "$(cat /run/secrets/PETAL_PUBLIC_KEY)" \
    --auth-key "$(cat /run/secrets/PETAL_LICENSE_KEY)"

We still need to pass in the secrets. From your local machine you can deploy like this:

fly deploy \
  --build-secret PETAL_PUBLIC_KEY=SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs \
  --build-secret PETAL_LICENSE_KEY=please_sign_in_as_a_pro_member_to_view_your_api_token

If you use GitHub Actions, you need to add the secrets.

PETAL_PUBLIC_KEY: SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs
PETAL_LICENSE_KEY: please_sign_in_as_a_pro_member_to_view_your_api_token

Then in your workflow:

    name: Deploy app
    runs-on: ubuntu-latest
      - uses: actions/checkout@v2
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: |
        flyctl deploy --remote-only \
          --build-secret PETAL_LICENSE_KEY=${{ secrets.PETAL_LICENSE_KEY }} \
          --build-secret PETAL_PUBLIC_KEY=${{ secrets.PETAL_PUBLIC_KEY }}

Authenticating for CI

If you have a CI tool that pulls down dependencies as part of a build step, you will need to add a step before the mix deps.get.

# In your CI config add this step BEFORE your `mix deps.get` step:
- name: Authorize Petal
run: |
  mix hex.repo add petal \
    --fetch-public-key ${{secrets.petal_public_key}} \
    --auth-key ${{secrets.petal_license_key}}

You will then need to add the following secrets to Github:

  • Name: petal_public_key, Value: SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs
  • Name: petal_license_key, Value: please_sign_in_as_a_pro_member_to_view_your_api_token


0.9.2 - 8 days ago

  • Fix regression breaking remote_options event submits from the combo box.

0.9.1 - 11 days ago

  • Fix a bug in the combo box hook causing stale multiple selection values on submit.
  • Fix broken render of custom menu item component functions.
  • Address custom menu item edge case when placing the item in a grouped main_menu_items list.

0.9.0 - 15 days ago

  • Introduce the floating_div/1 component (and associated FloatingHook) to leverage Floating UI.
  • Rename PetalFramework.Components.Menu module to PetalFramework.Components.SidebarMenu for clarity of layout compatibility.
  • Add :adjacent slot to sidebar_layout/1 to facilitate custom flyouts at the layout-level stacking context.
  • Enable custom menu items using new map structure in the :main_menu_items attribute of sidebar_layout/1. We will support the same for the stacked_layout/1 in a future release.

0.8.1 - 1 month ago

  • Update sidebar logo wrapping div class so not to apply padding to the logo icon when collapsed (because it squishes larger logo images).
  • Update logo icon wrapping anchor with mx-auto class to center it.

0.8.0 - 1 month ago

  • Collapsible Sidebar: Address grouped menus items, fix width class not applying correctly
  • Update deps

0.7.0 - 1 month ago

  • Make SidebarLayout collapsable. Requires Alpine Persist plugin.

0.6.0 - 4 months ago

  • Use PhoenixHTMLHelpers

0.5.2 - 4 months ago

  • Fix bug where if the value of a combobox was updated after it was initially rendered, it wouldn’t update like other input/select fields do
  • Update deps

0.5.1 - 7 months ago

  • Add remote_options_target to combo box for use in live components

0.5.0 - 7 months ago

  • Remove dependency on Timex #86
  • Add data table col attr date_format #76
  • Update deps (live view 0.20.0)

0.4.11 - 8 months ago

  • Added deprecation warning for translation helper module
  • Update deps

0.4.10 - 9 months ago

  • Relaxed Petal Components dep
  • Fix: data table translations now work (anyone using config :petal_framework, :translation_helper_module ..., please see new docs module docs for PetalFramework.TranslationHelpers)

0.4.9 - 10 months ago

  • Fix: updated some wrong field types on the generators

0.4.8 - 11 months ago

  • Fix: <.combo_box> dropdown staying open after selection
  • Fix: <.combo_box> dropdown closing when trying to select multiple

0.4.7 - 11 months ago

  • Updated: <.combo_box> now updates when options or placeholder change

0.4.6 - 11 months ago

  • Fix combo_box error issues

0.4.5 - 11 months ago

  • Fix public_layout mobile view menu

0.4.4 - 11 months ago

  • Bump phoenix_live_view dep
  • Combo-box now supports fully custom JS options (eg. render templates)

0.4.3 - 1 year ago

  • Fix: combo box styling on mobile
  • Updated: <.stacked_layout> has a new attr sticky

0.4.2 - 1 year ago

  • Touch up the styling for combo box

0.4.1 - 1 year ago

  • Fixed: <.combo_box> passing empty string in list when no value is selected
  • Updated: <.combo_box> error outline
  • Updated: generators now use the new Petal Component <.field>’s

0.4.0 - 1 year ago

  • New: <.combo_box> component
  • Updated: allow color scheme switch class to be customisable

0.3.2 - 1 year ago

  • Allow color_scheme_switch class to be customisable

0.3.1 - 1 year ago

  • Stacked & sidebar layouts updated and now support nested menu items

0.3.0 - 1 year ago

  • Breaking: Renamed notification/1 to flash/1
  • New: flash_group/1 component. Put this in your layout to render flashes

0.2.3 - 1 year ago

  • Fixed: compile error

0.2.2 - 1 year ago

  • Updated to use latest data_table changes

0.2.1 - 1 year ago

  • Fixed: petal.gen.html warnings

0.2.0 - 1 year ago

  • Changed: Added the function
  • Changed: no longer modifies the context file

0.1.4 - 1 year ago

  • Fix issue with bad module import

0.1.3 - 1 year ago

  • Fix issue with bad module import

0.1.2 - 1 year ago

  • Can override messages if you want to use translations

0.1.1 - 1 year ago

  • Added other components used in Petal Pro
  • added extensions
  • added page builder

0.1.0 - 1 year ago

  • Initial release
  • Added DataTable component
  • Added petal mix tasks