Examplary
Start for free
Developer docs

Components

Components are React components your app shows inside Examplary: a component setting in the app's settings, or the screens of an assessment prerequisite. They work like the components of custom question types.

You point at a component by its path, optionally with translations:

playerComponent: {
  path: "./components/player.tsx",
  translations: {
    title: { en: "Open the Acme browser", nl: "Open de Acme-browser" },
  },
},

Each component file default-exports a React component. When you publish the app, the CLI bundles each one for the browser, with everything it imports.

Props

Every component gets:

PropDescription
tTranslates a key from the component's translations into the current user's language.
i18nThe i18next instance, e.g. for i18n.language.
apiAn authenticated API client, as in question type components.

On top of these, each kind of component gets props of its own, described on the page of the setting or capability it belongs to. @examplary/ui has a type for each, like FrontendSettingsFieldComponent, so TypeScript knows what's there:

components/player.tsx
import { Button, FrontendPrerequisitePlayerComponent } from "@examplary/ui";
 
const Player: FrontendPrerequisitePlayerComponent = ({ t, exam }) => (
  <Button asChild>
    <a href={`acme-browser://open?url=${encodeURIComponent(exam.privateUrl)}`}>
      {t("title")}
    </a>
  </Button>
);
 
export default Player;

Styling and UI

Use the components of @examplary/ui, like Button, Input and Switch, so your app looks like the rest of Examplary. React and @examplary/ui are provided by the platform: they aren't included in your bundle, and you only need to install them for their types.

You can style your own elements with Tailwind CSS classes. When you publish the app, the CLI finds the classes used in your app's folder and bundles them into a stylesheet, which is loaded along with your components.

Keep components small

Components run in the browser of teachers and students, so other npm packages you import end up in the bundle they download. Do the heavy lifting in hooks instead, and call those from your component where the capability allows it, like an assessment prerequisite's callFunction().