Skip to main content
The @beeq/react package provides lightweight React wrappers around every BEEQ web component. It solves two fundamental incompatibilities between React and Custom Elements.

Why a React wrapper?

React and Custom Elements do not integrate well out of the box:
  • Rich data — React passes all props as HTML attributes, so objects and arrays become the string "[object Object]" instead of being forwarded as JavaScript values.
  • Custom events — React’s synthetic event system does not listen for DOM custom events emitted by web components. Without a wrapper, you must grab a ref and call addEventListener manually for every event.
@beeq/react solves both problems by exposing native React components that map props and events to the underlying custom element.

Installation

1

Install the packages

npm install @beeq/{core,react}
@beeq/core is a peer dependency of @beeq/react. Both packages must be installed.
2

Import BEEQ styles

Import the BEEQ global stylesheet at the top of your application entry file:
main.css
@import "@beeq/core/dist/beeq/beeq.css";
Or import it directly in your entry TypeScript/JavaScript file:
main.tsx
import '@beeq/core/dist/beeq/beeq.css';
3

Copy SVG icon assets

BEEQ loads SVG icons at runtime. Use vite-plugin-static-copy to copy the icon assets to your output directory:
npm
npm install -D vite-plugin-static-copy
vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { viteStaticCopy } from 'vite-plugin-static-copy';

export default defineConfig({
  plugins: [
    react(),
    viteStaticCopy({
      targets: [
        {
          src: './node_modules/@beeq/core/dist/beeq/svg/*',
          dest: 'icons/svg',
        },
      ],
    }),
  ],
});
Then set the base path in your entry file:
main.tsx
import { setBasePath } from '@beeq/core/dist/components';

setBasePath('icons/svg');
Note the import path: @beeq/core/dist/components (not @beeq/core) when using setBasePath in a Vite/React project.
You can skip the asset-copy step by pointing setBasePath at a CDN instead:
import { setBasePath } from '@beeq/core/dist/components';

setBasePath('https://cdn.jsdelivr.net/npm/[email protected]/24/outline');

Usage

Import BEEQ components from @beeq/react and use them like any other React component. Custom events are exposed as onBq* props:
App.tsx
import React from 'react';
import { BqButton } from '@beeq/react';

function App() {
  const handleButtonClick = (ev: CustomEvent) => {
    console.log(ev.detail);
  };

  return (
    <BqButton appearance="primary" onBqClick={handleButtonClick}>
      Click Me
    </BqButton>
  );
}

export default App;

Form input example

LoginForm.tsx
import React, { useState } from 'react';
import { BqInput, BqButton } from '@beeq/react';

function LoginForm() {
  const [email, setEmail] = useState('');

  const handleChange = (ev: CustomEvent<{ value: string }>) => {
    setEmail(ev.detail.value);
  };

  return (
    <form>
      <BqInput
        name="email"
        type="email"
        placeholder="[email protected]"
        value={email}
        onBqChange={handleChange}
      >
        <label slot="label">Email address</label>
      </BqInput>
      <BqButton appearance="primary" type="submit">
        Sign in
      </BqButton>
    </form>
  );
}

export default LoginForm;
All BEEQ custom events follow the bq prefix convention (e.g. bqClick, bqChange, bqClear). The React wrapper exposes these as camelCase onBq* props (e.g. onBqClick, onBqChange, onBqClear).

Build docs developers (and LLMs) love