Liquid Oxygen comes with React bindings for all Web Components. Although the rendered components are still Web Components, the bindings improve the developer experience by providing a more familiar API and a better integration with React.
On this page, you'll find detailed instructions on how to integrate Liquid Oxygen into your React project and how to use the components.
Liquid Oxygen is easy to integrate into an existing React project. We assume you already have a project set up. If not, you can create a new project with Vite.
npm create vite@latest your-project-name -- --template react-ts
For more information about this command and Vite, please refer to the Vite documentation.
Although this guide assumes your project is using Typescript, all examples should also be applicable to JavaScript projects.
Add Liquid Oxygen to your project with the package manager of your choice.
npm install @emdgroup-liquid/liquid
npm
, yarn
or pnpm
). For simplicity, we use npm
in this guide.
All Web Components are loaded togehter with their styles embedded. Therefore we only need to import the global stylesheet for Liquid Oxygen.
Add the following code to your App.tsx
file (or any similar file which is loaded for every page).
// App.tsx
import '@emdgroup-liquid/liquid/dist/css/liquid.global.css'
When adding Liquid Oxygen components to a React project, it is crucial to use the React bindings. All components are imported from @emdgroup-liquid/liquid/dist/react
. The bindings significantly improve JSX compatibility and your developer experience.
Let's have a look at how to add a LdButton to your project. This example also includes a LdIcon as it helps you to check if Liquid Oxygen assets are loaded correctly.
// SampleComponent.tsx
import { LdButton, LdIcon } from '@emdgroup-liquid/liquid/dist/react'
export function SampleComponent() {
return (
<LdButton>
Click me!
<LdIcon name="energy" />
</LdButton>
)
}
When you put this component on a page, you should see a blue button with the text "Click me!" and a lightning bolt icon.
When you look at the example above you may notice that we didn't have to define any custom elements anywhere. This is because the React output target includes the define custom elements logic and all custom elements get registered with the Custom Elements Registry as soon as imported (the Stencil includeDefineCustomElements
option is set to true
).
In some cases this convenience feature is not desireable, such as when bundling Liquid Oxygen components within your own library, or when you want to have more control over when your custom elements get registered. For this reason Liquid Oxygen exposes a React output target entry which does not include the defineCustomElements
utility.
Here is how you would implement the example above, using the React output target, that doesn not include the defineCustomElements
helper method.
// SampleComponent.tsx
import { LdButton, LdIcon } from '@emdgroup-liquid/liquid/dist/react-define-excluded'
export function SampleComponent() {
return (
<LdButton>
Click me!
<LdIcon name="energy" />
</LdButton>
)
}
Now you can register the components manually in two ways.
defineCustomElements
utility.import { defineCustomElements } from '@emdgroup-liquid/liquid/dist/loader'
defineCustomElements()
import { LdButton as LdButtonCE } from '@emdgroup-liquid/liquid/dist/components/ld-button'
import { LdIcon as LdIconCE } from "@emdgroup-liquid/liquid/dist/components/ld-icon"
customElements.get('ld-button') || customElements.define('ld-button', LdButtonCE)
customElements.get('ld-icon') || customElements.define('ld-icon', LdIconCE)
Liquid Oxygen components aim to work similarly to native HTML elements as much as possible. In most cases, you can expect the same events and behavior from a Liquid Oxygen component and its native equivalent. Custom events are documented on the respective component pages.
Let's take our button from above and add a click handler.
// SampleComponent.tsx
import { LdButton, LdIcon } from '@emdgroup-liquid/liquid/dist/react'
export function SampleComponent() {
return (
<LdButton onClick={() => alert('Clicked!')}>
Click me!
<LdIcon name="energy" />
</LdButton>
)
}
Please notice the camel case notation of the onClick
prop. This is the expected React convention, which differs from the native onclick
attribute (see related documentation). As we do not explicitly document these events, you need to apply this convention yourself. Typescript and your code editor's IntelliSense will assist you with that.
There are a few cases where native events of Web Components do not behave as expected by React. In these cases, Liquid Oxygen provides custom events prefixed with ld
and documented on the respective component pages.
onChange
event invokes when the component loses focus (and the value changed). This is the standard browser behavior but differs from the native React onChange
event. Use the onInput
event in cases you want to handle user input immediately while typing. Find additional information in the Event handling guide.
React Router is a widely used library for routing in client-side react applications. This recipe shows you how to integrate Liquid Oxygen navigation components with React Router. Although the recipe is based on React Router, interacting with other libraries should look quite similar.
Liquid Oxygen provides some sophisticated components for navigation. This recipe uses the following:
As this recipe focuses on how to put together Liquid Oxygen and React Router, we'll only highlight the relevant parts of the code. We assume you already have a basic React Router setup in place. If not, please refer to the React Router documentation.
Let's get started with routing. We will use the useNavigate hook to navigate to a different route. We cannot use the <Link>
component provided by React Router within LdSidenavNavitem
.
// Sidebar.tsx
//...
const navigate = useNavigate()
return (
<LdSidenav>
// ...
<LdSidenavNavitem
href="/processes"
onClick={(e) => {
e.preventDefault()
navigate('/processes')
}}
>
Processes
</LdSidenavNavitem>
// ...
</LdSidenav>
)
// ...
The href
prop of LdSidenavNavitem
tells the component to render a proper anchor tag. This is important for accessibility. As this would already work to navigate but bypass the client-side navigation of React Router, we also add a click handler. The click handler uses the navigate
function from the useNavigate
hook to navigate to the specified href. preventDefault()
is called to prevent the default behavior of the anchor tag.
LdSidenavNavitem
provides visual indicators for an active item. We can use the pathname
property of the useLocation()
hook provided by React Router to determine the active route and set selected
accordingly.
// Sidebar.tsx
//...
const { pathname } = useLocation()
return (
<LdSidenav>
// ...
<LdSidenavNavitem
href="/processes"
onClick={(e) => {
e.preventDefault()
navigate('/processes')
}}
selected={pathname === '/processes'} // Depending on your routes, you'll need a more sophisicated evaluation here
>
Processes
</LdSidenavNavitem>
// ...
</LdSidenav>
)
// ...
Using the same hooks, you can also generate breadcrumbs from pathname
. It's on you to resolve the path to human readable lables.
// Breadcrumbs.tsx
// ...
const navigate = useNavigate()
const { pathname } = useLocation()
const crumbs = useResolvedCrumbs(pathname) // This is up to you 😉 (e.g. /processes/e06dc3f9-811d-4931-b4e1-7599d0fa03fe -> [{label: "Processes", href: "/processes"}, {label: "Extraction #23", href: "/processes/e06dc3f9-811d-4931-b4e1-7599d0fa03fe"}])
return (
<LdBreadcrumbs>
{crumbs.map((crumb) => (
<LdCrumb
key={crumb.label}
onClick={(e) => {
e.preventDefault()
navigate(crumb.href)
}}
href={crumb.href}
>
{crumb.label}
</LdCrumb>
))}
</LdBreadcrumbs>
)
// ...
Similar to LdSidenavNavitem
, LdCrumb
renders an anchor tag when href
is specified. Therefore, we need to add a click handler again to prevent the default behavior and navigate to the specified path.
This guide shows you how to get started with Liquid Oxygen in your React project. Additionally, we provide several sandbox applications showing how to use Liquid Oxygen in various environments:
If you run into issues integrating Liquid Oxygen, please get in touch with us.