Files
reactbin/specs/016-copy-url-toast/contracts/toast-service.md
agatha 7d49c12ce2 Feat: Add Copy URL button and reusable toast notification system
Detail page now has a "Copy URL" button that copies the image's direct
file URL to the clipboard. A toast service (BehaviorSubject-backed,
auto-dismissing after 3s) confirms success or failure. ToastComponent
is registered at the app root and available to all future features.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 22:21:48 +00:00

51 lines
1.3 KiB
Markdown

# Contract: ToastService
**Location**: `ui/src/app/services/toast.service.ts`
**Provided in**: `root` (singleton)
## Interface
```typescript
interface Toast {
message: string;
type: 'success' | 'error';
}
class ToastService {
// Observable — emits a Toast when one is active, null when none.
readonly current$: Observable<Toast | null>;
// Show a toast. Replaces any currently-visible toast.
// duration defaults to 3000ms.
show(message: string, type?: 'success' | 'error', duration?: number): void;
}
```
## Behaviour
- `show()` emits the toast immediately on `current$`.
- After `duration` ms, emits `null` to dismiss.
- Calling `show()` again before the timer expires resets the timer (new toast replaces old).
- `type` defaults to `'success'`.
- `duration` defaults to `3000`.
## Usage Example
```typescript
// In any component:
constructor(private toast: ToastService) {}
async copyUrl() {
try {
await navigator.clipboard.writeText(url);
this.toast.show('URL copied!');
} catch {
this.toast.show('Failed to copy URL', 'error');
}
}
```
## Consumer: ToastComponent
`ToastComponent` subscribes to `current$` via the `async` pipe and renders/hides based on the emitted value. It is placed once in `AppComponent` and is always present in the DOM.