design-systems: add 74 brand DESIGN.md files (VoltAgent/awesome-design-md)

- 74 brands: airbnb, stripe, apple, figma, linear, vercel, etc.
- 147 files: DESIGN.md + README.md per brand (~2.1 MB)
- Each DESIGN.md contains structured brand analysis (colors, typography, components)
- Updated 00-overview.md with new design-systems directory
This commit is contained in:
neo committed 2026-06-21 20:40:35 +05:00
1 parent e3738f2b3e
commit 76c4c5b4fe
233 files changed
+54886 -1

No files matched your search

+151
View File
@@ -0,0 +1,151 @@
---
name: motion/magnetic-button
title: Magnetic Button Effect
description: Buttons that follow cursor within radius. Creates premium tactile feel.
tags: [motion, magnetic, button, micro-interaction, premium]
source: raycast.com, linear.app, brad.co, amppz.com
---
# Magnetic Button Effect
## Что это
Кнопки и элементы, которые притягиваются к курсору мыши в пределах радиуса. Создаёт ощущение тактильности и премиальности.
## Параметры
| Параметр | Значение |
|----------|----------|
| **Radius** | 60–100px |
| **Strength** | 0.1–0.3 |
| **Easing** | `cubic-bezier(0.25, 0.1, 0.25, 1)` |
| **Duration** | 0.3s |
## Реализация
```html
<button class="magnetic-btn">Hover me</button>
```
```css
.magnetic-btn {
padding: 16px 32px;
background: var(--color-accent);
color: white;
border: none;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
position: relative;
transition: transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
}
```
```javascript
class MagneticButton {
constructor(element, strength = 0.2, radius = 80) {
this.el = element;
this.strength = strength;
this.radius = radius;
this.rect = element.getBoundingClientRect();
this.isHovering = false;
this.animationId = null;
this.pos = { x: 0, y: 0 };
this.target = { x: 0, y: 0 };
this.init();
}
init() {
this.el.addEventListener('mouseenter', (e) => {
this.isHovering = true;
this.rect = this.el.getBoundingClientRect();
});
this.el.addEventListener('mouseleave', () => {
this.isHovering = false;
this.target = { x: 0, y: 0 };
this.animate();
});
this.el.addEventListener('mousemove', (e) => {
const x = e.clientX - this.rect.left - this.rect.width / 2;
const y = e.clientY - this.rect.top - this.rect.height / 2;
this.target = { x: x * this.strength, y: y * this.strength };
});
this.animate();
}
animate() {
if (this.isHovering) {
this.pos.x += (this.target.x - this.pos.x) * 0.1;
this.pos.y += (this.target.y - this.pos.y) * 0.1;
} else {
this.pos.x *= 0.9;
this.pos.y *= 0.9;
}
this.el.style.transform = `translate(${this.pos.x}px, ${this.pos.y}px)`;
this.animationId = requestAnimationFrame(() => this.animate());
}
destroy() {
cancelAnimationFrame(this.animationId);
}
}
// Usage
document.querySelectorAll('.magnetic-btn').forEach(el => {
new MagneticButton(el);
});
```
## Варианты силы притяжения
```javascript
// Слабое (для текста)
new MagneticButton(el, 0.1, 60);
// Среднее (для кнопок)
new MagneticButton(el, 0.2, 80);
// Сильное (для крупных элементов)
new MagneticButton(el, 0.3, 100);
```
## Anti-patterns
| ❌ Плохо | ✅ Хорошо |
|----------|-----------|
| `strength: 0.5` — слишком резко | `strength: 0.1–0.3` |
| Без `mouseleave` сброса | Всегда сбрасывать в 0,0 |
| Без `requestAnimationFrame` | Использовать RAF |
| На мобильных без mouse | Проверять `matchMedia('(pointer: fine)')` |
## Mobile Fallback
```javascript
if (window.matchMedia('(pointer: fine)').matches) {
document.querySelectorAll('.magnetic-btn').forEach(el => {
new MagneticButton(el);
});
}
// На мобильных — просто hover-эффект
```
## CV Service Validation
```bash
# Проверить micro-interactions
curl -s -X POST http://localhost:8001/design/analyze \
-H "Content-Type: application/json" \
-d '{"image_base64": "...", "full_analysis": false}' | python3 -c "
import sys, json
d = json.load(sys.stdin)
motion = d['dimensions'].get('motion_quality', {})
print(f\"Motion Quality: {motion.get('score', 'N/A')}/10\")
"
```
Ожидается: `motion_quality` > 6.