fix: NCWF-2 bugs and desing fixes (#7)
Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Reviewed-on: #7
This commit was merged in pull request #7.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
.moves {
|
||||
display: grid;
|
||||
grid-template-columns: 38px 1fr 1fr;
|
||||
font-family: var(--nc-mono);
|
||||
font-size: 12px;
|
||||
max-height: 260px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.moves-empty {
|
||||
grid-column: 1 / -1;
|
||||
padding: 16px;
|
||||
color: var(--nc-text-dim);
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mv-num {
|
||||
padding: 6px 12px 6px 10px;
|
||||
color: var(--nc-text-dim);
|
||||
text-align: right;
|
||||
border-right: 1px solid var(--nc-border);
|
||||
}
|
||||
|
||||
.mv {
|
||||
padding: 6px 10px;
|
||||
color: var(--nc-text);
|
||||
cursor: pointer;
|
||||
transition: background 0.1s, color 0.1s;
|
||||
}
|
||||
|
||||
.mv:hover {
|
||||
background: rgba(255, 69, 200, 0.06);
|
||||
color: var(--nc-neon);
|
||||
}
|
||||
|
||||
.mv.current {
|
||||
background: rgba(255, 69, 200, 0.10);
|
||||
color: var(--nc-neon);
|
||||
}
|
||||
|
||||
.mv.mv-empty {
|
||||
color: var(--nc-text-dim);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.mv.mv-empty:hover {
|
||||
background: transparent;
|
||||
color: var(--nc-text-dim);
|
||||
}
|
||||
|
||||
.moves-foot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
border-top: 1px solid var(--nc-border);
|
||||
}
|
||||
|
||||
.moves-nav {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: var(--nc-text-muted);
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s, border-color 0.15s;
|
||||
}
|
||||
|
||||
.icon-btn:hover {
|
||||
color: var(--nc-neon);
|
||||
border-color: var(--nc-border);
|
||||
}
|
||||
|
||||
.live-label {
|
||||
font-family: var(--nc-mono);
|
||||
font-size: 10px;
|
||||
color: var(--nc-neon);
|
||||
letter-spacing: 0.14em;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.moves::-webkit-scrollbar { width: 6px; }
|
||||
.moves::-webkit-scrollbar-track { background: transparent; }
|
||||
.moves::-webkit-scrollbar-thumb { background: var(--nc-border-strong); border-radius: 3px; }
|
||||
.moves::-webkit-scrollbar-thumb:hover { background: var(--nc-neon-soft); }
|
||||
@@ -0,0 +1,43 @@
|
||||
<div class="moves" role="list">
|
||||
@if (movePairs.length === 0) {
|
||||
<div class="moves-empty">No moves yet.</div>
|
||||
} @else {
|
||||
@for (pair of movePairs; track $index) {
|
||||
<div class="mv-num" role="presentation">{{ $index + 1 }}</div>
|
||||
<div class="mv" [class.current]="currentWhiteIndex === $index" role="listitem">
|
||||
{{ pair.white }}
|
||||
</div>
|
||||
<div class="mv" [class.current]="currentBlackIndex === $index" [class.mv-empty]="!pair.black" role="listitem">
|
||||
{{ pair.black ?? '…' }}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="moves-foot">
|
||||
<div class="moves-nav" role="group" aria-label="Move navigation">
|
||||
<button class="icon-btn" title="First move" (click)="navigate.emit('first')">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="11 17 6 12 11 7"/><polyline points="18 17 13 12 18 7"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="icon-btn" title="Previous move" (click)="navigate.emit('prev')">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="15 18 9 12 15 6"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="icon-btn" title="Next move" (click)="navigate.emit('next')">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="9 18 15 12 9 6"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="icon-btn" title="Last move" (click)="navigate.emit('last')">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="13 17 18 12 13 7"/><polyline points="6 17 11 12 6 7"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@if (plyCount > 0) {
|
||||
<span class="live-label">LIVE</span>
|
||||
}
|
||||
</div>
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||
|
||||
export type MoveNavDirection = 'first' | 'prev' | 'next' | 'last';
|
||||
|
||||
interface MovePair {
|
||||
white: string;
|
||||
black: string | null;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-move-history',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
templateUrl: './move-history.component.html',
|
||||
styleUrl: './move-history.component.css'
|
||||
})
|
||||
export class MoveHistoryComponent implements OnChanges {
|
||||
@Input({ required: true }) moves: string[] = [];
|
||||
@Output() navigate = new EventEmitter<MoveNavDirection>();
|
||||
|
||||
movePairs: MovePair[] = [];
|
||||
|
||||
get plyCount(): number {
|
||||
return this.moves.length;
|
||||
}
|
||||
|
||||
get currentWhiteIndex(): number {
|
||||
const lastPairIndex = this.movePairs.length - 1;
|
||||
if (lastPairIndex < 0) return -1;
|
||||
const lastMove = this.moves.length - 1;
|
||||
return lastMove % 2 === 0 ? lastPairIndex : -1;
|
||||
}
|
||||
|
||||
get currentBlackIndex(): number {
|
||||
const lastPairIndex = this.movePairs.length - 1;
|
||||
if (lastPairIndex < 0) return -1;
|
||||
const lastMove = this.moves.length - 1;
|
||||
return lastMove % 2 === 1 ? lastPairIndex : -1;
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.movePairs = this.buildPairs(this.moves);
|
||||
}
|
||||
|
||||
private buildPairs(moves: string[]): MovePair[] {
|
||||
const pairs: MovePair[] = [];
|
||||
for (let i = 0; i < moves.length; i += 2) {
|
||||
pairs.push({ white: moves[i], black: moves[i + 1] ?? null });
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user