diff --git a/src/app/shared/ui/pagination/pagination.component.html b/src/app/shared/ui/pagination/pagination.component.html index af7d941..d8f2a3c 100644 --- a/src/app/shared/ui/pagination/pagination.component.html +++ b/src/app/shared/ui/pagination/pagination.component.html @@ -6,7 +6,7 @@ [attr.aria-label]="previousLabel()" (click)="goTo(currentPage() - 1)" > - « + @for (page of pages(); track $index) { @@ -32,6 +32,6 @@ [attr.aria-label]="nextLabel()" (click)="goTo(currentPage() + 1)" > - » + diff --git a/src/app/shared/ui/pagination/pagination.component.ts b/src/app/shared/ui/pagination/pagination.component.ts index 97b9485..fa40b08 100644 --- a/src/app/shared/ui/pagination/pagination.component.ts +++ b/src/app/shared/ui/pagination/pagination.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core'; import { ButtonComponent } from '../button/button.component'; +import { IconComponent } from '../icon/icon.component'; const SIBLING_COUNT = 1; const ELLIPSIS = '…' as const; @@ -7,7 +8,7 @@ const ELLIPSIS = '…' as const; @Component({ selector: 'app-pagination', standalone: true, - imports: [ButtonComponent], + imports: [ButtonComponent, IconComponent], templateUrl: './pagination.component.html', styleUrl: './pagination.component.scss', changeDetection: ChangeDetectionStrategy.OnPush diff --git a/src/app/shared/ui/select/select.component.html b/src/app/shared/ui/select/select.component.html index c87e1b0..e852836 100644 --- a/src/app/shared/ui/select/select.component.html +++ b/src/app/shared/ui/select/select.component.html @@ -1,20 +1,23 @@ - +
+ + +
@if (activeDescription(); as description) { {{ description }} } diff --git a/src/app/shared/ui/select/select.component.scss b/src/app/shared/ui/select/select.component.scss index 451d9c2..30bfc13 100644 --- a/src/app/shared/ui/select/select.component.scss +++ b/src/app/shared/ui/select/select.component.scss @@ -7,8 +7,24 @@ width: 100%; } +.app-select-wrap { + position: relative; + width: 100%; +} + +.app-select-arrow { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--text-secondary, #6b7280); + pointer-events: none; +} + .app-select { width: 100%; + appearance: none; + padding-right: 36px; border: 1px solid var(--border-color, #e4e4e7); border-radius: var(--radius-md, 6px); background: var(--bg-primary, #fff); diff --git a/src/app/shared/ui/select/select.component.ts b/src/app/shared/ui/select/select.component.ts index 672bff0..737ad92 100644 --- a/src/app/shared/ui/select/select.component.ts +++ b/src/app/shared/ui/select/select.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component, forwardRef, inject, input } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { FormFieldContext } from '../form-field/form-field.component'; +import { IconComponent } from '../icon/icon.component'; export type SelectSize = 'sm' | 'md' | 'lg'; @@ -13,6 +14,7 @@ export interface SelectOption { @Component({ selector: 'app-select', standalone: true, + imports: [IconComponent], templateUrl: './select.component.html', styleUrl: './select.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/src/styles.scss b/src/styles.scss index 204299c..31fa29e 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -149,6 +149,46 @@ a, button, input, textarea, select { animation: app-icon-spin 1s linear infinite; } +/* Consistent, animated expander chevron for every native
/ + disclosure in the app, replacing the browser's default triangle marker + (which renders differently per browser). Matches the Lucide ChevronDown + path used everywhere else via app-icon, so expanders use the same icon + family as the rest of the UI without touching every call site. */ +details > summary { + list-style: none; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + + &::-webkit-details-marker { + display: none; + } + + &::after { + content: ''; + flex-shrink: 0; + width: 16px; + height: 16px; + background-color: currentColor; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + transition: transform 0.2s ease; + } +} + +details[open] > summary::after { + transform: rotate(180deg); +} + +@media (prefers-reduced-motion: reduce) { + details > summary::after { + transition: none; + } +} + /* Respect OS-level reduced-motion preference globally: neutralizes hover transforms, card-entrance/skeleton-shimmer animations, and smooth-scroll everywhere in one place rather than requiring every component to opt in