diff --git a/packages/boxel-ui/addon/src/components/resizable-panel-group/index.gts b/packages/boxel-ui/addon/src/components/resizable-panel-group/index.gts index 3ad54370f0..a9def6f6fc 100644 --- a/packages/boxel-ui/addon/src/components/resizable-panel-group/index.gts +++ b/packages/boxel-ui/addon/src/components/resizable-panel-group/index.gts @@ -245,6 +245,7 @@ export default class ResizablePanelGroup extends Component { (panelContext) => panelContext.lengthPx, ); + this.panelRatios = []; for (let index = 0; index < panelLengths.length; index++) { let panelLength = panelLengths[index]; if (panelLength == undefined) { diff --git a/packages/boxel-ui/addon/src/components/resizable-panel-group/panel.gts b/packages/boxel-ui/addon/src/components/resizable-panel-group/panel.gts index 18489b8939..ae75533bf6 100644 --- a/packages/boxel-ui/addon/src/components/resizable-panel-group/panel.gts +++ b/packages/boxel-ui/addon/src/components/resizable-panel-group/panel.gts @@ -1,8 +1,10 @@ import { registerDestructor } from '@ember/destroyable'; +import { action } from '@ember/object'; import { scheduleOnce } from '@ember/runloop'; import { htmlSafe } from '@ember/template'; import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; +import { modifier } from 'ember-modifier'; import createRef from 'ember-ref-bucket/modifiers/create-ref'; import cssVars from '../../helpers/css-var.ts'; @@ -22,6 +24,7 @@ interface Signature { Args: { collapsible?: boolean; //default true defaultLengthFraction: number; + isHidden?: boolean; //default false isLastPanel: (panelId: number) => boolean; lengthPx?: number; minLengthPx?: number; @@ -43,6 +46,16 @@ interface Signature { Element: HTMLDivElement; } +let managePanelRegistration = modifier( + (_element, [panel, isHidden]: [Panel, boolean | undefined]) => { + if (isHidden) { + scheduleOnce('afterRender', panel, panel.unregisterPanel); + } else { + scheduleOnce('afterRender', panel, panel.registerPanel); + } + }, +); + export default class Panel extends Component { ); + await sleep(100); // let didResizeModifier run + assert.hasNumericStyle('.panel-1-content', 'height', 218, 1); + assert.hasNumericStyle('.panel-2-content', 'height', 0, 0); + this.renderController.isPanel2Hidden = false; + await sleep(100); // let didResizeModifier run + assert.hasNumericStyle('.panel-1-content', 'height', 156, 1); + assert.hasNumericStyle('.panel-2-content', 'height', 62, 1); + this.renderController.isPanel2Hidden = true; + await sleep(100); // let didResizeModifier run + assert.hasNumericStyle('.panel-1-content', 'height', 218, 1); + assert.hasNumericStyle('.panel-2-content', 'height', 0, 0); + }); }); diff --git a/packages/host/app/components/ai-assistant/ai-assist-button-active-bg.webp b/packages/host/app/components/ai-assistant/ai-assist-button-active-bg.webp new file mode 100644 index 0000000000..cef6c30e6c Binary files /dev/null and b/packages/host/app/components/ai-assistant/ai-assist-button-active-bg.webp differ diff --git a/packages/host/app/components/ai-assistant/ai-assist-button-active-bg@2x.webp b/packages/host/app/components/ai-assistant/ai-assist-button-active-bg@2x.webp new file mode 100644 index 0000000000..6d534d1acf Binary files /dev/null and b/packages/host/app/components/ai-assistant/ai-assist-button-active-bg@2x.webp differ diff --git a/packages/host/app/components/ai-assistant/ai-assist-button-active-bg@3x.webp b/packages/host/app/components/ai-assistant/ai-assist-button-active-bg@3x.webp new file mode 100644 index 0000000000..9580d05658 Binary files /dev/null and b/packages/host/app/components/ai-assistant/ai-assist-button-active-bg@3x.webp differ diff --git a/packages/host/app/components/ai-assistant/ai-assist-icon-bw.png b/packages/host/app/components/ai-assistant/ai-assist-icon-bw.png new file mode 100644 index 0000000000..c54c819f3c Binary files /dev/null and b/packages/host/app/components/ai-assistant/ai-assist-icon-bw.png differ diff --git a/packages/host/app/components/ai-assistant/ai-assist-icon-bw@2x.png b/packages/host/app/components/ai-assistant/ai-assist-icon-bw@2x.png new file mode 100644 index 0000000000..f3066b1f2d Binary files /dev/null and b/packages/host/app/components/ai-assistant/ai-assist-icon-bw@2x.png differ diff --git a/packages/host/app/components/ai-assistant/ai-assist-icon-bw@3x.png b/packages/host/app/components/ai-assistant/ai-assist-icon-bw@3x.png new file mode 100644 index 0000000000..ce7a33216b Binary files /dev/null and b/packages/host/app/components/ai-assistant/ai-assist-icon-bw@3x.png differ diff --git a/packages/host/app/components/ai-assistant/button.gts b/packages/host/app/components/ai-assistant/button.gts index df4e8e1bf6..5c969537a1 100644 --- a/packages/host/app/components/ai-assistant/button.gts +++ b/packages/host/app/components/ai-assistant/button.gts @@ -1,13 +1,18 @@ import Component from '@glimmer/component'; +import { cn } from '@cardstack/boxel-ui/helpers'; + interface Signature { Element: HTMLButtonElement; + Args: { + isActive: boolean; + }; } export default class AiAssistantButton extends Component { } diff --git a/packages/host/app/components/ai-assistant/panel.gts b/packages/host/app/components/ai-assistant/panel.gts index 66f824290c..230e7f30f9 100644 --- a/packages/host/app/components/ai-assistant/panel.gts +++ b/packages/host/app/components/ai-assistant/panel.gts @@ -169,6 +169,7 @@ export default class AiAssistantPanel extends Component { grid-template-rows: auto 1fr; background-color: var(--boxel-ai-purple); border: none; + border-radius: 0; color: var(--boxel-light); height: 100%; position: relative; diff --git a/packages/host/app/components/operator-mode/stack-item.gts b/packages/host/app/components/operator-mode/stack-item.gts index c831bc72fc..0d58343509 100644 --- a/packages/host/app/components/operator-mode/stack-item.gts +++ b/packages/host/app/components/operator-mode/stack-item.gts @@ -319,10 +319,19 @@ export default class OperatorModeStackItem extends Component { }); private calculateLastSavedMsg() { - this.lastSavedMsg = - this.lastSaved != null - ? `Saved ${formatDistanceToNow(this.lastSaved, { addSuffix: true })}` - : undefined; + // runs frequently, so only change a tracked property if the value has changed + if (this.lastSaved == null) { + if (this.lastSavedMsg) { + this.lastSavedMsg = undefined; + } + } else { + let savedMessage = `Saved ${formatDistanceToNow(this.lastSaved, { + addSuffix: true, + })}`; + if (this.lastSavedMsg != savedMessage) { + this.lastSavedMsg = savedMessage; + } + } } private doWithStableScroll = restartableTask( diff --git a/packages/host/app/components/operator-mode/submode-layout.gts b/packages/host/app/components/operator-mode/submode-layout.gts index 3ec15e71e3..ca3d3b0a97 100644 --- a/packages/host/app/components/operator-mode/submode-layout.gts +++ b/packages/host/app/components/operator-mode/submode-layout.gts @@ -9,7 +9,7 @@ import onClickOutside from 'ember-click-outside/modifiers/on-click-outside'; import { ResizablePanelGroup } from '@cardstack/boxel-ui/components'; import type { PanelContext } from '@cardstack/boxel-ui/components'; -import { and, not } from '@cardstack/boxel-ui/helpers'; +import { and, cn, not } from '@cardstack/boxel-ui/helpers'; import AiAssistantButton from '@cardstack/host/components/ai-assistant/button'; import AiAssistantPanel from '@cardstack/host/components/ai-assistant/panel'; @@ -152,8 +152,10 @@ export default class SubmodeLayout extends Component {