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>
This commit is contained in:
@@ -0,0 +1,463 @@
|
||||
@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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user