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:
sdarbinyan
2026-07-16 01:59:45 +04:00
parent b8d89ca8e7
commit e18f542357
18 changed files with 679 additions and 0 deletions

View 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>

View 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;
}
}

View 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);
}
}