TenantAtlas/specs/141-shared-diff-presentation-foundation/quickstart.md
ahmido 0b5cadc234 feat: add shared diff presentation foundation (#170)
## Summary
- add a shared diff presentation layer under `app/Support/Diff` with deterministic row classification, summary derivation, and value stringification
- centralize diff-state badge semantics through `BadgeCatalog` with a dedicated `DiffRowStatusBadge`
- add reusable Filament diff partials, focused Pest coverage, and the full SpecKit artifact set for spec 141

## Testing
- `vendor/bin/sail artisan test --compact tests/Unit/Support/Diff/DiffRowStatusTest.php tests/Unit/Support/Diff/DiffRowTest.php tests/Unit/Support/Diff/DiffPresenterTest.php tests/Unit/Support/Diff/ValueStringifierTest.php tests/Unit/Badges/DiffRowStatusBadgeTest.php tests/Feature/Support/Diff/SharedDiffSummaryPartialTest.php tests/Feature/Support/Diff/SharedDiffRowPartialTest.php tests/Feature/Support/Diff/SharedInlineListDiffPartialTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`

## Filament / Livewire Contract
- Livewire v4.0+ compliance: unchanged and respected; this feature adds presentation support only within the existing Filament v5 / Livewire v4 stack
- Provider registration: unchanged; no panel/provider changes were required, so `bootstrap/providers.php` remains the correct registration location
- Global search: unchanged; no Resource or global-search behavior was added or modified
- Destructive actions: none introduced in this feature
- Asset strategy: no new registered Filament assets; shared Blade partials rely on the existing asset pipeline and standard deploy step for `php artisan filament:assets` when assets change generally
- Testing coverage: presenter, DTOs, stringifier, badge semantics, summary partial, row partial, and inline-list partial are covered by focused Pest unit and feature tests

## Notes
- Spec checklist status is complete for `specs/141-shared-diff-presentation-foundation/checklists/requirements.md`
- This PR preserves specialized diff renderers and documents incremental adoption rather than forcing migration in the same change

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #170
2026-03-14 12:32:08 +00:00

2.6 KiB

Quickstart: Shared Diff Presentation Foundation

Purpose

Use this foundation when a screen already has simple structured compare data and needs consistent change-state semantics, summary badges, row rendering, inline list add/remove display, and shared value formatting.

Do not use it to replace specialized normalized diff, script diff, or other advanced compare experiences that need domain-specific layout or token/line-level logic.

Prerequisites

  • The consuming surface already has authorized baseline/current compare data.
  • The values can be represented as simple keyed fields or simple lists.
  • The consumer does not need a new route, new persistence model, or new compare engine.

Basic adoption flow

  1. Build or adapt a simple compare input:
    • Baseline associative values
    • Current associative values
    • Optional changed keys
    • Optional label map
  2. Pass that input into DiffPresenter.
  3. Render the returned summary with the shared summary partial.
  4. Loop over the returned rows and render each row through the shared row partial.
  5. If a row is list-like, let the row partial delegate to the inline list diff partial.

Example adoption pattern

Presenter usage

$presentation = app(DiffPresenter::class)->present(
    baseline: $baseline,
    current: $current,
    changedKeys: $changedKeys,
    labels: $labels,
);

Blade usage

@include('filament.partials.diff.summary-badges', ['summary' => $presentation->summary])

@foreach ($presentation->rows as $row)
    @include('filament.partials.diff.row', [
        'row' => $row,
        'compact' => false,
        'dimUnchanged' => true,
    ])
@endforeach

Standalone stringifier usage

If a specialized view should not use DiffPresenter, it can still reuse ValueStringifier to standardize how nulls, booleans, scalars, simple lists, and compact structured values appear.

When not to use the foundation

  • The screen requires line-level or token-level script diff behavior.
  • The screen needs heavily specialized comparison layout that would become less clear if flattened into generic rows.
  • The screen would need new domain comparison rules rather than presentation reuse.

Testing expectations

  • Add Pest unit tests for any new presenter or stringifier behavior.
  • Add view-level tests for shared partial usage and state-specific rendering.
  • If a consumer adds a new diff-state badge domain mapping, cover it with badge tests.
  • Keep docs/ui/shared-diff-presentation-foundation.md aligned with the same presenter and partial names when adoption guidance changes.