* move script to scripts folder * add docfy to router and scripts * add docfy to router and scripts * fix jsdoc syntax * add component markdown files to gitignore * improve error handling for scripts * tidy up remaining jsdoc syntax * add sample jsdoc components * add known issue info * make not using multi-line components clearer * make generating docs clearer * update copy * final how to docfy cleanup * fix ts file @module syntax * fix read more syntax * make docfy typescript compatible
3.1 KiB
Building and consuming components
Components can range from small, highly reusable "atoms" to large units with lots of business logic specific to one workflow or action. In any scenario, these are things to keep in mind while developing components for the Vault UI.
Please note that these guidelines are aspirational and you will see instances of anti-patterns in the codebase. Many of these should be updated as we move forward. As with any rule set, sometimes it is appropriate to break the rule.
Page components for every route
Route templates should render a Page
component, which includes breadcrumbs, page title, and then renders whatever else should be on the page (often another scoped component).
- This component should be named something like
<Page::CreateFoo />
and you can create it likeember g component page/create-foo -gc
. - The Route should pass the model hook data into the component in the template. However, if the model hook returns multiple objects they should each be passed into the Page component as separate args. For example: within a route's template whose model hook returns two different data models, the route's template would look like:
<Page::CreateFoo @config={{this.model.config}} @foo={{this.model.foo}} />
Conditional rendering
Generally, we want the burden of deciding whether a component should render to live in the parent rather than the child.
- Readability - it's easier to tell at a glance that a component will sometimes not render if the
{{#if}}
block is on the parent. - Performance - when a component is in charge of its own rendering logic, the component's lifecycle hooks will fire whether or not the component will render on the page. This can lead to degraded performance, for example if hundreds of the same component are listed on the page.
Reusable components
- Consider yielding something instead of passing a new arg
- Less is more! Adding lots of rendering logic means the component is likely doing too much
💡 Tips for reusability | Example |
---|---|
✅ Add splattributes to the top level |
|
✅ Pass a class or helper that controls a style |
|
❌ Don't pass a new arg that controls a style |
|
✅ Minimize args passed, pass one arg that is rendered if present |
|
❌ Don't pass separate args required for icon to render |
|