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/split-button/split-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

463 lines
12 KiB
SCSS

@use 'ui-design-system/src/styles/semantic/index' as *;
.ui-split-button {
// Reset and base styles
display: inline-flex;
align-items: center;
position: relative;
border-radius: $semantic-border-radius-md;
overflow: hidden;
// Size variants
&--small {
height: $semantic-spacing-9; // 2.25rem
.ui-split-button__primary,
.ui-split-button__dropdown {
font-size: $semantic-typography-font-size-sm;
line-height: $semantic-typography-line-height-tight;
}
}
&--medium {
height: $semantic-spacing-11; // 2.75rem
.ui-split-button__primary,
.ui-split-button__dropdown {
font-size: $semantic-typography-font-size-md;
line-height: $semantic-typography-line-height-normal;
}
}
&--large {
height: $semantic-spacing-12; // 3rem
.ui-split-button__primary,
.ui-split-button__dropdown {
font-size: $semantic-typography-font-size-lg;
line-height: $semantic-typography-line-height-normal;
}
}
// Full width variant
&--full-width {
width: 100%;
}
// Disabled state
&--disabled {
opacity: 0.38;
cursor: not-allowed;
pointer-events: none;
}
// Primary button part
&__primary {
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
cursor: pointer;
text-decoration: none;
outline: none;
flex: 1;
height: 100%; // Match the container height
// Default colors (filled variant)
background-color: $semantic-color-interactive-primary;
color: $semantic-color-on-primary;
// Typography
font-family: $semantic-typography-font-family-sans;
font-size: $semantic-typography-font-size-md; // Default medium size
font-weight: $semantic-typography-font-weight-medium;
line-height: $semantic-typography-line-height-normal; // Default medium line-height
text-align: center;
text-transform: none;
letter-spacing: $semantic-typography-letter-spacing-normal;
white-space: nowrap;
// 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);
// Default hover state
&:hover:not(:disabled) {
background-color: $semantic-color-primary;
transform: translateY(-1px);
box-shadow: $semantic-shadow-button-hover;
}
&:active:not(:disabled) {
transform: scale(0.98);
box-shadow: $semantic-shadow-button-active;
}
&:focus-visible {
outline: 2px solid $semantic-color-primary;
outline-offset: 2px;
}
// Size-specific padding
.ui-split-button--small & {
padding: 0 $semantic-spacing-3; // 0.75rem
}
.ui-split-button--medium & {
padding: 0 $semantic-spacing-4; // 1rem
}
.ui-split-button--large & {
padding: 0 $semantic-spacing-6; // 1.5rem
}
}
// Dropdown button part
&__dropdown {
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
cursor: pointer;
outline: none;
position: relative;
// Default colors (filled variant)
background-color: $semantic-color-interactive-primary;
color: $semantic-color-on-primary;
// Typography
font-family: $semantic-typography-font-family-sans;
font-size: $semantic-typography-font-size-md; // Default medium size
font-weight: $semantic-typography-font-weight-medium;
line-height: $semantic-typography-line-height-normal; // Default medium line-height
// Default size (medium) - defaults only
width: $semantic-spacing-9; // Default to medium size
padding: 0 $semantic-spacing-2-5; // Default medium padding
// 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);
// Default hover state
&:hover:not(:disabled) {
background-color: $semantic-color-primary;
transform: translateY(-1px);
box-shadow: $semantic-shadow-button-hover;
}
&:active:not(:disabled) {
transform: scale(0.98);
box-shadow: $semantic-shadow-button-active;
}
&:focus-visible {
outline: 2px solid $semantic-color-primary;
outline-offset: 2px;
}
// Divider between buttons
&::before {
content: '';
position: absolute;
left: 0;
top: 20%;
height: 60%;
width: 1px;
background-color: currentColor;
opacity: 0.3;
}
}
// Size-specific dropdown dimensions (must come after default styles)
&--small &__dropdown {
width: $semantic-spacing-8; // 2rem - slightly smaller than height
height: $semantic-spacing-9; // Match small container height
padding: 0 $semantic-spacing-2; // 0.5rem
}
&--medium &__dropdown {
width: $semantic-spacing-9; // 2.25rem - smaller than height
height: $semantic-spacing-11; // Match medium container height
padding: 0 $semantic-spacing-2-5; // 0.625rem
}
&--large &__dropdown {
width: $semantic-spacing-10; // 2.5rem - smaller than height
height: $semantic-spacing-12; // Match large container height
padding: 0 $semantic-spacing-3; // 0.75rem
}
// Content wrapper
&__content {
display: flex;
align-items: center;
justify-content: center;
}
// Icon styles
&__icon {
display: inline-flex;
align-items: center;
flex-shrink: 0;
&--left {
margin-right: $semantic-spacing-2; // 0.5rem
}
&--right {
margin-left: $semantic-spacing-2; // 0.5rem
}
// Size-specific adjustments
.ui-split-button--small & {
font-size: $semantic-typography-font-size-xs;
&--left {
margin-right: $semantic-spacing-1-5; // 0.375rem
}
&--right {
margin-left: $semantic-spacing-1-5; // 0.375rem
}
}
.ui-split-button--medium & {
font-size: $semantic-typography-font-size-sm;
}
.ui-split-button--large & {
font-size: $semantic-typography-font-size-md;
&--left {
margin-right: $semantic-spacing-2-5; // 0.625rem
}
&--right {
margin-left: $semantic-spacing-2-5; // 0.625rem
}
}
}
// Dropdown arrow
&__arrow {
display: inline-flex;
align-items: center;
font-size: 0.875em; // Slightly larger for better visibility
transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
// Dropdown menu
&__menu {
position: absolute;
top: 100%;
left: 0;
min-width: 100%;
background: $semantic-color-surface-elevated;
border: $semantic-border-width-1 solid $semantic-color-border-primary;
border-radius: $semantic-border-radius-md;
box-shadow: $semantic-shadow-dropdown;
z-index: $semantic-z-index-dropdown;
opacity: 0;
visibility: hidden;
transform: translateY(-$semantic-spacing-2);
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
&--open {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
}
// Menu item
&__menu-item {
display: flex;
align-items: center;
width: 100%;
padding: $semantic-spacing-3 $semantic-spacing-4;
border: none;
background: transparent;
color: $semantic-color-text-primary;
font-family: $semantic-typography-font-family-sans;
font-size: $semantic-typography-font-size-sm;
font-weight: $semantic-typography-font-weight-normal;
text-align: left;
cursor: pointer;
transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
background: $semantic-color-surface-container;
}
&:first-child {
border-top-left-radius: $semantic-border-radius-md;
border-top-right-radius: $semantic-border-radius-md;
}
&:last-child {
border-bottom-left-radius: $semantic-border-radius-md;
border-bottom-right-radius: $semantic-border-radius-md;
}
}
// Filled variant (primary)
&--filled {
.ui-split-button__primary,
.ui-split-button__dropdown {
background-color: $semantic-color-interactive-primary;
color: $semantic-color-on-primary;
&:hover:not(:disabled) {
background-color: $semantic-color-primary;
transform: translateY(-1px);
box-shadow: $semantic-shadow-button-hover;
}
&:active:not(:disabled) {
transform: scale(0.98);
box-shadow: $semantic-shadow-button-active;
}
&:focus-visible {
outline: 2px solid $semantic-color-primary;
outline-offset: 2px;
}
}
.ui-split-button__dropdown:hover .ui-split-button__arrow {
transform: rotate(180deg);
}
}
// Tonal variant
&--tonal {
.ui-split-button__primary,
.ui-split-button__dropdown {
background-color: $semantic-color-surface-container;
color: $semantic-color-text-primary;
&:hover:not(:disabled) {
background-color: $semantic-color-surface-container;
transform: translateY(-1px);
box-shadow: $semantic-shadow-button-hover;
filter: brightness(0.95);
}
&:active:not(:disabled) {
transform: scale(0.98);
}
&:focus-visible {
outline: 2px solid $semantic-color-primary;
outline-offset: 2px;
}
}
.ui-split-button__dropdown:hover .ui-split-button__arrow {
transform: rotate(180deg);
}
}
// Outlined variant
&--outlined {
border: $semantic-border-width-1 solid $semantic-color-border-primary;
.ui-split-button__primary,
.ui-split-button__dropdown {
background-color: transparent;
color: $semantic-color-interactive-primary;
&:hover:not(:disabled) {
background-color: $semantic-color-surface-container;
transform: translateY(-1px);
}
&:active:not(:disabled) {
background-color: $semantic-color-surface-container;
transform: scale(0.98);
filter: brightness(0.9);
}
&:focus-visible {
outline: 2px solid $semantic-color-primary;
outline-offset: 2px;
}
}
.ui-split-button__dropdown:hover .ui-split-button__arrow {
transform: rotate(180deg);
}
}
// Loading state
&--loading {
.ui-split-button__primary {
cursor: wait;
.ui-split-button__content {
opacity: 0;
}
}
.ui-split-button__dropdown {
pointer-events: none;
opacity: 0.5;
}
}
// Loader
&__loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
&__spinner {
width: $semantic-spacing-4; // 1rem
height: $semantic-spacing-4; // 1rem
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
.ui-split-button__primary::after,
.ui-split-button__dropdown::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;
}
.ui-split-button__primary:active:not(:disabled)::after,
.ui-split-button__dropdown:active:not(:disabled)::after {
transform: scale(1);
opacity: 1;
transition: none;
}
}