🎯 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>
203 lines
4.8 KiB
SCSS
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;
|
|
}
|
|
} |