Agent code and restructuring
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# Cooldown Button Component
|
||||
|
||||
A square Blazor button with a 12-second cooldown animation: when clicked, the button greys out and a circular transparency wedge dials open clockwise, progressively revealing the normal button state underneath.
|
||||
|
||||
---
|
||||
|
||||
## Visual Design
|
||||
|
||||
The button has two visual states:
|
||||
|
||||
**Idle state** – A solid square button with the project's standard `--paper` background and `--primary` border. Hover inverts or brightens the paper. Click triggers a brief scale-down.
|
||||
|
||||
**Cooldown state** – The native button fades to `opacity: 0` while an absolutely-positioned overlay covers it. The overlay uses a `conic-gradient` CSS mask to create a "dialling open" effect. A number in the centre shows the remaining seconds.
|
||||
|
||||
---
|
||||
|
||||
## Core Technique: Conic-Gradient Mask
|
||||
|
||||
The cooldown reveal is accomplished with a **conic-gradient mask** applied to the overlay `<div>`:
|
||||
|
||||
```
|
||||
mask-image: conic-gradient(
|
||||
transparent 0deg,
|
||||
transparent {angle}deg,
|
||||
#000 {angle}deg,
|
||||
#000 360deg
|
||||
);
|
||||
```
|
||||
|
||||
- **`transparent`** – lets the button underneath show through (revealed area)
|
||||
- **`#000` (black)** – fully masks the overlay, making it visible (greyed-out area)
|
||||
|
||||
At `angle = 0deg`, transparent covers nothing and the mask is entirely black → the overlay is fully opaque (button completely greyed out).
|
||||
|
||||
At `angle = 360deg`, transparent covers the full circle and black covers nothing → the overlay is fully transparent (button completely visible).
|
||||
|
||||
The angle animates linearly from 0 to 360 over the cooldown duration. Because `conic-gradient` starts at the 12 o'clock position and sweeps clockwise, the reveal begins at the top of the button and rotates around, like a clock hand or a dial opening.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Architecture
|
||||
|
||||
### Component Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|------------------|-------------------|---------|------------------------------------|
|
||||
| `ChildContent` | `RenderFragment` | `null` | Text or content inside the button |
|
||||
| `OnClick` | `EventCallback` | — | Fired when the button is clicked |
|
||||
| `CooldownSeconds`| `int` | `12` | Duration of the cooldown in seconds|
|
||||
| `Size` | `int` | `120` | Width and height in pixels (square)|
|
||||
|
||||
### Timer Loop
|
||||
|
||||
A `System.Timers.Timer` fires every ~33 ms (≈30 fps) during the cooldown:
|
||||
|
||||
```
|
||||
OnTick:
|
||||
elapsed = UtcNow - startTime
|
||||
if elapsed >= CooldownSeconds → end cooldown, dispose timer
|
||||
_elapsedAngle = (elapsed / CooldownSeconds) * 360
|
||||
_remainingSeconds = CooldownSeconds - (int)elapsed
|
||||
InvokeAsync(StateHasChanged)
|
||||
```
|
||||
|
||||
On each tick, `_elapsedAngle` is written into the overlay's inline `style` attribute, causing Blazor to re-render the `mask-image`. The timer is disposed in `Dispose()` to prevent leaks.
|
||||
|
||||
### Disposal
|
||||
|
||||
The component implements `IDisposable` to clean up the timer when the component is removed from the render tree. This follows the same pattern used by `SearchDialogComponent` and `BuildChartComponent` elsewhere in the codebase.
|
||||
|
||||
---
|
||||
|
||||
## CSS Masking Details
|
||||
|
||||
Two vendor-prefixed properties are set to ensure cross-browser support:
|
||||
|
||||
```
|
||||
mask-image: conic-gradient(...);
|
||||
-webkit-mask-image: conic-gradient(...);
|
||||
```
|
||||
|
||||
The overlay uses `pointer-events: none` and `user-select: none` so that interaction passes through to the button underneath (which is disabled and transparent).
|
||||
|
||||
An `rgba(22, 22, 24, 0.82)` semi-transparent background on the overlay produces the greyed-out appearance. The mask controls *where* this background is visible.
|
||||
|
||||
---
|
||||
|
||||
## Usage on the Home Page
|
||||
|
||||
The component is added to `Pages/Pages/Home/HomePage.razor` inside the first `PaperComponent`:
|
||||
|
||||
```razor
|
||||
<CooldownButtonComponent CooldownSeconds="12"
|
||||
Size="120"
|
||||
OnClick="OnCooldownClick">
|
||||
Click Me
|
||||
</CooldownButtonComponent>
|
||||
```
|
||||
|
||||
The `OnCooldownClick` handler in the page's `@code` block currently returns `Task.CompletedTask` (a no-op). This is the extension point where real work (e.g. triggering a game action, calling an API, showing a toast) would go.
|
||||
|
||||
---
|
||||
|
||||
## Adapting the Component
|
||||
|
||||
- **Change cooldown duration** – set `CooldownSeconds` to any positive integer.
|
||||
- **Change button size** – set `Size` to any pixel dimension (button remains square).
|
||||
- **Custom content** – pass any Blazor markup as `ChildContent` (text, icons, spinners).
|
||||
- **Handle the click** – attach a handler to `OnClick` that returns `Task` or `void`.
|
||||
|
||||
The `--cooldown-size` CSS custom property is set inline on the wrapper so that the label, overlay, and button all scale together.
|
||||
Reference in New Issue
Block a user