mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Exemplars: Update UX to match new tooltips (#79916)
This commit is contained in:
@@ -4791,14 +4791,6 @@ exports[`better eslint`] = {
|
||||
"public/app/features/visualization/data-hover/DataHoverRows.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"]
|
||||
],
|
||||
"public/app/features/visualization/data-hover/DataHoverView.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "1"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "2"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "3"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "4"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "5"]
|
||||
],
|
||||
"public/app/plugins/datasource/alertmanager/DataSource.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
@@ -6514,19 +6506,6 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
|
||||
],
|
||||
"public/app/plugins/panel/timeseries/plugins/ExemplarMarker.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "1"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "2"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "3"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "4"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "5"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "6"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "7"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "8"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "9"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "10"]
|
||||
],
|
||||
"public/app/plugins/panel/timeseries/plugins/ThresholdDragHandle.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "1"],
|
||||
|
||||
@@ -10,10 +10,13 @@ import {
|
||||
GrafanaTheme2,
|
||||
LinkModel,
|
||||
} from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SortOrder, TooltipDisplayMode } from '@grafana/schema';
|
||||
import { TextLink, useStyles2 } from '@grafana/ui';
|
||||
import { renderValue } from 'app/plugins/panel/geomap/utils/uiUtils';
|
||||
|
||||
import { ExemplarHoverView } from './ExemplarHoverView';
|
||||
|
||||
export interface Props {
|
||||
data?: DataFrame; // source data
|
||||
rowIndex?: number | null; // the hover row
|
||||
@@ -110,6 +113,10 @@ export const DataHoverView = ({ data, rowIndex, columnIndex, sortOrder, mode, he
|
||||
|
||||
const { displayValues, links } = dispValuesAndLinks;
|
||||
|
||||
if (config.featureToggles.newVizTooltips && header === 'Exemplar') {
|
||||
return <ExemplarHoverView displayValues={displayValues} links={links} header={header} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
{header && (
|
||||
@@ -142,45 +149,44 @@ export const DataHoverView = ({ data, rowIndex, columnIndex, sortOrder, mode, he
|
||||
};
|
||||
const getStyles = (theme: GrafanaTheme2, padding = 0) => {
|
||||
return {
|
||||
wrapper: css`
|
||||
padding: ${padding}px;
|
||||
background: ${theme.components.tooltip.background};
|
||||
border-radius: ${theme.shape.borderRadius(2)};
|
||||
`,
|
||||
header: css`
|
||||
background: ${theme.colors.background.secondary};
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
display: flex;
|
||||
padding-bottom: ${theme.spacing(1)};
|
||||
`,
|
||||
title: css`
|
||||
font-weight: ${theme.typography.fontWeightMedium};
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
flex-grow: 1;
|
||||
`,
|
||||
infoWrap: css`
|
||||
padding: ${theme.spacing(1)};
|
||||
background: transparent;
|
||||
border: none;
|
||||
th {
|
||||
font-weight: ${theme.typography.fontWeightMedium};
|
||||
padding: ${theme.spacing(0.25, 2, 0.25, 0)};
|
||||
}
|
||||
wrapper: css({
|
||||
padding: `${padding}px`,
|
||||
background: theme.components.tooltip.background,
|
||||
borderRadius: theme.shape.borderRadius(2),
|
||||
}),
|
||||
header: css({
|
||||
background: theme.colors.background.secondary,
|
||||
alignItems: 'center',
|
||||
alignContent: 'center',
|
||||
display: 'flex',
|
||||
paddingBottom: theme.spacing(1),
|
||||
}),
|
||||
title: css({
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
overflow: 'hidden',
|
||||
display: 'inline-block',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
flexGrow: 1,
|
||||
}),
|
||||
infoWrap: css({
|
||||
padding: theme.spacing(1),
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
th: {
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
padding: theme.spacing(0.25, 2, 0.25, 0),
|
||||
},
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid ${theme.colors.border.weak};
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
`,
|
||||
highlight: css``,
|
||||
link: css`
|
||||
color: ${theme.colors.text.link};
|
||||
`,
|
||||
tr: {
|
||||
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
||||
'&:last-child': {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
},
|
||||
}),
|
||||
link: css({
|
||||
color: theme.colors.text.link,
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { GrafanaTheme2, LinkModel } from '@grafana/data';
|
||||
import { HorizontalGroup, LinkButton, useStyles2 } from '@grafana/ui';
|
||||
import { renderValue } from 'app/plugins/panel/geomap/utils/uiUtils';
|
||||
|
||||
import { DisplayValue } from './DataHoverView';
|
||||
|
||||
export interface Props {
|
||||
displayValues: DisplayValue[];
|
||||
links?: LinkModel[];
|
||||
header?: string;
|
||||
}
|
||||
|
||||
export const ExemplarHoverView = ({ displayValues, links, header = 'Exemplar' }: Props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const time = displayValues.find((val) => val.name === 'Time');
|
||||
displayValues = displayValues.filter((val) => val.name !== 'Time'); // time?
|
||||
|
||||
return (
|
||||
<div className={styles.exemplarWrapper}>
|
||||
<div className={styles.exemplarHeader}>
|
||||
<span className={styles.title}>{header}</span>
|
||||
{time && <span className={styles.time}>{renderValue(time.valueString)}</span>}
|
||||
</div>
|
||||
<div className={styles.exemplarContent}>
|
||||
{displayValues.map((displayValue, i) => (
|
||||
<HorizontalGroup key={i} justify={'space-between'} align={'center'} spacing={'md'}>
|
||||
<div className={styles.label}>{displayValue.name}</div>
|
||||
<div className={styles.value}>{renderValue(displayValue.valueString)}</div>
|
||||
</HorizontalGroup>
|
||||
))}
|
||||
</div>
|
||||
{links && (
|
||||
<div className={styles.exemplarFooter}>
|
||||
{links.map((link, i) => (
|
||||
<LinkButton key={i} href={link.href} className={styles.linkButton}>
|
||||
{link.title}
|
||||
</LinkButton>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2, padding = 0) => {
|
||||
return {
|
||||
exemplarWrapper: css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
whiteSpace: 'pre',
|
||||
borderRadius: theme.shape.radius.default,
|
||||
background: theme.colors.background.primary,
|
||||
border: `1px solid ${theme.colors.border.weak}`,
|
||||
boxShadow: `0 4px 8px ${theme.colors.background.primary}`,
|
||||
userSelect: 'text',
|
||||
}),
|
||||
exemplarHeader: css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
gap: theme.spacing(0.5),
|
||||
color: theme.colors.text.secondary,
|
||||
padding: theme.spacing(1),
|
||||
}),
|
||||
time: css({
|
||||
color: theme.colors.text.primary,
|
||||
}),
|
||||
exemplarContent: css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
gap: 4,
|
||||
borderTop: `1px solid ${theme.colors.border.medium}`,
|
||||
padding: theme.spacing(1),
|
||||
}),
|
||||
exemplarFooter: css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
borderTop: `1px solid ${theme.colors.border.medium}`,
|
||||
padding: theme.spacing(1),
|
||||
}),
|
||||
linkButton: css({
|
||||
width: 'fit-content',
|
||||
}),
|
||||
label: css({
|
||||
color: theme.colors.text.secondary,
|
||||
fontWeight: 400,
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
marginRight: theme.spacing(0.5),
|
||||
}),
|
||||
value: css({
|
||||
fontWeight: 500,
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
}),
|
||||
title: css({
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
overflow: 'hidden',
|
||||
display: 'inline-block',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
flexGrow: 1,
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -1,8 +1,15 @@
|
||||
import React from 'react';
|
||||
import React, { CSSProperties } from 'react';
|
||||
|
||||
import { CloseButton } from '../../../core/components/CloseButton/CloseButton';
|
||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||
|
||||
export function ExemplarModalHeader(props: { onClick: () => void; style?: React.CSSProperties }) {
|
||||
const defaultStyle: CSSProperties = {
|
||||
position: 'relative',
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
marginRight: 0,
|
||||
};
|
||||
|
||||
export function ExemplarModalHeader(props: { onClick: () => void }) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -12,15 +19,7 @@ export function ExemplarModalHeader(props: { onClick: () => void }) {
|
||||
paddingBottom: '6px',
|
||||
}}
|
||||
>
|
||||
<CloseButton
|
||||
onClick={props.onClick}
|
||||
style={{
|
||||
position: 'relative',
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
marginRight: 0,
|
||||
}}
|
||||
/>
|
||||
<CloseButton onClick={props.onClick} style={props.style ?? defaultStyle} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,16 +4,16 @@ import uPlot from 'uplot';
|
||||
|
||||
import {
|
||||
DataFrameType,
|
||||
formattedValueToString,
|
||||
getFieldDisplayName,
|
||||
GrafanaTheme2,
|
||||
getLinksSupplier,
|
||||
InterpolateFunction,
|
||||
ScopedVars,
|
||||
PanelData,
|
||||
LinkModel,
|
||||
Field,
|
||||
FieldType,
|
||||
formattedValueToString,
|
||||
getFieldDisplayName,
|
||||
getLinksSupplier,
|
||||
GrafanaTheme2,
|
||||
InterpolateFunction,
|
||||
LinkModel,
|
||||
PanelData,
|
||||
ScopedVars,
|
||||
} from '@grafana/data';
|
||||
import { HeatmapCellLayout } from '@grafana/schema';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
@@ -28,7 +28,7 @@ import { DataHoverView } from 'app/features/visualization/data-hover/DataHoverVi
|
||||
|
||||
import { HeatmapData } from './fields';
|
||||
import { renderHistogram } from './renderHistogram';
|
||||
import { getSparseCellMinMax, getFieldFromData, getHoverCellColor, formatMilliseconds } from './tooltip/utils';
|
||||
import { formatMilliseconds, getFieldFromData, getHoverCellColor, getSparseCellMinMax } from './tooltip/utils';
|
||||
|
||||
interface Props {
|
||||
dataIdxs: Array<number | null>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { css, cx } from '@emotion/css';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { usePopper } from 'react-popper';
|
||||
|
||||
import {
|
||||
@@ -8,12 +8,17 @@ import {
|
||||
dateTimeFormat,
|
||||
Field,
|
||||
FieldType,
|
||||
formattedValueToString,
|
||||
GrafanaTheme2,
|
||||
LinkModel,
|
||||
systemDateFormats,
|
||||
TimeZone,
|
||||
} from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { config as runtimeConfig } from '@grafana/runtime';
|
||||
import { FieldLinkList, Portal, UPlotConfigBuilder, useStyles2 } from '@grafana/ui';
|
||||
import { DisplayValue } from 'app/features/visualization/data-hover/DataHoverView';
|
||||
import { ExemplarHoverView } from 'app/features/visualization/data-hover/ExemplarHoverView';
|
||||
|
||||
import { ExemplarModalHeader } from '../../heatmap/ExemplarModalHeader';
|
||||
|
||||
@@ -143,6 +148,77 @@ export const ExemplarMarker = ({
|
||||
setClickedExemplarFieldIndex(undefined);
|
||||
};
|
||||
|
||||
let displayValues: DisplayValue[] = [];
|
||||
let links: LinkModel[] | undefined = [];
|
||||
orderedDataFrameFields.map((field: Field, i) => {
|
||||
const value = field.values[dataFrameFieldIndex.fieldIndex];
|
||||
|
||||
if (field.config.links?.length) {
|
||||
links?.push(...(field.getLinks?.({ valueRowIndex: dataFrameFieldIndex.fieldIndex }) || []));
|
||||
}
|
||||
|
||||
const fieldDisplay = field.display ? field.display(value) : { text: `${value}`, numeric: +value };
|
||||
|
||||
displayValues.push({
|
||||
name: field.name,
|
||||
value,
|
||||
valueString: formattedValueToString(fieldDisplay),
|
||||
highlight: false,
|
||||
});
|
||||
});
|
||||
|
||||
const exemplarHeaderCustomStyle: CSSProperties = {
|
||||
position: 'relative',
|
||||
top: '35px',
|
||||
right: '5px',
|
||||
marginRight: 0,
|
||||
};
|
||||
|
||||
const getExemplarMarkerContent = () => {
|
||||
if (runtimeConfig.featureToggles.newVizTooltips) {
|
||||
return (
|
||||
<>
|
||||
{isLocked && <ExemplarModalHeader onClick={onClose} style={exemplarHeaderCustomStyle} />}
|
||||
<ExemplarHoverView displayValues={displayValues} links={links} />
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
{isLocked && <ExemplarModalHeader onClick={onClose} />}
|
||||
<div className={styles.body}>
|
||||
<div className={styles.header}>
|
||||
<span className={styles.title}>Exemplars</span>
|
||||
</div>
|
||||
<div>
|
||||
<table className={styles.exemplarsTable}>
|
||||
<tbody>
|
||||
{orderedDataFrameFields.map((field: Field, i) => {
|
||||
const value = field.values[dataFrameFieldIndex.fieldIndex];
|
||||
const links = field.config.links?.length
|
||||
? field.getLinks?.({ valueRowIndex: dataFrameFieldIndex.fieldIndex })
|
||||
: undefined;
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td valign="top">{field.name}</td>
|
||||
<td>
|
||||
<div className={styles.valueWrapper}>
|
||||
<span>{field.type === FieldType.time ? timeFormatter(value) : value}</span>
|
||||
{links && <FieldLinkList links={links} />}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={onMouseEnter}
|
||||
@@ -152,37 +228,7 @@ export const ExemplarMarker = ({
|
||||
style={popperStyles.popper}
|
||||
{...attributes.popper}
|
||||
>
|
||||
<div className={styles.wrapper}>
|
||||
{isLocked && <ExemplarModalHeader onClick={onClose} />}
|
||||
<div className={styles.body}>
|
||||
<div className={styles.header}>
|
||||
<span className={styles.title}>Exemplars</span>
|
||||
</div>
|
||||
<div>
|
||||
<table className={styles.exemplarsTable}>
|
||||
<tbody>
|
||||
{orderedDataFrameFields.map((field: Field, i) => {
|
||||
const value = field.values[dataFrameFieldIndex.fieldIndex];
|
||||
const links = field.config.links?.length
|
||||
? field.getLinks?.({ valueRowIndex: dataFrameFieldIndex.fieldIndex })
|
||||
: undefined;
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td valign="top">{field.name}</td>
|
||||
<td>
|
||||
<div className={styles.valueWrapper}>
|
||||
<span>{field.type === FieldType.time ? timeFormatter(value) : value}</span>
|
||||
{links && <FieldLinkList links={links} />}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{getExemplarMarkerContent()}
|
||||
</div>
|
||||
);
|
||||
}, [
|
||||
@@ -246,102 +292,96 @@ const getExemplarMarkerStyles = (theme: GrafanaTheme2) => {
|
||||
const tableBgOdd = theme.isDark ? theme.v1.palette.dark3 : theme.v1.palette.gray6;
|
||||
|
||||
return {
|
||||
markerWrapper: css`
|
||||
padding: 0 4px 4px 4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
box-sizing: content-box;
|
||||
transform: translate3d(-50%, 0, 0);
|
||||
|
||||
&:hover {
|
||||
> svg {
|
||||
transform: scale(1.3);
|
||||
opacity: 1;
|
||||
filter: drop-shadow(0 0 8px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
}
|
||||
`,
|
||||
marker: css`
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 4px solid ${theme.v1.palette.red};
|
||||
pointer-events: none;
|
||||
`,
|
||||
wrapper: css`
|
||||
background: ${bg};
|
||||
border: 1px solid ${headerBg};
|
||||
border-radius: ${theme.shape.borderRadius(2)};
|
||||
box-shadow: 0 0 20px ${shadowColor};
|
||||
padding: ${theme.spacing(1)};
|
||||
`,
|
||||
exemplarsTable: css`
|
||||
width: 100%;
|
||||
|
||||
tr td {
|
||||
padding: 5px 10px;
|
||||
white-space: nowrap;
|
||||
border-bottom: 4px solid ${theme.components.panel.background};
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: ${theme.colors.background.primary};
|
||||
|
||||
&:nth-child(even) {
|
||||
background-color: ${tableBgOdd};
|
||||
}
|
||||
}
|
||||
`,
|
||||
valueWrapper: css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
column-gap: ${theme.spacing(1)};
|
||||
|
||||
> span {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
> * {
|
||||
flex: 1 1;
|
||||
align-self: center;
|
||||
}
|
||||
`,
|
||||
tooltip: css`
|
||||
background: none;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
max-height: 95vh;
|
||||
`,
|
||||
header: css`
|
||||
background: ${headerBg};
|
||||
padding: 6px 10px;
|
||||
display: flex;
|
||||
`,
|
||||
title: css`
|
||||
font-weight: ${theme.typography.fontWeightMedium};
|
||||
padding-right: ${theme.spacing(2)};
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
flex-grow: 1;
|
||||
`,
|
||||
body: css`
|
||||
font-weight: ${theme.typography.fontWeightMedium};
|
||||
border-radius: ${theme.shape.borderRadius(2)};
|
||||
overflow: hidden;
|
||||
`,
|
||||
marble: css`
|
||||
display: block;
|
||||
opacity: 0.5;
|
||||
transition: transform 0.15s ease-out;
|
||||
`,
|
||||
activeMarble: css`
|
||||
transform: scale(1.3);
|
||||
opacity: 1;
|
||||
filter: drop-shadow(0 0 8px rgba(0, 0, 0, 0.5));
|
||||
`,
|
||||
markerWrapper: css({
|
||||
padding: '0 4px 4px 4px',
|
||||
width: '8px',
|
||||
height: '8px',
|
||||
boxSizing: 'content-box',
|
||||
transform: 'translate3d(-50%, 0, 0)',
|
||||
'&:hover': {
|
||||
'> svg': {
|
||||
transform: 'scale(1.3)',
|
||||
opacity: 1,
|
||||
filter: 'drop-shadow(0 0 8px rgba(0, 0, 0, 0.5))',
|
||||
},
|
||||
},
|
||||
}),
|
||||
marker: css({
|
||||
width: 0,
|
||||
height: 0,
|
||||
borderLeft: '4px solid transparent',
|
||||
borderRight: '4px solid transparent',
|
||||
borderBottom: `4px solid ${theme.v1.palette.red}`,
|
||||
pointerEvents: 'none',
|
||||
}),
|
||||
wrapper: css({
|
||||
background: bg,
|
||||
border: `1px solid ${headerBg}`,
|
||||
borderRadius: theme.shape.borderRadius(2),
|
||||
boxShadow: `0 0 20px ${shadowColor}`,
|
||||
padding: theme.spacing(1),
|
||||
}),
|
||||
exemplarsTable: css({
|
||||
width: '100%',
|
||||
'tr td': {
|
||||
padding: '5px 10px',
|
||||
whiteSpace: 'nowrap',
|
||||
borderBottom: `4px solid ${theme.components.panel.background}`,
|
||||
},
|
||||
tr: {
|
||||
backgroundColor: theme.colors.background.primary,
|
||||
'&:nth-child(even)': {
|
||||
backgroundColor: tableBgOdd,
|
||||
},
|
||||
},
|
||||
}),
|
||||
valueWrapper: css({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
columnGap: theme.spacing(1),
|
||||
'> span': {
|
||||
flexGrow: 0,
|
||||
},
|
||||
'> *': {
|
||||
flex: '1 1',
|
||||
alignSelf: 'center',
|
||||
},
|
||||
}),
|
||||
tooltip: css({
|
||||
background: 'none',
|
||||
padding: 0,
|
||||
overflowY: 'auto',
|
||||
maxHeight: '95vh',
|
||||
}),
|
||||
header: css({
|
||||
background: headerBg,
|
||||
padding: '6px 10px',
|
||||
display: 'flex',
|
||||
}),
|
||||
title: css({
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
paddingRight: theme.spacing(2),
|
||||
overflow: 'hidden',
|
||||
display: 'inline-block',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
flexGrow: 1,
|
||||
}),
|
||||
body: css({
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
borderRadius: theme.shape.borderRadius(2),
|
||||
overflow: 'hidden',
|
||||
}),
|
||||
marble: css({
|
||||
display: 'block',
|
||||
opacity: 0.5,
|
||||
transition: 'transform 0.15s ease-out',
|
||||
}),
|
||||
activeMarble: css({
|
||||
transform: 'scale(1.3)',
|
||||
opacity: 1,
|
||||
filter: 'drop-shadow(0 0 8px rgba(0, 0, 0, 0.5))',
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user