| // Copyright (C) 2026 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Styles for the Heapdump Explorer plugin. |
| // The CSS reset is provided by Perfetto's global styles. |
| |
| .pf-hde-page { |
| // Domain-specific badge tokens — no --pf-* equivalent. |
| --pf-hde-badge-reachability: #d97706; |
| --pf-hde-badge-root: #f43f5e; |
| --pf-hde-badge-string: #047857; |
| |
| .pf-theme-provider--dark & { |
| --pf-hde-badge-reachability: #fbbf24; |
| --pf-hde-badge-root: #fb7185; |
| --pf-hde-badge-string: #34d399; |
| } |
| |
| height: 100%; |
| background: var(--pf-color-background-secondary); |
| display: flex; |
| flex-direction: column; |
| color: var(--pf-color-text); |
| overflow: hidden; |
| } |
| |
| .pf-hde-main { |
| flex: 1; |
| min-height: 0; |
| display: flex; |
| flex-direction: column; |
| overflow: hidden; |
| padding: 1rem; |
| max-width: 95%; |
| margin: 0 auto; |
| width: 100%; |
| font-size: 0.875rem; |
| line-height: 1.25rem; |
| |
| // The Tabs widget's content area must be a flex column so that DataGrid |
| // views (which use flex: 1 on .pf-hde-view-content) fill the available height. |
| .pf-tabs__content { |
| display: flex; |
| flex-direction: column; |
| } |
| } |
| |
| .pf-hde-heading-row { |
| display: flex; |
| align-items: baseline; |
| gap: 0.75rem; |
| margin-bottom: 0.75rem; |
| |
| // Remove the heading's own bottom margin when inside a heading row. |
| .pf-hde-view-heading { |
| margin-bottom: 0; |
| } |
| } |
| |
| // Inline label+control (e.g. "Path: <select>") sitting at the right edge |
| // of an .pf-hde-heading-row. |
| .pf-hde-heading-control { |
| margin-left: auto; |
| display: inline-flex; |
| align-items: center; |
| gap: 0.375rem; |
| font-size: 0.875rem; |
| |
| &__label { |
| color: var(--pf-color-text-hint); |
| } |
| } |
| |
| // Flex-growing wrapper for view content with a DataGrid that fills height. |
| .pf-hde-view-content { |
| flex: 1; |
| min-height: 0; |
| display: flex; |
| flex-direction: column; |
| } |
| |
| // Empty state for scroll views (bitmaps, etc.) where fillHeight cannot resolve |
| // against a fixed parent. Uses viewport-relative height minus the page shell |
| // (tab bar + padding) to vertically center the icon. |
| .pf-hde-empty-fill { |
| height: calc(100vh - 200px); |
| } |
| |
| .pf-hde-loading { |
| color: var(--pf-color-text-hint); |
| padding: 1rem; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| flex: 1; |
| } |
| |
| .pf-hde-dump-selector { |
| flex: none; |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| padding: 0.5rem 1rem; |
| background: var(--pf-color-background); |
| border-bottom: 1px solid var(--pf-color-border); |
| font-size: 0.875rem; |
| } |
| |
| .pf-hde-dump-selector__label { |
| color: var(--pf-color-text-hint); |
| } |
| |
| .pf-hde-error-text { |
| color: var(--pf-color-danger); |
| padding: 1rem; |
| } |
| |
| .pf-hde-view-heading { |
| font-size: 1.125rem; |
| line-height: 1.75rem; |
| font-weight: 600; |
| margin-bottom: 0.75rem; |
| color: var(--pf-color-text); |
| } |
| |
| .pf-hde-default-changed-callout { |
| margin-bottom: 1rem; |
| align-items: center; |
| gap: 0.75rem; |
| |
| p { |
| margin: 0; |
| display: flex; |
| align-items: center; |
| flex-wrap: wrap; |
| justify-content: space-between; |
| gap: 0.5rem; |
| } |
| } |
| |
| .pf-hde-muted-heading { |
| font-size: 0.875rem; |
| color: var(--pf-color-text-hint); |
| margin-bottom: 0.5rem; |
| } |
| |
| .pf-hde-sub-heading { |
| font-size: 0.8125rem; |
| line-height: 1.25rem; |
| font-weight: 600; |
| color: var(--pf-color-text-muted); |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| margin-bottom: 0.5rem; |
| } |
| |
| .pf-hde-card { |
| background: var(--pf-color-background); |
| border: 1px solid var(--pf-color-border); |
| padding: 1rem; |
| } |
| |
| .pf-hde-card--compact { |
| @extend .pf-hde-card; |
| padding: 0.75rem; |
| } |
| |
| .pf-hde-bitmap-image { |
| max-width: 100%; |
| max-height: 100%; |
| object-fit: contain; |
| image-rendering: pixelated; |
| } |
| |
| .pf-hde-bitmap-card { |
| border: 1px solid var(--pf-color-border); |
| border-radius: 3px; |
| overflow: hidden; |
| margin-bottom: 1rem; |
| } |
| |
| .pf-hde-bitmap-card__image { |
| margin: 0 auto; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| padding: 0.5rem; |
| } |
| |
| .pf-hde-bitmap-card__info { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| padding: 0.5rem 0.75rem; |
| border-top: 1px solid var(--pf-color-border); |
| font-size: 0.875rem; |
| } |
| |
| .pf-hde-bitmap-card__secondary { |
| margin-left: 0.75rem; |
| color: var(--pf-color-text-hint); |
| } |
| |
| .pf-hde-bitmap-card__path { |
| padding: 0.5rem 0.75rem; |
| border-top: 1px solid var(--pf-color-border-secondary); |
| font-size: 0.8125rem; |
| } |
| |
| .pf-hde-info-grid { |
| display: grid; |
| grid-template-columns: auto 1fr; |
| gap: 0.375rem 1rem; |
| } |
| |
| .pf-hde-info-grid--compact { |
| @extend .pf-hde-info-grid; |
| gap: 0.25rem 1rem; |
| } |
| |
| .pf-hde-info-grid__label { |
| color: var(--pf-color-text-muted); |
| } |
| |
| .pf-hde-section { |
| background: var(--pf-color-background); |
| border: 1px solid var(--pf-color-border); |
| } |
| |
| .pf-hde-section__header { |
| display: flex; |
| align-items: stretch; |
| } |
| |
| .pf-hde-section__toggle { |
| flex: 1; |
| padding: 0.5rem 1rem; |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| text-align: left; |
| &:hover { |
| background: var(--pf-color-background-secondary); |
| } |
| } |
| |
| .pf-hde-section__actions { |
| display: flex; |
| align-items: center; |
| padding: 0 1rem; |
| gap: 0.5rem; |
| border-left: 1px solid var(--pf-color-border-secondary); |
| } |
| |
| .pf-hde-section__title { |
| font-size: 0.875rem; |
| line-height: 1.25rem; |
| font-weight: 600; |
| color: var(--pf-color-text-muted); |
| } |
| |
| .pf-hde-section__chevron { |
| width: 0.75rem; |
| height: 0.75rem; |
| color: var(--pf-color-text-hint); |
| transition: transform 0.15s; |
| } |
| |
| .pf-hde-section__chevron--open { |
| transform: rotate(90deg); |
| } |
| |
| .pf-hde-section__body { |
| padding: 0.75rem 1rem; |
| border-top: 1px solid var(--pf-color-border-secondary); |
| overflow-x: auto; |
| |
| // Cap DataGrid height so each section grid scrolls internally via virtual |
| // scroll, while the page scrolls between sections. Use overflow: auto |
| // (overriding the DataGrid default of overflow: hidden) so the empty state |
| // icon is not clipped. |
| .pf-data-grid { |
| max-height: 400px; |
| overflow: auto; |
| } |
| } |
| |
| .pf-hde-link { |
| color: var(--pf-color-primary); |
| text-decoration: underline; |
| &:hover { |
| color: var(--pf-color-accent); |
| } |
| } |
| |
| .pf-hde-link--alt { |
| color: var(--pf-color-primary); |
| &:hover { |
| text-decoration: underline; |
| } |
| } |
| |
| .pf-hde-badge-reachability { |
| color: var(--pf-hde-badge-reachability); |
| font-size: 0.8125rem; |
| line-height: 1.25rem; |
| margin-right: 0.25rem; |
| } |
| |
| .pf-hde-badge-root { |
| color: var(--pf-hde-badge-root); |
| font-size: 0.8125rem; |
| line-height: 1.25rem; |
| margin-right: 0.25rem; |
| } |
| |
| .pf-hde-badge-string { |
| color: var(--pf-hde-badge-string); |
| margin-left: 0.25rem; |
| } |
| |
| .pf-hde-badge-referent { |
| color: var(--pf-color-text-hint); |
| margin-left: 0.25rem; |
| } |
| |
| .pf-hde-download-link { |
| font-size: 0.875rem; |
| line-height: 1.25rem; |
| color: var(--pf-color-primary); |
| cursor: pointer; |
| &:hover { |
| text-decoration: underline; |
| } |
| } |
| |
| .pf-hde-path-arrow { |
| color: var(--pf-color-text-hint); |
| } |
| |
| .pf-hde-path-field { |
| color: var(--pf-color-text-muted); |
| } |
| |
| .pf-hde-view-stack > * + * { |
| margin-top: 0.75rem; |
| } |
| |
| .pf-hde-view-stack--tight > * + * { |
| margin-top: 0.125rem; |
| } |
| |
| .pf-hde-mono { |
| font-family: var(--pf-font-monospace); |
| } |
| .pf-hde-semibold { |
| font-weight: 600; |
| } |
| .pf-hde-break-all { |
| word-break: break-all; |
| } |
| .pf-hde-opacity-60 { |
| opacity: 0.6; |
| } |
| |
| .pf-hde-view-heading--tight { |
| margin-bottom: 0.25rem; |
| } |
| |
| .pf-hde-action-row { |
| display: flex; |
| align-items: center; |
| gap: 0.75rem; |
| } |
| |
| .pf-hde-bitmap-meta { |
| display: flex; |
| align-items: center; |
| gap: 0.75rem; |
| color: var(--pf-color-text-muted); |
| } |
| |
| .pf-hde-path-entry { |
| display: flex; |
| align-items: center; |
| gap: 0.25rem; |
| padding-left: calc(min(var(--pf-hde-depth, 0), 20) * 0.75rem); |
| } |
| |
| .pf-hde-dup-grid-container { |
| height: 400px; |
| } |
| |
| .pf-hde-desc { |
| font-size: 0.875rem; |
| line-height: 1.25rem; |
| color: var(--pf-color-text-muted); |
| margin-bottom: 0.5rem; |
| } |
| |
| .pf-hde-str-color { |
| color: var(--pf-hde-badge-string); |
| } |
| |
| .pf-hde-str-badge { |
| color: var(--pf-hde-badge-string); |
| margin-left: 0.25rem; |
| } |
| |
| .pf-hde-muted { |
| color: var(--pf-color-text-muted); |
| } |
| |
| .pf-hde-flex-none { |
| flex-shrink: 0; |
| } |
| |
| // Spacing (minimal set) |
| .pf-hde-mt-1 { |
| margin-top: 0.25rem; |
| } |
| .pf-hde-mb-2 { |
| margin-bottom: 0.5rem; |
| } |
| .pf-hde-mb-3 { |
| margin-bottom: 0.75rem; |
| } |
| .pf-hde-mb-4 { |
| margin-bottom: 1rem; |
| } |
| .pf-hde-mt-4 { |
| margin-top: 1rem; |
| } |
| |
| .pf-hde-col-header { |
| display: inline-flex; |
| align-items: center; |
| gap: 0.25rem; |
| } |
| |
| .pf-hde-col-header__info { |
| color: var(--pf-color-fg-muted, #888); |
| font-size: 14px; |
| cursor: help; |
| opacity: 0; |
| transition: opacity 0.15s ease; |
| } |
| |
| .pf-hde-col-header:hover .pf-hde-col-header__info { |
| opacity: 1; |
| } |
| |
| .pf-hde-col-header__info:hover { |
| color: var(--pf-color-fg, #333); |
| } |