avo icon indicating copy to clipboard operation
avo copied to clipboard

[RFC] Use native Avo components to build custom content

Open adrianthedev opened this issue 2 years ago • 5 comments

Proposal

Expose internal Avo components to developers to enable them to create more meaningful custom UIs for their users using the same styling as Avo.

Examples

Create a form using Avo inputs

This would render a form that looks like any other edit resource page but in your own context. One might add it to a resource tool, a custom tool, or a dashboard, and the user wouldn't see any differences.

form_with '/' do |form|
  render Avo::SelectField::EditComponent.new(id: :status, options: [:done, :failed], form: form, help: "Choose a status for the project")
  render Avo::TextField::EditComponent.new(id: :name, form: form, required: true, disabled: -> { current_user.admin? })
  form.submit "Save"
end

CleanShot 2022-08-09 at 16 03 06

Alternate API

Evidently, calling the full component name Avo::TextField::EditComponent might not be the best thing and we'd be better off using something like the regular Rails form helpers.

form_with '/' do |form|
  avo_select_field(id: :status, options: [:done, :failed], form: form, help: "Choose a status for the project")
  form.submit "Save"
end

Create a listing view from an Avo resource

Given you configured a ProjectResource (check the one in the dummy app), you could use an Index type of component that will render the table in whichever resource or custom tool or on a dashboard.

render Avo::ResourceIndexcomponent.new resource: ProjectResource, scope: -> { query.where(published: true).for_organization(current_organization.id).order(published_at: :desc) }, description: "Published projects across the organization", filters: [StatusFilter], actions: [UpgradeProjects]

CleanShot 2022-08-09 at 16 08 33

Create cards using configuration

A developer might want to add cards in custom tools with the same design as on the Dashboards.

render Avo::MetricCard.new(title: 'Users count', description: 'Users description', refresh_every: 10.minutes, value: User.all_users_count)

render Avo::ChartkickCard.new(title: 'User signups', description: 'Some tiny description', initial_range: 30, ranges: {"7 days": 7, "30 days": 30}, value: -> { User.signups(range) })

CleanShot 2022-08-09 at 16 14 51 CleanShot 2022-08-09 at 16 15 02

Benefits

Code reusability

Instead of working with many partials, helpers, and controller methods to create the UI, you control everything in an isolated component that worries about its responsibilities.

Style consistency all throughout the app.

Using these components in the internal parts of Avo and in the external custom tools and dashboards, the developer can ensure that the app keeps a consistent look.

Theme the whole app at once

Using this "wrapper" approach, we can later change the style of the components making the whole app themable from one place. Imagine we have a "Tailwind CSS"-like configuration file where one can change the app's colors, spacing, border radius values, shadows, and more.

Current workarounds

Currently developers:

  • style their inputs and views using custom code. This might make the app look different from one page to another and lose consistency.
  • "borrow" styles from Avo's internal helpers. The internal helpers are undocumented and subject to change, breaking the app in the process
  • try to fake the internal components like @OlexYakov did here in an amazing way and managed to render the form fields

Additional context

The APIs exemplified here might not end up with that signature in the end. We might use some helpers instead of render COMPONENT.new **args statements or even helper objects that would lean on the already wonderful Resource-style DSL.

Feedback

We're looking for your feedback to make this a useful and productive feature for you guys.

adrianthedev avatar Aug 09 '22 13:08 adrianthedev

This was one of the first thing my team thought about with Avo, beyond the "basics" (which are already extremely useful)! It would be a huge feature 👏 We are going to need to build a bunch of custom tools, so having these primitives to build off of would make that so much easier.

I don't know enough about Rails rendering to comment much on the design, all of my company's apps were React/API-only until Avo. But this pretty much looks like what I'd hope for.

coffenbacher avatar Aug 11 '22 03:08 coffenbacher

Oh, that's cool @coffenbacher. Thanks for writing this. I appreciate the feedback.

Not sure if you're on the Discord server, but would you be open to having a short call with me? I'm interested in your use case with Avo.

adrianthedev avatar Aug 11 '22 06:08 adrianthedev

This would be of great interest and a significant boost to adopting Avo (I am currently testing an integration).

IMO the View Components as API works well, we are heavily using View Components also, but appreciate there may be benefits in providing wrappers :-)

Style consistency all throughout the app.

Not sure I fully understand this point, would it be possible to customise the styling somehow for use of these components for UI that users access?

pmackay avatar Aug 11 '22 10:08 pmackay

Style consistency all throughout the app.

This means that the component we use internally, and you in custom tools, are the same. So they are styled the same. All text fields will have the same look throughout the app.

In a future iteration, we're considering bringing in the theming feature. This way, you'd theme a component (text field, resource index, cards, etc.), and that styling will be propagated throughout all your app.

adrianthedev avatar Aug 11 '22 15:08 adrianthedev

This issue has been marked as stale because there was no activity for the past 15 days.

github-actions[bot] avatar Aug 27 '22 03:08 github-actions[bot]