Chore: Add noMargin prop to Card components (#110458)

* Chore: Add noMargin to Card components

* Update results

* Update ConfigureCorrelationSourceForm.tsx

* Update AlertsFolderView.tsx

* Update VariableSetEditableElement.tsx

* Update DataSourceCard.tsx

* Update data source lists

* Move betterer rule to eslint

* Update playlists

* Update query patterns

* Update AzureCheatSheet.tsx

* betterer

* Update NavLandingPageCard.tsx

* Update ServerStatsCard.tsx

* Cleanup

* Remove Field rule

* cleanup

* Update suppressions

* upd

* Merge

* lint

* Update public dashboards list
This commit is contained in:
Alex Khomenko
2025-10-16 09:22:03 +03:00
committed by GitHub
parent a9dc2994e1
commit bd95659759
33 changed files with 191 additions and 309 deletions
+2 -123
View File
@@ -420,11 +420,6 @@
"count": 1
}
},
"packages/grafana-prometheus/src/querybuilder/QueryPattern.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"packages/grafana-prometheus/src/querybuilder/components/LabelFilterItem.tsx": {
"@typescript-eslint/consistent-type-assertions": {
"count": 4
@@ -1229,16 +1224,6 @@
"count": 1
}
},
"public/app/core/components/AppChrome/History/HistoryWrapper.tsx": {
"no-restricted-syntax": {
"count": 2
}
},
"public/app/core/components/AppNotifications/StoredNotificationItem.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/core/components/DynamicImports/SafeDynamicImport.tsx": {
"@typescript-eslint/no-explicit-any": {
"count": 1
@@ -1285,11 +1270,6 @@
"count": 1
}
},
"public/app/core/components/NavLandingPage/NavLandingPageCard.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/core/components/OptionsUI/NumberInput.tsx": {
"no-restricted-syntax": {
"count": 1
@@ -1540,11 +1520,6 @@
"count": 1
}
},
"public/app/features/admin/ServerStatsCard.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/admin/UserCreatePage.tsx": {
"no-restricted-syntax": {
"count": 4
@@ -1624,16 +1599,6 @@
"count": 2
}
},
"public/app/features/alerting/unified/AlertsFolderView.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/RedirectToRuleViewer.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/components/AlertLabelDropdown.tsx": {
"no-restricted-syntax": {
"count": 1
@@ -1745,11 +1710,6 @@
"count": 1
}
},
"public/app/features/alerting/unified/components/receivers/form/GenerateAlertDataModal.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/components/receivers/form/GrafanaCommonChannelSettings.tsx": {
"no-restricted-syntax": {
"count": 1
@@ -1836,9 +1796,6 @@
"@typescript-eslint/consistent-type-assertions": {
"count": 1
},
"no-restricted-syntax": {
"count": 1
},
"react-prefer-function-component/react-prefer-function-component": {
"count": 1
}
@@ -1883,11 +1840,6 @@
"count": 1
}
},
"public/app/features/alerting/unified/components/rule-editor/rule-types/RuleType.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/components/rules/Filter/RulesFilter.v1.tsx": {
"no-restricted-syntax": {
"count": 4
@@ -1913,11 +1865,6 @@
"count": 1
}
},
"public/app/features/alerting/unified/components/settings/AlertmanagerCard.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/components/silences/MatchersField.tsx": {
"no-restricted-syntax": {
"count": 5
@@ -1984,11 +1931,6 @@
"count": 6
}
},
"public/app/features/alerting/unified/rule-list/FilterViewStatus.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/types/alerting.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 5
@@ -2136,11 +2078,6 @@
"count": 1
}
},
"public/app/features/connections/tabs/ConnectData/CardGrid/CardGrid.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/connections/tabs/ConnectData/CardGrid/index.tsx": {
"no-barrel-files/no-barrel-files": {
"count": 1
@@ -2187,11 +2124,6 @@
"count": 2
}
},
"public/app/features/correlations/Forms/ConfigureCorrelationSourceForm.tsx": {
"no-restricted-syntax": {
"count": 3
}
},
"public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx": {
"@typescript-eslint/consistent-type-assertions": {
"count": 2
@@ -2210,11 +2142,6 @@
"count": 4
}
},
"public/app/features/correlations/components/EmptyCorrelationsCTA.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/correlations/types.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
@@ -2491,11 +2418,6 @@
"count": 4
}
},
"public/app/features/dashboard-scene/settings/variables/VariableSetEditableElement.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/dashboard-scene/settings/variables/components/AdHocVariableForm.tsx": {
"no-restricted-syntax": {
"count": 1
@@ -2880,11 +2802,6 @@
"count": 1
}
},
"public/app/features/dashboard/components/TransformationsEditor/TransformationPicker.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx": {
"@typescript-eslint/consistent-type-assertions": {
"count": 2
@@ -3078,19 +2995,6 @@
"public/app/features/datasources/components/DataSourceTypeCard.tsx": {
"@grafana/no-aria-label-selectors": {
"count": 1
},
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/datasources/components/DataSourcesListCard.tsx": {
"no-restricted-syntax": {
"count": 2
}
},
"public/app/features/datasources/components/picker/DataSourceCard.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/datasources/state/actions.test.ts": {
@@ -3185,7 +3089,7 @@
},
"public/app/features/explore/CorrelationHelper.tsx": {
"no-restricted-syntax": {
"count": 3
"count": 2
}
},
"public/app/features/explore/CorrelationTransformationAddModal.tsx": {
@@ -3558,11 +3462,6 @@
"count": 1
}
},
"public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/manage-dashboards/state/actions.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
@@ -3649,11 +3548,6 @@
"count": 1
}
},
"public/app/features/playlist/PlaylistCard.tsx": {
"no-restricted-syntax": {
"count": 2
}
},
"public/app/features/playlist/PlaylistForm.tsx": {
"@grafana/no-aria-label-selectors": {
"count": 2
@@ -3793,11 +3687,6 @@
"count": 2
}
},
"public/app/features/provisioning/File/FileHistoryPage.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/provisioning/File/FileStatusPage.tsx": {
"@typescript-eslint/consistent-type-assertions": {
"count": 2
@@ -4392,7 +4281,7 @@
},
"public/app/plugins/datasource/azuremonitor/components/LogsQueryEditor/AzureCheatSheet.tsx": {
"no-restricted-syntax": {
"count": 2
"count": 1
}
},
"public/app/plugins/datasource/azuremonitor/components/LogsQueryEditor/index.tsx": {
@@ -4970,11 +4859,6 @@
"count": 1
}
},
"public/app/plugins/datasource/loki/querybuilder/components/QueryPattern.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/plugins/datasource/loki/querybuilder/state.ts": {
"no-restricted-syntax": {
"count": 2
@@ -5148,11 +5032,6 @@
"count": 1
}
},
"public/app/plugins/panel/annolist/AnnotationListItem.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/plugins/panel/barchart/bars.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
@@ -28,7 +28,7 @@ export const QueryPattern = (props: Props) => {
const lang = { grammar: promqlGrammar, name: 'promql' };
return (
<Card className={styles.card}>
<Card noMargin className={styles.card}>
<Card.Heading>{pattern.name}</Card.Heading>
<div className={styles.rawQueryContainer}>
<RawQuery
@@ -6,7 +6,7 @@ import { useMemo, useState } from 'react';
import { CoreApp, DataQuery, getNextRefId, GrafanaTheme2 } from '@grafana/data';
import { t, Trans } from '@grafana/i18n';
import { reportInteraction } from '@grafana/runtime';
import { Button, Collapse, Modal, useStyles2 } from '@grafana/ui';
import { Button, Collapse, Modal, Stack, useStyles2 } from '@grafana/ui';
import { PromQuery } from '../types';
@@ -125,7 +125,7 @@ export const QueryPatternsModal = (props: Props) => {
);
}}
>
<div className={styles.cardsContainer}>
<Stack wrap justifyContent="space-between">
{promQueryModeller
.getQueryPatterns()
.filter((pattern) => pattern.type === patternType)
@@ -140,7 +140,7 @@ export const QueryPatternsModal = (props: Props) => {
setSelectedPatternName={setSelectedPatternName}
/>
))}
</div>
</Stack>
</Collapse>
);
})}
@@ -160,12 +160,6 @@ export const QueryPatternsModal = (props: Props) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
cardsContainer: css({
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
}),
spacing: css({
marginBottom: theme.spacing(1),
}),
@@ -4,7 +4,7 @@ import { useState } from 'react';
import { FieldType, GrafanaTheme2, store } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Button, Card, IconButton, Space, Stack, Text, useStyles2, Box, Sparkline, useTheme2, Icon } from '@grafana/ui';
import { Box, Button, Card, Icon, IconButton, Space, Sparkline, Stack, Text, useStyles2, useTheme2 } from '@grafana/ui';
import { formatDate } from 'app/core/internationalization/dates';
import { HISTORY_LOCAL_STORAGE_KEY } from '../AppChromeService';
@@ -123,6 +123,7 @@ function HistoryEntryAppView({ entry, isSelected, onClick }: ItemProps) {
className={isExpanded ? styles.iconButtonDot : styles.iconButtonCircle}
/>
<Card
noMargin
onClick={() => {
store.setObject('CLICKING_HISTORY', true);
onClick();
@@ -182,6 +183,7 @@ function HistoryEntryAppView({ entry, isSelected, onClick }: ItemProps) {
return (
<Card
key={index}
noMargin
href={view.url}
onClick={() => {
store.setObject('CLICKING_HISTORY', true);
@@ -32,7 +32,7 @@ export const StoredNotificationItem = ({
const styles = getStyles(theme);
return (
<Card className={className} onClick={onClick}>
<Card noMargin className={className} onClick={onClick}>
<Card.Heading>{title}</Card.Heading>
<Card.Description>{children}</Card.Description>
<Card.Figure>
@@ -12,7 +12,7 @@ interface Props {
export function NavLandingPageCard({ description, text, url }: Props) {
const styles = useStyles2(getStyles);
return (
<Card className={styles.card} href={url}>
<Card noMargin className={styles.card} href={url}>
<Card.Heading>{text}</Card.Heading>
<Card.Description className={styles.description}>{description}</Card.Description>
</Card>
@@ -21,7 +21,6 @@ export function NavLandingPageCard({ description, text, url }: Props) {
const getStyles = (theme: GrafanaTheme2) => ({
card: css({
marginBottom: 0,
gridTemplateRows: '1fr 0 2fr',
}),
// Limit descriptions to 3 lines max before ellipsing
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
import Skeleton from 'react-loading-skeleton';
import { GrafanaTheme2 } from '@grafana/data';
import { Card, Stack, useStyles2, Tooltip, Icon } from '@grafana/ui';
import { Card, Icon, Stack, Tooltip, useStyles2 } from '@grafana/ui';
interface StatItem {
name: string;
@@ -21,7 +21,7 @@ export interface Props {
export const ServerStatsCard = ({ content, footer, isLoading }: Props) => {
const styles = useStyles2(getStyles);
return (
<Card className={styles.container}>
<Card noMargin className={styles.container}>
{content.map((item, index) => (
<Stack key={index} justifyContent="space-between" alignItems="center">
<Stack alignItems={'center'}>
@@ -50,7 +50,6 @@ const getStyles = (theme: GrafanaTheme2) => {
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2),
margin: 0,
padding: theme.spacing(2),
}),
indent: css({
@@ -83,10 +83,11 @@ export const AlertsFolderView = ({ folder, rules }: Props) => {
/>
</Stack>
<Stack direction="column" gap={1}>
<Stack direction="column">
{pageItems.map(({ grafana_alert, labels = {} }) => (
<Card
key={grafana_alert.uid}
noMargin
href={createGrafanaRuleViewLink(grafana_alert)}
className={styles.card}
data-testid="alert-card-row"
@@ -200,7 +201,6 @@ export const getStyles = (theme: GrafanaTheme2) => ({
}),
card: css({
gridTemplateColumns: 'auto 1fr 2fr',
margin: 0,
}),
pagination: css({
alignSelf: 'center',
@@ -130,7 +130,7 @@ export function RedirectToRuleViewer(): JSX.Element | null {
<div className={styles.rules}>
{rules.map((rule, index) => {
return (
<Card key={`${rule.name}-${index}`} href={createViewLink(rulesSource, rule, '/alerting/list')}>
<Card noMargin key={`${rule.name}-${index}`} href={createViewLink(rulesSource, rule, '/alerting/list')}>
<Card.Heading>{rule.name}</Card.Heading>
<Card.Meta separator={''}>
<Icon name="folder" />
@@ -102,7 +102,7 @@ export const GenerateAlertDataModal = ({ isOpen, onDismiss, onAccept }: Props) =
setStatus('firing');
}}
>
<Card>
<Card noMargin>
<Stack direction="column" gap={1}>
<div className={styles.section}>
<AnnotationsStep />
@@ -283,7 +283,7 @@ const DatasourceNotFound = ({ index, onUpdateDatasource, onRemoveQuery, model }:
return (
<EmptyQueryWrapper>
<QueryOperationRow title={refId} draggable index={index} id={refId} isOpen collapsable={false}>
<Card>
<Card noMargin>
<Card.Heading>
<Trans i18nKey="alerting.datasource-not-found.this-datasource-has-been-removed">
This datasource has been removed
@@ -30,7 +30,7 @@ const RuleType = (props: Props) => {
});
return (
<Card className={cardStyles} isSelected={selected} onClick={() => onClick(value)} disabled={disabled}>
<Card noMargin className={cardStyles} isSelected={selected} onClick={() => onClick(value)} disabled={disabled}>
<Card.Figure>
<img src={image} alt="" />
</Card.Figure>
@@ -43,7 +43,7 @@ export function AlertmanagerCard({
const showActions = !provisioned && Boolean(onEnable) && Boolean(onDisable);
return (
<Card data-testid={`alertmanager-card-${name}`}>
<Card noMargin data-testid={`alertmanager-card-${name}`}>
<Card.Heading>
<Stack alignItems="center" gap={1}>
{href ? (
@@ -10,7 +10,7 @@ interface FilterStatusProps {
export function FilterStatus({ state, numberOfRules, onCancel }: FilterStatusProps) {
return (
<Card>
<Card noMargin>
<Text color="secondary">
{/* done searching everything and found some results */}
{state === 'done' && (
@@ -4,7 +4,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { t } from '@grafana/i18n';
import { featureEnabled } from '@grafana/runtime';
import { Card, Grid, useStyles2, Stack, Badge } from '@grafana/ui';
import { Badge, Card, Grid, Stack, useStyles2 } from '@grafana/ui';
import { PluginDeprecatedBadge } from 'app/features/plugins/admin/components/Badges/PluginDeprecatedBadge';
import { PluginDisabledBadge } from 'app/features/plugins/admin/components/Badges/PluginDisabledBadge';
import { PluginInstalledBadge } from 'app/features/plugins/admin/components/Badges/PluginInstallBadge';
@@ -85,6 +85,7 @@ export const CardGrid = ({ items, onClickItem }: CardGridProps) => {
{items.map((item) => (
<Card
key={item.id}
noMargin
className={styles.card}
href={item.url}
onClick={(e) => {
@@ -3,7 +3,7 @@ import { Controller, useFormContext } from 'react-hook-form';
import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { Card, Field, FieldSet, Input, useStyles2 } from '@grafana/ui';
import { Card, Field, FieldSet, Input, Stack, useStyles2 } from '@grafana/ui';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
@@ -94,74 +94,78 @@ export const ConfigureCorrelationSourceForm = () => {
variables.
</p>
</Trans>
<Controller
control={control}
name="sourceUID"
rules={{
required: {
value: true,
message: t('correlations.source-form.control-required', 'This field is required.'),
},
}}
render={({ field: { onChange, value } }) => (
<Field
label={t('correlations.source-form.source-label', 'Source')}
description={t(
'correlations.source-form.source-description',
'Results from selected source data source have links displayed in the panel'
)}
htmlFor="source"
invalid={!!formState.errors.sourceUID}
error={formState.errors.sourceUID?.message}
>
<DataSourcePicker
onChange={withDsUID(onChange)}
noDefault
current={value}
inputId="source"
width={32}
disabled={correlation !== undefined}
/>
</Field>
)}
/>
<Field
label={t('correlations.source-form.results-label', 'Results field')}
description={t(
'correlations.source-form.results-description',
'The link will be shown next to the value of this field'
)}
className={styles.label}
invalid={!!formState.errors?.config?.field}
error={formState.errors?.config?.field?.message}
>
<Input
id={getInputId('field', correlation)}
{...register('config.field', {
required: t('correlations.source-form.results-required', 'This field is required.'),
})}
readOnly={readOnly}
<Stack direction="column" gap={2}>
<Controller
control={control}
name="sourceUID"
rules={{
required: {
value: true,
message: t('correlations.source-form.control-required', 'This field is required.'),
},
}}
render={({ field: { onChange, value } }) => (
<Field
noMargin
label={t('correlations.source-form.source-label', 'Source')}
description={t(
'correlations.source-form.source-description',
'Results from selected source data source have links displayed in the panel'
)}
htmlFor="source"
invalid={!!formState.errors.sourceUID}
error={formState.errors.sourceUID?.message}
>
<DataSourcePicker
onChange={withDsUID(onChange)}
noDefault
current={value}
inputId="source"
width={32}
disabled={correlation !== undefined}
/>
</Field>
)}
/>
</Field>
{variables.length > 0 && (
<Card>
<Card.Heading>{formText.heading}</Card.Heading>
<Card.Description>
{formText.descriptionPre}
<VariableList />
<br />
<Trans i18nKey="correlations.source-form.description">
A data point needs to provide values to all variables as fields or as transformations output to make the
correlation button appear in the visualization.
<Field
noMargin
label={t('correlations.source-form.results-label', 'Results field')}
description={t(
'correlations.source-form.results-description',
'The link will be shown next to the value of this field'
)}
className={styles.label}
invalid={!!formState.errors?.config?.field}
error={formState.errors?.config?.field?.message}
>
<Input
id={getInputId('field', correlation)}
{...register('config.field', {
required: t('correlations.source-form.results-required', 'This field is required.'),
})}
readOnly={readOnly}
/>
</Field>
{variables.length > 0 && (
<Card noMargin>
<Card.Heading>{formText.heading}</Card.Heading>
<Card.Description>
{formText.descriptionPre}
<VariableList />
<br />
Note: Not every variable needs to be explicitly defined below. A transformation such as{' '}
<span className={styles.variable}>logfmt</span> will create variables for every key/value pair.
</Trans>
</Card.Description>
</Card>
)}
<TransformationsEditor readOnly={readOnly} />
<Trans i18nKey="correlations.source-form.description">
A data point needs to provide values to all variables as fields or as transformations output to make
the correlation button appear in the visualization.
<br />
Note: Not every variable needs to be explicitly defined below. A transformation such as{' '}
<span className={styles.variable}>logfmt</span> will create variables for every key/value pair.
</Trans>
</Card.Description>
</Card>
)}
<TransformationsEditor readOnly={readOnly} />
</Stack>
</FieldSet>
</>
);
@@ -23,7 +23,7 @@ export const EmptyCorrelationsCTA = ({ onClick, canWriteCorrelations }: Props) =
</Trans>
</EmptyState>
) : (
<Card>
<Card noMargin>
<Card.Heading>
<Trans i18nKey="correlations.empty-correlations-cta.there-are-no-correlations-configured-yet">
There are no correlations configured yet.
@@ -6,7 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { SceneVariable, SceneVariableSet } from '@grafana/scenes';
import { Stack, Button, useStyles2, Text, Box, Card } from '@grafana/ui';
import { Box, Button, Card, Stack, Text, useStyles2 } from '@grafana/ui';
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
@@ -130,18 +130,21 @@ function VariableTypeSelection({ onAddVariable }: VariableTypeSelectionProps) {
<Box paddingBottom={1} display={'flex'}>
<Trans i18nKey="dashboard.edit-pane.variables.select-type">Choose variable type</Trans>
</Box>
{options.map((option) => (
<Card
isCompact
onClick={() => onAddVariable(option.value!)}
key={option.value}
title={t('dashboard.edit-pane.variables.select-type-card-tooltip', 'Click to select type')}
data-testid={selectors.components.PanelEditor.ElementEditPane.variableType(option.value!)}
>
<Card.Heading>{option.label}</Card.Heading>
<Card.Description className={styles.cardDescription}>{option.description}</Card.Description>
</Card>
))}
<Stack direction="column">
{options.map((option) => (
<Card
isCompact
noMargin
onClick={() => onAddVariable(option.value!)}
key={option.value}
title={t('dashboard.edit-pane.variables.select-type-card-tooltip', 'Click to select type')}
data-testid={selectors.components.PanelEditor.ElementEditPane.variableType(option.value!)}
>
<Card.Heading>{option.label}</Card.Heading>
<Card.Description className={styles.cardDescription}>{option.description}</Card.Description>
</Card>
))}
</Stack>
</Stack>
);
}
@@ -4,7 +4,7 @@ import { FormEventHandler, KeyboardEventHandler, ReactNode } from 'react';
import { DocsId, GrafanaTheme2, LocalStorageValueProvider, TransformerRegistryItem } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { Card, Container, Alert, Input, useStyles2, Stack } from '@grafana/ui';
import { Alert, Card, Container, Input, Stack, useStyles2 } from '@grafana/ui';
import { getDocsLink } from 'app/core/utils/docsLinks';
import { PluginStateInfo } from 'app/features/plugins/components/PluginStateInfo';
@@ -107,6 +107,7 @@ function TransformationCard({ transform, onClick }: TransformationCardProps) {
const styles = useStyles2(getStyles);
return (
<Card
noMargin
className={styles.card}
data-testid={selectors.components.TransformTab.newTransform(transform.name)}
onClick={onClick}
@@ -19,7 +19,7 @@ export function DataSourceTypeCard({ onClick, dataSourcePlugin }: Props) {
const styles = useStyles2(getStyles);
return (
<Card className={cx(styles.card, 'card-parent')} onClick={isClickable ? onClick : () => {}}>
<Card noMargin className={cx(styles.card, 'card-parent')} onClick={isClickable ? onClick : () => {}}>
{/* Name */}
<Card.Heading
className={styles.heading}
@@ -160,7 +160,7 @@ const getStyles = (theme: GrafanaTheme2) => {
list: css({
listStyle: 'none',
display: 'grid',
// gap: '8px', Add back when legacy support for old Card interface is dropped
gap: theme.spacing(1),
}),
};
};
@@ -21,7 +21,7 @@ export function DataSourcesListCard({ dataSource, hasWriteRights, hasExploreRigh
const styles = useStyles2(getStyles);
return (
<Card href={hasWriteRights ? dsLink : undefined}>
<Card noMargin href={hasWriteRights ? dsLink : undefined}>
<Card.Heading>{dataSource.name}</Card.Heading>
<Card.Figure>
<img src={dataSource.typeLogoUrl} alt="" height="40px" width="40px" className={styles.logo} />
@@ -80,7 +80,7 @@ export function DataSourcesListCard({ dataSource, hasWriteRights, hasExploreRigh
function DataSourcesListCardSkeleton({ hasExploreRights }: Pick<Props, 'hasExploreRights'>) {
const skeletonStyles = useStyles2(getSkeletonStyles);
return (
<Card>
<Card noMargin>
<Card.Heading>
<Skeleton width={140} />
</Card.Heading>
@@ -1,7 +1,7 @@
import { css, cx } from '@emotion/css';
import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data';
import { Card, TagList, useTheme2, Icon } from '@grafana/ui';
import { Card, Icon, TagList, useTheme2 } from '@grafana/ui';
interface DataSourceCardProps {
ds: DataSourceInstanceSettings;
@@ -27,6 +27,7 @@ export function DataSourceCard({
return (
<Card
key={ds.uid}
noMargin
onClick={onClick}
className={cx(styles.card, selected ? styles.selected : undefined)}
{...htmlProps}
@@ -64,8 +65,6 @@ function getStyles(theme: GrafanaTheme2, builtIn = false) {
card: css({
cursor: 'pointer',
backgroundColor: 'transparent',
// Move to list component
marginBottom: 0,
padding: theme.spacing(1),
'&:hover': {
@@ -75,7 +74,7 @@ function getStyles(theme: GrafanaTheme2, builtIn = false) {
heading: css({
width: '100%',
overflow: 'hidden',
// This is needed to enable ellipsis when text overlfows
// This is needed to enable ellipsis when text overflows
'> button': {
width: '100%',
},
@@ -1,23 +1,23 @@
import { css } from '@emotion/css';
import { useState, useEffect, useId } from 'react';
import { useEffect, useId, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useAsync } from 'react-use';
import { DataLinkTransformationConfig, ExploreCorrelationHelperData, GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import {
Collapse,
Alert,
Field,
Input,
Button,
Card,
IconButton,
useStyles2,
Collapse,
DeleteButton,
Tooltip,
Field,
Icon,
IconButton,
Input,
Stack,
Tooltip,
useStyles2,
} from '@grafana/ui';
import { useDispatch, useSelector } from 'app/types/store';
@@ -241,7 +241,7 @@ export const CorrelationHelper = ({ exploreId, correlations }: Props) => {
) : undefined,
].filter((val) => val);
return (
<Card key={`trans-${i}`}>
<Card noMargin key={`trans-${i}`}>
<Card.Heading>
{field}: {type}
</Card.Heading>
@@ -59,7 +59,7 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
const translatedPauseSharingText = t('shared-dashboard-list.toggle.pause-sharing-toggle-text', 'Pause access');
return (
<Card className={styles.card} href={`/d/${pd.dashboardUid}`}>
<Card noMargin className={styles.card} href={`/d/${pd.dashboardUid}`}>
<Card.Heading className={styles.heading}>
<span>{pd.title}</span>
</Card.Heading>
@@ -173,6 +173,9 @@ const getStyles = (theme: GrafanaTheme2) => ({
list: css({
listStyleType: 'none',
marginBottom: theme.spacing(2),
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
}),
card: css({
[theme.breakpoints.up('sm')]: {
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import Skeleton from 'react-loading-skeleton';
import { GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { t, Trans } from '@grafana/i18n';
import { Button, Card, LinkButton, ModalsController, Stack, useStyles2 } from '@grafana/ui';
import { attachSkeleton, SkeletonComponent } from '@grafana/ui/unstable';
import { contextSrv } from 'app/core/services/context_srv';
@@ -20,7 +20,7 @@ interface Props {
const PlaylistCardComponent = ({ playlist, setStartPlaylist, setPlaylistToDelete }: Props) => {
return (
<Card>
<Card noMargin>
<Card.Heading>
{playlist.spec?.title}
<ModalsController key="button-share">
@@ -66,7 +66,7 @@ const PlaylistCardComponent = ({ playlist, setStartPlaylist, setPlaylistToDelete
const PlaylistCardSkeleton: SkeletonComponent = ({ rootProps }) => {
const skeletonStyles = useStyles2(getSkeletonStyles);
return (
<Card {...rootProps}>
<Card noMargin {...rootProps}>
<Card.Heading>
<Skeleton width={140} />
</Card.Heading>
@@ -48,6 +48,7 @@ function getStyles(theme: GrafanaTheme2) {
return {
list: css({
display: 'grid',
gap: theme.spacing(1),
}),
listItem: css({
listStyle: 'none',
@@ -103,7 +103,7 @@ const getStyles = (theme: GrafanaTheme2) => {
list: css({
listStyle: 'none',
display: 'grid',
// gap: '8px', Add back when legacy support for old Card interface is dropped
gap: theme.spacing(1),
}),
};
};
@@ -78,7 +78,7 @@ function HistoryView({ history, path, repo }: Props) {
return (
<Stack direction={'column'}>
{history.items.map((item) => (
<Card href={`${PROVISIONING_URL}/${repo}/file/${path}?ref=${item.ref}`} key={item.ref}>
<Card noMargin href={`${PROVISIONING_URL}/${repo}/file/${path}?ref=${item.ref}`} key={item.ref}>
<Card.Heading>{item.message}</Card.Heading>
<Card.Meta>
<span>{formatTimestamp(item.createdAt)}</span>
@@ -13,6 +13,7 @@ import {
LoadingPlaceholder,
ScrollContainer,
Select,
Stack,
useStyles2,
} from '@grafana/ui';
@@ -190,50 +191,52 @@ const AzureCheatSheet = (props: AzureCheatSheetProps) => {
onToggle={(isOpen) => setAreDropdownsOpen({ ...areDropdownsOpen, [category]: isOpen })}
key={category}
>
{visibleQueries[category]!.map((query) => {
return (
<Card className={styles.card} key={query.id}>
<Card.Heading>{query.displayName}</Card.Heading>
<ScrollContainer showScrollIndicators maxHeight="100px">
<RawQuery
aria-label={t(
'components.azure-cheat-sheet.aria-label-raw-query',
'{{queryDisplayName}} raw query',
{ queryDisplayName: query.displayName }
)}
query={query.body}
lang={lang}
className={styles.rawQuery}
/>
</ScrollContainer>
<Card.Actions>
<Button
size="sm"
aria-label={t(
'components.azure-cheat-sheet.aria-label-use-query',
'Use this query button'
)}
onClick={() => {
props.onChange({
refId: 'A',
queryType: AzureQueryType.LogAnalytics,
azureLogAnalytics: { query: query.body },
datasource: props.datasource,
});
reportInteraction('grafana_azure_cheatsheet_logs_query_selected', {
id: query.id,
queryName: query.displayName,
query: query.body,
queryCategories: query.related.categories,
});
}}
>
<Trans i18nKey="components.azure-cheat-sheet.button-use-query">Use this query</Trans>
</Button>
</Card.Actions>
</Card>
);
})}
<Stack direction="column">
{visibleQueries[category]!.map((query) => {
return (
<Card noMargin className={styles.card} key={query.id}>
<Card.Heading>{query.displayName}</Card.Heading>
<ScrollContainer showScrollIndicators maxHeight="100px">
<RawQuery
aria-label={t(
'components.azure-cheat-sheet.aria-label-raw-query',
'{{queryDisplayName}} raw query',
{ queryDisplayName: query.displayName }
)}
query={query.body}
lang={lang}
className={styles.rawQuery}
/>
</ScrollContainer>
<Card.Actions>
<Button
size="sm"
aria-label={t(
'components.azure-cheat-sheet.aria-label-use-query',
'Use this query button'
)}
onClick={() => {
props.onChange({
refId: 'A',
queryType: AzureQueryType.LogAnalytics,
azureLogAnalytics: { query: query.body },
datasource: props.datasource,
});
reportInteraction('grafana_azure_cheatsheet_logs_query_selected', {
id: query.id,
queryName: query.displayName,
query: query.body,
queryCategories: query.related.categories,
});
}}
>
<Trans i18nKey="components.azure-cheat-sheet.button-use-query">Use this query</Trans>
</Button>
</Card.Actions>
</Card>
);
})}
</Stack>
</Collapse>
);
}
@@ -25,7 +25,7 @@ export const QueryPattern = (props: Props) => {
const lang = { grammar: logqlGrammar, name: 'logql' };
return (
<Card className={styles.card}>
<Card noMargin className={styles.card}>
<Card.Heading>{pattern.name}</Card.Heading>
<div className={styles.rawQueryContainer}>
<RawQuery
@@ -5,7 +5,7 @@ import { useMemo, useState } from 'react';
import { CoreApp, GrafanaTheme2, getNextRefId } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { DataQuery } from '@grafana/schema';
import { Button, Collapse, Modal, useStyles2 } from '@grafana/ui';
import { Button, Collapse, Modal, Stack, useStyles2 } from '@grafana/ui';
import { LokiQuery } from '../../types';
import { lokiQueryModeller } from '../LokiQueryModeller';
@@ -107,7 +107,7 @@ export const QueryPatternsModal = (props: Props) => {
)
}
>
<div className={styles.cardsContainer}>
<Stack wrap justifyContent="space-between">
{lokiQueryModeller
.getQueryPatterns()
.filter((pattern) => pattern.type === patternType)
@@ -122,7 +122,7 @@ export const QueryPatternsModal = (props: Props) => {
setSelectedPatternName={setSelectedPatternName}
/>
))}
</div>
</Stack>
</Collapse>
);
})}
@@ -135,12 +135,6 @@ export const QueryPatternsModal = (props: Props) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
cardsContainer: css({
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
}),
spacing: css({
marginBottom: theme.spacing(1),
}),
@@ -3,7 +3,7 @@ import { MouseEvent } from 'react';
import { AnnotationEvent, DateTimeInput, GrafanaTheme2, PanelProps } from '@grafana/data';
import { Trans } from '@grafana/i18n';
import { Card, TagList, Tooltip, RenderUserContentAsHTML, useStyles2 } from '@grafana/ui';
import { Card, RenderUserContentAsHTML, TagList, Tooltip, useStyles2 } from '@grafana/ui';
import { Options } from './panelcfg.gen';
@@ -30,7 +30,7 @@ export const AnnotationListItem = ({ options, annotation, formatDate, onClick, o
const showTimeStampEnd = timeEnd && timeEnd !== time && showTime;
return (
<Card className={styles.card} onClick={onItemClick}>
<Card noMargin className={styles.card} onClick={onItemClick}>
<Card.Heading>
<RenderUserContentAsHTML
className={styles.heading}