Skip to main content Accessibility Feedback

The edges of complexity

On a client project I’m currently working on, I’ve hit what I’m calling the edges of complexity.

I’m at the border of this uncomfortable place where manual DOM manipulation approaches are becoming increasingly complex and hard to manage, but state-based UI and reactive data introduce their own complexities and make some things that are currently easy with manual DOM manipulation a fair bit harder.

I’m not at the point where state-based UI is the obvious “easier path,” but manual DOM manipulation is starting to feel like an unmanageable slog.

Today, I wanted to explore that. Let’s dig in!

The project

I’m working on an app for a service industry company. The page I’m building in this app displays project details unique to each customer.

Some of the common elements on the page are pre-rendered HTML, but the stuff that’s unique to the customer and project are rendered with JavaScript and an API call.

Most of the page is only rendered once, and then selectively shown or hidden with things like toggle tabs and accordions. That makes traditional DOM manipulation very appealing. It’s more performant and “just works.”

It’s not all simple, though

There are a few sections on the page where we need to ask for more information from the user, then update the UI.

Let’s say we don’t have a phone number for the customer, yet. We might display a section like this…

<h2>We don't have a phone number for you</h2>
<button>Add a phone number</button>

The user clicks the button, a modal opens to get that information, and we update it. Now, that section should look like this…

<h2>Phone number added</h2>
<button disabled>Add a phone number</button>

There are a handful of those throughout the UI, and each one has more UI changes than what I’ve included in the example above.

Lots of little classes to toggle text color, attributes to affect interactivity, language changes. It adds up!

Where state-based UI kicks ass

This is normally the point where I’d say, “Ok, state-based UI and data reactivity make sense.”

Rather than worrying about what the current UI looks like and what needs to change in various places, state-based UI let’s me tell the library what the UI should look like based on different conditions.

// Our state
let data = {
	phone_number: null
};

// The UI template
function template () {

	// If there's no phone number
	if (!data.phone_number) {
		return `
			<h2>We don't have a phone number for you</h2>
			<button>Add a phone number</button>`;
	}

	// If there is
	return `
		<h2>Phone number added</h2>
		<button disabled>Add a phone number</button>`;

}

Then, I can just update a JavaScript variable and the UI figures itself out.

// After the user enters the phone number
// This will make the UI update
data.phone_number = '555-555-5555';

This becomes particularly useful when one piece of information affects the UI in multiple places.

In this particular app, that phone number might be displayed in the nav menu, the footer, and some section in the body. State-based UI let’s me update one property and automatically update the UI wherever its needed.

But of course, it’s not that easy…

The edges of complexity

While state-based UI makes some things a lot easier, it makes others a lot harder.

The page uses a small script toggle tabs that handles all of the accessibility stuff out-of-the-box. A switch to reactive, state-based UI would break how that script works, so it would need to be rewritten as a state-based component.

I wrote it, so I can do that, but still… it’s more work.

The page uses details and summary elements as simple, progressively enhanced disclosures. But reactive state-based UI would close open details elements whenever the UI is re-rendered. To stop that from happening, I’d need to keep track of the open/closed state in a JavaScript object and use it to affect rendering in my template.

The app uses the dialog element for simple, accessible modals. That would need to be rewritten as a state-based component, with all of the accessibility footguns that come along with it.

Even something simple like shifting focus to the heading after a page loads (for accessibility reasons) is much harder with a state-based UI library.

Which approach is “correct”?

Both. Neither.

Each one comes with substantial benefits and tradeoffs.

Reactive, state-based UI makes it much easier to maintain and reason about (in my opinion, in this particular case). Traditional DOM manipulation has fewer quirks, but more moving pieces to manage and maintain as the project grows.

I think I’m leaning towards converting to state-based UI… but I’m not 100% sure yet. What would you do?