This repository has been archived on 2026-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
Files
ui-essentials/src/lib/components/buttons/icon-button/icon-button.component.scss
Jules 0a0cade343 Initial commit - Angular library: ui-essentials
🎯 Implementation Complete!

This library has been extracted from the monorepo and is ready for Git submodule distribution.

Features:
- Standardized SCSS imports (no relative paths)
- Optimized public-api.ts exports
- Independent Angular library structure
- Ready for consumer integration as submodule

🚀 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 21:12:46 +10:00

203 lines
4.8 KiB
SCSS

@use 'ui-design-system/src/styles/semantic/index' as *;
.ui-icon-button {
// Reset and base styles
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
border-radius: $semantic-border-radius-md;
cursor: pointer;
text-decoration: none;
outline: none;
position: relative;
overflow: hidden;
// Make it square/circular
aspect-ratio: 1;
flex-shrink: 0;
// Interaction states
user-select: none;
-webkit-tap-highlight-color: transparent;
box-sizing: border-box;
// Transitions
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
// Size variants - square buttons with proper touch targets
&--small {
width: $semantic-spacing-component-padding-xl; // 1.5rem
height: $semantic-spacing-component-padding-xl;
border-radius: $semantic-border-radius-sm;
.icon-button-icon {
font-size: $semantic-spacing-component-md; // 0.75rem
}
}
&--medium {
width: $semantic-spacing-interactive-touch-target; // 2.75rem
height: $semantic-spacing-interactive-touch-target;
border-radius: $semantic-border-radius-md;
.icon-button-icon {
font-size: $semantic-spacing-component-lg; // 1rem
}
}
&--large {
width: $semantic-spacing-layout-section-xs; // 2rem but we need larger
height: $semantic-spacing-layout-section-xs;
border-radius: $semantic-border-radius-lg;
.icon-button-icon {
font-size: $semantic-spacing-component-xl; // 1.5rem
}
}
// Filled variant (primary)
&--filled {
background-color: $semantic-color-brand-primary;
color: $semantic-color-on-brand-primary;
&:hover:not(:disabled) {
background-color: $semantic-color-brand-primary;
transform: translateY(-1px);
box-shadow: $semantic-shadow-elevation-2;
filter: brightness(1.1);
}
&:active:not(:disabled) {
transform: scale(0.95);
box-shadow: $semantic-shadow-elevation-1;
}
&:focus-visible {
outline: 2px solid $semantic-color-brand-primary;
outline-offset: 2px;
}
}
// Tonal variant
&--tonal {
background-color: $semantic-color-surface-interactive;
color: $semantic-color-text-primary;
&:hover:not(:disabled) {
background-color: $semantic-color-surface-interactive;
transform: translateY(-1px);
box-shadow: $semantic-shadow-elevation-2;
filter: brightness(0.95);
}
&:active:not(:disabled) {
transform: scale(0.95);
}
&:focus-visible {
outline: 2px solid $semantic-color-brand-primary;
outline-offset: 2px;
}
}
// Outlined variant
&--outlined {
background-color: transparent;
color: $semantic-color-brand-primary;
border: $semantic-border-width-1 solid $semantic-color-border-primary;
&:hover:not(:disabled) {
background-color: $semantic-color-surface-interactive;
border-color: $semantic-color-brand-primary;
transform: translateY(-1px);
}
&:active:not(:disabled) {
background-color: $semantic-color-surface-interactive;
transform: scale(0.95);
filter: brightness(0.9);
}
&:focus-visible {
outline: 2px solid $semantic-color-brand-primary;
outline-offset: 2px;
}
}
// States
&--disabled {
opacity: $semantic-opacity-disabled;
cursor: not-allowed;
pointer-events: none;
}
&--loading {
cursor: wait;
.icon-button-icon {
opacity: 0;
}
}
&--pressed {
background-color: $semantic-color-surface-selected;
color: $semantic-color-text-primary;
&.ui-icon-button--outlined {
border-color: $semantic-color-brand-primary;
}
}
// Icon styles
.icon-button-icon {
display: inline-flex;
align-items: center;
justify-content: center;
transition: opacity 200ms ease;
}
// Loader styles
.icon-button-loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.icon-button-spinner {
width: $semantic-spacing-component-lg; // 1rem
height: $semantic-spacing-component-lg;
border: 2px solid currentColor;
border-top: 2px solid transparent;
border-radius: 50%;
animation: spin 1s linear infinite;
opacity: 0.7;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
// Ripple effect
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
transform: scale(0);
opacity: 0;
pointer-events: none;
transition: transform 0.3s ease, opacity 0.3s ease;
}
&:active:not(:disabled)::after {
transform: scale(1);
opacity: 1;
transition: none;
}
}