Skip to content

Upgrade guide

We'll update this page when we release new Avo 4 versions.

If you're looking for the Avo 3 to Avo 4 upgrade guide, please visit the dedicated page.

Migrating to TailwindCSS 4? See the TailwindCSS 4 Migration Guide.

Unreleased — resizable sidebar

Breaking Change

The sidebar is now resizable, and as part of that change sidebar link, section, and group labels render on a single line with an ellipsis when they overflow, instead of wrapping onto multiple lines. The full label shows in a tooltip on hover.

Action required: None for most apps. If your navigation relied on long labels wrapping, either shorten the labels or point users at the drag handle to widen the sidebar.

Hosts with an accessibility conformance obligation can disable the drag handle with sidebar[:resizable].

.container-small is now max-width-based

Breaking Change

.container-small (the wrapper around show and edit pages) used a fixed width; it now fills its container up to a max-width so content adapts when the sidebar is wide. If you override .container-small's width from your own stylesheets, the new Avo-owned max-width now clamps it — override max-width instead.

Action required: None unless you override .container-small.

Upgrade to avo-dashboards 4.0.9

The per-card refresh control is opt-in

Breaking Change

avo-dashboards 4.0.8 rendered a refresh control on every card, with no way to remove it — including on html and static partial cards, where refreshing re-renders identical content. The control is now off by default and turns on per card with refresh_button, the same name and the same default as the dashboard-wide control that shipped alongside it.

Action required: None unless you were on 4.0.8 and want the control kept on a card.

Maintaining Previous Behavior

Turn it back on for each card that should keep it:

ruby
# app/avo/cards/users_metric.rb
class Avo::Cards::UsersMetric < Avo::Cards::MetricCard
  self.id = 'users_metric'
  self.refresh_button = true
end

Setting it on a dashboard does not turn it on for that dashboard's cards — the two controls are independent opt-ins under the same name.

Upgrade to 4.0.18

Resource and field translations are used verbatim

Breaking Change

Avo used to humanize every resource and field label it resolved from your locale files. That silently overrode the casing you wrote: 'Payment Intent ID' rendered as Payment intent id, and 'API Products' rendered as Api products.

Avo now renders a resolved translation exactly as written and humanizes only the name it generates for you when no translation is found.

Lowercase translations now render lowercase

If your locale entries are lowercase, they used to appear capitalized. They will now appear as written.

Action Required

Review your locale files. If every resource_translations and field_translations entry is already written the way you want it on screen, there's nothing to do.

Avo's own interface strings are unaffected — the "New", "Edit", and "View" labels still render as before.

Steps to Update

Grep your locale files for resource_translations and field_translations, and capitalize any entry you want capitalized on screen:

yaml
# config/locales/avo.pt-BR.yml
pt-BR:
  avo:
    resource_translations:
      user:
        zero: 'usuários'
        one: 'usuário'
        other: 'usuários'
        zero: 'Usuários'
        one: 'Usuário'
        other: 'Usuários'
    field_translations:
      file:
        zero: 'arquivos'
        one: 'arquivo'
        other: 'arquivos'
        zero: 'Arquivos'
        one: 'Arquivo'
        other: 'Arquivos'

Nothing else changes: resources and fields without a translation still fall back to the humanized class or attribute name.

See Localization (i18n) for the full picture.