Skip to content

Use with a framework ​

This page has not been reviewed by a human.

The components are standard custom elements, also called web components. Any framework that can render an HTML element, set properties on it, and listen to DOM events can use them. This page shows one Source Card, Micah 6:6-8, with one selection handler, written three ways.

Install and register the elements ​

Register the elements before your framework renders them, so their JavaScript properties, such as selectedPosition, are ready when the framework sets them. Import the package once at the top of your app, or use the script tag from Start here.

A community-driven project with Sefaria backing and support. The toolkit is experimental; names and APIs may change. License

sh
npm install @sefaria/web-components@0.1.0-alpha.0
ts
import "@sefaria/web-components";

Element subpaths such as /source-card don't register their element. They export types and a few helpers. Install and status covers package installation and versions.

Attributes and properties ​

Strings and booleans can be attributes. Objects and arrays can't, so you set them as JavaScript properties. These are the ones this example needs:

NameKindMeaning
srefAttributeThe reference to load, such as Micah 6:6-8.
selectableAttributeLets readers select a verse.
selectedPositionProperty onlyMarks the selected verse. Set it to the position from the select event.
dataProperty onlyYour own data, so the card makes no request.
statusProperty, read onlyThe current state: empty, loading, ready, or error.

React 19 sets selectedPosition as a property, not an attribute, because the element defines that property. Alpine binds attributes, so the Alpine file sets the property with x-effect="$el.selectedPosition = ...".

Learn more: Reference › Components

The same handler in three places ​

Each Source Card is selectable. On sefaria-source-select, the handler keeps event.detail, which is { position, ref }. It sets the card's selectedPosition to that position and shows You selected Micah 6:7 (position 1).

Custom events bubble and cross the component boundary, so you listen for them the usual way for your framework. Source Card fires two events:

  • sefaria-source-select: a reader selected a verse. The detail is { position, ref }.
  • sefaria-source-card-error: loading from sref failed. The detail is { error, sref }.

Learn more: Component events

Plain JavaScript ​

This example is the tested file examples/site-snippets/source-card-select.html. It runs live here. You can read it but not edit it. It listens with addEventListener("sefaria-source-select", ...).

Source Card selection in plain JavaScript
<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/@sefaria/web-components@0.1.0-alpha.0/dist/browser/sefaria-elements.js"
></script>
<div style="max-height: 16rem; overflow: auto">
  <sefaria-source-card sref="Micah 6:6-8" selectable></sefaria-source-card>
</div>
<p id="selection">Select a verse number.</p>
<button id="cite" type="button" hidden></button>
<script type="module">
  const card = document.querySelector("sefaria-source-card");
  const output = document.querySelector("#selection");
  const cite = document.querySelector("#cite");
  card.addEventListener("sefaria-source-select", (event) => {
    const { position, ref } = event.detail;
    card.selectedPosition = position;
    output.textContent = `You selected ${ref} (position ${position.join(", ")}).`;
    cite.textContent = `Cite ${ref}`;
    cite.hidden = false;
  });
  cite.addEventListener("click", () => {
    output.textContent = `Cited: ${cite.textContent.slice(5)}.`;
  });
</script>

React and Alpine manage the listener they add for you. When the card is removed and nothing else keeps it, the listener goes with it. In plain JavaScript, remove your listener yourself when you remove the card, for example with removeEventListener or an AbortController signal.

Learn more: addEventListener (MDN)

React ​

This example is the tested file examples/react-vite/src/site-source-card.tsx. It runs in the repository's tests, not on this page. In React 19, the handler is the prop onsefaria-source-select, with the event name in lowercase after on.

examples/react-vite/src/site-source-card.tsx
import "@sefaria/web-components";
import { useState } from "react";

export function SourceCardWithSelection() {
  const [selected, setSelected] = useState<{
    position: readonly number[];
    ref: string;
  }>();

  return (
    <>
      <sefaria-source-card
        sref="Micah 6:6-8"
        selectable
        selectedPosition={selected?.position}
        onsefaria-source-select={(event) => setSelected(event.detail)}
      />
      <p>
        {selected
          ? `You selected ${selected.ref} (position ${selected.position.join(", ")}).`
          : "Select a verse number."}
      </p>
    </>
  );
}

With TypeScript, declare the element's JSX props once. The example project does this in examples/react-vite/src/custom-elements.d.ts.

Alpine ​

This example is the tested file examples/alpine-vite/src/site-source-card.html. It runs in the repository's tests, not on this page. Alpine listens with @sefaria-source-select="...".

examples/alpine-vite/src/site-source-card.html
<div x-data="{ selected: undefined }">
  <sefaria-source-card
    sref="Micah 6:6-8"
    selectable
    x-effect="$el.selectedPosition = selected?.position"
    @sefaria-source-select="selected = $event.detail"
  ></sefaria-source-card>
  <p
    x-text="selected
      ? `You selected ${selected.ref} (position ${selected.position.join(', ')}).`
      : 'Select a verse number.'"
  ></p>
</div>

Requests ​

A fresh load of each example makes one request. Re-rendering with the same values makes no request. Changing sref, the data source, or the edition and language choices loads again. If you supplied data, the card instead redraws from your data with no request. Display settings such as layout and content-language never load again.

Loading, failure and empty states ​

Read status from a ref or the element. Listen for the error event the same way as the select event. For Source Card it is sefaria-source-card-error, with detail { error, sref }.

SituationWhat readers seestatusError event
Waiting for SefariaA loading messageloadingNo
Sefaria can't be reachedAn error message as an alert. A card that already showed text keeps it.errorsefaria-source-card-error
Sefaria says the text isn't a referenceSefaria's messageerrorNo
No sref and no dataNothingemptyNo

Learn more: Source Card empty states · Troubleshoot a page

Use your own data ​

To skip the request, set data as a property. Then the card makes zero requests. See Give components your own data.

Next steps ​

Sefaria Frontend ToolkitCommunity-driven with Sefaria backing and support. GitHub Get support

AI-generated documentation.

About this documentation

Like the codebase, this documentation was scaffolded and written with GitHub Copilot. I don't have a background in technical writing, and wanted to get something out there.

Pages that have not undergone any human review are explicitly marked, but the others may also read funny or need work too. Sorry about that.

Please report any issues so they can be prioritized.

Thanks, Avi