@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; } }