commit b3aaa061927951f2fb223f0c2a2f335c65a73db2
parent 3a3bf79d00190ea611d1085815a80f4d7b998464
Author: Florian Zia <zia.florian@gmail.com>
Date: Tue, 9 Dec 2025 19:12:01 +0000
Bug 2002022, 2002315 - Setup Storybook for AI Window r=ai-frontend-reviewers,desktop-theme-reviewers,mstriemer,fluent-reviewers,bolsson,mlucks,ngrato
Differential Revision: https://phabricator.services.mozilla.com/D273857
Diffstat:
10 files changed, 210 insertions(+), 4 deletions(-)
diff --git a/browser/components/aiwindow/ui/aiChatContent.html b/browser/components/aiwindow/ui/aiChatContent.html
@@ -16,6 +16,9 @@
<title>AI Chat Content</title>
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css" />
<script src="chrome://browser/content/contentTheme.js"></script>
+ <!-- TODO: load appropriate component modules
+ "chrome://browser/content/aiwindow/ui/components/input-cta.mjs"
+ -->
</head>
<body id="ai-window-wrapper">
Placeholder for AI Chat Content
diff --git a/browser/components/aiwindow/ui/assets/input-cta-arrow-icon.svg b/browser/components/aiwindow/ui/assets/input-cta-arrow-icon.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at https://mozilla.org/MPL/2.0/. -->
+<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11.4391 6.75033H0V5.25033H11.4393L7.24967 1.06066L8.31033 0L13.7803 5.47C13.921 5.61066 14 5.80144 14 6.00036C14 6.19929 13.921 6.39006 13.7803 6.53071L8.31028 11.9997L7.24972 10.939L11.4391 6.75033Z" fill="#5b5b66"/>
+</svg>
diff --git a/browser/components/aiwindow/ui/components/input-cta/input-cta.css b/browser/components/aiwindow/ui/components/input-cta/input-cta.css
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:host {
+ display: inline-flex;
+}
+
+moz-button.input-cta {
+ --button-background-color-disabled: var(--color-gray-20);
+ --button-text-color: white;
+ --button-text-color-disabled: white;
+ --button-text-color-hover: white;
+ --button-text-color-active: white;
+ --button-text-color-selected: white;
+ --button-border-radius: var(--border-radius-circle);
+
+ border-radius: var(--button-border-radius);
+}
+
+moz-button[type="default"].input-cta::part(button) {
+ padding-inline: var(--space-xxlarge);
+}
+
+moz-button[type="split"].input-cta {
+ background: linear-gradient(260deg, rgba(255, 183, 148, 0.8) -45%, rgba(181, 62, 175, 0.8) 65%, rgba(131, 62, 181, 0.8) 150%);
+}
+
+moz-button[type="split"].input-cta::part(chevron-button) {
+ padding-inline-end: var(--space-xsmall);
+}
diff --git a/browser/components/aiwindow/ui/components/input-cta/input-cta.mjs b/browser/components/aiwindow/ui/components/input-cta/input-cta.mjs
@@ -0,0 +1,107 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import {
+ html,
+ ifDefined,
+ repeat,
+} from "chrome://global/content/vendor/lit.all.mjs";
+import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+// eslint-disable-next-line import/no-unassigned-import
+import "chrome://global/content/elements/moz-button.mjs";
+
+/**
+ * Input CTA button with action menu extending `moz-button`.
+ *
+ * @property {string|null} action - Current action or null for initial state.
+ */
+export class InputCta extends MozLitElement {
+ static shadowRootOptions = {
+ ...MozLitElement.shadowRootOptions,
+ delegatesFocus: true,
+ };
+
+ static properties = {
+ action: { type: String, reflect: true },
+ };
+
+ static ACTIONS = ["chat", "search", "navigate"];
+
+ constructor() {
+ super();
+ this.action = null;
+ this._menuId = `actions-menu-${crypto.randomUUID()}`;
+ }
+
+ get actionLabelId() {
+ return this.action ? `aiwindow-input-cta-label-${this.action}` : "";
+ }
+
+ #setAction(key) {
+ if (key === this.action || !InputCta.ACTIONS.includes(key)) {
+ return;
+ }
+
+ this.action = key;
+ this.dispatchEvent(
+ new CustomEvent("aiwindow-input-cta:action-change", {
+ detail: { action: key },
+ bubbles: true,
+ composed: true,
+ })
+ );
+ }
+
+ willUpdate(changedProps) {
+ if (
+ changedProps.has("action") &&
+ this.action !== null &&
+ !InputCta.ACTIONS.includes(this.action)
+ ) {
+ console.warn(`Invalid action: ${this.action}`);
+ this.action = null;
+ }
+ }
+
+ render() {
+ const panelListTemplate = this.action
+ ? html`<panel-list id=${this._menuId}>
+ ${repeat(
+ InputCta.ACTIONS,
+ key => key,
+ key =>
+ html`<panel-item
+ @click=${() => this.#setAction(key)}
+ data-l10n-id=${`aiwindow-input-cta-label-${key}`}
+ ></panel-item>`
+ )}
+ </panel-list>`
+ : null;
+
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://browser/content/aiwindow/ui/components/input-cta.css"
+ />
+ <moz-button
+ type=${this.action ? "split" : "default"}
+ class="input-cta"
+ menuId=${ifDefined(this.action ? this._menuId : undefined)}
+ .iconSrc=${this.action
+ ? undefined
+ : "chrome://browser/content/aiwindow/ui/assets/input-cta-arrow-icon.svg"}
+ ?disabled=${!this.action}
+ >
+ <slot>
+ <span
+ data-l10n-id=${ifDefined(this.actionLabelId || undefined)}
+ ></span>
+ </slot>
+ </moz-button>
+ ${panelListTemplate}
+ `;
+ }
+}
+
+customElements.define("input-cta", InputCta);
diff --git a/browser/components/aiwindow/ui/components/input-cta/input-cta.stories.mjs b/browser/components/aiwindow/ui/components/input-cta/input-cta.stories.mjs
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { html } from "chrome://global/content/vendor/lit.all.mjs";
+import "chrome://browser/content/aiwindow/ui/components/input-cta.mjs";
+
+export default {
+ title: "Domain-specific UI Widgets/AI Window/Input CTA",
+ component: "input-cta",
+ parameters: {
+ fluent: `
+aiwindow-input-cta-label-chat = Chat
+aiwindow-input-cta-label-search = Search
+aiwindow-input-cta-label-navigate = Navigate
+ `,
+ },
+ argTypes: {
+ action: {
+ options: [null, "chat", "search", "navigate"],
+ control: { type: "select" },
+ },
+ },
+};
+
+const Template = ({ action }) => html`
+ <input-cta .action=${action}></input-cta>
+`;
+
+export const Disabled = Template.bind({});
+
+export const Chat = Template.bind({});
+Chat.args = {
+ action: "chat",
+};
+
+export const Search = Template.bind({});
+Search.args = {
+ action: "search",
+};
+
+export const Navigate = Template.bind({});
+Navigate.args = {
+ action: "navigate",
+};
diff --git a/browser/components/aiwindow/ui/jar.mn b/browser/components/aiwindow/ui/jar.mn
@@ -2,7 +2,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-# This file was copied from browser/components/aiwindow/ui/moz.build.
-
browser.jar:
content/browser/aiwindow/ui/aiChatContent.html
+ content/browser/aiwindow/ui/assets/input-cta-arrow-icon.svg (assets/input-cta-arrow-icon.svg)
+ content/browser/aiwindow/ui/components/input-cta.css (components/input-cta/input-cta.css)
+ content/browser/aiwindow/ui/components/input-cta.mjs (components/input-cta/input-cta.mjs)
diff --git a/browser/components/storybook/.storybook/main.js b/browser/components/storybook/.storybook/main.js
@@ -37,6 +37,8 @@ module.exports = {
`${projectRoot}/toolkit/components/satchel/megalist/content/**/*.stories.mjs`,
// WebRTC components stories
`${projectRoot}/browser/components/webrtc/content/**/*.stories.mjs`,
+ // AI Window components stories
+ `${projectRoot}/browser/components/aiwindow/ui/**/*.stories.mjs`,
// Everything else
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx|md)",
// Design system files
diff --git a/browser/components/storybook/component-status/components.json b/browser/components/storybook/component-status/components.json
@@ -1,5 +1,5 @@
{
- "generatedAt": "2025-12-02T20:33:36.933Z",
+ "generatedAt": "2025-12-05T16:54:08.681Z",
"count": 29,
"items": [
{
diff --git a/browser/locales-preview/aiWindow.ftl b/browser/locales-preview/aiWindow.ftl
@@ -15,3 +15,9 @@ menu-file-new-ai-window =
menu-file-new-classic-window =
.label = New Classic Window
+
+## Input CTA
+
+aiwindow-input-cta-label-chat = Chat
+aiwindow-input-cta-label-search = Search
+aiwindow-input-cta-label-navigate = Navigate
diff --git a/toolkit/content/widgets/moz-button/moz-button.mjs b/toolkit/content/widgets/moz-button/moz-button.mjs
@@ -307,7 +307,12 @@ export default class MozButton extends MozLitElement {
@click=${e => e.stopPropagation()}
@mousedown=${e => e.stopPropagation()}
>
- <span class="button-background" type=${this.type} size=${this.size}>
+ <span
+ class="button-background"
+ part="chevron-button"
+ type=${this.type}
+ size=${this.size}
+ >
<img
src="chrome://global/skin/icons/arrow-down.svg"
role="presentation"