Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import type {Meta, StoryObj} from '@storybook/web-vite';
import {html} from 'lit';
import {ObcAnalogValve} from './analog-valve.js';
import {AutomationButtonReadoutPosition} from '../automation-button/automation-button.js';
import {AutomationButtonReadoutStackSize} from '../../components/automation-button-readout-stack/automation-button-readout-stack.js';
import './analog-valve.js';
import {crossDecorator} from '../../storybook-util.js';
import '../automation-badge/automation-badge.js';
import '../../icons/icon-pressure.js';
import {argTypesAbstractAutomationButtonPassiveRound} from '../automation-button/abstract-automation-button-storybook-helpers.js';
import {
AutomationButtonBadgeAlert,
AutomationButtonBadgeCommandLocked,
AutomationButtonBadgeControl,
AutomationButtonBadgeInterlock,
} from '../automation-button/abstract-automation-button.js';
import {ObcAlertFrameType} from '../../components/alert-frame/alert-frame.js';

const meta: Meta<typeof ObcAnalogValve> = {
title: 'Automation/Automation Devices/Analog Valve',
Expand Down Expand Up @@ -60,3 +63,28 @@ export const WithBadges: Story = {
badgeCommandLocked: AutomationButtonBadgeCommandLocked.CommandLocked,
},
};

export const AlertFrameWithIcon: Story = {
args: {
open: true,
value: 20,
alert: true,
alertFrameType: ObcAlertFrameType.LargeSideFlip,
showAlertIcon: true,
},
render: (args) => html`
<obc-analog-valve
.open=${args.open}
.value=${args.value}
.tag=${args.tag}
.readoutPosition=${args.readoutPosition}
.readoutSize=${args.readoutSize}
.showReadoutStack=${args.showReadoutStack}
?alert=${args.alert}
.alertFrameType=${args.alertFrameType}
.showAlertIcon=${args.showAlertIcon}
>
<obi-pressure slot="alert-icon"></obi-pressure>
</obc-analog-valve>
`,
};
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ export enum AutomationButtonBadgeCommandLocked {
CommandLocked = 'command-locked',
}

