Skip to content

Make components respond to each other ​

This page has not been reviewed by a human.

Components don't talk to each other directly. Your page connects them in four steps:

  1. A component reports what the reader did through an event.
  2. Your page updates its own state.
  3. Your page sets the other component's inputs, as attributes or properties.
  4. That component redraws or loads.

This page builds these steps with one example. Selecting a verse in a Source Card highlights it and shows that verse's connections in a Connections Panel. The card starts with Micah 6:8 selected, at position [2]. Positions count from 0, so verse 8 of Micah 6:6-8 is position 2. Selecting Micah 6:7 makes the panel show Connections for Micah 6:7.

Each component's own events are covered in Show an attributed passage and Show commentary and connected texts.

In React, one state value holds the selection, and it drives both components. When the card reports a selection, the handler stores it. React then re-renders both components. The card gets the new selectedPosition. The panel gets the selected verse's ref as its sref.

This is the tested file examples/react-vite/src/site-source-card-to-connections.tsx. It runs in the repository's tests, not on this page. The TypeScript JSX declarations it needs are in custom-elements.d.ts. Use components with a framework explains them.

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

export function SourceCardToConnections() {
  const [selected, setSelected] = useState({
    position: [2] as readonly number[],
    ref: "Micah 6:8",
  });

  return (
    <>
      <sefaria-source-card
        sref="Micah 6:6-8"
        selectable
        selectedPosition={selected.position}
        onsefaria-source-select={(event) => setSelected(event.detail)}
      />
      <sefaria-connections-panel sref={selected.ref} />
    </>
  );
}

For setup, and for which values are attributes and which are properties, see Use with a framework.

Plain JavaScript ​

Without a framework, you write each update by hand. The listener on sefaria-source-select copies event.detail.position to the card's selectedPosition and event.detail.ref to the panel's sref.

This example runs live here. To try changes, choose Edit, change the code, and choose Run.

Source Card selection updating a Connections Panel
<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/@sefaria/web-components@0.1.0-alpha.0/dist/browser/sefaria-elements.js"
></script>
<sefaria-source-card sref="Micah 6:6-8" selectable></sefaria-source-card>
<sefaria-connections-panel sref="Micah 6:8"></sefaria-connections-panel>
<script type="module">
  const card = document.querySelector("sefaria-source-card");
  const panel = document.querySelector("sefaria-connections-panel");
  card.selectedPosition = [2];
  card.addEventListener("sefaria-source-select", (event) => {
    card.selectedPosition = event.detail.position;
    panel.sref = event.detail.ref;
  });
</script>

In plain JavaScript, remove your listeners when you remove the components. Use with a framework shows how.

Why a reactive framework helps ​

As coordination grows, a reactive framework such as React, Vue, Svelte, or Alpine helps. One piece of state drives every component, and the framework keeps them in sync. You can do the same in plain JavaScript. Keep state in one place and update components from one function. A framework does that bookkeeping for you.

How many requests this adds ​

Coordination adds only the requests each component makes for its own new inputs. It doesn't create hidden requests.

On a fresh load of the example, the card makes one text request and the panel makes one links request. Changing the panel's reference starts one load. That load makes one links request unless the toolkit already has that response cached. Selecting the verse that's already selected doesn't change the panel's sref, so nothing loads. The card makes no request when the selection changes.

When to stop and use something else ​

If you start rebuilding navigation, history, and panes, use the complete Reader instead. For a custom multi-pane layout, see the composed multi-pane Reader example.

Learn more: How the toolkit works · Component events

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