Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { ifDefined } from 'lit/directives/if-defined.js';
import { styleMap } from 'lit/directives/style-map.js';
import { ResizeController } from '@lit-labs/observers/resize-controller.js';

import { Chevron75Icon } from '@adobe/spectrum-wc/icon/elements/index.js';
import {
focusgroupNavigationActiveChange,
type FocusgroupNavigationActiveChangeDetail,
Expand All @@ -40,6 +39,7 @@ import {
getActiveElement,
} from '@adobe/spectrum-wc-core/utils/index.js';

import '@adobe/spectrum-wc/components/action-button/swc-action-button.js';
import '@adobe/spectrum-wc/components/icon/swc-icon.js';
import '../../../components/ui-icons/swc-ui-icon.js';

Expand Down Expand Up @@ -583,7 +583,8 @@ export class PromptField extends SpectrumElement {
// wherever focus was before the page turned) — its Close button when
// visible, mirroring the forward tile -> Close -> Next chain in reverse,
// otherwise the tile itself.
if (active === nextButton && event.shiftKey) {
// deepContains: focus delegates to the chevron's inner shadow button.
if (nextButton && deepContains(nextButton, active) && event.shiftKey) {
const activeTile = this._artifactNavigation.getActiveItem();
if (activeTile) {
event.preventDefault();
Expand All @@ -594,7 +595,7 @@ export class PromptField extends SpectrumElement {

// From the Prev chevron: plain Tab moves forward into the roving
// controller's current active tile, for the same reason as above.
if (active === prevButton && !event.shiftKey) {
if (prevButton && deepContains(prevButton, active) && !event.shiftKey) {
const activeTile = this._artifactNavigation.getActiveItem();
if (activeTile) {
event.preventDefault();
Expand Down Expand Up @@ -908,18 +909,22 @@ export class PromptField extends SpectrumElement {
>
${this._artifactScrollOverflow
? html`
<button
type="button"
<swc-action-button
quiet
size="s"
class="swc-PromptField-artifacts-scroll-prev"
aria-label=${this.artifactScrollPrevLabel}
accessible-label=${this.artifactScrollPrevLabel}
aria-disabled=${!this._artifactCanScrollPrev}
tabindex=${this._artifactCanScrollPrev ? nothing : -1}
@click=${this._handleArtifactScrollPrev}
>
<swc-icon size="s" aria-hidden="true">
${Chevron75Icon()}
</swc-icon>
</button>
<swc-ui-icon
slot="icon"
icon="chevron"
size="s"
aria-hidden="true"
></swc-ui-icon>
</swc-action-button>
`
: nothing}
<div
Expand Down Expand Up @@ -963,18 +968,22 @@ export class PromptField extends SpectrumElement {
</div>
${this._artifactScrollOverflow
? html`
<button
type="button"
<swc-action-button
quiet
size="s"
class="swc-PromptField-artifacts-scroll-next"
aria-label=${this.artifactScrollNextLabel}
accessible-label=${this.artifactScrollNextLabel}
aria-disabled=${!this._artifactCanScrollNext}
tabindex=${this._artifactCanScrollNext ? nothing : -1}
@click=${this._handleArtifactScrollNext}
>
<swc-icon size="s" aria-hidden="true">
${Chevron75Icon()}
</swc-icon>
</button>
<swc-ui-icon
slot="icon"
icon="chevron"
size="s"
aria-hidden="true"
></swc-ui-icon>
</swc-action-button>
`
: nothing}
</div>
Expand All @@ -984,26 +993,26 @@ export class PromptField extends SpectrumElement {

private _renderSendButton(): TemplateResult {
return html`
<button
<swc-action-button
class="swc-PromptField-send"
?disabled=${!this._isPopulated || this.disabled}
aria-label=${this.sendLabel}
accessible-label=${this.sendLabel}
@click=${this._handleSendClick}
>
<swc-icon aria-hidden="true">${ChevronUpIcon()}</swc-icon>
</button>
<swc-icon slot="icon" aria-hidden="true">${ChevronUpIcon()}</swc-icon>
</swc-action-button>
`;
}

private _renderStopButton(): TemplateResult {
return html`
<button
<swc-action-button
class="swc-PromptField-stop"
aria-label=${this.stopLabel}
accessible-label=${this.stopLabel}
@click=${this._handleStopClick}
>
<swc-icon aria-hidden="true">${StopIcon()}</swc-icon>
</button>
<swc-icon slot="icon" aria-hidden="true">${StopIcon()}</swc-icon>
</swc-action-button>
`;
}

Expand Down Expand Up @@ -1070,14 +1079,17 @@ export class PromptField extends SpectrumElement {
.inert=${this.collapsed}
>
<div class="swc-PromptField-leading-actions-row">
<button
<swc-action-button
quiet
class="swc-PromptField-upload"
aria-label=${this.uploadLabel}
accessible-label=${this.uploadLabel}
?disabled=${this.disabled}
@click=${this._handleUploadClick}
>
<swc-icon aria-hidden="true">${PlusIcon()}</swc-icon>
</button>
<swc-icon slot="icon" aria-hidden="true">
${PlusIcon()}
</swc-icon>
</swc-action-button>
</div>
</div>
${showStop ? this._renderStopButton() : this._renderSendButton()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,30 +284,27 @@

.swc-PromptField-artifacts-scroll-prev,
.swc-PromptField-artifacts-scroll-next {
display: inline-flex;
position: absolute;
inset-block-start: calc((var(--swc-prompt-field-artifact-badge-clearance, 0) + var(--swc-prompt-field-artifact-media-block-size, 68px)) / 2);
z-index: 4;
flex: 0 0 auto;
align-items: center;
justify-content: center;
inline-size: var(--swc-prompt-field-artifact-scroll-button-inline-size, 32px);
block-size: var(--swc-prompt-field-artifact-scroll-button-block-size, 32px);
padding: 0;
color: token("gray-800");
background: var(--_swc-prompt-field-artifact-scroll-button-background);
border: 1px solid transparent;
border-radius: token("corner-radius-800");
cursor: pointer;
transform: translateY(-50%);

--_swc-prompt-field-artifact-scroll-button-background: token("gray-100");
--_swc-prompt-field-artifact-scroll-icon-transform: none;
--swc-action-button-min-block-size: var(--swc-prompt-field-artifact-scroll-button-block-size, 32px);
--swc-action-button-icon-size: token("ui-icon-small");
--swc-action-button-edge-to-visual-only: calc((var(--swc-prompt-field-artifact-scroll-button-inline-size, 32px) - token("ui-icon-small")) / 2);
--swc-action-button-border-radius: token("corner-radius-800");
--swc-action-button-content-color-default: token("gray-800");
--swc-action-button-content-color-hover: token("gray-800");
--swc-action-button-background-color-default: token("gray-100");
--swc-action-button-background-color-hover: token("gray-200");
--swc-action-button-down-state-transform: none;
}

/* aria-disabled, not the disabled attribute, and hidden with opacity, not
* display/visibility: a chevron at the end of the strip stays mounted and
* keeps any focus it already has (native disabled and display/visibility
* keeps any focus it already has (the disabled property and display/visibility
* removal both blur it), so the button never needs a manual focus-redirect
* when scrolling makes it unusable. */
.swc-PromptField-artifacts-scroll-prev[aria-disabled="true"],
Expand All @@ -324,10 +321,8 @@
* not landing on a clean device pixel, which can leave a 1px unpainted
* sliver at a mask boundary that touches its edge exactly.
*
* z-index: -1, not 0: the button's own :focus-visible outline paints with
* its background/border layer, before z-index: 0 positioned descendants,
* so a z-index: 0 mask paints over (hides) the outline. A negative z-index
* puts this mask in the layer painted before that, so the outline is never
* z-index: -1 keeps the mask behind the shadow button face and its focus
* ring, which paint in the descendants layer above it, so neither is
* covered. */
.swc-PromptField-artifacts-scroll-prev::before,
.swc-PromptField-artifacts-scroll-next::before {
Expand All @@ -340,17 +335,6 @@
content: "";
}

.swc-PromptField-artifacts-scroll-prev::after,
.swc-PromptField-artifacts-scroll-next::after {
position: absolute;
inset: 0;
z-index: 1;
background: var(--_swc-prompt-field-artifact-scroll-button-background);
border-radius: inherit;
pointer-events: none;
content: "";
}

.swc-PromptField-artifacts-scroll-prev {
inset-inline-start: 0;

Expand All @@ -371,27 +355,11 @@
background: token("background-layer-2-color");
}

.swc-PromptField-artifacts-scroll-prev:hover,
.swc-PromptField-artifacts-scroll-next:hover {
--_swc-prompt-field-artifact-scroll-button-background: token("gray-200");
}

.swc-PromptField-artifacts-scroll-prev swc-icon,
.swc-PromptField-artifacts-scroll-next swc-icon {
display: inline-flex;
position: relative;
z-index: 2;
align-items: center;
justify-content: center;
.swc-PromptField-artifacts-scroll-prev swc-ui-icon,
.swc-PromptField-artifacts-scroll-next swc-ui-icon {
transform: var(--_swc-prompt-field-artifact-scroll-icon-transform);
}

.swc-PromptField-artifacts-scroll-prev:focus-visible,
.swc-PromptField-artifacts-scroll-next:focus-visible {
outline: token("focus-indicator-thickness") solid token("focus-indicator-color");
outline-offset: token("focus-ring-gap");
}

:host(:dir(rtl)) .swc-PromptField-artifacts-scroll-prev {
--_swc-prompt-field-artifact-scroll-icon-transform: none;
}
Expand Down Expand Up @@ -477,109 +445,54 @@
}

/* Upload button (quiet, left side) */

.swc-PromptField-upload {
display: flex;
align-items: center;
justify-content: center;
inline-size: var(--swc-prompt-field-upload-inline-size, 32px);
block-size: var(--swc-prompt-field-upload-block-size, 32px);
padding: 0;
color: token("gray-800");
background: transparent;
border: 1px solid transparent;
border-radius: token("corner-radius-500");
}

.swc-PromptField-upload:hover {
color: token("gray-800");
background: token("gray-75");
--swc-action-button-min-block-size: var(--swc-prompt-field-upload-block-size, 32px);
--swc-action-button-edge-to-visual-only: calc((var(--swc-prompt-field-upload-inline-size, 32px) - token("workflow-icon-medium")) / 2);
--swc-action-button-icon-size: token("workflow-icon-medium");
--swc-action-button-border-radius: token("corner-radius-500");
--swc-action-button-content-color-default: token("gray-800");
--swc-action-button-content-color-hover: token("gray-800");
--swc-action-button-background-color-hover: token("gray-75");
--swc-action-button-content-color-disabled: token("gray-400");
--swc-action-button-background-color-disabled: transparent;
}

.swc-PromptField-upload:disabled {
color: token("gray-400");
background: transparent;
}

.swc-PromptField-upload swc-icon {
--swc-icon-inline-size: token("workflow-icon-medium");
--swc-icon-block-size: token("workflow-icon-medium");
}

/* Send button (filled circle, right side) */

.swc-PromptField-send {
display: flex;
align-items: center;
justify-content: center;
inline-size: var(--swc-prompt-field-send-inline-size, 32px);
block-size: var(--swc-prompt-field-send-block-size, 32px);
padding: 0;
color: token("gray-25");
background: token("neutral-background-color-default");
border: 1px solid transparent;
border-radius: token("corner-radius-full");
}

.swc-PromptField-stop {
display: flex;
align-items: center;
justify-content: center;
inline-size: var(--swc-prompt-field-stop-inline-size, 32px);
block-size: var(--swc-prompt-field-stop-block-size, 32px);
padding: 0;
color: token("gray-25");
background: token("gray-900");
border: 1px solid transparent;
border-radius: token("corner-radius-full");
}
/* Send/stop buttons (filled round, anchored bottom-right) */

/* Anchored to .controls's own bottom-right, so it re-aligns on its own as .controls grows or shrinks with either row's content. */
.swc-PromptField-send,
.swc-PromptField-stop {
position: absolute;
inset-block-end: 0;
inset-inline-end: 0;
transition: background token("animation-duration-100") ease;
}

.swc-PromptField-send:disabled {
color: token("gray-400");
background: token("gray-100");
}

.swc-PromptField-send:focus-visible,
.swc-PromptField-stop:focus-visible {
outline: token("focus-indicator-thickness") solid token("focus-indicator-color");
outline-offset: token("focus-ring-gap");
}

.swc-PromptField-send:active,
.swc-PromptField-stop:active {
transform: perspective(64px) translate3d(0, 0, -1px);
transition: transform token("animation-duration-200") ease;
transition-timing-function: token("animation-ease-in-out");
will-change: transform;
--swc-action-button-min-block-size: var(--swc-prompt-field-send-block-size, 32px);
--swc-action-button-edge-to-visual-only: calc((var(--swc-prompt-field-send-inline-size, 32px) - token("workflow-icon-medium")) / 2);
--swc-action-button-icon-size: token("workflow-icon-medium");
--swc-action-button-border-radius: token("corner-radius-full");
--swc-action-button-down-state-transform: perspective(64px) translate3d(0, 0, -1px);
}

.swc-PromptField-send:hover:not(:disabled) {
background: token("neutral-background-color-hover");
}

.swc-PromptField-send swc-icon {
--swc-icon-inline-size: token("workflow-icon-medium");
--swc-icon-block-size: token("workflow-icon-medium");
}

/* Stop button (filled black circle, right side) */

.swc-PromptField-stop:hover {
background: token("gray-800");
/* Send button (filled neutral circle) */
.swc-PromptField-send {
--swc-action-button-content-color-default: token("gray-25");
--swc-action-button-content-color-hover: token("gray-25");
--swc-action-button-content-color-down: token("gray-25");
--swc-action-button-background-color-default: token("neutral-background-color-default");
--swc-action-button-background-color-hover: token("neutral-background-color-hover");
--swc-action-button-background-color-down: token("neutral-background-color-default");
--swc-action-button-content-color-disabled: token("gray-400");
--swc-action-button-background-color-disabled: token("gray-100");
}

.swc-PromptField-stop swc-icon {
--swc-icon-inline-size: token("workflow-icon-medium");
--swc-icon-block-size: token("workflow-icon-medium");
/* Stop button (filled black circle) */
.swc-PromptField-stop {
--swc-action-button-content-color-default: token("gray-25");
--swc-action-button-content-color-hover: token("gray-25");
--swc-action-button-content-color-down: token("gray-25");
--swc-action-button-background-color-default: token("gray-900");
--swc-action-button-background-color-hover: token("gray-800");
--swc-action-button-background-color-down: token("gray-900");
}

/* ─────────────────────────────────────
Expand Down
Loading
Loading