/**
* Abstract base class for automation device buttons (e.g. valves, pumps,
* tanks). Subclasses provide the device symbol through the `icon` getter and
* its on/off state through `_on`, while this class renders the underlying
* `<obc-automation-button>` and forwards the shared slots and properties.
*
* ### Alert frame slots
*
* When `alert` is enabled the button is wrapped in an `<obc-alert-frame>`. The
* alert frame can show a custom icon, label and timer, depending on the
* selected `alertFrameType`. These are exposed using the same slot names as
* `<obc-automation-button>` and are forwarded all the way down to the alert
* frame, for every `positioning` value:
*
* | Slot Name | Renders When... | Purpose |
* |--------------|--------------------------------------------------------------|-------------------------------------------------------------------------|
* | alert-icon | `alert` and `showAlertIcon` and `alertFrameType` in [`large-side-flip`, `bottom-flip`, `top-flip`] | Custom icon shown in the alert frame flap, in addition to the alert category icon. |
* | alert-label | `alert` and `alertFrameType` in [`bottom-flip`, `top-flip`] | Label text shown in the alert frame flap. |
* | alert-timer | `alert` and `alertFrameType` in [`bottom-flip`, `top-flip`] | Timer / clock shown in the alert frame flap. |
*
* The slot content is remapped on its way down: `alert-icon`
* (`obc-automation-button`) -> `icon` (`obc-alert-frame`), and likewise for
* the label and timer slots.
*
* @slot alert-icon - Custom icon shown in the alert frame flap (requires `showAlertIcon` and a flap variant that supports an icon).
* @slot alert-label - Label text shown in the alert frame flap (`bottom-flip`/`top-flip`).
* @slot alert-timer - Timer / clock shown in the alert frame flap (`bottom-flip`/`top-flip`).
* @slot badge-top-right - Custom badge in the top-right corner (overrides `badgeAlert`).
* @slot badge-top-left - Custom badge in the top-left corner (overrides `badgeControl`).
* @slot badge-bottom-left - Custom badge in the bottom-left corner (overrides `badgeInterlock`).
* @slot badge-bottom-right - Custom badge in the bottom-right corner (overrides `badgeCommandLocked`).
*/
export class ObcAbstractAutomationButton extends LitElement {
@property({type: Boolean, attribute: false}) showReadoutStack: boolean = true;
/** @availableWhen showReadoutStack==true */
Expand Down Expand Up @@ -262,6 +294,9 @@ export class ObcAbstractAutomationButton extends LitElement {
.positioning=${this.positioning}
>
${this.icon}
<slot name="alert-icon" slot="alert-icon"></slot>
<slot name="alert-label" slot="alert-label"></slot>
<slot name="alert-timer" slot="alert-timer"></slot>
<slot
name="badge-top-right"
slot="badge-top-right"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,54 @@ export const ValveAlert: Story = {
},
};

export const ValveAlertButtonPositioning: Story = {
argTypes: {
alertFrameType: {
options: Object.values(ObcAlertFrameType),
control: {
type: 'select',
},
},
alertFrameStatus: {
options: Object.values(ObcAlertFrameStatus),
control: {
type: 'select',
},
},
},
args: {
alert: true,
alertFrameType: ObcAlertFrameType.BottomFlip,
alertFrameStatus: ObcAlertFrameStatus.Alarm,
positioning: AutomationButtonPositioning.button,
},
render(args) {
const readouts: AutomationButtonReadoutStack[] = [];
const tag: string | null = '#0000';
return html` <obc-automation-button
state="open"
.showReadoutStack=${args.showReadoutStack}
.readouts=${readouts}
.tag=${tag}
.alertFrameStatus=${args.alertFrameStatus}
.alertFrameType=${args.alertFrameType}
.showAlertCategoryIcon=${args.showAlertCategoryIcon}
.showAlertIcon=${args.showAlertIcon}
.positioning=${args.positioning}
?alert=${args.alert}
>
<obi-twoway-digital-open
usecsscolor
slot="icon"
style="display: block; transform: rotate(90deg); line-height: 0;"
></obi-twoway-digital-open>
<obi-placeholder slot="alert-icon"></obi-placeholder>
<div slot="alert-label">Label</div>
<div slot="alert-timer">00:45</div>
</obc-automation-button>`;
},
};

export const ValveBadges: Story = {
render(args) {
const readouts: AutomationButtonReadoutStack[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
ObcAlertFrameThickness,
ObcAlertFrameType,
ObcAlertFrameMode,
wrapWithAlertFrame,
} from '../../components/alert-frame/alert-frame.js';
import {AlertType} from '../../types.js';
import {customElement} from '../../decorator.js';
Expand Down Expand Up @@ -196,19 +195,7 @@ export class ObcAutomationButton extends LitElement {
`
: nothing}
${this.alert && this.positioning === AutomationButtonPositioning.point
? html` <obc-alert-frame
class="alert-frame"
.type=${this.alertFrameType}
.thickness=${this.alertFrameThickness}
.status=${this.alertFrameStatus}
.mode=${this.alertFrameMode}
.showAlertCategoryIcon=${this.showAlertCategoryIcon}
.showIcon=${this.showAlertIcon}
>
<span slot="icon"><slot name="alert-icon"></slot></span>
<span slot="label"><slot name="alert-label"></slot></span>
<span slot="timer"><slot name="alert-timer"></slot></span>
</obc-alert-frame>`
? this.renderAlertFrame(nothing, true)
: nothing}
</button>
`);
Expand All @@ -218,19 +205,9 @@ export class ObcAutomationButton extends LitElement {
if (this.positioning === AutomationButtonPositioning.point) {
return html`<div class="point-wrapper">${content}</div>`;
}
const innerContent = wrapWithAlertFrame(
this.alert
? {
type: this.alertFrameType,
thickness: this.alertFrameThickness,
status: this.alertFrameStatus,
mode: this.alertFrameMode,
showIcon: this.showAlertIcon,
showAlertCategoryIcon: this.showAlertCategoryIcon,
}
: false,
content
);
const innerContent = this.alert
? this.renderAlertFrame(content, false)
: content;
if (this.positioning === AutomationButtonPositioning.symbol) {
return html`<div
class=${classMap({
Expand All @@ -244,6 +221,35 @@ export class ObcAutomationButton extends LitElement {
return innerContent;
}

/**
* Renders the `<obc-alert-frame>` together with the `alert-icon`,
* `alert-label` and `alert-timer` slots so that slotted content reaches the
* frame regardless of the `positioning`. When `overlay` is true the frame is
* an absolutely-positioned overlay (used by `point` positioning) and
* `content` is empty; otherwise the frame wraps `content` (used by `symbol`
* and `button` positioning).
*/
private renderAlertFrame(
content: HTMLTemplateResult | typeof nothing,
overlay: boolean
): HTMLTemplateResult {
return html`<obc-alert-frame
class=${overlay ? 'alert-frame' : nothing}
.type=${this.alertFrameType}
.thickness=${this.alertFrameThickness}
.status=${this.alertFrameStatus}
.mode=${this.alertFrameMode}
.showAlertCategoryIcon=${this.showAlertCategoryIcon}
.showIcon=${this.showAlertIcon}
.wrapContent=${!overlay}
>
<span slot="icon"><slot name="alert-icon"></slot></span>
<span slot="label"><slot name="alert-label"></slot></span>
<span slot="timer"><slot name="alert-timer"></slot></span>
${content}
</obc-alert-frame>`;
}

static override styles = unsafeCSS(compentStyle);

private get effectiveVariant(): AutomationButtonVariant {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
} from './automation-tank.js';
import './automation-tank.js';
import {html} from 'lit';
import '../../icons/icon-tank.js';
import '../../icons/icon-timer-google.js';
import {crossDecorator} from '../../storybook-util.js';
import {AdviceType} from '../../navigation-instruments/watch/advice.js';
import type {LinearAdvice} from '../../building-blocks/instrument-linear/advice.js';
Expand Down Expand Up @@ -484,6 +486,48 @@ export const WithAlertAlarm: Story = {
`,
};

export const WithAlertBottomFlip: Story = {
args: {
type: TankType.atmospheric,
alert: true,
alertFrameStatus: ObcAlertFrameStatus.Alarm,
alertFrameType: ObcAlertFrameType.BottomFlip,
showAlertIcon: true,
},
render: (args) => html`
<obc-automation-tank
.value=${args.value}
.max=${args.max}
.trend=${args.trend}
.tag=${args.tag}
.type=${args.type}
.orientation=${args.orientation}
.compact=${args.compact}
.static=${args.static}
.positioning=${args.positioning}
.chartMode=${args.chartMode}
.chartData=${args.chartData}
.advice=${args.advice}
.hasAdvice=${args.hasAdvice}
.hasGraphIcon=${args.hasGraphIcon}
.showTrendSymbol=${args.showTrendSymbol}
.percentFractionDigits=${args.percentFractionDigits}
.readout=${args.readout}
?alert=${args.alert}
.alertFrameType=${args.alertFrameType}
.alertFrameThickness=${args.alertFrameThickness}
.alertFrameStatus=${args.alertFrameStatus}
.showAlertCategoryIcon=${args.showAlertCategoryIcon}
.showAlertIcon=${args.showAlertIcon}
.priority=${args.priority}
>
<obi-tank slot="alert-icon"></obi-tank>
<span slot="alert-label">Level alarm</span>
<obi-timer-google slot="alert-timer"></obi-timer-google>
</obc-automation-tank>
`,
};

/**
* Warning-status alert on a horizontal atmospheric tank — demonstrates the
* ring tracks the tank's host orientation correctly.
Expand Down
Loading