import { css, html, nothing, TemplateResult } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import { OmniElement } from '../core/OmniElement.js'; /** * Control that allows an action to be executed. * * @import * ```js * import '@capitec/omni-components/button'; * ``` * * @example * ```html * * * ``` * * @element omni-button * * @slot - Content to render inside button, can be positioned using {@link slotPosition} property. * * @cssprop --omni-button-font-family - Component font family. * @cssprop --omni-button-font-size - Component font size. * @cssprop --omni-button-font-weight - Component font weight. * @cssprop --omni-button-line-height - Component line height. * @cssprop --omni-button-border-radius - Component border radius. * @cssprop --omni-button-padding-top - Component padding top. * @cssprop --omni-button-padding-bottom - Component padding bottom. * @cssprop --omni-button-padding-left - Component padding left. * @cssprop --omni-button-padding-right - Component padding right. * * PRIMARY * @cssprop --omni-button-primary-background - Primary "type" background. * @cssprop --omni-button-primary-border-color - Primary "type" border color. * @cssprop --omni-button-primary-border-width - Primary "type" border width. * @cssprop --omni-button-primary-color - Primary "type" color. * * @cssprop --omni-button-primary-hover-background - Primary "type" hover background. * @cssprop --omni-button-primary-hover-border-color - Primary "type" hover border color. * @cssprop --omni-button-primary-hover-border-width - Primary "type" hover border width. * @cssprop --omni-button-primary-hover-color - Primary "type" hover color. * @cssprop --omni-button-primary-hover-box-shadow - Primary "type" hover box shadow. * * @cssprop --omni-button-primary-active-background - Primary "type" active back color. * @cssprop --omni-button-primary-active-border-color - Primary "type" active border color. * @cssprop --omni-button-primary-active-border-width - Primary "type" active border width. * @cssprop --omni-button-primary-active-color - Primary "type" active color. * * @cssprop --omni-button-primary-disabled-background - Primary "type" disabled back color. * @cssprop --omni-button-primary-disabled-border-color - Primary "type" disabled border color. * @cssprop --omni-button-primary-disabled-border-width - Primary "type" disabled border width. * @cssprop --omni-button-primary-disabled-color - Primary "type" disabled color. * * SECONDARY * @cssprop --omni-button-secondary-background - Secondary "type" background. * @cssprop --omni-button-secondary-border-color - Secondary "type" border color. * @cssprop --omni-button-secondary-border-width - Secondary "type" border width. * @cssprop --omni-button-secondary-color - Secondary "type" color. * * @cssprop --omni-button-secondary-hover-background - Secondary "type" hover background. * @cssprop --omni-button-secondary-hover-border-color - Secondary "type" hover border color. * @cssprop --omni-button-secondary-hover-border-width - Secondary "type" hover border width. * @cssprop --omni-button-secondary-hover-color - Secondary "type" hover color. * @cssprop --omni-button-secondary-hover-box-shadow - Secondary "type" hover box shadow. * * @cssprop --omni-button-secondary-active-background - Secondary "type" active background. * @cssprop --omni-button-secondary-active-border-color - Secondary "type" active border color. * @cssprop --omni-button-secondary-active-border-width - Secondary "type" active border width. * @cssprop --omni-button-secondary-active-color - Secondary "type" active color. * * @cssprop --omni-button-secondary-disabled-background - Secondary "type" disabled back color. * @cssprop --omni-button-secondary-disabled-border-color - Secondary "type" disabled border color. * @cssprop --omni-button-secondary-disabled-border-width - Secondary "type" disabled border width. * @cssprop --omni-button-secondary-disabled-color - Secondary "type" disabled color. * * CLEAR * @cssprop --omni-button-clear-background - Clear "type" background. * @cssprop --omni-button-clear-border-color - Clear "type" border color. * @cssprop --omni-button-clear-border-width - Clear "type" border width. * @cssprop --omni-button-clear-color - Clear "type" color. * * @cssprop --omni-button-clear-hover-background - Clear "type" hover background. * @cssprop --omni-button-clear-hover-border-color - Clear "type" hover border color. * @cssprop --omni-button-clear-hover-border-width - Clear "type" hover border width. * @cssprop --omni-button-clear-hover-color - Clear "type" hover color. * * @cssprop --omni-button-clear-active-background - Clear "type" active background. * @cssprop --omni-button-clear-active-border-color - Clear "type" active border color. * @cssprop --omni-button-clear-active-border-width - Clear "type" active border width. * @cssprop --omni-button-clear-active-color - Clear "type" active color. * * @cssprop --omni-button-clear-disabled-background - Clear "type" disabled back color. * @cssprop --omni-button-clear-disabled-border-color - Clear "type" disabled border color. * @cssprop --omni-button-clear-disabled-border-width - Clear "type" disabled border width. * @cssprop --omni-button-clear-disabled-color - Clear "type" disabled color. * * WHITE * @cssprop --omni-button-white-background - White "type" background. * @cssprop --omni-button-white-border-color - White "type" border color. * @cssprop --omni-button-white-border-width - White "type" border width. * @cssprop --omni-button-white-color - White "type" color. * * @cssprop --omni-button-white-hover-background - White "type" hover background. * @cssprop --omni-button-white-hover-border-color - White "type" hover border color. * @cssprop --omni-button-white-hover-border-width - White "type" hover border width. * @cssprop --omni-button-white-hover-box-shadow - White "type" hover box shadow. * * @cssprop --omni-button-white-active-background - White "type" active background. * @cssprop --omni-button-white-active-border-color - White "type" active border color. * @cssprop --omni-button-white-active-border-width - White "type" active border width. * @cssprop --omni-button-white-active-color - White "type" hover color. * @cssprop --omni-button-white-disabled-background - White "type" disabled back color. * @cssprop --omni-button-white-disabled-border-color - White "type" disabled border color. * @cssprop --omni-button-white-disabled-border-width - White "type" disabled border width. * @cssprop --omni-button-white-disabled-color - White "type" disabled color. * @cssprop --omni-button-disabled-border-color - Disabled border color. * @cssprop --omni-button-disabled-background - Disabled background. * @cssprop --omni-button-disabled-active-hover-background - Disabled hover and active background. * * @cssprop --omni-button-slot-margin-right - Slot margin left (When positioned right of label). * @cssprop --omni-button-slot-margin-bottom - Slot margin bottom (When positioned top of label). * @cssprop --omni-button-slot-margin-left - Slot margin left (When positioned right of label). * @cssprop --omni-button-slot-margin-top - Slot margin top (When positioned bottom of label). */ @customElement('omni-button') export class Button extends OmniElement { /** * Display type. * @attr */ @property({ type: String, reflect: true }) type: 'primary' | 'secondary' | 'clear' | 'white' = 'secondary'; /** * Text label. * @attr */ @property({ type: String, reflect: true }) label?: string; /** * Position of slotted content. * @attr [slot-position="left"] */ @property({ type: String, reflect: true, attribute: 'slot-position' }) slotPosition: 'left' | 'top' | 'right' | 'bottom' = 'left'; /** * Indicator if the component is disabled. * @attr */ @property({ type: Boolean, reflect: true }) disabled?: boolean; static override get styles() { return [ super.styles, css` :host { box-sizing: border-box; display: inline-flex; } :host([disabled]), :host([disabled]) > * { pointer-events: none; } .button { width: 100%; height: 100%; display: flex; flex-direction: row; align-items: center; justify-content: center; text-align: left; font-family: var(--omni-button-font-family, var(--omni-font-family)); font-size: var(--omni-button-font-size, var(--omni-font-size)); font-weight: var(--omni-button-font-weight, bolder); line-height: var(--omni-button-line-height); border-radius: var(--omni-button-border-radius, var(--omni-border-radius)); border-style: solid; padding-top: var(--omni-button-padding-top, 10px); padding-bottom: var(--omni-button-padding-bottom, 10px); padding-left: var(--omni-button-padding-left, 10px); padding-right: var(--omni-button-padding-right, 10px); cursor: pointer; /* prettier-ignore */ transition: opacity .1s ease, background-color .1s ease, border .1s ease, color .1s ease, box-shadow .1s ease, background .1s ease, -webkit-box-shadow .1s ease; } .button > .label { cursor: pointer; } .button.disabled > .label { cursor: default; } /* PRIMARY */ .button.primary { background: var(--omni-button-primary-background, var(--omni-primary-color)); border-color: var(--omni-button-primary-border-color, var(--omni-primary-color)); border-width: var(--omni-button-primary-border-width, var(--omni-border-width)); color: var(--omni-button-primary-color, var(--omni-background-color)); } .button.primary:hover { background: var(--omni-button-primary-hover-background, var(--omni-primary-hover-color)); border-color: var(--omni-button-primary-hover-border-color, var(--omni-primary-hover-color)); border-width: var(--omni-button-primary-hover-border-width, var(--omni-border-width)); color: var(--omni-button-primary-hover-color, var(--omni-background-color)); box-shadow: var(--omni-button-primary-hover-box-shadow, 0 2px 4px 0 rgba(0, 0, 0, 0.25), 0 1px 3px rgba(0, 0, 0, 0.15)); } .button.primary:active { background: var(--omni-button-primary-active-background, var(--omni-primary-active-color)); border-color: var(--omni-button-primary-active-border-color, var(--omni-primary-active-color)); border-width: var(--omni-button-primary-active-border-width, var(--omni-border-width)); color: var(--omni-button-primary-active-color, var(--omni-background-color)); box-shadow: none; } .button.primary.disabled { background: var(--omni-button-primary-disabled-background, var(--omni-disabled-background-color)); border-color: var(--omni-button-primary-disabled-border-color, var(--omni-disabled-border-color)); border-width: var(--omni-button-primary-disabled-border-width, var(--omni-border-width)); color: var(--omni-button-primary-disabled-color, var(--omni-background-color)); } /* SECONDARY */ .button.secondary { background: var(--omni-button-secondary-background, var(--omni-background-color)); border-color: var(--omni-button-secondary-border-color, var(--omni-primary-color)); border-width: var(--omni-button-secondary-border-width, var(--omni-border-width)); color: var(--omni-button-secondary-color, var(--omni-primary-color)); } .button.secondary:hover { background: var(--omni-button-secondary-hover-background, var(--omni-background-hover-color)); border-color: var(--omni-button-secondary-hover-border-color, var(--omni-primary-hover-color)); border-width: var(--omni-button-secondary-hover-border-width, var(--omni-border-width)); color: var(--omni-button-secondary-hover-color, var(--omni-primary-color)); box-shadow: var(--omni-button-secondary-hover-box-shadow, 0 2px 4px 0 rgba(0, 0, 0, 0.25), 0 1px 3px rgba(0, 0, 0, 0.15)); } .button.secondary:active { background: var(--omni-button-secondary-active-background, var(--omni-background-active-color)); border-color: var(--omni-button-secondary-active-border-color, var(--omni-primary-hover-color)); border-width: var(--omni-button-secondary-active-border-width, var(--omni-border-width)); color: var(--omni-button-secondary-active-color, var(--omni-primary-color)); box-shadow: none; } .button.secondary.disabled { background: var(--omni-button-secondary-disabled-background, var(--omni-disabled-background-color)); border-color: var(--omni-button-secondary-disabled-border-color, var(--omni-disabled-border-color)); border-width: var(--omni-button-secondary-disabled-border-width, var(--omni-border-width)); color: var(--omni-button-secondary-disabled-color, var(--omni-primary-color)); } /* CLEAR */ .button.clear { background: var(--omni-button-clear-background, transparent); border-color: var(--omni-button-clear-border-color, transparent); border-width: var(--omni-button-clear-border-width, var(--omni-border-width)); color: var(--omni-button-clear-color, var(--omni-primary-color)); } .button.clear:hover { background: var(--omni-button-clear-hover-background, var(--omni-background-hover-color)); border-color: var(--omni-button-clear-hover-border-color, transparent); border-width: var(--omni-button-clear-hover-border-width, var(--omni-border-width)); color: var(--omni-button-clear-hover-color, var(--omni-primary-color)); } .button.clear:active { background: var(--omni-button-clear-active-background, var(--omni-background-active-color)); border-color: var(--omni-button-clear-active-border-color, transparent); border-width: var(--omni-button-clear-active-border-width, var(--omni-border-width)); color: var(--omni-button-clear-active-color, var(--omni-primary-color)); box-shadow: none; outline: none; } .button.clear.disabled { background: var(--omni-button-clear-disabled-background, var(--omni-disabled-background-color)); border-color: var(--omni-button-clear-disabled-border-color, var(--omni-disabled-background-color)); border-width: var(--omni-button-clear-disabled-border-width, var(--omni-border-width)); color: var(--omni-button-clear-disabled-color, var(--omni-primary-color)); } /* WHITE */ .button.white { background: var(--omni-button-white-background, white); border-color: var(--omni-button-white-border-color, white); border-width: var(--omni-button-white-border-width, var(--omni-border-width)); color: var(--omni-button-white-color, var(--omni-primary-color)); } .button.white:hover { background: var(--omni-button-white-hover-background, white); border-color: var(--omni-button-white-hover-border-color, white); border-width: var(--omni-button-white-hover-border-width, var(--omni-border-width)); box-shadow: var(--omni-button-white-hover-box-shadow, 0 2px 4px 0 rgba(0, 0, 0, 0.25), 0 1px 3px rgba(0, 0, 0, 0.15)); } .button.white:active { background: var(--omni-button-white-active-background, var(--omni-background-active-color)); border-color: var(--omni-button-white-active-border-color, transparent); border-width: var(--omni-button-white-active-border-width, var(--omni-border-width)); color: var(--omni-button-white-active-color, var(--omni-primary-color)); box-shadow: none; outline: none; } .button.white:disabled { background: var(--omni-button-white-disabled-background, var(--omni-disabled-background-color)); border-color: var(--omni-button-white-disabled-border-color, var(--omni-disabled-border-color)); border-width: var(--omni-button-white-disabled-border-width, var(--omni-border-width)); color: var(--omni-button-white-disabled-color, var(--omni-background-color)); } /* DISABLED */ .button.disabled { cursor: default; } .button.disabled:hover, .button.disabled:active { box-shadow: none; background: var(--omni-button-disabled-active-hover-background, var(--omni-disabled-background-color)); } .button.disabled:focus { outline: 0; } .button:focus { outline: none; } /** * Disable the hover state on touch enabled devices, e.g. mobile phones. * On these devices hover acts like focus instead which keeps the button looking like it is in a pressed state. * Learn more here: https://webdevpuneet.com/how-to-remove-hover-on-touch-devices. */ @media (hover: none) { .button.clear:hover:not(.disabled) { background: var(--omni-button-clear-hover-background, unset); } .button.primary:hover, .button.secondary:hover, .button.clear:hover, .button.white:hover { box-shadow: unset; } } /* SLOT POSITION */ .button.slot-left { flex-direction: row; text-align: left; } .button.slot-right { flex-direction: row-reverse; text-align: left; } .button.slot-top { flex-direction: column; text-align: center; } .button.slot-bottom { flex-direction: column-reverse; text-align: center; } /* SLOT MARGINS */ .button.slot-left > ::slotted(*) { margin-right: var(--omni-button-slot-margin-right, 10px); } .button.slot-top > ::slotted(*) { margin-bottom: var(--omni-button-slot-margin-bottom, 10px); } .button.slot-right > ::slotted(*) { margin-left: var(--omni-button-slot-margin-left, 10px); } .button.slot-bottom > ::slotted(*) { margin-top: var(--omni-button-slot-margin-top, 10px); } ` ]; } protected override render(): TemplateResult { return html` `; } } declare global { interface HTMLElementTagNameMap { 'omni-button': Button; } }