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
npm install @sefaria/web-components@0.1.0-alpha.0import "@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:
| Name | Kind | Meaning |
|---|---|---|
sref | Attribute | The reference to load, such as Micah 6:6-8. |
selectable | Attribute | Lets readers select a verse. |
selectedPosition | Property only | Marks the selected verse. Set it to the position from the select event. |
data | Property only | Your own data, so the card makes no request. |
status | Property, read only | The 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 fromsreffailed. 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", ...).
<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.
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="...".
<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 }.
| Situation | What readers see | status | Error event |
|---|---|---|---|
| Waiting for Sefaria | A loading message | loading | No |
| Sefaria can't be reached | An error message as an alert. A card that already showed text keeps it. | error | sefaria-source-card-error |
| Sefaria says the text isn't a reference | Sefaria's message | error | No |
No sref and no data | Nothing | empty | No |
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
- Show commentary and connected texts: show what a selected verse connects to.
- Add the complete Reader: add the full reading experience.
- Make components respond to each other: link one component's selection to another.
- Reference › Components: every attribute and event.