I’ve had the opportunity to use Kelp on a big client project for the last few weeks, and it’s been so awesome to work with!
Writing HTML is so nice!
I love that HTML elements are styled out-of-the-box…
<!-- This looks good without any classes! -->
<button>Press Me</button>I love that you can change the look and feel of components with a few simple, semantically named classes…
<!-- This button is now outlined and uses the secondary color -->
<button class="secondary outline">Press Me</button>I love that instead of complicated class names like in BEM…
<!-- Kelp does NOT do this -->
<button class="btn btn--secondary btn--outline">
Press Me
</button>
<div class="callout callout--secondary callout--outline">
I'm a callout
</div>
It leans on CSS variables to reuse the same consistent and predictable classes everywhere.
<!-- Kelp does THIS -->
<button class="secondary outline">
Press Me
</button>
<div class="callout secondary outline">
I'm a callout
</div>
Its results in way less CSS, way less repeated code, and way less mental overhead when coding.
But where Kelp really shines is with its web components!
Web Components FTW!
The project I’m working on uses server rendered HTML, but has a lot of interactive elements.
Tabs for in-page navigation. Modals with forms in them for editing and modifying content on the page.
Traditionally, for a site with so many moving parts like this, you would need to either…
- Grab React or Vue, render all of your HTML with JS, and track the state of things in a JS object.
- Write a lot of JS to intercept clicks and form submits, make fetch requests, and surgically update the UI.
Kelp gives you a third option, and it’s glorious!
Interactive HTML
Kelp’s Tabs component starts life as a fully-functional list of anchor links, and enhances into an accessible tabs component automatically if the JS loads.
<kelp-tabs>
<ul class="list-inline" tabs>
<li><a href="#wizard">Wizard</a></li>
<li><a href="#sorcerer">Sorcerer</a></li>
<li><a href="#druid">Druid</a></li>
</ul>
<div id="wizard">...</div>
<div id="sorcerer">...</div>
<div id="druid">...</div>
</kelp-tabs>
But the real workhorse on this project has been the <dialog> element paired with the Invoker Commands API.
<button
command="show-modal"
commandfor="greeting"
>
Show Modal
</button>
<dialog id="greeting">
đź‘‹ Hi there!
</dialog>
Kelp includes a polyfill for browsers that don’t support Invoker Commands yet, but the whole thing works with browser-native HTML attributes.
Handling Forms
The other secret sauce on this project has been a new still-in-the-works <kelp-form-ajax> component.
Rather than writing JS to handle every form submission, I can wrap my forms in a web component that intercepts submit events, sends data to the form endpoint with fetch(), and handles the response.
It uses the <form> element’s [action], [method], and (optional) [enctype] attributes to make it’s API call. That means that if JS doesn’t work, you could have a fully server-rendered fallback flow if you wanted.
<kelp-form-ajax>
<form
action="/path/to/endpoint"
method="post"
>
<!-- Form fields... -->
<button>Submit</button>
</form>
</kelp-form-ajax>
It uses various HTML attributes to configure different behaviors.
You can use a generic success message when the form is submitted…
<kelp-form-ajax msg-success="You're signed up for the newsletter!">
<!-- ... -->
</kelp-form-ajax>Or specific a response path, and grab a message from the API’s JSON response data…
<!--
if the response data looks like this...
{
"ok": true,
"code": 200,
"messages": {
"code": "ay6hf",
"status": {
"text": "You're signed up.",
"reason": "XR7"
}
}
}
-->
<kelp-form-ajax path-success="messages.status.text">
<!-- ... -->
</kelp-form-ajax>You can hide the form and show a loading spinner while submitting…
<kelp-form-ajax submit-loading>
<!-- ... -->
</kelp-form-ajax>Or remove the form from the DOM entirely after it successfully submits…
<kelp-form-ajax remove-on-success>
<!-- ... -->
</kelp-form-ajax>It’s been a real workhorse that lets me live in my HTML file and write less custom JS.
It will be coming to the public version of Kelp really soon!
Ajax HTML Updates
The <kelp-form-ajax> component pairs really nicely with <kelp-html-ajax>.
When a form is successfully submitted, sometimes sections of an existing page need to be updated. Rather than reload the whole page, the <kelp-html-ajax> listens for events, then fetches a fresh copy of the page and replaces itself the latest version… without a full page reload.
<p>I might have a bunch of content on a page.</p>
<p>And a table of data specific to the user. When they add an item, it needs to get rendered again.</p>
<kelp-html-ajax
id="user-table"
events="kelp-form:success"
keys="new-user-data"
>
<table>
<!-- ... -->
</table>
</kelp-html-ajax>
Whenever the <kelp-form-ajax> form successfully submits, it emits a custom event. You can also specify an eventKey that gets added to the event object, for filtering one form on the page from another.
The <kelp-html-ajax> can then respond to those events automatically, updated just the HTML that needs updating.
This one is also coming to the public release soon.
Kelp Updates
After working with Kelp so intensely on a real project, I’ve pushed a bunch of documentation updates to make working with it easier.
- Fewer sections. Having different sections for forms, content, navigation, and components resulted in a lot of jumping around and scrolling to find things. All of that is bundled under Components now, sorted alphabetically.
- Clearer customization. The old docs were too focused on how Kelp is built. I cleaned up the entire Customization section to make updating Kelp for your project simpler and more obvious, and moved the Theme Builder tool under that section, too.
I also made some under-the-hood changes that make my life as a maintainer a bit easier.
If you have any questions or comments, get in touch!
Like this? A Lean Web Club membership is the best way to support my work and help me create more free content.