Add heart shape and document kind 0 shape extension in NIP.md
- Add 'heart' as the 8th avatar shape using SVG path() clip-path with cubic beziers - Document the kind 0 'shape' metadata extension in NIP.md with all 8 defined values, client behavior rules, and forward-compatibility guidance
This commit is contained in:
@@ -251,3 +251,47 @@ After resolution (assuming `$follows` = `["pk1", "pk2"]`):
|
||||
- To **clear** all tabs: publish a kind 16769 event with no `tab` tags (only `alt`).
|
||||
- Clients MUST filter by `authors: [pubkey]` when querying to prevent spoofing.
|
||||
- `var` tags are shared across all `tab` tags in the same event.
|
||||
|
||||
---
|
||||
|
||||
## Kind 0 Extension: Avatar Shape
|
||||
|
||||
### Summary
|
||||
|
||||
An optional `shape` property on kind 0 (profile metadata) that controls how the user's avatar is masked/clipped when displayed. Clients that support this extension render the avatar using the specified geometric shape instead of the default circle.
|
||||
|
||||
### Metadata Field
|
||||
|
||||
The `shape` field is added to the JSON content of a kind 0 event alongside standard fields like `name`, `picture`, etc.
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": 0,
|
||||
"content": "{\"name\":\"Alice\",\"picture\":\"https://example.com/alice.jpg\",\"shape\":\"hexagon\"}"
|
||||
}
|
||||
```
|
||||
|
||||
### Defined Shape Values
|
||||
|
||||
| Value | Description |
|
||||
|----------------------|----------------------------------------------------------------|
|
||||
| `circle` | Standard circular avatar (the default when `shape` is absent) |
|
||||
| `triangle` | Equilateral triangle pointing up |
|
||||
| `inverted-triangle` | Equilateral triangle pointing down |
|
||||
| `hexagon` | Regular hexagon (6-sided polygon) |
|
||||
| `star` | 5-pointed star |
|
||||
| `inverted-star` | 5-pointed star pointing down |
|
||||
| `hexagram` | 6-pointed star (Star of David) |
|
||||
| `heart` | Heart shape with curved lobes |
|
||||
|
||||
### Client Behavior
|
||||
|
||||
- When `shape` is absent or set to `"circle"`, clients SHOULD render the avatar as a circle (the current universal default).
|
||||
- When `shape` is set to a recognized value, clients SHOULD apply the corresponding geometric mask (e.g. via CSS `clip-path`) to the avatar image and fallback.
|
||||
- When `shape` is set to an **unrecognized** value, clients MUST fall back to `"circle"`. This ensures forward compatibility as new shapes are added.
|
||||
- The `shape` field is purely cosmetic and has no protocol-level significance.
|
||||
- Clients MAY choose not to support this extension, in which case avatars render as circles as usual.
|
||||
|
||||
### Implementation Notes
|
||||
|
||||
Non-circle shapes are best implemented using CSS `clip-path` with `polygon()` for straight-edged shapes and `path()` for curved shapes (e.g. heart). The `circle` shape should continue to use `border-radius: 50%` (or equivalent) for simplicity and compatibility.
|
||||
|
||||
@@ -7,6 +7,7 @@ export const AVATAR_SHAPES = [
|
||||
'star',
|
||||
'inverted-star',
|
||||
'hexagram',
|
||||
'heart',
|
||||
] as const;
|
||||
|
||||
export type AvatarShape = (typeof AVATAR_SHAPES)[number];
|
||||
@@ -28,6 +29,7 @@ export function getAvatarShapeLabel(shape: AvatarShape): string {
|
||||
case 'star': return 'Star';
|
||||
case 'inverted-star': return 'Inv. Star';
|
||||
case 'hexagram': return 'Hexagram';
|
||||
case 'heart': return 'Heart';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,5 +97,9 @@ export function getAvatarClipPath(shape: AvatarShape | undefined): string | unde
|
||||
|
||||
case 'hexagram':
|
||||
return starPolygon(6, 0.577, -90);
|
||||
|
||||
case 'heart':
|
||||
// SVG path normalized to a 1×1 viewBox. Uses cubic beziers for the curved lobes.
|
||||
return 'path("M0.5 0.92 C0.28 0.75, 0 0.56, 0 0.34 C0 0.16, 0.13 0.04, 0.28 0.04 C0.37 0.04, 0.45 0.09, 0.5 0.17 C0.55 0.09, 0.63 0.04, 0.72 0.04 C0.87 0.04, 1 0.16, 1 0.34 C1 0.56, 0.72 0.75, 0.5 0.92 Z")';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user