Accessibility is an important part of web development, enabling individuals with disabilities to have access to the content and web apps that are necessary for day-to-day tasks. In particular, making applications accessible using ARIA Standards helps individuals with disabilities to leverage things like screen readers.
In this article, we’ll walk through how to build a SolidJS UI with Kobalte, a toolkit for building accessible apps with SolidJS. To follow along with the code examples, feel free to clone my sample repo on GitHub. Let’s get started!
Jump ahead:
- What is SolidJS?
- Getting started with Kobalte
- Your first Kobalte component
- Advanced Kobalte components
What is SolidJS?
SolidJS is a library that helps you build reactive and performant frontend applications. SolidJS utilizes a concept called signals, which help to preserve reactivity in the application:
import {createSignal} from "solid-js" const [value, setValue] = createSignal("value");
Signals in SolidJS are very similar to the useState
Hook that we see in React. SolidJS also tracks data side effects using createEffect
, which is similar to the useEffect
Hook in React:
// originally copied from https://www.solidjs.com/docs/latest/api#createeffect const [a, setA] = createSignal(initialValue); // effect that depends on signal `a` createEffect(() => doSideEffect(a()));
SolidJS supports stores, which centralize state management in your application:
// originally copied from https://www.solidjs.com/docs/latest/api#createstore import { createStore } from "solid-js/store"; import type { StoreNode, Store, SetStoreFunction } from "solid-js/store"; function createStore<T extends StoreNode>( state: T | Store<T> ): [get: Store<T>, set: SetStoreFunction<T>]; type Store<T> = T; // conceptually readonly, but not typed as such
Putting it all together, you can build components with SolidJS functions in a very similar way to how you would in a React application:
import { createSignal, onCleanup } from "solid-js"; function Counter() { const [count, setCount] = createSignal(0); const timer = setInterval(() => setCount(count() + 1), 1000); onCleanup(() => clearInterval(timer)); return <div>Count: {count()}</div>; }
Getting started with Kobalte
To add Kobalte to a SolidJS project, you can use the following simple npm install:
npm install @kobalte/core
Kobalte provides a set of components that follow the WAI-ARIA Authoring Practices, so the components you build with Kobalte are accessible by default. Kobalte components are composable and give you access to each component’s granular parts. The code below shows a TextField
:
import { TextField } from "@kobalte/core"; import "./style.css"; function App() { return ( <TextField.Root class="text-field"> <TextField.Label class="text-field__label">Favorite fruit</TextField.Label> <TextField.Input class="text-field__input" /> </TextField.Root> ); }
Here, the TextField.Root
is the basis for the component, but you also have TextField.Label
and TextField.Input
, which you can use to access properties and styles.
Kobalte comes without styling, so you can either directly apply Vanilla CSS or use a supported framework like Tailwind CSS. To learn more, check out the documentation on the Kobalte website. With Kobalte, there is a large number of components that you can choose from. In the next few sections, I’ll explain what they look like and show how you can either change your existing components or start fresh with Kobalte.
Your first Kobalte component
If you cloned my sample repo, then you’ll see a very simple SolidJS application:
Notice there are three pages in the application. WithoutKobalte.tsx
is a page that has a basic to-do application with just an input field and values. WithKobalte.tsx
is a page that has the same application as WithoutKobalte.tsx
but with Kobalte components. Finally, KobalteAdvanced.tsx
is a page that showcases more Kobalte components with styles.
For our first Kobalte component, let’s look at the input
and button
elements in the WithoutKobalte.tsx
page:
<input type="text" ref={input} placeholder="What do you have to do today?" name="todo" ></input> <button onClick={() => { addTodoItem(input); }} > Add Todo </button>
The input
and button
elements are pretty simple and consistent with what you’d expect in a normal web application. We have a placeholder, a value defined for the input, and an onClick
event set for the button. If you look at the same components in WithKobalte.tsx
, you’ll see that we now have access to the granular pieces of these elements:
<TextField.Root value={input()} onValueChange={setInput} validationState={ input() !== 'something' ? 'invalid' : 'valid' } > <TextField.Label /> <TextField.Input placeholder="What do you have to do today?" name="todo" /> <TextField.Description> You can have a description appear like this </TextField.Description> <TextField.ErrorMessage class={styles.error}> If you type anything other than "something" the error shows </TextField.ErrorMessage> </TextField.Root> <Button.Root class={styles.kobalteButton} onClick={() => { addTodoItem(); }} > Add Todo </Button.Root>
You’ll notice that the TextField
in particular has elements for Description
, ErrorMessage
, Label
, and Input
. Additionally, when you run the application, you’ll notice the presence of the ARIA attributes on the Kobalte components versus the standard web components.
The image below shows the WithoutKobalte.tsx
page:
While the image below shows the WithKobalte.tsx
page:
With the ARIA attributes all set up for you, your life as a developer is much easier. Furthermore, the granularity of the components makes development and maintenance easier.
Using advanced Kobalte components
Now that we’re familiar with some basics of Kobalte, we can briefly go over some of the more advanced components. In KobalteAdvanced.tsx
, we have the following components: Progress Bar, Hover Card, Popover, and Tabs.
All of these components are both granular and composable, just like the TextField
that we saw earlier. Below is the ProgressBar
code:
<section> <h2>Progress Bar</h2> <Progress.Root value={80} class="progress"> <div class="progress__label-container"> <Progress.Label class="progress__label"> Loading... </Progress.Label> <Progress.ValueLabel class="progress__value-label" /> </div> <Progress.Track class="progress__track"> <Progress.Fill class="progress__fill" /> </Progress.Track> </Progress.Root> </section>
Notice that in this case, I’m using custom CSS classes. You could just as easily integrate with a CSS framework. Below is the HoverCard
component:
<section> <h2>Hover Card (move mouse over to see it)</h2> <HoverCard.Root> <HoverCard.Trigger class="hovercard__trigger" href="https://twitter.com/mlfabien" target="_blank" > @MLFabien </HoverCard.Trigger> <HoverCard.Portal> <HoverCard.Content class="hovercard__content"> <HoverCard.Arrow /> <img src="https://pbs.twimg.com/profile_images/1509139491671445507/pzWYjlYN_400x400.jpg" alt="Fabien MARIE-LOUISE" class="hovercard__avatar" /> <h2 class="hovercard__title"> Fabien MARIE-LOUISE </h2> <p class="hovercard__description"> Developer and UI Design enthusiast. Building UI related stuffs for @solid_js </p> </HoverCard.Content> </HoverCard.Portal> </HoverCard.Root> </section>
The Popover
component is similar; you could easily install this popover component into your frontend. Often times, libraries don’t have a popover component specifically, so you’d have to create one yourself. This is definitely another advantage of using Kobalte:
<section> <h2>Popover (click open to see it)</h2> <Popover.Root> <Popover.Trigger class="popover__trigger"> Open </Popover.Trigger> <Popover.Portal> <Popover.Content class="popover__content"> <Popover.Arrow /> <div class="popover__header"> <Popover.Title class="popover__title"> About Kobalte </Popover.Title> <Popover.CloseButton class="popover__close-button"> X </Popover.CloseButton> </div> <Popover.Description class="popover__description"> A UI toolkit for building accessible web apps and design systems with SolidJS. </Popover.Description> </Popover.Content> </Popover.Portal> </Popover.Root> </section>
Finally, the Tabs
component is very similar to what you would see in other frontend libraries. Again, the composition capabilities make it great to use in any app:
<section> <h2>Tabs</h2> <Tabs.Root aria-label="Main navigation" class="tabs"> <Tabs.List class="tabs__list"> <Tabs.Trigger class="tabs__trigger" value="profile"> Profile </Tabs.Trigger> <Tabs.Trigger class="tabs__trigger" value="dashboard"> Dashboard </Tabs.Trigger> <Tabs.Trigger class="tabs__trigger" value="settings"> Settings </Tabs.Trigger> <Tabs.Trigger class="tabs__trigger" value="contact"> Contact </Tabs.Trigger> <Tabs.Indicator class="tabs__indicator" /> </Tabs.List> <Tabs.Content class="tabs__content" value="profile"> Profile details </Tabs.Content> <Tabs.Content class="tabs__content" value="dashboard"> Dashboard details </Tabs.Content> <Tabs.Content class="tabs__content" value="settings"> Settings details </Tabs.Content> <Tabs.Content class="tabs__content" value="contact"> Contact details </Tabs.Content> </Tabs.Root> </section>
Conclusion
In this article, we explored getting started with Kobalte by running through a few examples. I demonstrated how to create your first component, and then we covered some more advanced use cases. Kobalte is simple to integrate into your SolidJS applications, and building applications is even easier when the ARIA Standards are already set up for you. I recommend checking out my sample repo, as well as the Kobalte docs.
Thanks for reading! Follow my writing on rhythmandbinary.com and Twitter at @AndrewEvans0102.
The post Build a SolidJS UI with Kobalte appeared first on LogRocket Blog.
from LogRocket Blog https://ift.tt/XPJ7M2F
Gain $200 in a week
via Read more