diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/AI Custom Prompt.mdx b/packages/website/docs/components/patterns/AI Custom Prompt/AI Custom Prompt.mdx new file mode 100644 index 000000000000..1bd30abf76f2 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/AI Custom Prompt.mdx @@ -0,0 +1,14 @@ +--- +sidebar_class_name: newComponentBadge expComponentBadge +--- + +:::info +The AI Custom Prompt and its levels are availabe since 2.3.0 under an experimental flag and their structure and behaviour are subject to change. +::: + +### Overview + +The Custom Prompt pattern serves as a method for users to enter queries or prompts within an AI interface. It dynamically expands as needed and may present extra functionalities in a toolbar. While typically found within the AI Container, it's also applicable for integration into Tool Header toolbars, dialogs, and popovers - defined by pattern definition. + + + diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/Level 1.md b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/Level 1.md new file mode 100644 index 000000000000..586ac9fcf490 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/Level 1.md @@ -0,0 +1,9 @@ +import html from '!!raw-loader!./sample.html'; +import css from '!!raw-loader!./main.css'; +import js from '!!raw-loader!./main.js'; + + +### Overview +Simple Avatar and Prompt input in a Panel. + + diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/main.css b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/main.css new file mode 100644 index 000000000000..c521fa437dc6 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/main.css @@ -0,0 +1,9 @@ +body { + background-color: var(--sapBackgroundColor); +} + +#panelContent { + display: flex; + align-items: center; + gap: 0.5rem; +} diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/main.js b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/main.js new file mode 100644 index 000000000000..9e70b5d6eb9e --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/main.js @@ -0,0 +1,5 @@ +// Import stylesheets +import '@ui5/webcomponents/dist/Avatar.js'; +import '@ui5/webcomponents-ai/dist/Button.js'; +import '@ui5/webcomponents-ai/dist/PromptInput.js'; +import '@ui5/webcomponents/dist/Panel.js'; diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/sample.html b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/sample.html new file mode 100644 index 000000000000..83f6e7f6d3e0 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 1/sample.html @@ -0,0 +1,33 @@ + + + + + + + + + Sample + + + + +
+ + AI Pattern / Level 1 + + +
+ + SAP Logo + + +
+
+
+ + + + + + + \ No newline at end of file diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/Level 2.md b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/Level 2.md new file mode 100644 index 000000000000..31f19115af6a --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/Level 2.md @@ -0,0 +1,8 @@ +import html from '!!raw-loader!./sample.html'; +import css from '!!raw-loader!./main.css'; +import js from '!!raw-loader!./main.js'; + +### Overview +On top of Level 1, different actions are added in a Toolbar below the Prompt input. + + diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/main.css b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/main.css new file mode 100644 index 000000000000..cbc541cee2d6 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/main.css @@ -0,0 +1,17 @@ +body { + background-color: var(--sapBackgroundColor) +} + +#panelContent, +#panelContentFirstRow { + display: flex; + flex: 1; + width: 100%; + flex-direction: column; + align-items: center; +} + +#panelContentFirstRow { + flex-direction: row; + gap: .5rem; +} \ No newline at end of file diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/main.js b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/main.js new file mode 100644 index 000000000000..c4c7965894d0 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/main.js @@ -0,0 +1,11 @@ +import '@ui5/webcomponents/dist/Avatar.js'; +import '@ui5/webcomponents-icons/dist/background.js'; +import '@ui5/webcomponents-icons/dist/doc-attachment.js'; +import '@ui5/webcomponents-icons/dist/sound-loud.js'; +import '@ui5/webcomponents-icons/dist/history.js'; +import '@ui5/webcomponents-icons/dist/favorite.js'; +import '@ui5/webcomponents-ai/dist/PromptInput.js'; +import '@ui5/webcomponents/dist/Toolbar.js'; +import '@ui5/webcomponents/dist/ToolbarButton.js'; +import '@ui5/webcomponents/dist/ToolbarSeparator.js'; +import '@ui5/webcomponents/dist/Panel.js'; diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/sample.html b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/sample.html new file mode 100644 index 000000000000..ac05ed088a71 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 2/sample.html @@ -0,0 +1,45 @@ + + + + + + + + + Sample + + + + +
+ + AI Pattern / Level 2 + + +
+
+ + SAP Logo + + +
+ + + + + + + + + +
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/Level 3.md b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/Level 3.md new file mode 100644 index 000000000000..3068b4b6af8d --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/Level 3.md @@ -0,0 +1,8 @@ +import html from '!!raw-loader!./sample.html'; +import css from '!!raw-loader!./main.css'; +import js from '!!raw-loader!./main.js'; + +### Overview +On top of Level 2, we can now chose a different AI model from the top-left dropdown. Additionally we have prompt count and AI button with more options in the top-right of the panel. + + diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/main.css b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/main.css new file mode 100644 index 000000000000..1bd08b0e7939 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/main.css @@ -0,0 +1,31 @@ +body { + background-color: var(--sapBackgroundColor) +} + +#panelContent, +#panelContentFirstRow, +#panelHeader { + display: flex; + flex: 1; + width: 100%; + flex-direction: column; + align-items: center; +} + +#panelContentFirstRow, +#panelHeader { + flex-direction: row; + gap: .5rem; +} + +#panelHeader { + justify-content: end; +} + +#panelHeader > ui5-button { + margin-right: auto; +} + +#promptCountWrapper { + display: flex +} \ No newline at end of file diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/main.js b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/main.js new file mode 100644 index 000000000000..12372ef4ec6b --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/main.js @@ -0,0 +1,80 @@ +import '@ui5/webcomponents/dist/Avatar.js'; +import '@ui5/webcomponents-ai/dist/Button.js'; +import '@ui5/webcomponents-ai/dist/PromptInput.js'; +import '@ui5/webcomponents-icons/dist/ai.js'; +import '@ui5/webcomponents-icons/dist/stop.js'; +import '@ui5/webcomponents-icons/dist/slim-arrow-down.js'; +import '@ui5/webcomponents-icons/dist/navigation-down-arrow.js'; +import '@ui5/webcomponents-icons/dist/doc-attachment.js'; +import '@ui5/webcomponents-icons/dist/background.js'; +import '@ui5/webcomponents-icons/dist/sound-loud.js'; +import '@ui5/webcomponents-icons/dist/history.js'; +import '@ui5/webcomponents-icons/dist/favorite.js'; + +import '@ui5/webcomponents/dist/Input.js'; +import '@ui5/webcomponents/dist/Panel.js'; + +import '@ui5/webcomponents/dist/Label.js'; +import '@ui5/webcomponents/dist/Text.js'; +import '@ui5/webcomponents/dist/Toolbar.js'; +import '@ui5/webcomponents/dist/Menu.js'; +import '@ui5/webcomponents/dist/MenuItem.js'; +import '@ui5/webcomponents/dist/ToolbarButton.js'; +import '@ui5/webcomponents/dist/ToolbarSeparator.js'; + +var generationId, +promptCounter = 0; + +function startGeneration(button) { + console.warn('startGeneration'); + generationId = setTimeout(function () { + console.warn('Generation completed'); + button.state = 'revise'; + }, 3000); +} + +function stopGeneration() { + console.warn('stopGeneration'); + clearTimeout(generationId); +} + +function aiButtonClickHandler(evt) { + var button = evt.target; + switch (button.state) { + case '': + case 'generate': + button.state = 'generating'; + startGeneration(button); + break; + case 'generating': + button.state = 'generate'; + stopGeneration(); + break; + case 'revise': + menu.opener = button; + menu.open = true; + break; + } +} + +myAiButtonIconOnly.addEventListener('click', aiButtonClickHandler); +promptInput.addEventListener('ui5-change', function () { + promptCounter++; + promptCount.textContent = promptCounter; +}); + +menu.addEventListener('item-click', function (evt) { + var button = menu.opener; + if (evt.detail.text === 'Regenerate') { + button.state = 'generating'; + startGeneration(button); + } +}); + +aiModelSelector.addEventListener('click', function (event) { + aiModelMenu.open = !aiModelMenu.open; +}); + +aiModelMenu.addEventListener('ui5-item-click', function (event) { + myAvatar.colorScheme = event.detail.text; +}); diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/sample.html b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/sample.html new file mode 100644 index 000000000000..38ce5f8e70f4 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 3/sample.html @@ -0,0 +1,84 @@ + + + + + + + + + Sample + + + + +
+ + AI Pattern / Level 3 + + +
+ + AI Model
+ + + + + + + +
+ Prompt count: + 0 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + + + + + + + +
+
+
+ + + + + + + \ No newline at end of file diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/Level 4.md b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/Level 4.md new file mode 100644 index 000000000000..bb579c846a0e --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/Level 4.md @@ -0,0 +1,8 @@ +import html from '!!raw-loader!./sample.html'; +import css from '!!raw-loader!./main.css'; +import js from '!!raw-loader!./main.js'; + +### Overview +On top of Level 3, we can now give feedback. Also receive feedback in a Message Strip whether our response is a success, error, or warning. For the sake of the sample those feedback message strips are simulated by the buttons at the top. + + diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/main.css b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/main.css new file mode 100644 index 000000000000..d8ad321de6f1 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/main.css @@ -0,0 +1,31 @@ +body { + background-color: var(--sapBackgroundColor) +} + +#panelContent, +#panelContentFirstRow, +#panelHeader { + display: flex; + flex: 1; + width: 100%; + flex-direction: column; + align-items: center; +} + +#panelContentFirstRow, +#panelHeader { + flex-direction: row; + gap: .5rem; +} + +#panelHeader { + justify-content: end; +} + +#aiModelSelector { + margin-right: auto; +} + +#promptCountWrapper { + display: flex +} \ No newline at end of file diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/main.js b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/main.js new file mode 100644 index 000000000000..391e37e34d44 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/main.js @@ -0,0 +1,117 @@ +import '@ui5/webcomponents/dist/Avatar.js'; +import '@ui5/webcomponents-ai/dist/Button.js'; +import '@ui5/webcomponents-ai/dist/PromptInput.js'; +import '@ui5/webcomponents-icons/dist/ai.js'; +import '@ui5/webcomponents-icons/dist/stop.js'; +import '@ui5/webcomponents-icons/dist/slim-arrow-down.js'; +import '@ui5/webcomponents-icons/dist/navigation-down-arrow.js'; +import '@ui5/webcomponents-icons/dist/doc-attachment.js'; +import '@ui5/webcomponents-icons/dist/background.js'; +import '@ui5/webcomponents-icons/dist/sound-loud.js'; +import '@ui5/webcomponents-icons/dist/history.js'; +import '@ui5/webcomponents-icons/dist/favorite.js'; +import '@ui5/webcomponents/dist/Input.js'; +import '@ui5/webcomponents/dist/Panel.js'; + +import '@ui5/webcomponents/dist/Label.js'; +import '@ui5/webcomponents/dist/Text.js'; +import '@ui5/webcomponents/dist/Toolbar.js'; +import '@ui5/webcomponents/dist/TextArea.js'; +import '@ui5/webcomponents/dist/Menu.js'; +import '@ui5/webcomponents/dist/MessageStrip.js'; +import '@ui5/webcomponents/dist/MenuItem.js'; +import '@ui5/webcomponents/dist/ToolbarButton.js'; +import '@ui5/webcomponents/dist/ToolbarSeparator.js'; + +var generationId, +promptCounter = 0, +feedbackOpener = document.getElementById("feedbackOpener"), +dialog = document.getElementById("dialog"), +feedbackClosers = [...dialog.querySelectorAll(".dialogCloser")]; + +function startGeneration(button) { + console.warn("startGeneration"); + generationId = setTimeout(function() { + console.warn("Generation completed"); + button.state = "revise"; + }, 3000); +} + +function stopGeneration() { + console.warn("stopGeneration"); + clearTimeout(generationId); +} + +function aiButtonClickHandler(evt) { + var button = evt.target; + switch(button.state) { + case "": + case "generate": + button.state = "generating"; + startGeneration(button); + break; + case "generating": + button.state = "generate"; + stopGeneration(); + break; + case "revise": + menu.opener = button; + menu.open = true; + break; + } +} + +myAiButtonIconOnly.addEventListener("click", aiButtonClickHandler); +promptInput.addEventListener("ui5-change", function(evt) { + promptCounter++; + promptCount.textContent = promptCounter; + responseTextArea.value = "your response ot query " + evt.target.value + " is that."; +}) + +menu.addEventListener("item-click", function(evt) { +var button = menu.opener; + if (evt.detail.text === "Regenerate") { + button.state = "generating"; + startGeneration(button); + } +}); + +aiModelSelector.addEventListener("click", function(event) { + aiModelMenu.open = !aiModelMenu.open; +}); + +aiModelMenu.addEventListener("ui5-item-click", function(event) { + myAvatar.colorScheme = event.detail.text; +}); + +feedbackOpener.accessibilityAttributes = { + hasPopup: "dialog", + controls: dialog.id, +}; +feedbackOpener.addEventListener("click", () => { + dialog.open = true; +}); +feedbackClosers.forEach(btn => { + btn.addEventListener("click", () => { + dialog.open = false; + }); +}) + +function hideMessageStrip(evt) { + evt.target.hidden = true; +} + +succStrip.addEventListener("click", hideMessageStrip); +errStrip.addEventListener("click", hideMessageStrip); +warnStrip.addEventListener("click", hideMessageStrip); + +function showMessageStrip(evt) { + const button = evt.target; + succStrip.hidden = button != simSucc; + errStrip.hidden = button != simError; + warnStrip.hidden = button != simWarn; +} + +simSucc.addEventListener("click", showMessageStrip); +simError.addEventListener("click", showMessageStrip); +simWarn.addEventListener("click", showMessageStrip); diff --git a/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/sample.html b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/sample.html new file mode 100644 index 000000000000..455aaf4df7d6 --- /dev/null +++ b/packages/website/docs/components/patterns/AI Custom Prompt/Level 4/sample.html @@ -0,0 +1,103 @@ + + + + + + + + + Sample + + + + +
+ Simulate Success + Simulate Error + Simulate Warning + + AI Pattern / Level 4 + + +
+ + AI Model
+ + + + + + + +
+ Prompt count: + 0 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Give Feedback + + + +
+
+ Submit +
+
+
+
+
+ + +
+ + + + + + + + + +
+
+ + + + + + +
+ + + + + + + \ No newline at end of file