UNPKG

chrome-devtools-frontend

Version:
945 lines (807 loc) • 21.5 kB
/* * Copyright 2024 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ * { box-sizing: border-box; margin: 0; padding: 0; } :host { width: 100%; height: 100%; user-select: text; display: flex; flex-direction: column; background-color: var(--sys-color-cdt-base-container); } .chat-ui { width: 100%; height: 100%; max-height: 100%; display: flex; flex-direction: column; container-type: size; container-name: --chat-ui-container; } .input-form { display: flex; flex-direction: column; padding: 0 var(--sys-size-5) 0 var(--sys-size-5); max-width: var(--sys-size-36); background-color: var(--sys-color-cdt-base-container); width: 100%; position: sticky; z-index: 9999; bottom: 0; padding-bottom: var(--sys-size-5); /* The `box-shadow` is a workaround to hide the content appearing between the `.input-form` and the footer in some resolutions even though the `.input-form` has `bottom: 0`. */ box-shadow: 0 1px var(--sys-color-cdt-base-container); /* Prevents the input form from jumping when the scrollbar is shown */ /* 688px is the max width of the input form + left and right paddings: var(--sys-size-36) + 2 * var(--sys-size-5) */ @container (width > 688px) { --half-scrollbar-width: calc((100cqw - 100%) / 2); margin-left: var(--half-scrollbar-width); margin-right: calc(-1 * var(--half-scrollbar-width)); } /* when there isn't enough space to view the messages, do not overlay the input form on top of the messages */ /* height < var(--sys-size-27) */ @container (height < 224px) { margin-top: var(--sys-size-4); margin-bottom: var(--sys-size-4); position: static; } @container --chat-ui-container (width < 400px) { /* The footer already adds necessary paddings for this state. However, without the `padding-bottom` here, the outline in the bottom is rendered behind the footer. So, we add 1px space here to make sure that the outline is rendered fully. */ padding-bottom: var(--sys-size-1); } } .chat-readonly-container { display: flex; width: 100%; max-width: var(--sys-size-36); justify-content: center; align-items: center; background-color: var(--sys-color-surface3); font: var(--sys-typescale-body4-regular); padding: var(--sys-size-5) 0; border-radius: var(--sys-shape-corner-medium-small); margin-bottom: var(--sys-size-5); color: var(--sys-color-on-surface-subtle); } .chat-input-container { width: 100%; display: flex; position: relative; flex-direction: column; border: 1px solid var(--sys-color-neutral-outline); border-radius: var(--sys-shape-corner-small); &:focus-within { outline: 1px solid var(--sys-color-primary); border-color: var(--sys-color-primary); } &.disabled { background-color: var(--sys-color-state-disabled-container); border-color: transparent; & .chat-input-disclaimer { border-color: var(--sys-color-state-disabled); } } &.single-line-layout { flex-direction: row; justify-content: space-between; .chat-input { flex-shrink: 1; padding: var(--sys-size-4); } .chat-input-actions { flex-shrink: 0; padding-block: 0; align-items: flex-end; padding-bottom: var(--sys-size-1); } } & .image-input-container { margin: var(--sys-size-3) var(--sys-size-4) 0; max-width: 100%; width: fit-content; position: relative; devtools-button { position: absolute; top: calc(-1 * var(--sys-size-2)); right: calc(-1 * var(--sys-size-3)); border-radius: var(--sys-shape-corner-full); border: 1px solid var(--sys-color-neutral-outline); background-color: var(--sys-color-cdt-base-container); } img { max-height: var(--sys-size-18); max-width: 100%; border: 1px solid var(--sys-color-neutral-outline); border-radius: var(--sys-shape-corner-small); } .loading { margin: var(--sys-size-4) 0; display: inline-flex; justify-content: center; align-items: center; height: var(--sys-size-18); width: var(--sys-size-19); background-color: var(--sys-color-surface3); border-radius: var(--sys-shape-corner-small); border: 1px solid var(--sys-color-neutral-outline); devtools-spinner { color: var(--sys-color-state-disabled); } } } & .chat-input-disclaimer-container { display: flex; align-items: center; padding-right: var(--sys-size-3); flex-shrink: 0; } & .chat-input-disclaimer { display: flex; justify-content: center; align-items: center; font: var(--sys-typescale-body5-regular); border-right: 1px solid var(--sys-color-divider); padding-right: 8px; &.hide-divider { border-right: none; } } /* Hide the inline disclaimer on narrow widths (< 400px) because space is limited and the disclaimer is shown in the footer instead for this case. */ @container --chat-ui-container (width < 400px) { & .chat-input-disclaimer-container { display: none; } } } .chat-input { scrollbar-width: none; field-sizing: content; resize: none; width: 100%; max-height: 84px; /* 4 rows */ border: 0; border-radius: var(--sys-shape-corner-small); font: var(--sys-typescale-body4-regular); line-height: 18px; min-height: var(--sys-size-11); color: var(--sys-color-on-surface); background-color: var(--sys-color-cdt-base-container); padding: var(--sys-size-4) var(--sys-size-4) var(--sys-size-3) var(--sys-size-4); &::placeholder { opacity: 60%; } &:focus-visible { outline: 0; } &:disabled { color: var(--sys-color-state-disabled); background-color: transparent; border-color: transparent; &::placeholder { color: var(--sys-color-on-surface-subtle); opacity: 100%; } } } .chat-input-actions { display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding-left: var(--sys-size-4); padding-right: var(--sys-size-2); gap: var(--sys-size-6); padding-bottom: var(--sys-size-2); & .chat-input-actions-left { flex: 1 1 0; min-width: 0; } & .chat-input-actions-right { flex-shrink: 0; display: flex; & .start-new-chat-button { padding-bottom: var(--sys-size-2); padding-right: var(--sys-size-3); } } } .chat-inline-button { padding-left: 3px; } .chat-cancel-context-button { padding-bottom: 3px; padding-right: var(--sys-size-3); } footer.chat-view-footer { display: flex; justify-content: center; padding-block: var(--sys-size-3); font: var(--sys-typescale-body5-regular); border-top: 1px solid var(--sys-color-divider); text-wrap: balance; text-align: center; /* The footer (for active conversations) is hidden by default on wider screens because the disclaimer is shown inline within the chat input actions. Show it only on narrow widths (< 400px). */ &.has-conversation:not(.is-read-only) { display: none; border: none; @container --chat-ui-container (width < 400px) { display: flex; } } } .messages-container { flex-grow: 1; width: 100%; max-width: var(--sys-size-36); /* Prevents the container from jumping when the scrollbar is shown */ /* 688px is the max width of the input form + left and right paddings: var(--sys-size-36) + 2 * var(--sys-size-5) */ @container (width > 688px) { --half-scrollbar-width: calc((100cqw - 100%) / 2); margin-left: var(--half-scrollbar-width); margin-right: calc(-1 * var(--half-scrollbar-width)); } } .chat-message { user-select: text; cursor: initial; display: flex; flex-direction: column; gap: var(--sys-size-5); width: 100%; padding: var(--sys-size-7) var(--sys-size-5); font-size: 12px; word-break: normal; overflow-wrap: anywhere; border-bottom: var(--sys-size-1) solid var(--sys-color-divider); &:last-of-type { border-bottom: 0; } .message-info { display: flex; align-items: center; height: var(--sys-size-11); gap: var(--sys-size-4); font: var(--sys-typescale-body4-bold); img { border: 0; border-radius: var(--sys-shape-corner-full); display: block; height: var(--sys-size-9); width: var(--sys-size-9); } h2 { font: var(--sys-typescale-body4-bold); } } .actions { display: flex; flex-direction: column; gap: var(--sys-size-8); max-width: 100%; } .aborted { color: var(--sys-color-on-surface-subtle); } .image-link { width: fit-content; border-radius: var(--sys-shape-corner-small); outline-offset: var(--sys-size-2); img { max-height: var(--sys-size-20); max-width: 100%; border-radius: var(--sys-shape-corner-small); border: 1px solid var(--sys-color-neutral-outline); width: fit-content; vertical-align: bottom; } } .unavailable-image { margin: var(--sys-size-4) 0; display: inline-flex; justify-content: center; align-items: center; height: var(--sys-size-17); width: var(--sys-size-18); background-color: var(--sys-color-surface3); border-radius: var(--sys-shape-corner-small); border: 1px solid var(--sys-color-neutral-outline); devtools-icon { color: var(--sys-color-state-disabled); } } } .select-element { display: flex; gap: var(--sys-size-3); align-items: center; .resource-link, .resource-task { cursor: pointer; padding: var(--sys-size-2) var(--sys-size-3); font: var(--sys-typescale-body5-regular); border: var(--sys-size-1) solid var(--sys-color-divider); border-radius: var(--sys-shape-corner-extra-small); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; /* Allow the link/task item to shrink below its intrinsic minimum width in the flex container, enabling text-overflow ellipsis to work correctly. */ min-width: 0; line-height: 1; & .title { vertical-align: middle; font: var(--sys-typescale-body5-regular); } &.has-picker-behavior { overflow: visible; } &:focus-visible { outline: 2px solid var(--sys-color-state-focus-ring); } devtools-icon, devtools-file-source-icon { display: inline-flex; vertical-align: middle; width: var(--sys-size-7); height: var(--sys-size-7); } /* CSS styling for `network-override-marker` is similar to https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/network/networkLogView.css;l=379. There is a difference in `left` and `top` values to make sure it is placed correctly for the network icon in assistance panel. */ .network-override-marker { position: relative; float: left; } .network-override-marker::before { content: var(--image-file-empty); width: var(--sys-size-4); height: var(--sys-size-4); border-radius: 50%; outline: var(--sys-size-1) solid var(--icon-gap-focus-selected); left: 11px; position: absolute; top: 13px; z-index: 1; background-color: var(--sys-color-purple-bright); } .image.icon { display: inline-flex; justify-content: center; align-items: center; vertical-align: middle; margin-right: var(--sys-size-3); img { max-width: var(--sys-size-7); max-height: var(--sys-size-7); } } } .resource-link.disabled, .resource-task.disabled, .resource-link.not-selected, .resource-task.not-selected { color: var(--sys-color-state-disabled); border-color: var(--sys-color-neutral-outline); } .resource-link.disabled, .resource-task.disabled { pointer-events: none; } } .indicator { color: var(--sys-color-green-bright); } .summary { display: grid; grid-template-columns: auto 1fr auto; padding: var(--sys-size-3); line-height: var(--sys-size-9); cursor: default; gap: var(--sys-size-3); justify-content: center; align-items: center; .title { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; font: var(--sys-typescale-body4-regular); .paused { font: var(--sys-typescale-body4-bold); } } } .step-code { display: flex; flex-direction: column; gap: var(--sys-size-2); } .js-code-output { devtools-code-block { --code-block-max-code-height: 50px; } } .context-details { devtools-code-block { --code-block-max-code-height: 80px; } } .step { width: fit-content; background-color: var(--sys-color-surface3); border-radius: var(--sys-size-6); position: relative; &.empty { pointer-events: none; .arrow { display: none; } } &:not(&[open]):hover::after { content: ''; height: 100%; width: 100%; border-radius: inherit; position: absolute; top: 0; left: 0; pointer-events: none; background-color: var(--sys-color-state-hover-on-subtle); } &.paused { .indicator { color: var(--sys-color-on-surface-subtle); } } &.canceled { .summary { color: var(--sys-color-state-disabled); text-decoration: line-through; } .indicator { color: var(--sys-color-state-disabled); } } devtools-markdown-view { --code-background-color: var(--sys-color-surface1); } devtools-icon { vertical-align: bottom; } devtools-spinner { width: var(--sys-size-9); height: var(--sys-size-9); padding: var(--sys-size-2); } &[open] { width: auto; .summary .title { white-space: normal; overflow: unset; } .summary .arrow { transform: rotate(180deg); } } summary::marker { content: ''; } summary { border-radius: var(--sys-size-6); } .step-details { padding: 0 var(--sys-size-5) var(--sys-size-4) var(--sys-size-12); display: flex; flex-direction: column; gap: var(--sys-size-6); devtools-code-block { --code-block-background-color: var(--sys-color-surface1); } } } .link { color: var(--text-link); text-decoration: underline; cursor: pointer; } button.link { border: none; background: none; font: inherit; &:focus-visible { outline: var(--sys-size-2) solid var(--sys-color-state-focus-ring); outline-offset: 0; border-radius: var(--sys-shape-corner-extra-small); } } .select-an-element-text { margin-left: 2px; } main { overflow: hidden auto; display: flex; flex-direction: column; align-items: center; height: 100%; container-type: size; scrollbar-width: thin; /* Even though `transform: translateZ(1px)` doesn't have a visual effect, it puts `main` element into another rendering layer which somehow fixes the `.input-form` jumping on scroll issue. */ transform: translateZ(1px); scroll-timeline: --scroll-timeline y; } .empty-state-container { flex-grow: 1; display: grid; align-items: center; justify-content: center; font: var(--sys-typescale-headline4); gap: var(--sys-size-8); padding: var(--sys-size-3); max-width: var(--sys-size-33); /* Prevents the container from jumping when the scrollbar is shown */ /* 688px is the max width of the input form + left and right paddings: var(--sys-size-36) + 2 * var(--sys-size-5) */ @container (width > 688px) { --half-scrollbar-width: calc((100cqw - 100%) / 2); margin-left: var(--half-scrollbar-width); margin-right: calc(-1 * var(--half-scrollbar-width)); } .header { display: flex; flex-direction: column; width: 100%; align-items: center; justify-content: center; align-self: end; gap: var(--sys-size-5); .icon { display: flex; justify-content: center; align-items: center; height: var(--sys-size-14); width: var(--sys-size-14); border-radius: var(--sys-shape-corner-small); background: linear-gradient( 135deg, var(--sys-color-gradient-primary), var(--sys-color-gradient-tertiary) ); } h1 { font: var(--sys-typescale-headline4); } p { text-align: center; font: var(--sys-typescale-body4-regular); } } .empty-state-content { display: flex; flex-direction: column; gap: var(--sys-size-5); align-items: center; justify-content: center; align-self: start; } } .disabled-view { display: flex; max-width: var(--sys-size-34); border-radius: var(--sys-shape-corner-small); box-shadow: var(--sys-elevation-level3); background-color: var(--app-color-card-background); font: var(--sys-typescale-body4-regular); text-wrap: pretty; padding: var(--sys-size-6) var(--sys-size-8); margin: var(--sys-size-4) 0; line-height: var(--sys-size-9); .disabled-view-icon-container { border-radius: var(--sys-shape-corner-extra-small); width: var(--sys-size-9); height: var(--sys-size-9); background: linear-gradient( 135deg, var(--sys-color-gradient-primary), var(--sys-color-gradient-tertiary) ); margin-right: var(--sys-size-5); devtools-icon { margin: var(--sys-size-2); width: var(--sys-size-8); height: var(--sys-size-8); } } } .error-step { color: var(--sys-color-error); } .side-effect-confirmation { display: flex; flex-direction: column; gap: var(--sys-size-5); padding-bottom: var(--sys-size-4); } .side-effect-buttons-container { display: flex; gap: var(--sys-size-4); } .change-summary { background-color: var(--sys-color-surface3); border-radius: var(--sys-shape-corner-medium-small); position: relative; margin: 0 var(--sys-size-5) var(--sys-size-7) var(--sys-size-5); padding: 0 var(--sys-size-5); &.saved-to-disk { pointer-events: none; } & .header-container { display: flex; align-items: center; gap: var(--sys-size-3); height: var(--sys-size-14); padding-left: var(--sys-size-3); devtools-spinner { width: var(--sys-size-6); height: var(--sys-size-6); margin-left: var(--sys-size-3); margin-right: var(--sys-size-3); } & devtools-icon.summary-badge { width: var(--sys-size-8); height: var(--sys-size-8); } & .green-bright-icon { color: var(--sys-color-green-bright); } & .on-tonal-icon { color: var(--sys-color-on-tonal-container); } & .header-text { font: var(--sys-typescale-body4); color: var(--sys-color-on-surface); white-space: nowrap; overflow-x: hidden; text-overflow: ellipsis; } & .arrow { margin-left: auto; } &::marker { content: ''; } } /* TODO(b/412621009): Remove this once the bug is fixed on the VE logging side */ &:not(.saved-to-disk, &[open]) > *:not(summary) { display: none; } &:not(.saved-to-disk, &[open]):hover::after { content: ''; height: 100%; width: 100%; border-radius: inherit; position: absolute; top: 0; left: 0; pointer-events: none; background-color: var(--sys-color-state-hover-on-subtle); } &[open]:not(.saved-to-disk) { &::details-content { height: fit-content; padding: var(--sys-size-2) 0; border-radius: inherit; } summary .arrow { transform: rotate(180deg); } } devtools-code-block { margin-bottom: var(--sys-size-5); --code-block-background-color: var(--sys-color-surface1); } .error-container { display: flex; align-items: center; gap: var(--sys-size-3); color: var(--sys-color-error); devtools-icon { color: var(--sys-color-error); } } .footer { display: flex; flex-flow: row wrap; justify-content: space-between; margin: var(--sys-size-5) 0 var(--sys-size-5) var(--sys-size-2); gap: var(--sys-size-6) var(--sys-size-5); .disclaimer-link { align-self: center; } .left-side { flex-grow: 1; display: flex; align-self: center; gap: var(--sys-size-3); } .save-or-discard-buttons { flex-grow: 1; display: flex; justify-content: flex-end; gap: var(--sys-size-3); } .change-workspace { display: flex; flex-direction: row; align-items: center; gap: var(--sys-size-3); min-width: var(--sys-size-22); flex: 1 1 40%; .folder-name { white-space: nowrap; overflow-x: hidden; text-overflow: ellipsis; } } .loading-text-container { margin-right: var(--sys-size-3); display: flex; justify-content: center; align-items: center; gap: var(--sys-size-3); } .apply-to-workspace-container { display: flex; align-items: center; gap: var(--sys-size-3); min-width: fit-content; justify-content: flex-end; flex-grow: 1; flex-shrink: 1; devtools-icon { /* var(--sys-size-8) is too small and var(--sys-size-9) is too big. */ width: 18px; height: 18px; margin-left: var(--sys-size-2); } } } } @keyframes reveal { 0%, 99% { opacity: 100%; } 100% { opacity: 0%; } }