feat: docs.pivoine.art
This commit is contained in:
@@ -48,15 +48,17 @@ import { PivoineDocsIcon } from '@/components/icons'
|
||||
#### Animations
|
||||
|
||||
**Default State:**
|
||||
- Flower starts **closed** as a tight bud (petals 30-50% size)
|
||||
- Subtle pulsing background
|
||||
- Twinkling sparkles (2s cycle)
|
||||
- Orbiting particles (8s cycle)
|
||||
- Gentle page floating
|
||||
- Text lines appear on mount
|
||||
|
||||
**On Hover:**
|
||||
**On Hover (Blooming!):**
|
||||
- Icon scales and lifts
|
||||
- Petals bloom in sequence (outer → middle → inner)
|
||||
- Petals **bloom open** to full size (smooth 0.8s transition)
|
||||
- Bloom sequence: outer → middle → inner (staggered)
|
||||
- Center glows intensely
|
||||
- Sparkles burst
|
||||
- Pages fan out with rotation
|
||||
|
||||
252
Projects/docs.pivoine.art/components/icons/BLOOM_UPDATE.md
Normal file
252
Projects/docs.pivoine.art/components/icons/BLOOM_UPDATE.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# 🌸 Pivoine Docs Icon - Closed/Open States Update
|
||||
|
||||
## ✨ New Behavior: Closed → Open on Hover
|
||||
|
||||
The Pivoine Docs Icon now features a beautiful **blooming animation**!
|
||||
|
||||
### Initial State: CLOSED 🌷
|
||||
- Petals start **small and close to the center**
|
||||
- Outer petals: 30% size, 50% opacity
|
||||
- Middle petals: 40% size, 60% opacity
|
||||
- Inner petals: 50% size, 70% opacity
|
||||
- Flower appears as a **tight bud**
|
||||
|
||||
### Hover State: OPEN 🌸
|
||||
- Petals **bloom outward** to full size
|
||||
- Smooth 0.8s cubic-bezier transition
|
||||
- Staggered timing for natural bloom:
|
||||
- Outer petals bloom first
|
||||
- Middle petals follow (0.05s delay)
|
||||
- Inner petals last (0.1s delay)
|
||||
- All petals reach 100% size and full opacity
|
||||
- Enhanced glow effects activate
|
||||
|
||||
### Visual Effect
|
||||
```
|
||||
Closed (default): Hover (blooming): Click (burst):
|
||||
🌷 → 🌸 → ✨
|
||||
(bud) (full bloom) (explosion)
|
||||
```
|
||||
|
||||
## 🎯 States Comparison
|
||||
|
||||
| State | Outer Petals | Middle Petals | Inner Petals | Effect |
|
||||
|-------|-------------|---------------|--------------|--------|
|
||||
| **Closed (default)** | 30% scale | 40% scale | 50% scale | Tight bud |
|
||||
| **Non-interactive** | 85% scale | 88% scale | 90% scale | Slightly open |
|
||||
| **Hover (bloom)** | 100% scale | 100% scale | 100% scale | Full bloom |
|
||||
| **Click (burst)** | 130% scale | 130% scale | 130% scale | Explosion |
|
||||
|
||||
## 🎨 Animation Details
|
||||
|
||||
### Timing
|
||||
- **Transition duration**: 0.8s
|
||||
- **Easing**: cubic-bezier(0.34, 1.56, 0.64, 1) - bouncy bloom
|
||||
- **Stagger delays**: 0s → 0.05s → 0.1s (outer to inner)
|
||||
|
||||
### Visual Changes
|
||||
**Closed State:**
|
||||
- Petals scaled down and condensed
|
||||
- Reduced opacity for depth
|
||||
- Documents still visible in center
|
||||
- Sparkles still twinkling
|
||||
- Subtle animations continue
|
||||
|
||||
**Open State (Hover):**
|
||||
- Petals expand to natural size
|
||||
- Full opacity and glow
|
||||
- Enhanced shadow effects
|
||||
- Center glows brightly
|
||||
- All animations intensify
|
||||
|
||||
## 💡 Why This Works
|
||||
|
||||
1. **Metaphor**: Represents knowledge "blooming" as you explore
|
||||
2. **Engagement**: Invites interaction through visual curiosity
|
||||
3. **Delight**: Satisfying transformation surprises users
|
||||
4. **Natural**: Mimics real flower behavior
|
||||
5. **Smooth**: Staggered timing feels organic
|
||||
|
||||
## 📝 Code Changes
|
||||
|
||||
### Before (Always Open)
|
||||
```css
|
||||
.petal {
|
||||
transform: scale(1);
|
||||
opacity: 0.85;
|
||||
}
|
||||
```
|
||||
|
||||
### After (Closed → Open)
|
||||
```css
|
||||
/* Closed by default */
|
||||
.outer-petal {
|
||||
transform: scale(0.3);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Open on hover */
|
||||
.is-interactive:hover .outer-petal {
|
||||
transform: scale(1);
|
||||
opacity: 0.85;
|
||||
}
|
||||
```
|
||||
|
||||
## 🎭 Usage Notes
|
||||
|
||||
### Interactive Mode (Default)
|
||||
- Starts **closed** (tight bud)
|
||||
- **Opens on hover** (full bloom)
|
||||
- Click for burst effect
|
||||
- Returns to closed on mouse leave
|
||||
|
||||
### Non-Interactive Mode
|
||||
- Starts **slightly open** (85-90% size)
|
||||
- Static, no hover effects
|
||||
- Better for cards/lists where you want visibility
|
||||
- Still shows the beautiful design
|
||||
|
||||
### Example Usage
|
||||
```tsx
|
||||
// Interactive - starts closed, blooms on hover
|
||||
<PivoineDocsIcon size="200px" />
|
||||
|
||||
// Non-interactive - slightly open, static
|
||||
<PivoineDocsIcon size="64px" interactive={false} />
|
||||
```
|
||||
|
||||
## ✨ Benefits
|
||||
|
||||
✅ **More engaging** - Invites user interaction
|
||||
✅ **Metaphorical** - "Knowledge blooms" as you explore
|
||||
✅ **Delightful** - Surprising transformation creates joy
|
||||
✅ **Natural** - Follows real flower blooming behavior
|
||||
✅ **Smooth** - Staggered animation feels organic
|
||||
✅ **Accessible** - Reduced motion users see semi-open state
|
||||
|
||||
## 🎬 Animation Timeline
|
||||
|
||||
```
|
||||
Time Event
|
||||
────────────────────────────────────
|
||||
0.0s Mouse enters → bloom starts
|
||||
0.0s Outer petals begin expanding
|
||||
0.05s Middle petals begin expanding
|
||||
0.1s Inner petals begin expanding
|
||||
0.8s All petals fully bloomed
|
||||
(continuous hover animations)
|
||||
──── Mouse leaves → petals close
|
||||
0.8s Back to closed bud state
|
||||
```
|
||||
|
||||
## 🎨 Visual States
|
||||
|
||||
### 1. Initial Load (Closed)
|
||||
```
|
||||
•
|
||||
• • •
|
||||
• 🗎 •
|
||||
• • •
|
||||
•
|
||||
(bud)
|
||||
```
|
||||
|
||||
### 2. Hover Start (Blooming)
|
||||
```
|
||||
• •
|
||||
• • •
|
||||
• 🗎 •
|
||||
• • •
|
||||
• •
|
||||
(opening)
|
||||
```
|
||||
|
||||
### 3. Fully Bloomed
|
||||
```
|
||||
• • •
|
||||
• • •
|
||||
• 🗎 •
|
||||
• • •
|
||||
• • •
|
||||
(bloom!)
|
||||
```
|
||||
|
||||
### 4. Click (Burst)
|
||||
```
|
||||
• • •
|
||||
• • •
|
||||
• ✨🗎✨ •
|
||||
• • •
|
||||
• • •
|
||||
(explode!)
|
||||
```
|
||||
|
||||
## 🔧 Customization
|
||||
|
||||
Want to adjust the closed/open states?
|
||||
|
||||
### Change Initial Size (Closed State)
|
||||
```css
|
||||
.outer-petal {
|
||||
transform: scale(0.3); /* 0 = fully closed, 1 = fully open */
|
||||
}
|
||||
```
|
||||
|
||||
### Adjust Bloom Speed
|
||||
```css
|
||||
.outer-petal {
|
||||
transition: all 0.8s; /* Make faster: 0.4s, slower: 1.2s */
|
||||
}
|
||||
```
|
||||
|
||||
### Modify Stagger Timing
|
||||
```css
|
||||
.outer-petal { transition-delay: 0s; }
|
||||
.middle-petal { transition-delay: 0.05s; } /* Adjust these */
|
||||
.inner-petal { transition-delay: 0.1s; }
|
||||
```
|
||||
|
||||
## 📱 Responsive Behavior
|
||||
|
||||
### Desktop
|
||||
- Full bloom animation on hover
|
||||
- Smooth 0.8s transition
|
||||
- Staggered petal opening
|
||||
|
||||
### Mobile/Touch
|
||||
- Tap to trigger bloom
|
||||
- Automatic return to closed after interaction
|
||||
- Optimized touch targets
|
||||
|
||||
### Reduced Motion
|
||||
- Shows in semi-open state (85-90%)
|
||||
- No animations
|
||||
- Static display
|
||||
- Still beautiful and clear
|
||||
|
||||
## 🎯 Perfect For
|
||||
|
||||
✅ Hero sections - dramatic entrance effect
|
||||
✅ Landing pages - engaging first impression
|
||||
✅ About pages - tells a story
|
||||
✅ Portfolio sites - shows attention to detail
|
||||
✅ Documentation hubs - "knowledge blooming"
|
||||
|
||||
## 🚀 See It In Action
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Visit http://localhost:3000 and:
|
||||
1. **See the closed bud** on page load
|
||||
2. **Hover over icon** to watch it bloom open
|
||||
3. **Move mouse away** to see it close again
|
||||
4. **Click** for burst effect
|
||||
5. **Enjoy** the smooth, natural animation!
|
||||
|
||||
---
|
||||
|
||||
**Updated for Valknar** | [pivoine.art](http://pivoine.art)
|
||||
|
||||
*From bud to bloom - knowledge opens up* 🌷→🌸
|
||||
333
Projects/docs.pivoine.art/components/icons/KomposeIcon.css
Normal file
333
Projects/docs.pivoine.art/components/icons/KomposeIcon.css
Normal file
@@ -0,0 +1,333 @@
|
||||
/* Kompose Icon Styles */
|
||||
|
||||
.kompose-icon-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper:not(.is-interactive) {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.kompose-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
filter: drop-shadow(0 4px 20px rgba(0, 220, 130, 0.2));
|
||||
transition: filter 0.4s ease;
|
||||
}
|
||||
|
||||
/* Hover Effects */
|
||||
.kompose-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.05) translateY(-2px);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .kompose-icon {
|
||||
filter: drop-shadow(0 8px 30px rgba(0, 220, 130, 0.4));
|
||||
animation: subtle-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .bg-rect {
|
||||
animation: bg-glow 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-letter {
|
||||
animation: letter-glow 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-vertical {
|
||||
animation: line-slide-vertical 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-diagonal-top {
|
||||
animation: line-slide-diagonal-top 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-diagonal-bottom {
|
||||
animation: line-slide-diagonal-bottom 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .status-dot {
|
||||
animation: pulse-expand 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .status-ring {
|
||||
animation: ring-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .corner {
|
||||
opacity: 1 !important;
|
||||
animation: corner-extend 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
/* Click/Active Effects */
|
||||
.kompose-icon-wrapper.is-clicked {
|
||||
animation: click-bounce 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-clicked .kompose-icon {
|
||||
animation: rotate-3d 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
filter: drop-shadow(0 12px 40px rgba(0, 220, 130, 0.6));
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-clicked .k-letter {
|
||||
animation: letter-flash 0.6s ease-out;
|
||||
filter: url(#intenseglow192);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-clicked .status-dot {
|
||||
animation: dot-burst 0.6s ease-out;
|
||||
}
|
||||
|
||||
/* Ripple Effect */
|
||||
.ripple {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(0, 220, 130, 0.6) 0%,
|
||||
rgba(0, 220, 130, 0) 70%
|
||||
);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
animation: ripple-expand 0.8s ease-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Default animations for status dot */
|
||||
.status-dot {
|
||||
animation: default-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.status-ring {
|
||||
animation: default-ring-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Keyframe Animations */
|
||||
@keyframes subtle-pulse {
|
||||
0%,
|
||||
100% {
|
||||
filter: drop-shadow(0 8px 30px rgba(0, 220, 130, 0.4));
|
||||
}
|
||||
50% {
|
||||
filter: drop-shadow(0 8px 35px rgba(0, 220, 130, 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bg-glow {
|
||||
0%,
|
||||
100% {
|
||||
filter: brightness(1);
|
||||
}
|
||||
50% {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes letter-glow {
|
||||
0%,
|
||||
100% {
|
||||
filter: url(#glow192);
|
||||
}
|
||||
50% {
|
||||
filter: url(#intenseglow192);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-slide-vertical {
|
||||
0% {
|
||||
stroke-dasharray: 96;
|
||||
stroke-dashoffset: 96;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 96;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-slide-diagonal-top {
|
||||
0% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 68;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-slide-diagonal-bottom {
|
||||
0% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 68;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse-expand {
|
||||
0%,
|
||||
100% {
|
||||
r: 11.52;
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
r: 14;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ring-pulse {
|
||||
0%,
|
||||
100% {
|
||||
r: 17.28;
|
||||
opacity: 0.3;
|
||||
stroke-width: 3;
|
||||
}
|
||||
50% {
|
||||
r: 20;
|
||||
opacity: 0.6;
|
||||
stroke-width: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes corner-extend {
|
||||
0% {
|
||||
stroke-dasharray: 13.44;
|
||||
stroke-dashoffset: 13.44;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 13.44;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes click-bounce {
|
||||
0% {
|
||||
transform: scale(1) translateY(0) rotateY(0deg);
|
||||
}
|
||||
30% {
|
||||
transform: scale(0.92) translateY(0) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.08) translateY(-4px) rotateY(180deg);
|
||||
}
|
||||
70% {
|
||||
transform: scale(0.98) translateY(0) rotateY(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1) translateY(0) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate-3d {
|
||||
0% {
|
||||
transform: perspective(800px) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: perspective(800px) rotateY(180deg);
|
||||
}
|
||||
100% {
|
||||
transform: perspective(800px) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes letter-flash {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
20%,
|
||||
60% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
40%,
|
||||
80% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dot-burst {
|
||||
0% {
|
||||
r: 11.52;
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
r: 20;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
r: 11.52;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple-expand {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(2.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes default-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
r: 11.52;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
r: 13.44;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes default-ring-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.3;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.kompose-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.03) translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.kompose-icon-wrapper,
|
||||
.kompose-icon,
|
||||
.kompose-icon *,
|
||||
.ripple {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch device optimizations */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.kompose-icon-wrapper.is-interactive:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import './KomposeIcon.css'
|
||||
|
||||
interface KomposeIconProps {
|
||||
size?: string
|
||||
@@ -36,9 +37,16 @@ export default function KomposeIcon({
|
||||
handleClick()
|
||||
}
|
||||
|
||||
const wrapperClasses = [
|
||||
'kompose-icon-wrapper',
|
||||
isClicked && 'is-clicked',
|
||||
interactive && 'is-interactive',
|
||||
className
|
||||
].filter(Boolean).join(' ')
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`kompose-icon-wrapper ${isClicked ? 'is-clicked' : ''} ${interactive ? 'is-interactive' : ''} ${className}`}
|
||||
className={wrapperClasses}
|
||||
onClick={handleClick}
|
||||
onTouchStart={handleTouch}
|
||||
style={{ width: size, height: size }}
|
||||
@@ -106,329 +114,6 @@ export default function KomposeIcon({
|
||||
|
||||
{/* Ripple effect container */}
|
||||
{showRipple && <div className="ripple"></div>}
|
||||
|
||||
<style jsx>{`
|
||||
.kompose-icon-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper:not(.is-interactive) {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.kompose-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
filter: drop-shadow(0 4px 20px rgba(0, 220, 130, 0.2));
|
||||
transition: filter 0.4s ease;
|
||||
}
|
||||
|
||||
/* Hover Effects */
|
||||
.kompose-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.05) translateY(-2px);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .kompose-icon {
|
||||
filter: drop-shadow(0 8px 30px rgba(0, 220, 130, 0.4));
|
||||
animation: subtle-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .bg-rect {
|
||||
fill: url(#bgGrad192);
|
||||
opacity: 1;
|
||||
animation: bg-glow 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-letter {
|
||||
animation: letter-glow 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-vertical {
|
||||
animation: line-slide-vertical 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-diagonal-top {
|
||||
animation: line-slide-diagonal-top 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .k-diagonal-bottom {
|
||||
animation: line-slide-diagonal-bottom 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .status-dot {
|
||||
animation: pulse-expand 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .status-ring {
|
||||
animation: ring-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover .corner {
|
||||
opacity: 1 !important;
|
||||
stroke: #00DC82;
|
||||
animation: corner-extend 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
/* Click/Active Effects */
|
||||
.kompose-icon-wrapper.is-clicked {
|
||||
animation: click-bounce 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-clicked .kompose-icon {
|
||||
animation: rotate-3d 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
filter: drop-shadow(0 12px 40px rgba(0, 220, 130, 0.6));
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-clicked .k-letter {
|
||||
animation: letter-flash 0.6s ease-out;
|
||||
filter: url(#intenseglow192);
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-clicked .status-dot {
|
||||
animation: dot-burst 0.6s ease-out;
|
||||
}
|
||||
|
||||
/* Ripple Effect */
|
||||
.ripple {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(0, 220, 130, 0.6) 0%, rgba(0, 220, 130, 0) 70%);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
animation: ripple-expand 0.8s ease-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Default animations for status dot */
|
||||
.status-dot {
|
||||
animation: default-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.status-ring {
|
||||
animation: default-ring-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Keyframe Animations */
|
||||
@keyframes subtle-pulse {
|
||||
0%, 100% {
|
||||
filter: drop-shadow(0 8px 30px rgba(0, 220, 130, 0.4));
|
||||
}
|
||||
50% {
|
||||
filter: drop-shadow(0 8px 35px rgba(0, 220, 130, 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bg-glow {
|
||||
0%, 100% {
|
||||
filter: brightness(1);
|
||||
}
|
||||
50% {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes letter-glow {
|
||||
0%, 100% {
|
||||
filter: url(#glow192);
|
||||
}
|
||||
50% {
|
||||
filter: url(#intenseglow192);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-slide-vertical {
|
||||
0% {
|
||||
stroke-dasharray: 96;
|
||||
stroke-dashoffset: 96;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 96;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-slide-diagonal-top {
|
||||
0% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 68;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-slide-diagonal-bottom {
|
||||
0% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 68;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 68;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse-expand {
|
||||
0%, 100% {
|
||||
r: 11.52;
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
r: 14;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ring-pulse {
|
||||
0%, 100% {
|
||||
r: 17.28;
|
||||
opacity: 0.3;
|
||||
stroke-width: 3;
|
||||
}
|
||||
50% {
|
||||
r: 20;
|
||||
opacity: 0.6;
|
||||
stroke-width: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes corner-extend {
|
||||
0% {
|
||||
stroke-dasharray: 13.44;
|
||||
stroke-dashoffset: 13.44;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 13.44;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes click-bounce {
|
||||
0% {
|
||||
transform: scale(1) translateY(0) rotateY(0deg);
|
||||
}
|
||||
30% {
|
||||
transform: scale(0.92) translateY(0) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.08) translateY(-4px) rotateY(180deg);
|
||||
}
|
||||
70% {
|
||||
transform: scale(0.98) translateY(0) rotateY(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1) translateY(0) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate-3d {
|
||||
0% {
|
||||
transform: perspective(800px) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: perspective(800px) rotateY(180deg);
|
||||
}
|
||||
100% {
|
||||
transform: perspective(800px) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes letter-flash {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
20%, 60% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
40%, 80% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dot-burst {
|
||||
0% {
|
||||
r: 11.52;
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
r: 20;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
r: 11.52;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple-expand {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(2.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes default-pulse {
|
||||
0%, 100% {
|
||||
opacity: 0.6;
|
||||
r: 11.52;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
r: 13.44;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes default-ring-pulse {
|
||||
0%, 100% {
|
||||
opacity: 0.3;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.kompose-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.03) translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.kompose-icon-wrapper,
|
||||
.kompose-icon,
|
||||
.kompose-icon *,
|
||||
.ripple {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.kompose-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch device optimizations */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.kompose-icon-wrapper.is-interactive:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ interface PivoineDocsIconProps {
|
||||
## ✨ Animations & Effects
|
||||
|
||||
### Default State
|
||||
- **Flower starts CLOSED** as a tight bud 🌷
|
||||
- Outer petals: 30% size, 50% opacity
|
||||
- Middle petals: 40% size, 60% opacity
|
||||
- Inner petals: 50% size, 70% opacity
|
||||
- **Subtle pulsing** background circle
|
||||
- **Twinkling sparkles** at corners
|
||||
- **Orbiting particles** around the flower
|
||||
@@ -104,11 +108,14 @@ interface PivoineDocsIconProps {
|
||||
|
||||
### Hover State (when `interactive={true}`)
|
||||
- Icon **scales up** and **lifts** (transform 3D)
|
||||
- **PETALS BLOOM OPEN** to full size! 🌸
|
||||
- Smooth 0.8s transition
|
||||
- Staggered timing for natural bloom:
|
||||
- Outer petals bloom first (0s delay)
|
||||
- Middle petals follow (0.05s delay)
|
||||
- Inner petals last (0.1s delay)
|
||||
- All reach 100% size and full opacity
|
||||
- Enhanced **shadow and glow** effects
|
||||
- Petals **bloom** outward in sequence
|
||||
- Outer petals bloom first
|
||||
- Middle petals follow (0.1s delay)
|
||||
- Inner petals last (0.2s delay)
|
||||
- Center golden circle **glows intensely**
|
||||
- Sparkles **burst** and expand
|
||||
- Pages **fan out** slightly with rotation
|
||||
|
||||
477
Projects/docs.pivoine.art/components/icons/PivoineDocsIcon.css
Normal file
477
Projects/docs.pivoine.art/components/icons/PivoineDocsIcon.css
Normal file
@@ -0,0 +1,477 @@
|
||||
/* Pivoine Docs Icon Styles */
|
||||
|
||||
.pivoine-docs-icon-wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
cursor: pointer;
|
||||
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper:not(.is-interactive) {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
filter: drop-shadow(0 10px 40px rgba(168, 85, 247, 0.3));
|
||||
transition: filter 0.4s ease;
|
||||
}
|
||||
|
||||
/* Background pulse */
|
||||
.bg-circle {
|
||||
animation: bg-pulse 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* CLOSED STATE - Petals start small and close to center */
|
||||
.outer-petal {
|
||||
transform-origin: 128px 128px;
|
||||
transform: scale(0.3);
|
||||
opacity: 0.5;
|
||||
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.middle-petal {
|
||||
transform-origin: 128px 128px;
|
||||
transform: scale(0.4);
|
||||
opacity: 0.6;
|
||||
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.05s;
|
||||
}
|
||||
|
||||
.inner-petal {
|
||||
transform-origin: 128px 128px;
|
||||
transform: scale(0.5);
|
||||
opacity: 0.7;
|
||||
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s;
|
||||
}
|
||||
|
||||
/* Non-interactive version stays slightly more open */
|
||||
.pivoine-docs-icon-wrapper:not(.is-interactive) .outer-petal {
|
||||
transform: scale(0.85);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper:not(.is-interactive) .middle-petal {
|
||||
transform: scale(0.88);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper:not(.is-interactive) .inner-petal {
|
||||
transform: scale(0.9);
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
/* Sparkles twinkle */
|
||||
.sparkle {
|
||||
animation: twinkle 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.sparkle-1 {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.sparkle-2 {
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
.sparkle-3 {
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
.sparkle-4 {
|
||||
animation-delay: 1.5s;
|
||||
}
|
||||
|
||||
/* Particles orbit */
|
||||
.particle {
|
||||
animation: orbit 8s linear infinite;
|
||||
transform-origin: 128px 128px;
|
||||
}
|
||||
|
||||
.particle-1 {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.particle-2 {
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
.particle-3 {
|
||||
animation-delay: 4s;
|
||||
}
|
||||
|
||||
.particle-4 {
|
||||
animation-delay: 6s;
|
||||
}
|
||||
|
||||
/* Center circle pulse */
|
||||
.center-circle {
|
||||
animation: center-pulse 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Pages subtle movement */
|
||||
.page {
|
||||
transform-origin: center;
|
||||
animation: page-float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.page-1 {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.page-2 {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.page-3 {
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
/* Text lines appear */
|
||||
.text-line {
|
||||
stroke-dasharray: 30;
|
||||
stroke-dashoffset: 30;
|
||||
animation: line-appear 2s ease-out forwards;
|
||||
}
|
||||
|
||||
.line-1 {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.line-2 {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.line-3 {
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
.line-4 {
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.line-5 {
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
/* HOVER - BLOOM OPEN! */
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.08) translateY(-8px);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .pivoine-docs-icon {
|
||||
filter: drop-shadow(0 20px 60px rgba(168, 85, 247, 0.6));
|
||||
}
|
||||
|
||||
/* Petals bloom open on hover */
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .outer-petal {
|
||||
transform: scale(1);
|
||||
opacity: 0.85;
|
||||
filter: url(#intense-glow);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .middle-petal {
|
||||
transform: scale(1);
|
||||
opacity: 0.9;
|
||||
filter: url(#intense-glow);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .inner-petal {
|
||||
transform: scale(1);
|
||||
opacity: 0.95;
|
||||
filter: url(#intense-glow);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .center-circle {
|
||||
animation: center-glow 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .sparkle {
|
||||
animation: sparkle-burst 0.8s ease-out infinite;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .page {
|
||||
animation: page-fan 0.8s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Click effects */
|
||||
.pivoine-docs-icon-wrapper.is-clicked {
|
||||
animation: icon-bounce 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-clicked .pivoine-docs-icon {
|
||||
animation: icon-spin 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
filter: drop-shadow(0 25px 80px rgba(168, 85, 247, 0.9));
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-clicked .petal {
|
||||
animation: petal-explode 0.8s ease-out;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-clicked .center-circle {
|
||||
animation: center-burst 0.8s ease-out;
|
||||
}
|
||||
|
||||
/* Ripple effect */
|
||||
.ripple-effect {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(168, 85, 247, 0.6) 0%, rgba(168, 85, 247, 0) 70%);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
animation: ripple-expand 1s ease-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Label */
|
||||
.icon-label {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #a855f7, #ec4899);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
animation: label-shimmer 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Keyframes */
|
||||
@keyframes bg-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.4;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0.7;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.4;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.3);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes orbit {
|
||||
from {
|
||||
transform: rotate(0deg) translateX(80px) rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg) translateX(80px) rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes center-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.15);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes page-float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes line-appear {
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes center-glow {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.8;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.2);
|
||||
filter: url(#intense-glow);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sparkle-burst {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.8;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.8);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes page-fan {
|
||||
0% {
|
||||
transform: translateY(0) rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-3px) rotate(2deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes icon-bounce {
|
||||
0% {
|
||||
transform: scale(1) translateY(0) rotateZ(0deg);
|
||||
}
|
||||
30% {
|
||||
transform: scale(0.9) translateY(0) rotateZ(0deg);
|
||||
}
|
||||
60% {
|
||||
transform: scale(1.15) translateY(-15px) rotateZ(180deg);
|
||||
}
|
||||
80% {
|
||||
transform: scale(0.95) translateY(0) rotateZ(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1) translateY(0) rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes icon-spin {
|
||||
0% {
|
||||
transform: perspective(1000px) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: perspective(1000px) rotateY(180deg);
|
||||
}
|
||||
100% {
|
||||
transform: perspective(1000px) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes petal-explode {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.3);
|
||||
opacity: 0.8;
|
||||
filter: url(#intense-glow);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
filter: url(#petal-glow);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes center-burst {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.8);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple-expand {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(3);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes label-shimmer {
|
||||
0%,
|
||||
100% {
|
||||
filter: brightness(1);
|
||||
}
|
||||
50% {
|
||||
filter: brightness(1.3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.05) translateY(-4px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.pivoine-docs-icon-wrapper,
|
||||
.pivoine-docs-icon,
|
||||
.petal,
|
||||
.sparkle,
|
||||
.particle,
|
||||
.center-circle,
|
||||
.page,
|
||||
.text-line,
|
||||
.ripple-effect,
|
||||
.label-text {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
/* Show petals in semi-open state for reduced motion */
|
||||
.outer-petal {
|
||||
transform: scale(0.85);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.middle-petal {
|
||||
transform: scale(0.88);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.inner-petal {
|
||||
transform: scale(0.9);
|
||||
opacity: 0.95;
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch devices */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.pivoine-docs-icon-wrapper.is-interactive:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import './PivoineDocsIcon.css'
|
||||
|
||||
interface PivoineDocsIconProps {
|
||||
size?: string
|
||||
@@ -38,9 +39,16 @@ export default function PivoineDocsIcon({
|
||||
handleClick()
|
||||
}
|
||||
|
||||
const wrapperClasses = [
|
||||
'pivoine-docs-icon-wrapper',
|
||||
isClicked && 'is-clicked',
|
||||
interactive && 'is-interactive',
|
||||
className
|
||||
].filter(Boolean).join(' ')
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`pivoine-docs-icon-wrapper ${isClicked ? 'is-clicked' : ''} ${interactive ? 'is-interactive' : ''} ${className}`}
|
||||
className={wrapperClasses}
|
||||
onClick={handleClick}
|
||||
onTouchStart={handleTouch}
|
||||
style={{ width: size, height: size }}
|
||||
@@ -117,7 +125,7 @@ export default function PivoineDocsIcon({
|
||||
fill={`url(#petal-gradient-${(i % 3) + 1})`}
|
||||
filter="url(#petal-glow)"
|
||||
transform={`rotate(${angle} 128 128)`}
|
||||
opacity="0.85"
|
||||
style={{ transformOrigin: '128px 128px' }}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
@@ -135,7 +143,7 @@ export default function PivoineDocsIcon({
|
||||
fill={`url(#petal-gradient-${((i + 1) % 3) + 1})`}
|
||||
filter="url(#petal-glow)"
|
||||
transform={`rotate(${angle} 128 128)`}
|
||||
opacity="0.9"
|
||||
style={{ transformOrigin: '128px 128px' }}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
@@ -153,14 +161,13 @@ export default function PivoineDocsIcon({
|
||||
fill={`url(#petal-gradient-${((i + 2) % 3) + 1})`}
|
||||
filter="url(#petal-glow)"
|
||||
transform={`rotate(${angle} 128 128)`}
|
||||
opacity="0.95"
|
||||
style={{ transformOrigin: '128px 128px' }}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
|
||||
{/* Center - Document pages */}
|
||||
<g className="center-docs">
|
||||
{/* Page stack */}
|
||||
<rect
|
||||
className="page page-3"
|
||||
x="102"
|
||||
@@ -232,289 +239,6 @@ export default function PivoineDocsIcon({
|
||||
<span className="label-text">Pivoine Docs</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<style jsx>{`
|
||||
.pivoine-docs-icon-wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
cursor: pointer;
|
||||
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper:not(.is-interactive) {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
filter: drop-shadow(0 10px 40px rgba(168, 85, 247, 0.3));
|
||||
transition: filter 0.4s ease;
|
||||
}
|
||||
|
||||
/* Background pulse */
|
||||
.bg-circle {
|
||||
animation: bg-pulse 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Petal animations */
|
||||
.petal {
|
||||
transform-origin: 128px 128px;
|
||||
transition: all 0.4s ease;
|
||||
}
|
||||
|
||||
/* Sparkles twinkle */
|
||||
.sparkle {
|
||||
animation: twinkle 2s ease-in-out infinite;
|
||||
}
|
||||
.sparkle-1 { animation-delay: 0s; }
|
||||
.sparkle-2 { animation-delay: 0.5s; }
|
||||
.sparkle-3 { animation-delay: 1s; }
|
||||
.sparkle-4 { animation-delay: 1.5s; }
|
||||
|
||||
/* Particles orbit */
|
||||
.particle {
|
||||
animation: orbit 8s linear infinite;
|
||||
transform-origin: 128px 128px;
|
||||
}
|
||||
.particle-1 { animation-delay: 0s; }
|
||||
.particle-2 { animation-delay: 2s; }
|
||||
.particle-3 { animation-delay: 4s; }
|
||||
.particle-4 { animation-delay: 6s; }
|
||||
|
||||
/* Center circle pulse */
|
||||
.center-circle {
|
||||
animation: center-pulse 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Pages subtle movement */
|
||||
.page {
|
||||
transform-origin: center;
|
||||
animation: page-float 3s ease-in-out infinite;
|
||||
}
|
||||
.page-1 { animation-delay: 0s; }
|
||||
.page-2 { animation-delay: 0.3s; }
|
||||
.page-3 { animation-delay: 0.6s; }
|
||||
|
||||
/* Text lines appear */
|
||||
.text-line {
|
||||
stroke-dasharray: 30;
|
||||
stroke-dashoffset: 30;
|
||||
animation: line-appear 2s ease-out forwards;
|
||||
}
|
||||
.line-1 { animation-delay: 0.2s; }
|
||||
.line-2 { animation-delay: 0.4s; }
|
||||
.line-3 { animation-delay: 0.6s; }
|
||||
.line-4 { animation-delay: 0.8s; }
|
||||
.line-5 { animation-delay: 1s; }
|
||||
|
||||
/* Hover effects */
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.08) translateY(-8px);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .pivoine-docs-icon {
|
||||
filter: drop-shadow(0 20px 60px rgba(168, 85, 247, 0.6));
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .outer-petal {
|
||||
animation: petal-bloom 1.2s ease-out forwards;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .middle-petal {
|
||||
animation: petal-bloom 1.2s ease-out 0.1s forwards;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .inner-petal {
|
||||
animation: petal-bloom 1.2s ease-out 0.2s forwards;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .center-circle {
|
||||
animation: center-glow 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .sparkle {
|
||||
animation: sparkle-burst 0.8s ease-out infinite;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover .page {
|
||||
animation: page-fan 0.8s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Click effects */
|
||||
.pivoine-docs-icon-wrapper.is-clicked {
|
||||
animation: icon-bounce 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-clicked .pivoine-docs-icon {
|
||||
animation: icon-spin 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
filter: drop-shadow(0 25px 80px rgba(168, 85, 247, 0.9));
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-clicked .petal {
|
||||
animation: petal-explode 0.8s ease-out;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-clicked .center-circle {
|
||||
animation: center-burst 0.8s ease-out;
|
||||
}
|
||||
|
||||
/* Ripple effect */
|
||||
.ripple-effect {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(168, 85, 247, 0.6) 0%, rgba(168, 85, 247, 0) 70%);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
animation: ripple-expand 1s ease-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Label */
|
||||
.icon-label {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #a855f7, #ec4899);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
animation: label-shimmer 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Keyframes */
|
||||
@keyframes bg-pulse {
|
||||
0%, 100% { opacity: 0.4; transform: scale(1); }
|
||||
50% { opacity: 0.7; transform: scale(1.05); }
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: 0.4; transform: scale(1); }
|
||||
50% { opacity: 1; transform: scale(1.3); }
|
||||
}
|
||||
|
||||
@keyframes orbit {
|
||||
from { transform: rotate(0deg) translateX(80px) rotate(0deg); }
|
||||
to { transform: rotate(360deg) translateX(80px) rotate(-360deg); }
|
||||
}
|
||||
|
||||
@keyframes center-pulse {
|
||||
0%, 100% { opacity: 0.6; transform: scale(1); }
|
||||
50% { opacity: 1; transform: scale(1.15); }
|
||||
}
|
||||
|
||||
@keyframes page-float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-2px); }
|
||||
}
|
||||
|
||||
@keyframes line-appear {
|
||||
to { stroke-dashoffset: 0; }
|
||||
}
|
||||
|
||||
@keyframes petal-bloom {
|
||||
0% { opacity: 0.85; }
|
||||
50% { opacity: 1; filter: url(#intense-glow); }
|
||||
100% { opacity: 0.95; filter: url(#petal-glow); }
|
||||
}
|
||||
|
||||
@keyframes center-glow {
|
||||
0%, 100% { opacity: 0.8; transform: scale(1); }
|
||||
50% { opacity: 1; transform: scale(1.2); filter: url(#intense-glow); }
|
||||
}
|
||||
|
||||
@keyframes sparkle-burst {
|
||||
0%, 100% { opacity: 0.8; transform: scale(1); }
|
||||
50% { opacity: 1; transform: scale(1.8); }
|
||||
}
|
||||
|
||||
@keyframes page-fan {
|
||||
0% { transform: translateY(0) rotate(0deg); }
|
||||
100% { transform: translateY(-3px) rotate(2deg); }
|
||||
}
|
||||
|
||||
@keyframes icon-bounce {
|
||||
0% { transform: scale(1) translateY(0) rotateZ(0deg); }
|
||||
30% { transform: scale(0.9) translateY(0) rotateZ(0deg); }
|
||||
60% { transform: scale(1.15) translateY(-15px) rotateZ(180deg); }
|
||||
80% { transform: scale(0.95) translateY(0) rotateZ(360deg); }
|
||||
100% { transform: scale(1) translateY(0) rotateZ(360deg); }
|
||||
}
|
||||
|
||||
@keyframes icon-spin {
|
||||
0% { transform: perspective(1000px) rotateY(0deg); }
|
||||
50% { transform: perspective(1000px) rotateY(180deg); }
|
||||
100% { transform: perspective(1000px) rotateY(360deg); }
|
||||
}
|
||||
|
||||
@keyframes petal-explode {
|
||||
0% { transform: scale(1); opacity: 1; }
|
||||
50% { transform: scale(1.3); opacity: 0.8; filter: url(#intense-glow); }
|
||||
100% { transform: scale(1); opacity: 1; filter: url(#petal-glow); }
|
||||
}
|
||||
|
||||
@keyframes center-burst {
|
||||
0% { transform: scale(1); opacity: 0.8; }
|
||||
50% { transform: scale(1.8); opacity: 1; }
|
||||
100% { transform: scale(1); opacity: 0.8; }
|
||||
}
|
||||
|
||||
@keyframes ripple-expand {
|
||||
0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }
|
||||
100% { transform: translate(-50%, -50%) scale(3); opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes label-shimmer {
|
||||
0%, 100% { filter: brightness(1); }
|
||||
50% { filter: brightness(1.3); }
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.05) translateY(-4px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.pivoine-docs-icon-wrapper,
|
||||
.pivoine-docs-icon,
|
||||
.petal,
|
||||
.sparkle,
|
||||
.particle,
|
||||
.center-circle,
|
||||
.page,
|
||||
.text-line,
|
||||
.ripple-effect,
|
||||
.label-text {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.pivoine-docs-icon-wrapper.is-interactive:hover {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch devices */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.pivoine-docs-icon-wrapper.is-interactive:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user