feat(shared-ui): add toggle, select, color-picker, section-card, locale-tabs, key-value-editor primitives
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
14
src/app/shared/ui/locale-tabs/locale-tabs.component.html
Normal file
14
src/app/shared/ui/locale-tabs/locale-tabs.component.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="app-locale-tabs" role="tablist">
|
||||
@for (locale of locales(); track locale) {
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
class="app-locale-tab"
|
||||
[class.app-locale-tab--active]="currentLocale() === locale"
|
||||
[attr.aria-selected]="currentLocale() === locale"
|
||||
(click)="select(locale)"
|
||||
>
|
||||
{{ locale }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
43
src/app/shared/ui/locale-tabs/locale-tabs.component.scss
Normal file
43
src/app/shared/ui/locale-tabs/locale-tabs.component.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.app-locale-tabs {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
border-bottom: 1px solid var(--border-color, #d3dad9);
|
||||
}
|
||||
|
||||
.app-locale-tab {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
background: transparent;
|
||||
color: var(--text-secondary, #5f6e6a);
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
transition: color var(--transition-fast, 120ms ease),
|
||||
border-color var(--transition-fast, 120ms ease);
|
||||
|
||||
&:hover {
|
||||
color: var(--text-primary, #1e3c38);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color, #2f6e5d) 25%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.app-locale-tab--active {
|
||||
color: var(--primary-color, #2f6e5d);
|
||||
border-bottom-color: var(--primary-color, #2f6e5d);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.app-locale-tab {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
27
src/app/shared/ui/locale-tabs/locale-tabs.component.ts
Normal file
27
src/app/shared/ui/locale-tabs/locale-tabs.component.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { ChangeDetectionStrategy, Component, input, output, signal } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-locale-tabs',
|
||||
standalone: true,
|
||||
templateUrl: './locale-tabs.component.html',
|
||||
styleUrl: './locale-tabs.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class LocaleTabsComponent {
|
||||
readonly locales = input.required<string[]>();
|
||||
readonly defaultLocale = input<string | null>(null);
|
||||
readonly activeLocale = output<string>();
|
||||
|
||||
private readonly selected = signal<string | null>(null);
|
||||
|
||||
protected currentLocale(): string {
|
||||
const explicit = this.selected();
|
||||
if (explicit && this.locales().includes(explicit)) return explicit;
|
||||
return this.defaultLocale() ?? this.locales()[0] ?? '';
|
||||
}
|
||||
|
||||
protected select(locale: string): void {
|
||||
this.selected.set(locale);
|
||||
this.activeLocale.emit(locale);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user