avo
avo copied to clipboard
[RFC] Use native Avo components to build custom content
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
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]
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) })
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.
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.
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.
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?
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.
This issue has been marked as stale because there was no activity for the past 15 days.