Button
Interactive button components with LYD brand colors, luxury gradients, and premium styling for the luxury real estate segment.
Button Variants
Primary Button
Main call to action with LYD primary gradient
Secondary Button
Alternative action with Royal Blue
Outline Button
Transparent background with primary border
Ghost Button
Minimal style with subtle hover
Glassmorphism Button
Premium glass effect with blur
Icon Only Buttons
Compact buttons with icons only
Button States
Loading State
Asynchronous action indicator
Disabled State
Inactive button state
Button Sizes
Size Variations
Different button sizes for various use cases
Real Estate Use Cases
Property Actions
Contact Actions
Implementation Guide
HTML Implementation
<!-- Primary Button -->
<button class="lyd-button lyd-button-primary">
Primary Button
</button>
<!-- Button with Icon -->
<button class="lyd-button lyd-button-secondary">
<svg viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10...">
</svg>
With Icon
</button>
<!-- Loading Button -->
<button class="lyd-button lyd-button-primary loading">
Loading...
</button>
React/Next.js Component
import React, { useState } from 'react';
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'glass';
size?: 'small' | 'default' | 'large';
loading?: boolean;
disabled?: boolean;
icon?: React.ReactNode;
children: React.ReactNode;
onClick?: () => void;
}
export const Button: React.FC<ButtonProps> = ({
variant = 'primary',
size = 'default',
loading = false,
disabled = false,
icon,
children,
onClick
}) => {
const classes = [
'lyd-button',
`lyd-button-${variant}`,
size !== 'default' && `lyd-button-${size}`,
loading && 'loading'
].filter(Boolean).join(' ');
return (
<button
className={classes}
disabled={disabled || loading}
onClick={onClick}
>
{icon && !loading && icon}
{children}
</button>
);
};
JavaScript Behavior
// Handle loading state
function handleAsyncAction(button) {
button.classList.add('loading');
button.disabled = true;
// Simulate async operation
setTimeout(() => {
button.classList.remove('loading');
button.disabled = false;
}, 2000);
}
// Add ripple effect
function addRippleEffect(button) {
button.addEventListener('click', function(e) {
const ripple = document.createElement('span');
ripple.classList.add('ripple');
this.appendChild(ripple);
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
setTimeout(() => ripple.remove(), 600);
});
}
API Reference
| Class | Description | Usage |
|---|---|---|
.lyd-button |
Base button class | Required on all buttons |
.lyd-button-primary |
Primary button variant | Main CTAs |
.lyd-button-secondary |
Secondary button variant | Alternative actions |
.lyd-button-outline |
Outline button variant | Tertiary actions |
.lyd-button-ghost |
Ghost button variant | Minimal emphasis |
.lyd-button-glass |
Glassmorphism button | Premium sections |
.lyd-button-small |
Small size modifier | Compact layouts |
.lyd-button-large |
Large size modifier | Hero sections |
.lyd-button-icon-only |
Icon-only button | Toolbars, actions |
.loading |
Loading state | Async operations |
Accessibility & Best Practices
Accessibility Guidelines
- Use semantic
<button>elements for actions - Provide clear, descriptive button text
- Ensure minimum touch target size of 44x44px
- Include focus states for keyboard navigation
- Add
aria-labelfor icon-only buttons - Use
aria-busy="true"for loading states - Maintain WCAG AA contrast ratios
LYD Brand Guidelines
- Primary buttons use the LYD gradient
- Maintain consistent button heights across the application
- Use SVG icons for sharp rendering at all sizes
- Apply hover effects for better interactivity
- Keep button text concise and action-oriented
- Group related buttons with consistent spacing
- Use loading states for operations > 300ms