Skip to main content

Command Palette

Search for a command to run...

UI Components Responsibility

Published
•3 min read•View as Markdown

When designing UI components, I often struggle with deciding where to put certain logic. Not all components have this issue, some components are purely visually, but other components (such as dialogs) are sometimes more specific and are not meant to be re-used for other cases. So what do we do in that case?

Imaging the following situation: you have a dialog that pops up when a user is editing his information. This means that from his profile page, the dialog gets shown when he clicks the edit button. When the user clicks the save button, the information should be sent to the server. But how does that data flow? Is it the dialog itself that will make the call, or does it use a callback provided by the page to pass the information and the page will make the call?

In some way, it is weird that a dialog should be responsible for making a call to save the information. On the other hand though, it does feel very natural becuase that is where all the information is, as well as the save button. Why would the dialog have to pass it on to the page that has no information about any of it? Isn't the page just there to show the information as well as provide the options to edit it, but how the information gets updated may be outside of the scope of the page itself.

It becomes even more cumbersome if you have a table on your page. You may provide the option to edit a single row (by having action buttons on the row itself). In that case the flow is page > table > row > dialog. If the update responsibility resides with the page, the table and the row need to have a simple pass-through callback to provide the information all the way up to the page.

Another issue that comes with this approach is that the page can become a garbage. Since it is responsible for handling all the logic, keeping the page at a manageable size is almost impossible. And it grows with extra information and edit options. What about showing an error or success message? You will want to show the error message on the dialog itself (and keep it open), in that case you have to pass the result all the way back to the dialog. You will not show a success message on the dialog, since it will be closed when saved. But this isn't a problem, since you will need to have an option to notify the parent component the dialog is closed, you may as well use this signal to show the message.

I do tend to opt for specialised components with logic to actually handle the data itself over handling everything in some main parent component. There are some exceptions though, and that is for real visual components. One example of this is my feedback button that I have written. This button shows a certain text and when clicked it shows a loading/spinner icon until the callback is finished. This is a component you want to re-use for many different cases, and it doesn't make sense that this button would make calls to a backend.

One final note: since I started to use Svelte, I also decided to do more HTML and CSS myself instead of relying on some UI framework, and I have noticed that many things that would have been a component in my React + Material UI projects, are simply CSS classes in my Svelte project. This removes the question whether a component is a visual one, or has specialised logic and thus can do actions itself.