/** Button universal styling: - Border radius: 4px - Darken on hover - Darker on active - Outline on focus with no offset or "jump" - Lighten on disabled */ $base-class: "button"; @mixin button-focus-outline() { &::after { content: ""; width: 100%; height: 100%; position: absolute; border: 1px solid $core-focused-outline; border-radius: $border-radius; } } @mixin unstyled-button-focus-outline($offset: 1px) { outline-color: $core-focused-outline; outline-offset: $offset; outline-style: solid; outline-width: 1px; } // Buttons with background colors @mixin button-pad-8px-16px { padding: $pad-small $pad-medium; height: 36px; } // Buttons without background colors @mixin button-pad-8px-8px { padding: $pad-small $pad-small; height: 36px; } // Size small buttons (with and without background colors) @mixin button-pad-4px-8px { padding: $pad-xsmall $pad-small; height: 28px; } @mixin button-variant( $color, $hover: null, $active: null, $inverse: false, $unstyled: false ) { background-color: $color; @if $inverse { @include button-pad-8px-8px; &__small { @include button-pad-4px-8px; } &:hover { background-color: $ui-fleet-black-5; &:active { background-color: $ui-fleet-black-5-down; } } &:focus-visible { @include button-focus-outline(); } } @else if $unstyled { &:hover:not(.button--disabled) { background-color: $hover; &:active { background-color: $active; } } &:focus-visible { @include unstyled-button-focus-outline(); } } @else { &:hover:not(.button--disabled) { background-color: $hover; &:active { background-color: $active; } } &:focus-visible { @include button-focus-outline(); } } } .#{$base-class} { @include button-pad-8px-16px; transition: color 150ms ease-in-out, background 150ms ease-in-out, top 50ms ease-in-out, box-shadow 50ms ease-in-out, border 50ms ease-in-out; position: relative; color: $core-fleet-white; text-decoration: none; flex-direction: row; justify-content: center; align-items: center; border-radius: $border-radius; font-size: $x-small; font-family: "Inter", sans-serif; font-weight: $bold; display: inline-flex; top: 0; border: 0; position: relative; cursor: pointer; &:focus { outline: none; } .transparent-text { opacity: 0; } .children-wrapper { display: flex; flex-direction: row; align-items: center; } &--default { @include button-variant( $core-fleet-green, $core-fleet-green-over, $core-fleet-green-down ); display: flex; text-wrap: nowrap; } &--success { @include button-variant($ui-success, $ui-success-over, $ui-success-down); display: flex; text-wrap: nowrap; } &--alert { @include button-variant( $core-vibrant-red, $core-vibrant-red-over, $core-vibrant-red-down ); display: flex; .loading-spinner { &__ring { div { border-color: $ui-error transparent transparent transparent; } } } } &--pill { @include button-variant( $ui-off-white, $core-vibrant-blue-over, null, $inverse: true ); color: $core-fleet-green; border: 1px solid $core-fleet-green; box-sizing: border-box; font-size: $xx-small; padding: $pad-xsmall 10px; height: 24px; white-space: nowrap; &:active { box-shadow: inset 2px 2px 2px rgba(0, 0, 0, 0.25); } &:hover, &:focus { border: 1px solid $core-fleet-green; } } &--text-link { @include button-variant(transparent); border: 0; box-shadow: none; color: $ui-fleet-black-75; font-size: $x-small; cursor: pointer; margin: 0; padding: 0; height: auto; line-height: normal; text-align: left; &:focus { outline: none; } &:hover, &:focus { color: $ui-fleet-black-75-over; background-color: transparent; box-shadow: none; text-decoration: underline; } &:active { color: $ui-fleet-black-75-down; box-shadow: none; top: 0; } &.light-text { font-weight: $regular; } } &--text-link-dark { @include button-variant(transparent); border: 0; box-shadow: none; color: $core-fleet-black; font-size: $x-small; cursor: pointer; margin: 0; padding: 0; height: auto; line-height: normal; text-align: left; &:focus { outline: none; } &:hover, &:focus { background-color: transparent; box-shadow: none; text-decoration: underline; } &:active { box-shadow: none; top: 0; } } // &--icon is used for svg icon buttons without text &--text-icon, &--icon { @include button-variant( $core-fleet-white, $core-fleet-green-over, $core-fleet-green-down, $inverse: true ); background-color: transparent; padding: 0; border: 0; box-shadow: none; color: $ui-fleet-black-75; font-size: $x-small; font-weight: $bold; cursor: pointer; white-space: nowrap; img { transform: scale(0.5); } &:focus { outline: none; } &:focus-visible { @include button-focus-outline(); } &:hover, &:focus { color: $ui-fleet-black-75-over; background-color: $ui-fleet-black-5; svg { path { fill: $ui-fleet-black-75-over; } } &:active { color: $ui-fleet-black-75-down; background-color: $ui-fleet-black-5-down; svg { path { fill: $ui-fleet-black-75-down; } } } // If .button--icon-stroke is present, use stroke instead of fill // Some SVG icons in these buttons contain a `stroke` instead of a `fill`, // so we need to modify that property instead. Adding a custom `fill` // could make these icons render incorrectly. &.button--icon-stroke { &:hover, &:focus { svg { path { fill: none; // Prevent fill from interfering stroke: $ui-fleet-black-75-over; } } &:active { svg { path { stroke: $ui-fleet-black-75-down; } } } } } } // globally styled gap between text and icon .children-wrapper { gap: $pad-small; } } // Used for primary buttons with green icon and green text, no underline on hover &--brand-inverse-icon { @include button-variant(transparent); @include button-pad-8px-8px; border: 0; box-shadow: none; color: $core-fleet-green; font-size: $x-small; font-weight: $bold; cursor: pointer; white-space: nowrap; &__small { @include button-pad-4px-8px; } img { transform: scale(0.5); } &:focus { outline: none; } &:focus-visible { @include button-focus-outline(); } &:hover, &:focus { background-color: rgba($core-fleet-black, 0.05); color: $core-fleet-green-over; svg { path { fill: $core-fleet-green-over; } } &:active { color: $core-fleet-green-down; svg { path { fill: $core-fleet-green-down; } } } } // If .button--icon-stroke is present, use stroke instead of fill // Some SVG icons in these buttons contain a `stroke` instead of a `fill`, // so we need to modify that property instead. Adding a custom `fill` // could make these icons render incorrectly. &.button--icon-stroke { &:hover, &:focus { svg { path { fill: none; // Prevent fill from interfering stroke: $core-fleet-green-over; } } &:active { svg { path { stroke: $core-fleet-green-over; } } } } } // globally styled gap between text and icon .children-wrapper { gap: $pad-small; } } &--icon { @include button-variant( $core-fleet-white, $core-fleet-green-over, $core-fleet-green-down, $inverse: true ); background-color: transparent; width: 36px; // Matches Figma design for icon-only buttons &__small { width: 28px; // Matches Figma design for small icon-only buttons } } &--inverse { @include button-variant( $core-fleet-white, $core-fleet-green-over, $core-fleet-green-down, $inverse: true ); background-color: transparent; color: $ui-fleet-black-75; box-sizing: border-box; .children-wrapper { gap: $pad-small; // For icons next to text like Pagination buttons } } &--inverse-alert { @include button-variant( $core-fleet-white, $core-vibrant-red-over, $core-vibrant-red-down, $inverse: true ); color: $core-vibrant-red; box-sizing: border-box; } &--disabled { @include disabled; } &--unstyled { @include button-variant(transparent, null, null, false, $unstyled: true); border: 0; box-shadow: none; color: $core-fleet-black; cursor: pointer; margin: 0; padding: 0; height: auto; line-height: normal; font-weight: normal; &:active { box-shadow: none; top: 0; } } &--unstyled-modal-query { @include button-variant(transparent, null, null, false, $unstyled: true); border: 0; box-shadow: none; color: $core-fleet-black; cursor: pointer; margin: 0; padding: 15px 12px; height: auto; line-height: normal; display: block; width: 100%; border-radius: 0px; border-bottom: 1px solid $ui-fleet-black-10; &:active { box-shadow: none; top: 0; } &:focus { outline: none; } &:hover, &:focus { background-color: $ui-fleet-black-5; box-shadow: none; } .children-wrapper { display: flex; width: 100%; flex-direction: column; gap: $pad-xsmall; align-items: flex-start; .info { &__header { display: block; text-align: left; } &__data { display: block; width: 100%; font-weight: normal; text-align: left; } } } } &--oversized { background-color: $core-fleet-black; padding: $pad-large $pad-small; font-size: $medium; width: 100%; } // Designed to offset padding for text to justify left of parent component &.button--justify-left { left: -$pad-small; margin-right: -$pad-small; } // Designed to offset padding for text to justify right of parent component &.button--justify-right { right: -$pad-small; margin-left: -$pad-small; } }