Skip to content

Commit

Permalink
[shared-ui/visual-editor] Various small UI fixes (#4188)
Browse files Browse the repository at this point in the history
  • Loading branch information
paullewis authored Jan 23, 2025
1 parent f2d0061 commit 664db61
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 148 deletions.
6 changes: 6 additions & 0 deletions .changeset/quick-islands-sort.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@breadboard-ai/visual-editor": patch
"@breadboard-ai/shared-ui": patch
---

Various small UI fixes
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export class ComponentSelectorOverlay extends LitElement {
@property()
graphStore: MutableGraphStore | null = null;

@property({ reflect: true })
detached = false;

@property()
showExperimentalComponents = false;

Expand Down Expand Up @@ -77,6 +80,7 @@ export class ComponentSelectorOverlay extends LitElement {
}
header {
display: none;
height: 40px;
padding: var(--bb-grid-size-3) var(--bb-grid-size-3) var(--bb-grid-size-2)
var(--bb-grid-size-6);
Expand All @@ -87,6 +91,10 @@ export class ComponentSelectorOverlay extends LitElement {
var(--bb-font-family);
}
:host([detached="true"]) header {
display: block;
}
#controls {
height: 96px;
display: grid;
Expand Down
8 changes: 4 additions & 4 deletions packages/shared-ui/src/elements/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,15 +493,15 @@ export class Editor extends LitElement implements DragConnectorReceiver {
& #run {
min-width: 76px;
height: var(--bb-grid-size-7);
background: var(--bb-ui-500) var(--bb-icon-play-filled-inverted) 4px
height: var(--bb-grid-size-9);
background: var(--bb-ui-500) var(--bb-icon-play-filled-inverted) 8px
center / 20px 20px no-repeat;
color: #fff;
border-radius: 20px;
border: none;
font: 400 var(--bb-label-medium) / var(--bb-label-line-height-medium)
font: 400 var(--bb-label-large) / var(--bb-label-line-height-large)
var(--bb-font-family);
padding: 0 var(--bb-grid-size-3) 0 var(--bb-grid-size-7);
padding: 0 var(--bb-grid-size-5) 0 var(--bb-grid-size-9);
opacity: 0.3;
&.running {
Expand Down
150 changes: 52 additions & 98 deletions packages/shared-ui/src/elements/input/llm-input/llm-input-chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { AllowedLLMContentTypes } from "../../../types/types.js";
import { map } from "lit/directives/map.js";
import { classMap } from "lit/directives/class-map.js";
import { Ref, createRef, ref } from "lit/directives/ref.js";
import { until } from "lit/directives/until.js";
Expand All @@ -36,6 +35,7 @@ import type {
LLMContent,
StoredDataCapabilityPart,
} from "@breadboard-ai/types";
import { repeat } from "lit/directives/repeat.js";

const inlineDataTemplate = { inlineData: { data: "", mimeType: "" } };

Expand Down Expand Up @@ -295,6 +295,10 @@ export class LLMInputChat extends LitElement {
#value-container {
min-height: var(--bb-grid-size-9);
max-height: max(20svh, 340px);
overflow: auto;
scrollbar-width: none;
scroll-padding-bottom: 30px;
border: 1px solid var(--bb-neutral-300);
border-radius: var(--bb-grid-size-5);
background: var(--bb-neutral-0);
Expand Down Expand Up @@ -327,74 +331,40 @@ export class LLMInputChat extends LitElement {
.part {
position: relative;
}
.part-controls {
display: none;
position: absolute;
top: calc(var(--bb-grid-size-4) * -1 - 2px);
right: calc(var(--bb-grid-size-2) * -1);
height: var(--bb-grid-size-7);
padding: var(--bb-grid-size) var(--bb-grid-size-2);
border-radius: var(--bb-grid-size-8);
border: 1px solid var(--bb-neutral-300);
background: var(--bb-neutral-0);
}
.part:hover .part-controls {
display: flex;
}
.part-controls .add-part-after,
.part-controls .move-part-up,
.part-controls .move-part-down,
.part-controls .delete-part {
width: 20px;
height: 20px;
opacity: 0.5;
margin-right: var(--bb-grid-size);
border: none;
border-radius: 0;
font-size: 0;
cursor: pointer;
}
.part-controls .add-part-after {
background: var(--bb-neutral-0) var(--bb-icon-add) center center / 16px
16px no-repeat;
}
.part-controls .move-part-up {
background: var(--bb-neutral-0) var(--bb-icon-move-up) center center /
16px 16px no-repeat;
}
padding-right: var(--bb-grid-size-7);
.part-controls .move-part-down {
background: var(--bb-neutral-0) var(--bb-icon-move-down) center center /
16px 16px no-repeat;
}
& .part-controls {
display: none;
position: absolute;
top: 4px;
right: 4px;
height: var(--bb-grid-size-7);
width: var(--bb-grid-size-7);
border-radius: var(--bb-grid-size-8);
border: 1px solid var(--bb-neutral-300);
background: var(--bb-neutral-0);
}
.part-controls .delete-part {
background: var(--bb-neutral-0) var(--bb-icon-delete) center center / 16px
16px no-repeat;
margin-right: 0;
}
&:hover .part-controls {
display: flex;
.part-controls .add-part-after:hover,
.part-controls .move-part-up:hover,
.part-controls .move-part-down:hover,
.part-controls .delete-part:hover,
.part-controls .add-part-after:focus,
.part-controls .move-part-up:focus,
.part-controls .move-part-down:focus,
.part-controls .delete-part:focus {
opacity: 1;
}
& .delete-part {
width: 28px;
height: 28px;
opacity: 0.5;
margin: 0;
border: none;
border-radius: 0;
font-size: 0;
cursor: pointer;
background: var(--bb-icon-delete) center center / 20px 20px no-repeat;
.part-controls .move-part-up[disabled],
.part-controls .move-part-down[disabled] {
opacity: 0.3;
cursor: auto;
&:hover,
&:focus {
opacity: 1;
}
}
}
}
.value {
Expand Down Expand Up @@ -690,6 +660,15 @@ export class LLMInputChat extends LitElement {

if (focusLastPart && this.#lastPartRef.value) {
this.#lastPartRef.value.focus();

const lastPart = this.#lastPartRef.value;
requestAnimationFrame(() => {
lastPart.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "end",
});
});
}

if (triggerSelectionFlow) {
Expand Down Expand Up @@ -884,8 +863,7 @@ export class LLMInputChat extends LitElement {

async #getPartDataAsHTML(
idx: number,
part: InlineDataCapabilityPart | StoredDataCapabilityPart,
isLastPart = false
part: InlineDataCapabilityPart | StoredDataCapabilityPart
) {
let mimeType;
let getData: () => Promise<string>;
Expand All @@ -912,8 +890,6 @@ export class LLMInputChat extends LitElement {
};
}

console.log(url, mimeType);

switch (mimeType) {
case "image/png":
case "image/jpg":
Expand Down Expand Up @@ -949,7 +925,6 @@ export class LLMInputChat extends LitElement {
const accept = this.#createAcceptList();
return html`<label for="part-${idx}"
><input
${isLastPart ? ref(this.#lastInputRef) : nothing}
@input=${(evt: InputEvent) => {
evt.preventDefault();
evt.stopImmediatePropagation();
Expand Down Expand Up @@ -1143,7 +1118,7 @@ export class LLMInputChat extends LitElement {
${this.value &&
Array.isArray(this.value.parts) &&
this.value.parts.length
? map(this.value.parts, (part, idx) => {
? repeat(this.value.parts, (part, idx) => {
const isLastPart = idx === (this.value?.parts.length || 0) - 1;
let partClass = "";
Expand All @@ -1162,7 +1137,6 @@ export class LLMInputChat extends LitElement {
part.text = evt.target.value;
}}
.value=${part.text.trim()}
${isLastPart ? ref(this.#lastPartRef) : nothing}
></textarea>`;
} else if (isFunctionCallCapabilityPart(part)) {
partClass = "function-call";
Expand All @@ -1176,48 +1150,28 @@ export class LLMInputChat extends LitElement {
partClass = "inline-data";
value = html`${until(
this.#getPartDataAsHTML(idx, part, isLastPart),
this.#getPartDataAsHTML(idx, part),
"Loading..."
)}`;
} else if (isInlineData(part)) {
partClass = "inline-data";
value = html`${until(
this.#getPartDataAsHTML(idx, part, isLastPart),
this.#getPartDataAsHTML(idx, part),
"Loading..."
)}`;
}
return html`<div
class=${classMap({ part: true, [partClass]: true })}
>
<div class="content">
<div
class="content"
${isLastPart ? ref(this.#lastPartRef) : nothing}
>
<span class="value">${value}</span>
</div>
<div class="part-controls">
<button
class="add-part-after"
@click=${() => this.#addPartAfter(idx)}
title="Add text after"
>
Add text after
</button>
<button
class="move-part-up"
@click=${() => this.#movePartUp(idx)}
?disabled=${idx === 0}
title="Move up"
>
Move up
</button>
<button
class="move-part-down"
@click=${() => this.#movePartDown(idx)}
?disabled=${isLastPart}
title="Move down"
>
Move down
</button>
<button
class="delete-part"
@click=${() => this.#deletePart(idx)}
Expand Down
34 changes: 29 additions & 5 deletions packages/shared-ui/src/elements/llm-output/llm-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ import { cache } from "lit/directives/cache.js";
import { classMap } from "lit/directives/class-map.js";
import { map } from "lit/directives/map.js";
import { until } from "lit/directives/until.js";
import {
markdown,
renderMarkdownToHtmlString,
} from "../../directives/markdown.js";
import { markdown } from "../../directives/markdown.js";
import { ToastEvent, ToastType } from "../../events/events.js";
import { appendToDocUsingDriveKit } from "../google-drive/append-to-doc-using-drive-kit.js";
import { tokenVendorContext } from "../elements.js";
Expand Down Expand Up @@ -218,6 +215,31 @@ export class LLMOutput extends LitElement {
opacity: 1;
}
.copy-image-to-clipboard {
position: relative;
& button {
width: 32px;
height: 32px;
background: var(--bb-neutral-0) var(--bb-icon-copy-to-clipboard) center
center / 20px 20px no-repeat;
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
border-radius: 50%;
cursor: pointer;
border: 1px solid var(--bb-neutral-300);
font-size: 0;
opacity: 0;
transition: opacity 0.2s cubic-bezier(0, 0, 0.3, 1);
}
&:hover button {
opacity: 1;
}
}
bb-export-toolbar {
position: absolute;
top: -16px;
Expand Down Expand Up @@ -330,7 +352,9 @@ export class LLMOutput extends LitElement {
)
);
}}
></button>
>
Copy image to clipboard
</button>
</div>`
: html`<img src="${url}" alt="LLM Image" />`}
`);
Expand Down
Loading

0 comments on commit 664db61

Please sign in to comment.