BreakpointObserverService
Answer one question as a signal — is the viewport narrower than the md breakpoint? — for structural choices CSS cannot express.
BreakpointObserverService answers one question as a signal: is the viewport narrower than the md
breakpoint (768px)? It exists for the cases CSS cannot express — choosing a component (a sheet instead of a
side panel), a placement (bottom-start instead of left-start), a size input.
Prefer a Tailwind md: variant when you can
Anything that is purely a matter of layout belongs in a Tailwind md: variant instead: the CSS costs nothing
at runtime, needs no injection, and cannot fall out of sync with the service.
Minimal example
import { Component, computed, inject } from "@angular/core";
import { BreakpointObserverService } from "@sinequa/galactik";
@Component({
selector: "sample-component",
template: `
@if (breakpoints.isMobile()) {
<sheet-previewer [record]="record()" />
} @else {
<preview-column [record]="record()" />
}
`,
})
export class SampleComponent {
protected readonly breakpoints = inject(BreakpointObserverService);
protected readonly menuPlacement = computed(() => (this.breakpoints.isMobile() ? "bottom-start" : "left-start"));
}How it works
The service is backed by matchMedia, observing (width < 768px) — the exact negation of Tailwind's md, so
the signal and the CSS always agree at every width. It reacts to a resize with no resize listener of its
own, removes its listener when the injector is destroyed, and is inert under server-side rendering (no
window access — the signal stays false).
The viewport is measured in the constructor, not in an afterNextRender callback, so a consumer that injects
the service and reads isMobile() during change detection — a computed, a template expression — gets the
real answer straight away, with no render needed first.
Options
Prop
Type