Skip to content

Commit

Permalink
[shared-ui] Add capabilities view (#3855)
Browse files Browse the repository at this point in the history
  • Loading branch information
paullewis authored and timswanson-google committed Dec 3, 2024
1 parent c8238c2 commit cb8ce91
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .changeset/dull-dryers-sneeze.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
---

Add capabilities view
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { LitElement, html, css, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { map } from "lit/directives/map.js";

@customElement("bb-capabilities-selector")
export class CapabilitiesSelector extends LitElement {
@property()
capabiliies = new Map([
[
"Fetch",
{
icon: "fetch",
code: `import fetch from "@fetch";`,
description: "Obtains data from a remote source like a website or API.",
},
],
[
"Secrets",
{
icon: "secrets",
code: `import secrets from "@secrets";`,
description:
"Retrieves user-provided data such as API keys and passwords.",
},
],
[
"Invoke",
{
icon: "invoke",
code: `import externalInvoke from "@invoke";`,
description: "Runs another board and returns its output values.",
},
],
]);

static styles = css`
* {
box-sizing: border-box;
}
:host {
display: block;
}
ul {
margin: 0;
padding: 0 0 var(--bb-grid-size-3) 0;
display: block;
list-style: none;
}
ul li.capability-item .capability-id {
position: relative;
white-space: nowrap;
margin: var(--bb-grid-size) 0;
font: 600 var(--bb-label-medium) / var(--bb-label-line-height-medium)
var(--bb-font-family);
}
ul li.capability-item .capability-description {
font: 400 var(--bb-label-small) / var(--bb-label-line-height-small)
var(--bb-font-family);
white-space: normal;
position: relative;
overflow: hidden;
}
ul li.capability-item {
margin: var(--bb-grid-size) 0;
padding: var(--bb-grid-size-2) var(--bb-grid-size-4);
width: 100%;
border-radius: 12px;
position: relative;
background: #fff;
cursor: grab;
display: grid;
grid-template-columns: 28px minmax(0, auto);
column-gap: var(--bb-grid-size-2);
}
ul li.capability-item:hover::before {
content: "";
background: var(--bb-ui-50);
position: absolute;
left: var(--bb-grid-size-2);
top: 1px;
bottom: 1px;
right: var(--bb-grid-size-2);
border-radius: var(--bb-grid-size);
z-index: 0;
opacity: 1;
}
ul li.capability-item:active {
cursor: grabbing;
}
ul li.capability-item span {
position: relative;
z-index: 1;
}
ul li.capability-item .capability-icon {
position: relative;
}
ul li.capability-item .capability-icon::before {
content: "";
position: absolute;
width: 28px;
height: 28px;
background: none top left / 28px 28px no-repeat;
top: 0;
left: 0;
}
ul li.capability-item .capability-icon.fetch::before {
background-image: var(--bb-icon-fetch);
}
ul li.capability-item .capability-icon.secrets::before {
background-image: var(--bb-icon-secrets);
}
ul li.capability-item .capability-icon.invoke::before {
background-image: var(--bb-icon-invoke);
}
`;

render() {
return html`<ul>
${map(this.capabiliies, ([title, details]) => {
return html`<li
draggable="true"
class="capability-item"
@dragstart=${(evt: DragEvent) => {
evt.dataTransfer?.setData("text/plain", `${details.code}\n`);
}}
>
<div
class=${classMap({
"capability-icon": true,
[details.icon]: true,
})}
></div>
<div>
<div class="capability-id">${title}</div>
${details.description
? html`<div class="capability-description">
${details.description}
</div>`
: nothing}
</div>
</li>`;
})}
</ul>`;
}
}
1 change: 1 addition & 0 deletions packages/shared-ui/src/elements/elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export { BoardDetailsOverlay } from "./overlay/board-details.js";
export { BoardEditOverlay } from "./overlay/board-edit.js";
export { BoardSelector } from "./input/board-selector/board-selector.js";
export { BoardServerOverlay } from "./overlay/provider.js";
export { CapabilitiesSelector } from "./capabilities-selector/capabilities-selector.js";
export { CodeEditor } from "./input/code-editor/code-editor.js";
export { CommandPalette } from "./command-palette/command-palette.js";
export { CommentOverlay } from "./overlay/comment.js";
Expand Down
11 changes: 11 additions & 0 deletions packages/shared-ui/src/elements/input/code-editor/code-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,17 @@ export class CodeEditor extends LitElement {
parent: this.#content.value,
});

this.#editor.scrollDOM.addEventListener("dragover", (evt) => {
evt.preventDefault();
evt.stopImmediatePropagation();
});

this.#editor.scrollDOM.addEventListener("drop", (evt) => {
evt.preventDefault();
evt.stopImmediatePropagation();
console.log(evt);
});

