fix: settings cards with the page's padding and compact buttons

The Git, automations, webhooks and import cards had no inner padding and
oversized buttons, because the settings page's styles do not reach child
components; they now share a stylesheet with the same pills. The template
button gets its own column instead of squeezing the type's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 20:23:20 +02:00
parent 62fac8ef45
commit 58fe5e8301
6 changed files with 188 additions and 106 deletions

View File

@@ -347,16 +347,6 @@ function idFrom(name: string): string {
"
/>
<code class="ts-id">{{ type.id }}</code>
<button
type="button"
class="ts-plain-link ts-template-toggle"
[attr.aria-expanded]="openTemplate() === i"
(click)="
openTemplate.set(openTemplate() === i ? null : i)
"
>
Plantilla{{ hasTemplate(type) ? ' ●' : '' }}
</button>
</span>
<select
class="ts-input"
@@ -388,6 +378,18 @@ function idFrom(name: string): string {
</option>
}
</select>
<button
type="button"
class="ts-add ts-template-toggle"
[class.has-template]="hasTemplate(type)"
[attr.aria-expanded]="openTemplate() === i"
[attr.aria-label]="'Plantilla de ' + type.name"
(click)="
openTemplate.set(openTemplate() === i ? null : i)
"
>
Plantilla{{ hasTemplate(type) ? ' ●' : '' }}
</button>
<ng-container
[ngTemplateOutlet]="archive"
[ngTemplateOutletContext]="{
@@ -804,12 +806,15 @@ function idFrom(name: string): string {
}
}
.ts-template-toggle {
font-size: 0.75rem;
white-space: nowrap;
&.has-template {
border-color: var(--ts-brand) !important;
color: var(--ts-ink) !important;
}
}
.ts-type-grid {
display: grid;
grid-template-columns: 2rem minmax(8rem, 1fr) 7rem 7rem 6.5rem;
grid-template-columns: 2rem minmax(8rem, 1fr) 7rem 7rem auto 6.5rem;
align-items: center;
gap: 0.5rem;
}
@@ -940,6 +945,7 @@ function idFrom(name: string): string {
/* @pi/ui styles every <button>: these opt back into a compact look. */
.ts-add,
.ts-archive,
.ts-template-toggle,
.ts-primary,
.ts-secondary {
min-width: 0 !important;

View File

@@ -11,7 +11,6 @@ import {
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
PiActionButtonComponent,
PiSelectFieldComponent,
PiTextFieldComponent,
type PiSelectFieldOption,
@@ -51,11 +50,8 @@ const ACTION: Record<AutomationActionKind, string> = {
@Component({
selector: 'ts-automations',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
PiActionButtonComponent,
PiSelectFieldComponent,
PiTextFieldComponent,
],
imports: [PiSelectFieldComponent, PiTextFieldComponent],
styleUrl: './settings-card.scss',
template: `
<section class="ts-panel ts-block ts-rules" aria-labelledby="rules-title">
<div>
@@ -85,20 +81,20 @@ const ACTION: Record<AutomationActionKind, string> = {
}
</p>
<div class="ts-rules__actions">
<pi-action-button
size="small"
color="grey"
appearance="ghost"
[text]="rule.active ? 'Pausar' : 'Reanudar'"
(execute)="toggle(rule)"
/>
<pi-action-button
size="small"
color="grey"
appearance="ghost"
text="Borrar"
(execute)="remove(rule)"
/>
<button
type="button"
class="ts-btn ts-btn--ghost"
(click)="toggle(rule)"
>
{{ rule.active ? 'Pausar' : 'Reanudar' }}
</button>
<button
type="button"
class="ts-btn ts-btn--ghost"
(click)="remove(rule)"
>
Borrar
</button>
</div>
</article>
}
@@ -150,13 +146,14 @@ const ACTION: Record<AutomationActionKind, string> = {
}
</div>
<div>
<pi-action-button
size="small"
color="primary"
text="Añadir regla"
<button
type="button"
class="ts-btn ts-btn--primary"
[disabled]="!canCreate()"
(execute)="create()"
/>
(click)="create()"
>
Añadir regla
</button>
</div>
</form>
</section>

View File

@@ -9,7 +9,6 @@ import {
untracked,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { PiActionButtonComponent } from '@pi/ui';
import { ToastService } from '@task-stream/web/shared/ui';
import { GitGateway, GitIntegration } from '@task-stream/web/tracker/domain';
@@ -20,7 +19,8 @@ import { GitGateway, GitIntegration } from '@task-stream/web/tracker/domain';
@Component({
selector: 'ts-git-integration',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [PiActionButtonComponent],
imports: [],
styleUrl: './settings-card.scss',
template: `
<section class="ts-panel ts-block ts-git" aria-labelledby="git-title">
<div>
@@ -74,29 +74,30 @@ import { GitGateway, GitIntegration } from '@task-stream/web/tracker/domain';
<em>pull/merge request</em>.
</p>
<div class="ts-git__actions">
<pi-action-button
size="small"
color="grey"
appearance="outline"
text="Cambiar el secreto"
(execute)="enable()"
/>
<pi-action-button
size="small"
color="grey"
appearance="ghost"
text="Desactivar"
(execute)="disable()"
/>
<button
type="button"
class="ts-btn ts-btn--secondary"
(click)="enable()"
>
Cambiar el secreto
</button>
<button
type="button"
class="ts-btn ts-btn--ghost"
(click)="disable()"
>
Desactivar
</button>
</div>
} @else {
<div>
<pi-action-button
size="small"
color="primary"
text="Activar"
(execute)="enable()"
/>
<button
type="button"
class="ts-btn ts-btn--primary"
(click)="enable()"
>
Activar
</button>
</div>
}
}

View File

@@ -0,0 +1,74 @@
// Shared by the cards of the settings page (Git, automations, webhooks,
// import and export): the same padding and the same compact pill buttons as
// the rest of that page, whose own styles do not reach child components.
:host {
display: block;
}
.ts-block {
display: grid;
gap: 0.75rem;
min-width: 0;
padding: 1.25rem;
h3 {
margin: 0;
font-size: 1rem;
font-weight: 700;
}
> div > p,
> div > h3 + p {
margin: 0.25rem 0 0;
}
}
.ts-btn {
display: inline-flex;
align-items: center;
justify-content: center;
height: 2.125rem;
padding: 0 0.875rem;
border: 1px solid var(--ts-line-strong);
border-radius: 999px;
background: var(--ts-surface);
color: var(--ts-ink-soft);
font: inherit;
font-size: 0.8125rem;
font-weight: 600;
white-space: nowrap;
cursor: pointer;
&:hover:not(:disabled) {
border-color: var(--ts-brand);
color: var(--ts-ink);
}
&:disabled {
opacity: 0.5;
cursor: default;
}
}
.ts-btn--primary {
border-color: transparent;
background: var(--ts-brand);
color: #fff;
&:hover:not(:disabled) {
color: #fff;
filter: brightness(1.08);
}
}
.ts-btn--ghost {
border-color: transparent;
background: none;
}
.ts-btn-row {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}

View File

@@ -7,7 +7,7 @@ import {
signal,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { PiActionButtonComponent, PiFileUploadComponent } from '@pi/ui';
import { PiFileUploadComponent } from '@pi/ui';
import { ToastService } from '@task-stream/web/shared/ui';
import { ImportReport, TransferGateway } from '@task-stream/web/tracker/domain';
@@ -15,7 +15,8 @@ import { ImportReport, TransferGateway } from '@task-stream/web/tracker/domain';
@Component({
selector: 'ts-transfer',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [PiActionButtonComponent, PiFileUploadComponent],
imports: [PiFileUploadComponent],
styleUrl: './settings-card.scss',
template: `
<section
class="ts-panel ts-block ts-transfer"
@@ -30,14 +31,14 @@ import { ImportReport, TransferGateway } from '@task-stream/web/tracker/domain';
</p>
</div>
<div>
<pi-action-button
size="small"
color="grey"
appearance="outline"
[text]="exporting() ? 'Exportando…' : 'Exportar CSV'"
<button
type="button"
class="ts-btn ts-btn--secondary"
[disabled]="exporting()"
(execute)="exportCsv()"
/>
(click)="exportCsv()"
>
{{ exporting() ? 'Exportando…' : 'Exportar CSV' }}
</button>
</div>
<pi-file-upload
@@ -85,17 +86,18 @@ import { ImportReport, TransferGateway } from '@task-stream/web/tracker/domain';
</details>
}
@if (plan.dryRun && plan.rows) {
<pi-action-button
size="small"
color="primary"
[text]="
<button
type="button"
class="ts-btn ts-btn--primary"
[disabled]="importing()"
(click)="importCsv()"
>
{{
importing()
? 'Importando…'
: 'Importar ' + plan.rows + ' tickets'
"
[disabled]="importing()"
(execute)="importCsv()"
/>
}}
</button>
}
</div>
}

View File

@@ -9,7 +9,7 @@ import {
untracked,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { PiActionButtonComponent, PiTextFieldComponent } from '@pi/ui';
import { PiTextFieldComponent } from '@pi/ui';
import { ToastService } from '@task-stream/web/shared/ui';
import { Webhook, WebhooksGateway } from '@task-stream/web/tracker/domain';
import { timeAgo } from './copy';
@@ -38,7 +38,8 @@ const EVENT_LABEL: Record<string, string> = {
@Component({
selector: 'ts-webhooks',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [PiActionButtonComponent, PiTextFieldComponent],
imports: [PiTextFieldComponent],
styleUrl: './settings-card.scss',
template: `
<section class="ts-panel ts-block ts-hooks" aria-labelledby="hooks-title">
<div>
@@ -79,27 +80,27 @@ const EVENT_LABEL: Record<string, string> = {
</p>
}
<div class="ts-hooks__actions">
<pi-action-button
size="small"
color="grey"
appearance="outline"
text="Probar"
(execute)="test(hook)"
/>
<pi-action-button
size="small"
color="grey"
appearance="ghost"
[text]="hook.active ? 'Pausar' : 'Reanudar'"
(execute)="toggle(hook)"
/>
<pi-action-button
size="small"
color="grey"
appearance="ghost"
text="Borrar"
(execute)="remove(hook)"
/>
<button
type="button"
class="ts-btn ts-btn--secondary"
(click)="test(hook)"
>
Probar
</button>
<button
type="button"
class="ts-btn ts-btn--ghost"
(click)="toggle(hook)"
>
{{ hook.active ? 'Pausar' : 'Reanudar' }}
</button>
<button
type="button"
class="ts-btn ts-btn--ghost"
(click)="remove(hook)"
>
Borrar
</button>
</div>
</article>
}
@@ -133,13 +134,14 @@ const EVENT_LABEL: Record<string, string> = {
}
</fieldset>
<div>
<pi-action-button
size="small"
color="primary"
text="Añadir webhook"
<button
type="button"
class="ts-btn ts-btn--primary"
[disabled]="!url().trim() || !picked().length"
(execute)="create()"
/>
(click)="create()"
>
Añadir webhook
</button>
</div>
</form>
</section>