LogisBaseLogisBase

Templates & Components

Build engine templates and Glimmer components using @logisbase/ember-ui — layout primitives, common widgets, and how to render extension components inside other engines.

Templates & Components

Engine templates use standard Handlebars + Ember. The console ships a large component library — @logisbase/ember-ui — that gives you matching chrome (layouts, headers, tables, modals, form inputs) without re-implementing styles.

Templates

Engine templates live under addon/templates/, mirroring the route map:

addon/
├── routes.js                                 # this.route('orders', { ... })
├── routes/
│   └── orders.js
├── controllers/
│   └── orders.js
└── templates/
    ├── application.hbs                       # outermost layout for the engine
    └── orders.hbs                            # rendered for the orders route

The engine's application.hbs is your top-level layout — wrap content in the standard <Layout::Section> chrome so it sits correctly inside the console:

{{! addon/templates/application.hbs }}
<Layout::Container>
  <Layout::Sidebar />
  <Layout::Section>
    {{outlet}}
  </Layout::Section>
</Layout::Container>

Glimmer Components

Components live under addon/components/. Use Octane (@glimmer/component):

// addon/components/order-summary.js
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';

export default class OrderSummaryComponent extends Component {
  @service fetch;
  @service notifications;

  @tracked isLoading = false;

  @action
  async refresh() {
    this.isLoading = true;
    try {
      await this.fetch.get(
        `my-extension/v1/orders/${this.args.order.id}/refresh`,
      );
      this.notifications.success('Refreshed');
    } finally {
      this.isLoading = false;
    }
  }
}
{{! addon/components/order-summary.hbs }}
<div class='rounded-md border p-4'>
  <h3 class='font-semibold'>{{@order.public_id}}</h3>
  <Button
    @text='Refresh'
    @icon='rotate'
    @isLoading={{this.isLoading}}
    @onClick={{this.refresh}}
  />
</div>

Using @logisbase/ember-ui

@logisbase/ember-ui is already on your engine's resolver path — components are available globally without imports. The library covers the platform's design system; reach for it before building chrome from scratch.

Full component reference: LogisBase UI docs. Each component below links to its dedicated page with props, slots, examples, and edge cases.

Layout primitives

ComponentPurposeDocs
<Layout::Container>Outer wrapper with sidebar + section gridLayout overview
<Layout::Sidebar>Collapsible engine sidebarLayout overview
<Layout::Section>Main content column with header/body slotsLayout overview
<Layout::Section::Header @title="…" />Page header barLayout overview
<Layout::Section::Body>Scrollable body containerLayout overview
<ContentPanel @title @open>Collapsible labeled sectionContent Panel
<Drawer>Slide-out side panelDrawer
<Overlay>Backdrop + portal targetOverlay
<Spacer @height>Vertical spacingSpacer

Actions

ComponentPurposeDocs
<Button @text @icon @type @onClick @isLoading />Variants: primary, magic, danger, etc.Button
<ClickToCopy @value />Copy-on-click affordanceClick to Copy
<ClickToReveal />Reveal hidden content (secrets, tokens)Click to Reveal

Display

ComponentPurposeDocs
<Spinner />Loading indicatorSpinner
<Badge @text @type />Status badgesBadge
<Pill @text />Compact label chipPill
<Table @data @columns />Sortable, paginatable data tableTable
<Timeline />Vertical event timelineTimeline
<ActivityLog />Activity feedActivity Log
<ProgressBar />Progress indicatorProgress Bar

Form Inputs

ComponentPurposeDocs
<Select @options @onChange />Styled selectSelect
<MultiSelect />Multiple selection with chipsMulti Select
<ComboBox />Searchable dropdownCombo Box
<Checkbox /> / <Toggle />Boolean inputsCheckbox, Toggle
<DatePicker /> / <DateTimeInput />Date / date-time pickersDate Picker
<MoneyInput />Currency-aware amount inputMoney Input
<UnitInput />Number with unit selectorUnit Input
<PhoneInput />International phone inputPhone Input
<FileUpload />Drag-and-drop file uploadFile Upload
<CoordinatesInput />Lat/lng + mapCoordinates Input
<ModelSelect />Searchable Ember Data record pickerModel Select
<InputGroup />Label + input + help text wrapperInput Group

For complete documentation — including extending components, slot content, and accessibility notes — see the LogisBase UI documentation.

Cross-engine Components

When another extension wants to render a component from your engine — say, on the Fleet-Ops order details page — the boundary crosses engines. You don't pass component names directly; you pass an ExtensionComponent, which the host resolves lazily.

import { ExtensionComponent } from '@logisbase/ember-core/contracts';

const ref = new ExtensionComponent(
  '@logisbase/storefront-engine',
  'storefront-order-summary', // resolves to addon/components/storefront-order-summary.{js,hbs}
);

The receiving registry (e.g. 'fleet-ops:component:order:details') renders ref via <LazyEngineComponent>, which loads the source engine on demand if it isn't already booted.

{{! inside the host engine }}
<LazyEngineComponent
  @component={{this.extensionComponent}}
  @params={{this.componentArgs}}
/>

You don't usually invoke <LazyEngineComponent> yourself — the Registry Service and Virtual Routes wire it for you.

Tailwind & Styling

The console uses Tailwind utility classes and a small set of design tokens. Most ember-ui components accept utility class strings via @class or pass-through HTML attributes (class="…"). For one-off styles, scope them to your engine via component-tree CSS or Tailwind utilities.

If you need engine-scoped global CSS, drop a stylesheet under addon/styles/ember-cli-build.js will pick it up.

Services Available in Components

These host services are wired into your engine via @logisbase/ember-core/exports and can be injected into any component. Detailed reference: Ember Services.

ServiceUse for
fetchAuthenticated HTTP requests — pass { namespace } to hit your extension's API
storeEmber Data StorefindRecord, query, etc.
notificationsToast notifications (success, error, info, warning)
currentUserLogged-in user
sessionAuth session, including session.data.authenticated
modalsManagerImperative modal API
themeSet body classes, toggle dark mode
intli18n / translations
abilitiesRole-based permission checks (ember-can)
crudGeneric CRUD action helpers
eventsApp-wide event bus
socketReal-time pub/sub
appCacheBrowser-storage-backed cache
universeThe universe service itself + sub-services
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';

export default class extends Component {
  @service fetch;
  @service notifications;
  @service abilities;
}

See Also

Source

FileDescription
packages/ember-ui/addon/componentsAll shared UI components (source)
packages/ember-core/addon/exports/services.jsServices available to engines
Templates & Components | LogisBase