this.#attemptEditorUpdate();
this.attemptEditorFocus();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ export const styles = css`
}
#toggle-components,
#toggle-workspace-overview {
#toggle-workspace-overview,
#toggle-capabilities {
width: 32px;
height: 32px;
font-size: 0;
Expand All @@ -302,7 +303,8 @@ export const styles = css`
}
#toggle-components::after,
#toggle-workspace-overview::after {
#toggle-workspace-overview::after,
#toggle-capabilities::after {
background: var(--bb-neutral-800);
color: var(--bb-neutral-0);
padding: var(--bb-grid-size-2);
Expand All @@ -327,8 +329,13 @@ export const styles = css`
content: "Workspace";
}
#toggle-capabilities::after {
content: "Capabilities";
}
#toggle-components:hover::after,
#toggle-workspace-overview:hover::after {
#toggle-workspace-overview:hover::after,
#toggle-capabilities:hover::after {
opacity: 1;
}
Expand All @@ -342,6 +349,11 @@ export const styles = css`
24px 24px no-repeat;
}
#toggle-capabilities {
background: transparent var(--bb-icon-capabilities-inverted) center center /
24px 24px no-repeat;
}
#toggle-components:hover,
#toggle-components:focus,
#toggle-components.active {
Expand All @@ -355,4 +367,11 @@ export const styles = css`
background: oklch(from var(--bb-neutral-0) l c h/0.22)
var(--bb-icon-workspace-inverted) center center / 24px 24px no-repeat;
}
#toggle-capabilities:hover,
#toggle-capabilities:focus,
#toggle-capabilities.active {
background: oklch(from var(--bb-neutral-0) l c h/0.22)
var(--bb-icon-capabilities-inverted) center center / 24px 24px no-repeat;
}
`;
12 changes: 12 additions & 0 deletions packages/shared-ui/src/elements/ui-controller/ui-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ export class UI extends LitElement {
if (this.sideNavItem === "components" && this.moduleId) {
this.sideNavItem = null;
}

if (this.sideNavItem === "capabilities" && !this.moduleId) {
this.sideNavItem = null;
}
}

if (changedProperties.has("mode") || changedProperties.has("subGraphId")) {
Expand Down Expand Up @@ -342,6 +346,8 @@ export class UI extends LitElement {
const sideNavItems = ["workspace-overview"];
if (!this.moduleId) {
sideNavItems.push("components");
} else {
sideNavItems.push("capabilities");
}

const sideNav = html`<div id="side-nav">
Expand Down Expand Up @@ -399,6 +405,12 @@ export class UI extends LitElement {
break;
}

case "capabilities": {
sideNavItem = html`<h1 id="side-nav-title">Capabilities</h1>
<bb-capabilities-selector></bb-capabilities-selector>`;
break;
}

case "components": {
sideNavItem = html`${guard(
[graph?.kits],
Expand Down
5 changes: 3 additions & 2 deletions packages/visual-editor/public/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
--bb-icon-board-inverted: url(/third_party/icons/board-inverted.svg);
--bb-icon-braces: url(/third_party/icons/braces.svg);
--bb-icon-bug: url(/third_party/icons/bug.svg);
--bb-icon-capability: url(/third_party/icons/capability.svg);
--bb-icon-capability-inverted: url(/third_party/icons/capability-inverted.svg);
--bb-icon-capabilities: url(/third_party/icons/capabilities.svg);
--bb-icon-capabilities-inverted: url(/third_party/icons/capabilities-inverted.svg);
--bb-icon-close: url(/third_party/icons/close.svg);
--bb-icon-check-inverted: url(/third_party/icons/check-inverted.svg);
--bb-icon-collapse: url(/third_party/icons/collapse.svg);
Expand Down Expand Up @@ -115,6 +115,7 @@
--bb-icon-input: url(/third_party/icons/input.svg);
--bb-icon-info: url(/third_party/icons/info.svg);
--bb-icon-info-filled: url(/third_party/icons/info-filled.svg);
--bb-icon-invoke: url(/third_party/icons/invoke.svg);
--bb-icon-jsonata: url(/third_party/icons/jsonata.svg);
--bb-icon-javascript: url(/third_party/icons/js.svg);
--bb-icon-library-add: url(/third_party/icons/library-add.svg);
Expand Down
5 changes: 5 additions & 0 deletions packages/visual-editor/public/third_party/icons/invoke.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 12 additions & 11 deletions packages/visual-editor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3201,36 +3201,37 @@ export class Main extends LitElement {
></bb-command-palette>`
: nothing;

const tabModules = this.tab?.graph.modules
? Object.keys(this.tab?.graph.modules)
: [];
const tabModules = Object.entries(this.tab?.graph.modules ?? {});

// For standard, non-imperative graphs prepend the main board ID
if (!this.tab?.graph.main) {
tabModules.unshift(BreadboardUI.Constants.MAIN_BOARD_ID);
tabModules.unshift([
BreadboardUI.Constants.MAIN_BOARD_ID,
{ code: "" },
]);
}

const modules: BreadboardUI.Types.Command[] = tabModules
.filter((module) => {
.filter(([id]) => {
if (this.tab?.moduleId) {
return module !== this.tab?.moduleId;
return id !== this.tab?.moduleId;
}

return module !== BreadboardUI.Constants.MAIN_BOARD_ID;
return id !== BreadboardUI.Constants.MAIN_BOARD_ID;
})
.map((module) => {
if (module === BreadboardUI.Constants.MAIN_BOARD_ID) {
.map(([id, module]): BreadboardUI.Types.Command => {
if (id === BreadboardUI.Constants.MAIN_BOARD_ID) {
return {
title: `Open Main Board...`,
icon: "open",
name: "open",
};
}
return {
title: `Open ${module}...`,
title: `Open ${module.metadata?.title ?? id}...`,
icon: "open",
name: "open",
secondaryAction: module,
secondaryAction: id,
};
});

Expand Down

0 comments on commit cb8ce91

Please sign in to comment.