Skip to content

getelena/react-example-project

Repository files navigation

Elena + React Example

A minimal example demonstrating how to use Elena web components (@elenajs/core) inside a React 19 application, built with Vite and TypeScript.

What is Elena?

Elena is a lightweight (2kB) library for building Progressive Web Components that work natively in the browser. This example uses both @elenajs/core and @elenajs/components, an example component library built on top of Elena.

What This Example Demonstrates

All examples live in src/App.tsx and cover:

  • Variants: default, primary, and danger button styles
  • Interactive counter: React state (useState) driving Elena button click handlers
  • Dynamic attribute binding: cycling through variants reactively via JSX expressions

Prerequisites

  • Node.js v20+
  • pnpm v10+

Getting Started

# Install dependencies
pnpm install

# Start the development server
pnpm start

Open http://localhost:5173 in your browser.

Available Scripts

Command Description
pnpm start Start the Vite dev server
pnpm build Type-check and build for production
pnpm preview Preview the production build locally

Project Structure

src/
├── main.tsx        # React entry point (mounts <App />)
├── App.tsx         # Main component, all Elena examples live here
├── App.css         # Application styles
├── elena.d.ts      # TypeScript JSX declarations for Elena elements
└── vite-env.d.ts   # Vite environment types
index.html          # HTML shell
vite.config.ts      # Vite configuration
tsconfig.json       # TypeScript configuration

How Elena Web Components Are Used

Import the component and its styles, then use it as a regular JSX tag:

import "@elenajs/components/dist/button.js"; // registers <elena-button>
import "@elenajs/components/dist/button.css"; // button styles

function App() {
  return (
    <>
      <elena-button variant="primary" onClick={() => console.log("clicked!")}>
        Click me
      </elena-button>
    </>
  );
}

TypeScript Support

Elena exports a CustomElements type map from @elenajs/components that describes every element’s attributes. To get full IntelliSense and type-checking for Elena elements in React, you need to wire this into React’s JSX type system.

Setup

  1. Create a type declaration file (e.g. src/elena.d.ts):
import type { CustomElements } from "@elenajs/components";

type ElenaIntrinsicElements = {
  [K in keyof CustomElements]: CustomElements[K] & {
    onClick?: (e: MouseEvent) => void;
    onFocus?: (e: FocusEvent) => void;
    onBlur?: (e: FocusEvent) => void;
    children?: React.ReactNode;
  };
};

declare module "react/jsx-runtime" {
  namespace JSX {
    interface IntrinsicElements extends ElenaIntrinsicElements {}
  }
}

declare module "react/jsx-dev-runtime" {
  namespace JSX {
    interface IntrinsicElements extends ElenaIntrinsicElements {}
  }
}
  1. Make sure tsconfig.json includes the file, the src directory must be in the include array:
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "moduleResolution": "bundler"
  },
  "include": ["src"]
}
  1. Restart the TypeScript server in your editor (in VSCode: Cmd+Shift+P → "TypeScript: Restart TS Server").

How It Works

  • CustomElements is a type map exported by @elenajs/components that maps tag names (e.g. "elena-button") to their prop types (e.g. ButtonProps & BaseProps & BaseEvents).
  • The ElenaIntrinsicElements type extends each entry with React event handlers (onClick, onFocus, onBlur) and children, since these aren’t part of the web component attribute definitions.
  • The declare module blocks augment React’s JSX namespace so that TypeScript recognizes <elena-button>, <elena-stack>, etc. as valid JSX elements with typed props.
  • Both react/jsx-runtime (production) and react/jsx-dev-runtime (development) are augmented because Vite’s "jsx": "react-jsx" transform uses different runtimes depending on the mode.

About

An example demonstrating how to use Elena inside a React 19 application, built with Vite and TypeScript.

Topics

Resources

License

Stars

Watchers

Forks

Contributors