import { LitElement, type PropertyValues, css, html, nothing } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { NavigationMixin } from '../navigation/navigation.mixin';
import { type BreakpointDevice, breakpoints } from '../structure/devices';
/**
* Fab visual element for collapsable button/links.
*/
@customElement('er-fab')
export class ErFab extends NavigationMixin(LitElement) {
static styles = [
css`
:host {
align-items: center;
background-color: var(
--er-fab-background-color,
var(--md-sys-color-surface)
);
border: 1px solid var(--er-fab-border-color, transparent);
border-radius: var(--er-fab-border-radius, var(--space-small));
box-sizing: border-box;
color: var(--er-fab-color, var(--md-sys-color-on-surface));
cursor: pointer;
display: inline-flex;
flex-direction: row;
flex-wrap: nowrap;
gap: var(--space-small);
line-height: 1;
padding: var(--space-small) var(--space-medium);
white-space: nowrap;
}
:host([disabled]) {
cursor: initial;
opacity: 0.5;
}
:host([highlight]) {
background:
radial-gradient(
ellipse at 70% 5%,
color-mix(in srgb, var(--er-fab-highlight-color) 32%, transparent),
transparent 60%
),
radial-gradient(
ellipse at 12% 185%,
color-mix(in srgb, var(--er-fab-highlight-color) 35%, transparent),
transparent 60%
);
}
:host(.noLink) {
cursor: initial;
}
:host(.primary) {
--er-fab-background-color: var(--er-fab-theme-background-color);
--er-fab-color: var(--er-fab-theme-color);
--er-icon-color: var(--er-fab-theme-background-color);
--er-icon-on-color: var(--er-fab-theme-color);
}
:host(.secondary) {
--er-fab-border-color: var(--er-fab-theme-background-color);
--er-fab-color: var(--er-fab-theme-background-color);
--er-icon-on-color: var(--er-fab-theme-background-color);
}
:host(.tertiary) {
--er-fab-background-color: transparent;
--er-fab-color: var(--er-fab-theme-background-color);
--er-icon-on-color: var(--er-fab-theme-background-color);
}
:host(.themePrimary) {
--er-fab-theme-background-color: var(--md-sys-color-primary);
--er-fab-theme-color: var(--md-sys-color-on-primary);
}
:host(.themeSecondary) {
--er-fab-theme-background-color: var(--md-sys-color-secondary);
--er-fab-theme-color: var(--md-sys-color-on-secondary);
}
:host(.themeTertiary) {
--er-fab-theme-background-color: var(--md-sys-color-tertiary);
--er-fab-theme-color: var(--md-sys-color-on-tertiary);
}
:host(.themeError) {
--er-fab-theme-background-color: var(--md-sys-color-error);
--er-fab-theme-color: var(--md-sys-color-on-error);
}
:host([path]:hover:not([disabled])),
:host(.link:hover:not([disabled])) {
outline: 1px solid
color-mix(
in srgb,
var(--er-fab-theme-background-color) 60%,
transparent
);
outline-offset: -1px;
}
`,
// Targeted breakpoint styles.
...breakpoints.mixupStyles((breakpoint) => {
const styling = css`
:host(.full${breakpoint?.targetClass ?? css``}) {
width: 100%;
}
:host(.center${breakpoint?.targetClass ?? css``}) {
justify-content: center;
}
`;
if (!breakpoint) {
return styling;
}
return css`
${breakpoint.mediaQuery} {
${styling}
}
`;
}),
];
@property({ attribute: 'icon' })
icon?: string;
@property({ attribute: 'expanded', type: Boolean })
expanded = false;
@property({})
highlight?: string;
@property({})
label?: string;
connectedCallback(): void {
super.connectedCallback();
this.title = this.label ?? '';
this.updateHighlight();
}
get isExpanded(): boolean {
if (this.expanded) {
return true;
}
let matchingBreakpoints: BreakpointDevice[] | undefined;
for (const className of this.classList) {
if (className === 'expanded') {
return true;
}
// Allow expanding based on breakpoints using css classes.
if (className.startsWith('expanded-')) {
if (matchingBreakpoints === undefined) {
matchingBreakpoints = breakpoints.findActiveBreakpoints();
}
for (const matchingBreakpoint of matchingBreakpoints) {
if (
className === `expanded${matchingBreakpoint.targetClass.toString()}`
) {
return true;
}
}
}
}
return false;
}
render() {
return html`${this.renderIcon()}${this.renderLabel()}`;
}
renderIcon() {
if (!this.icon) {
return nothing;
}
return html`