diff --git a/libs/design/src/core/breakpoints/README.md b/libs/design/src/core/breakpoints/README.md new file mode 100644 index 0000000000..8a77c795cb --- /dev/null +++ b/libs/design/src/core/breakpoints/README.md @@ -0,0 +1,42 @@ +# Breakpoints + +Breakpoints provides utilities for observing and reacting to viewport size changes. + +## Overview + +It provides a set of standardized, mobile-first `min-width` media query strings for building responsive layouts with Angular CDK's [`BreakpointObserver`](https://material.angular.io/cdk/layout/overview#breakpointobserver). It includes a server-safe observer that gracefully handles server-side rendering (SSR) by substituting a noop implementation on the server. + +## Breakpoint map + +The `DaffBreakpoints` enum maps common device viewport widths to CSS media query strings. Each value targets a `min-width` threshold, so styles cascade upward from smaller screens to larger ones. + +| Breakpoint | Min Width | +|---|---| +| `MOBILE` | 480px | +| `TABLET` | 768px | +| `BIG_TABLET` | 1024px | +| `SMALL_LAPTOP` | 1200px | +| `LAPTOP` | 1440px | +| `DESKTOP` | 1920px | + +## Server-safe observer + +`SERVER_SAFE_BREAKPOINT_OBSERVER` is an injection token that resolves to Angular CDK's [`BreakpointObserver`](https://material.angular.io/cdk/layout/overview#breakpointobserver) in the browser and a `NoopBreakpointObserver` on the server, preventing SSR errors when observing breakpoints. + +## Usage + +```ts +import { + SERVER_SAFE_BREAKPOINT_OBSERVER, + DaffBreakpoints +} from '@daffodil/design'; + +@Component({ ... }) +export class MyComponent { + private breakpointObserver = inject(SERVER_SAFE_BREAKPOINT_OBSERVER); + + isBigTablet$ = this.breakpointObserver + .observe(DaffBreakpoints.BIG_TABLET) + .pipe(map((result) => result.matches)); +} +``` diff --git a/libs/design/src/core/breakpoints/breakpoints.ts b/libs/design/src/core/breakpoints/breakpoints.ts index 19dc4561bf..82130fe8ca 100644 --- a/libs/design/src/core/breakpoints/breakpoints.ts +++ b/libs/design/src/core/breakpoints/breakpoints.ts @@ -1,8 +1,17 @@ +/** + * Sensible breakpoints for layouts and interfaces used across `@daffodil/design` components. + */ export enum DaffBreakpoints { + /** `min-width: 1920px` */ DESKTOP = '(min-width: 1920px)', + /** `min-width: 1440px` */ LAPTOP = '(min-width: 1440px)', + /** `min-width: 1200px` */ SMALL_LAPTOP = '(min-width: 1200px)', + /** `min-width: 1024px` */ BIG_TABLET = '(min-width: 1024px)', + /** `min-width: 768px` */ TABLET = '(min-width: 768px)', + /** `min-width: 480px` */ MOBILE = '(min-width: 480px)', } diff --git a/libs/design/src/core/breakpoints/noop.service.ts b/libs/design/src/core/breakpoints/noop.service.ts index 3bacc39a90..cd16027840 100644 --- a/libs/design/src/core/breakpoints/noop.service.ts +++ b/libs/design/src/core/breakpoints/noop.service.ts @@ -9,17 +9,30 @@ import { } from 'rxjs'; /** - * A stubbed out breakpoint observer service. + * A no-op implementation of Angular CDK's `BreakpointObserver` that always reports + * no breakpoints as matched. Useful for server-side rendering or testing contexts + * where browser layout APIs are unavailable. */ @Injectable({ providedIn: 'root', }) export class NoopBreakpointObserver implements Omit { + /** + * @docs-private + */ // eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method, @angular-eslint/use-lifecycle-interface ngOnDestroy(): void {} + + /** + * Always returns `false`, indicating that none of the given media queries are active. + */ isMatched(value: string | readonly string[]): boolean { return false; } + + /** + * Returns an observable that never emits a `BreakpointState`, making breakpoint-dependent logic inert. + */ observe(value: string | readonly string[]): Observable { return of(); }