From 7e7a5ebab98ad1e114ffbbdb0a6b6cceb43effbe Mon Sep 17 00:00:00 2001 From: Lorenz Hilpert Date: Fri, 4 Apr 2025 18:00:49 +0200 Subject: [PATCH] Introduced responsive layout utilities and directives for Angular. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ✨ **Feature**: Added breakpoint utility for responsive design - ✨ **Feature**: Implemented BreakpointDirective for conditional rendering - 🛠️ **Refactor**: Updated styles for filter and order-by components - 📚 **Docs**: Created README and documentation for ui-layout library - ⚙️ **Config**: Added TypeScript and ESLint configurations for the new library --- apps/isa-app/stories/ui/layout/breakpoint.mdx | 36 ++++++++ jest.config.js | 5 -- .../return-search-result.component.html | 23 +++-- .../return-search-result.component.ts | 9 +- .../filter-menu-button.component.html | 8 +- .../filter-menu/filter-menu.component.scss | 4 +- .../input-menu/input-menu.component.scss | 3 +- .../order-by/order-by-toolbar.component.html | 2 +- .../order-by/order-by-toolbar.component.scss | 3 + libs/ui/layout/README.md | 47 ++++++++++ libs/ui/layout/eslint.config.mjs | 34 ++++++++ libs/ui/layout/jest.config.ts | 21 +++++ libs/ui/layout/project.json | 20 +++++ libs/ui/layout/src/index.ts | 2 + .../ui/layout/src/lib/breakpoint.directive.ts | 50 +++++++++++ libs/ui/layout/src/lib/breakpoint.ts | 87 +++++++++++++++++++ libs/ui/layout/src/test-setup.ts | 6 ++ libs/ui/layout/tsconfig.json | 28 ++++++ libs/ui/layout/tsconfig.lib.json | 17 ++++ libs/ui/layout/tsconfig.spec.json | 16 ++++ tailwind.config.js | 1 + tsconfig.base.json | 1 + 22 files changed, 398 insertions(+), 25 deletions(-) create mode 100644 apps/isa-app/stories/ui/layout/breakpoint.mdx delete mode 100644 jest.config.js create mode 100644 libs/ui/layout/README.md create mode 100644 libs/ui/layout/eslint.config.mjs create mode 100644 libs/ui/layout/jest.config.ts create mode 100644 libs/ui/layout/project.json create mode 100644 libs/ui/layout/src/index.ts create mode 100644 libs/ui/layout/src/lib/breakpoint.directive.ts create mode 100644 libs/ui/layout/src/lib/breakpoint.ts create mode 100644 libs/ui/layout/src/test-setup.ts create mode 100644 libs/ui/layout/tsconfig.json create mode 100644 libs/ui/layout/tsconfig.lib.json create mode 100644 libs/ui/layout/tsconfig.spec.json diff --git a/apps/isa-app/stories/ui/layout/breakpoint.mdx b/apps/isa-app/stories/ui/layout/breakpoint.mdx new file mode 100644 index 000000000..83bf9103c --- /dev/null +++ b/apps/isa-app/stories/ui/layout/breakpoint.mdx @@ -0,0 +1,36 @@ +import { Meta } from '@storybook/addon-docs'; + + + +# Breakpoint Utility + +The `breakpoint` utility allows you to create a Signal that evaluates to `true` if the current viewport matches the specified breakpoints. + +## Usage + +### Example + +```typescript +import { Component } from '@angular/core'; +import { breakpoint, Breakpoint } from 'ui-layout'; + +@Component({ + selector: 'app-breakpoint-demo', + template: ` +
This content is visible only on tablet viewports.
+ `, + imports: [BreakpointDirective], +}) +export class BreakpointDemoComponent { + isTablet = breakpoint(Breakpoint.Tablet); +} +``` + +### Breakpoints Table + +| Breakpoint | CSS Media Query Selector | +| ------------ | --------------------------------------------- | +| `tablet` | `(max-width: 1279px)` | +| `desktop` | `(min-width: 1280px) and (max-width: 1439px)` | +| `desktop-l` | `(min-width: 1440px) and (max-width: 1919px)` | +| `desktop-xl` | `(min-width: 1920px)` | diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 649f8a6e5..000000000 --- a/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const nxPreset = require('@nx/jest/preset').default; - -module.exports = { - ...nxPreset, -}; diff --git a/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.html b/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.html index fa8825a9d..5b5eb18c1 100644 --- a/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.html +++ b/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.html @@ -12,18 +12,23 @@ [rollbackOnClose]="true" > - @if (isMobileDevice()) { - - - - } @else { - - } + + + -@if (isMobileDevice() && toggleOrderByToolbar()) { - +@if (orderByVisible()) { + } diff --git a/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.ts b/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.ts index 4b4efe074..d220e5306 100644 --- a/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.ts +++ b/libs/oms/feature/return-search/src/lib/return-search-result/return-search-result.component.ts @@ -22,11 +22,11 @@ import { import { IconButtonComponent } from '@isa/ui/buttons'; import { EmptyStateComponent } from '@isa/ui/empty-state'; import { restoreScrollPosition } from '@isa/core/scroll-position'; -import { Platform } from '@angular/cdk/platform'; import { NgIconComponent, provideIcons } from '@ng-icons/core'; import { isaActionSort } from '@isa/icons'; import { ReturnSearchEntity, ReturnSearchStatus, ReturnSearchStore } from '@isa/oms/data-access'; import { ReturnSearchResultItemComponent } from './return-search-result-item/return-search-result-item.component'; +import { BreakpointDirective } from '@isa/ui/layout'; type EmptyState = { title: string; @@ -47,18 +47,20 @@ type EmptyState = { EmptyStateComponent, NgIconComponent, FilterMenuButtonComponent, + BreakpointDirective, ], providers: [provideIcons({ isaActionSort })], }) export class ReturnSearchResultComponent { #route = inject(ActivatedRoute); #router = inject(Router); - #platform = inject(Platform); private _processId = injectActivatedProcessId(); private _returnSearchStore = inject(ReturnSearchStore); private _filterService = inject(FilterService); + orderByVisible = signal(false); + ReturnSearchStatus = ReturnSearchStatus; filterInputs = computed(() => @@ -94,9 +96,6 @@ export class ReturnSearchResultComponent { listElements = viewChildren>('listElement'); - isMobileDevice = signal(this.#platform.ANDROID || this.#platform.IOS); - toggleOrderByToolbar = signal(false); - searchEffectFn = () => effect(() => { const processId = this._processId(); diff --git a/libs/shared/filter/src/lib/menus/filter-menu/filter-menu-button.component.html b/libs/shared/filter/src/lib/menus/filter-menu/filter-menu-button.component.html index f71d71540..e5419a9fc 100644 --- a/libs/shared/filter/src/lib/menus/filter-menu/filter-menu-button.component.html +++ b/libs/shared/filter/src/lib/menus/filter-menu/filter-menu-button.component.html @@ -14,11 +14,15 @@ [cdkConnectedOverlayOrigin]="trigger" [cdkConnectedOverlayOpen]="open()" [cdkConnectedOverlayHasBackdrop]="true" - [cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'" + cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop " [cdkConnectedOverlayScrollStrategy]="scrollStrategy" [cdkConnectedOverlayOffsetX]="-10" [cdkConnectedOverlayOffsetY]="18" (backdropClick)="toggle()" > - + diff --git a/libs/shared/filter/src/lib/menus/filter-menu/filter-menu.component.scss b/libs/shared/filter/src/lib/menus/filter-menu/filter-menu.component.scss index f3b2c494e..41a857605 100644 --- a/libs/shared/filter/src/lib/menus/filter-menu/filter-menu.component.scss +++ b/libs/shared/filter/src/lib/menus/filter-menu/filter-menu.component.scss @@ -1,7 +1,7 @@ :host { - @apply grid grid-flow-row; + @apply inline-flex flex-col; @apply bg-isa-white; @apply rounded-[1.25rem]; @apply w-[14.3125rem] max-h-[33.5rem]; - box-shadow: 0px 0px 16px 0px rgba(0, 0, 0, 0.15); + @apply shadow-overlay; } diff --git a/libs/shared/filter/src/lib/menus/input-menu/input-menu.component.scss b/libs/shared/filter/src/lib/menus/input-menu/input-menu.component.scss index 02943e416..5d5edbef1 100644 --- a/libs/shared/filter/src/lib/menus/input-menu/input-menu.component.scss +++ b/libs/shared/filter/src/lib/menus/input-menu/input-menu.component.scss @@ -1,3 +1,4 @@ :host { - @apply grid grid-flow-row bg-isa-white rounded-[1.25rem] shadow-[0px,0px,16px,0px,rgba(0,0,0,0.15)] max-h-[32.3rem]; + @apply inline-flex flex-col; + @apply shadow-overlay bg-isa-white rounded-[1.25rem] max-h-[32.3rem]; } diff --git a/libs/shared/filter/src/lib/order-by/order-by-toolbar.component.html b/libs/shared/filter/src/lib/order-by/order-by-toolbar.component.html index 83caa33b6..02b0780a5 100644 --- a/libs/shared/filter/src/lib/order-by/order-by-toolbar.component.html +++ b/libs/shared/filter/src/lib/order-by/order-by-toolbar.component.html @@ -3,7 +3,7 @@
@for (orderBy of orderByOptions(); track orderBy.by) {