Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Switch
✓ import { Switch } from 'ember-primitives/components/switch';
✗ import Switch from 'ember-primitives/components/switch';
const Switch = require('ember-primitives/components/switch');
Components are typically named exports and reside in a nested `components` directory. ESM imports are standard for modern Ember apps.
Drawer
✓ import { Drawer } from 'ember-primitives/components/drawer';
✗ import { Drawer } from 'ember-primitives'; // Incorrect top-level import for components
import * as Drawer from 'ember-primitives/components/drawer';
For tree-shaking and explicit dependency, components should be imported directly from their specific paths.
Rating
✓ import { Rating } from 'ember-primitives/components/rating';
✗ import { Rating } from 'ember-primitives/rating'; // Missing 'components' directory
import type { RatingSignature } from 'ember-primitives/components/rating';
Type imports for signatures (e.g., `RatingSignature`) should be used for Glint template type checking, typically following the same path but with `type` prefix.
This quickstart demonstrates the usage of `Switch`, `Drawer`, `Separator`, and `Rating` components within an Ember Glimmer component, showcasing basic state management and event handling with TypeScript.
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { Switch } from 'ember-primitives/components/switch';
import { Drawer } from 'ember-primitives/components/drawer';
import { Separator } from 'ember-primitives/components/separator';
import { Rating } from 'ember-primitives/components/rating';
interface MyDemoArgs {}
export default class MyDemo extends Component<MyDemoArgs> {
@tracked isDrawerOpen = false;
@tracked isSwitchOn = false;
@tracked currentRating = 3;
@action
toggleDrawer() {
this.isDrawerOpen = !this.isDrawerOpen;
}
@action
handleSwitchChange(checked: boolean, event: Event) {
this.isSwitchOn = checked;
console.log('Switch is now:', checked, 'Event:', event.type);
}
@action
handleRatingChange(rating: number) {
this.currentRating = rating;
console.log('New rating:', rating);
}
}
/*
<template>
<h2 class="text-2xl font-bold mb-4">Ember Primitives Demo</h2>
<div class="p-4 border rounded-md mb-4">
<button type="button" {{on "click" this.toggleDrawer}} class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Toggle Drawer
</button>
<Drawer @isOpen={{this.isDrawerOpen}} @onClose={{this.toggleDrawer}} class="bg-white dark:bg-gray-800 shadow-lg p-6">
<div class="p-4">
<h3 class="text-xl font-semibold mb-2">Drawer Content</h3>
<p class="text-gray-700 dark:text-gray-300">This is some content inside the drawer. It's fully customizable!</p>
<button type="button" {{on "click" this.toggleDrawer}} class="mt-4 bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
Close Drawer
</button>
</div>
</Drawer>
</div>
<div class="flex items-center space-x-2 my-4 p-4 border rounded-md">
<Switch
@checked={{this.isSwitchOn}}
@onChange={{this.handleSwitchChange}}
id="my-switch"
class="w-10 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-checked:bg-blue-600 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all"
/>
<label for="my-switch" class="text-gray-700 dark:text-gray-300">Enable Feature ({{if this.isSwitchOn "On" "Off"}})</label>
</div>
<Separator class="my-6 border-t border-gray-300 dark:border-gray-600" />
<div class="my-4 p-4 border rounded-md">
<h3 class="text-xl font-semibold mb-2">Rate this Component:</h3>
<Rating
@value={{this.currentRating}}
@max={{5}}
@onChange={{this.handleRatingChange}}
@item={{fn (mut (hash class="text-yellow-400 text-3xl cursor-pointer"))}}
/>
<p class="mt-2 text-gray-700 dark:text-gray-300">Current rating: {{this.currentRating}} stars</p>
</div>
</template>
*/
Errors
Common errors & fixes
TypeError: Cannot read properties of undefined (reading 'call')
Often occurs when an `@action` is not correctly bound or passed, especially in older Ember versions or when using `this.actionName()` directly without `{{action this.actionName}}` or `{{on 'event' this.actionName}}` in templates.
fixEnsure actions are properly decorated with `@action` in your component class and invoked correctly in templates using `{{on "event" this.actionName}}` or passed as arguments to child components via `@action={{this.actionName}}`. Could not find module 'ember-primitives/components/switch'
Incorrect import path or the component was not properly discovered by the Ember build system (e.g., due to caching issues or a new component not being present).
fixVerify the import path matches the component's file structure (e.g., `ember-primitives/components/switch`). Clear your Ember cache (`rm -rf tmp/ node_modules/.cache/ && npm install`) and restart the Ember development server (`ember s`).
Argument of type '(...args: any[]) => void' is not assignable to parameter of type '(checked: boolean, event: Event) => void'.
A Glint type error indicating a mismatch between the expected arguments of an `@onChange` handler (or similar event handler) and the provided function's signature.
fixAdjust your event handler function to match the expected signature, especially for components like `Switch` which changed argument order in `v0.53.1`. For example, for a `Switch`, ensure your function accepts `(checked: boolean, event: Event)`.
Audit
Dependencies
@ember/test-helpersrequiredProvides utilities for testing Ember applications, particularly for interacting with components and rendering.
@ember/test-waitersrequiredManages asynchronous operations during tests to ensure consistent and reliable test execution.
@glimmer/componentrequiredThe foundational component model for modern Ember applications, essential for building UI components.
@glint/templaterequiredProvides type definitions and static analysis for Ember templates, enabling TypeScript usage within templates.
ember-modifierrequiredEnables the creation and usage of element modifiers in Ember templates, often used for DOM interactions or lifecycle hooks.
ember-resourcesrequiredOffers composable, stateful primitives for managing component lifecycle and reactive data flows in Ember.