diff --git a/packages/grafana-data/src/field/fieldColor.ts b/packages/grafana-data/src/field/fieldColor.ts
index 8c7702c2bb0..a7957f9f44e 100644
--- a/packages/grafana-data/src/field/fieldColor.ts
+++ b/packages/grafana-data/src/field/fieldColor.ts
@@ -218,7 +218,7 @@ export class FieldColorSchemeMode implements FieldColorMode {
}
} else if (this.useSeriesName) {
return (_: number, _percent: number, _threshold?: Threshold) => {
- return colors[Math.abs(stringHash(field.state?.displayName ?? field.name)) % colors.length];
+ return getColorByStringHash(colors, field.state?.displayName ?? field.name);
};
} else {
return (_: number, _percent: number, _threshold?: Threshold) => {
@@ -263,6 +263,10 @@ export function getFieldSeriesColor(field: Field, theme: GrafanaTheme2): ColorSc
return scale(value);
}
+export function getColorByStringHash(colors: string[], string: string) {
+ return colors[Math.abs(stringHash(string)) % colors.length];
+}
+
function getFixedColor(field: Field, theme: GrafanaTheme2) {
return () => {
return theme.visualization.getColorByName(field.config.color?.fixedColor ?? FALLBACK_COLOR);
diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts
index bc9e4d245db..c51f2f17c7c 100644
--- a/packages/grafana-data/src/index.ts
+++ b/packages/grafana-data/src/index.ts
@@ -137,6 +137,8 @@ export {
fieldColorModeRegistry,
type FieldColorMode,
getFieldSeriesColor,
+ /** @internal */
+ getColorByStringHash,
} from './field/fieldColor';
export { FieldConfigOptionsRegistry } from './field/FieldConfigOptionsRegistry';
export { sortThresholds, getActiveThreshold } from './field/thresholds';
diff --git a/packages/grafana-schema/src/common/common.gen.ts b/packages/grafana-schema/src/common/common.gen.ts
index ff937656095..37273bee0cf 100644
--- a/packages/grafana-schema/src/common/common.gen.ts
+++ b/packages/grafana-schema/src/common/common.gen.ts
@@ -977,8 +977,6 @@ export enum ComparisonOperation {
}
export interface TablePillCellOptions {
- color?: string;
- colorMode?: ('auto' | 'fixed' | 'mapped');
type: TableCellDisplayMode.Pill;
}
diff --git a/packages/grafana-schema/src/common/table.cue b/packages/grafana-schema/src/common/table.cue
index 0858150ae4c..acf4a6b7480 100644
--- a/packages/grafana-schema/src/common/table.cue
+++ b/packages/grafana-schema/src/common/table.cue
@@ -111,7 +111,4 @@ TableFieldOptions: {
TablePillCellOptions: {
type: TableCellDisplayMode & "pill"
- color?: string
- colorMode?: "auto" | "fixed" | "mapped"
} @cuetsy(kind="interface")
-
diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx
index a216a9221d1..b7249e88b2b 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx
@@ -1,16 +1,18 @@
-import { render, screen } from '@testing-library/react';
+import { render, RenderResult } from '@testing-library/react';
import { DataFrame, Field, FieldType, GrafanaTheme2, MappingType, createTheme } from '@grafana/data';
import { TableCellDisplayMode, TablePillCellOptions } from '@grafana/schema';
import { mockThemeContext } from '../../../../themes/ThemeContext';
-import { PillCell, inferPills } from './PillCell';
+import { PillCell, getStyles } from './PillCell';
describe('PillCell', () => {
+ let pillClass: string;
let restoreThemeContext: () => void;
beforeEach(() => {
+ pillClass = getStyles(createTheme()).pill;
restoreThemeContext = mockThemeContext(createTheme());
});
@@ -20,7 +22,6 @@ describe('PillCell', () => {
const mockCellOptions: TablePillCellOptions = {
type: TableCellDisplayMode.Pill,
- colorMode: 'auto',
};
const mockField: Field = {
@@ -37,7 +38,6 @@ describe('PillCell', () => {
};
const defaultProps = {
- value: 'test-value',
field: mockField,
justifyContent: 'flex-start' as const,
cellOptions: mockCellOptions,
@@ -50,170 +50,102 @@ describe('PillCell', () => {
showFilters: false,
};
- describe('pill parsing', () => {
- it('should render pills for single values', () => {
- render();
- expect(screen.getByText('test-value')).toBeInTheDocument();
- });
+ const ser = new XMLSerializer();
- it('should render pills for CSV values', () => {
- render();
- expect(screen.getByText('value1')).toBeInTheDocument();
- expect(screen.getByText('value2')).toBeInTheDocument();
- expect(screen.getByText('value3')).toBeInTheDocument();
- });
+ const expectHTML = (result: RenderResult, expected: string) => {
+ let actual = ser.serializeToString(result.asFragment()).replace(/xmlns=".*?" /g, '');
+ expect(actual).toEqual(expected.replace(/^\s*|\n/gm, ''));
+ };
- it('should render pills for JSON array values', () => {
- render();
- expect(screen.getByText('item1')).toBeInTheDocument();
- expect(screen.getByText('item2')).toBeInTheDocument();
- expect(screen.getByText('item3')).toBeInTheDocument();
- });
+ // one class for lightTextPill, darkTextPill
- it('should show dash for empty values', () => {
- render();
- expect(screen.getByText('-')).toBeInTheDocument();
- });
+ describe('Color by hash (classic palette)', () => {
+ const props = { ...defaultProps };
- it('should show dash for null values', () => {
- render();
- expect(screen.getByText('-')).toBeInTheDocument();
+ it('single value', () => {
+ expectHTML(
+ render(),
+ `value1`
+ );
});
- });
-
- describe('color mapping', () => {
- // These tests primarily ensure the color logic executes without throwing.
- // For true color verification, visual regression tests would be needed.
- it('should use mapped colors when colorMode is mapped', () => {
- const mappedOptions: TablePillCellOptions = {
- type: TableCellDisplayMode.Pill,
- colorMode: 'mapped',
- };
-
- render();
-
- const successPill = screen.getByText('success');
- const errorPill = screen.getByText('error');
- const warningPill = screen.getByText('warning');
- const unknownPill = screen.getByText('unknown');
-
- expect(successPill).toBeInTheDocument();
- expect(errorPill).toBeInTheDocument();
- expect(warningPill).toBeInTheDocument();
- expect(unknownPill).toBeInTheDocument();
+ it('empty string', () => {
+ expectHTML(render(), '');
});
- it('should use field-level value mappings when available', () => {
- const mappedOptions: TablePillCellOptions = {
- type: TableCellDisplayMode.Pill,
- colorMode: 'mapped',
- };
-
- // Mock field with value mappings
- const fieldWithMappings: Field = {
- ...mockField,
- config: {
- ...mockField.config,
- mappings: [
- {
- type: MappingType.ValueToText,
- options: {
- success: { color: '#00FF00' },
- error: { color: '#FF0000' },
- warning: { color: '#FFFF00' },
- },
- },
- ],
- },
- display: (value: unknown) => ({
- text: String(value),
- color:
- String(value) === 'success'
- ? '#00FF00'
- : String(value) === 'error'
- ? '#FF0000'
- : String(value) === 'warning'
- ? '#FFFF00'
- : '#FF780A',
- numeric: 0,
- }),
- };
-
- render(
-
+ // it('null', () => {
+ // expectHTML(
+ // render(),
+ // 'value1'
+ // );
+ // });
+
+ it('CSV values', () => {
+ expectHTML(
+ render(),
+ `
+ value1
+ value2
+ value3
+ `
);
-
- const successPill = screen.getByText('success');
- const errorPill = screen.getByText('error');
- const warningPill = screen.getByText('warning');
- const unknownPill = screen.getByText('unknown');
-
- expect(successPill).toBeInTheDocument();
- expect(errorPill).toBeInTheDocument();
- expect(warningPill).toBeInTheDocument();
- expect(unknownPill).toBeInTheDocument();
- });
-
- it('should use fixed color when colorMode is fixed', () => {
- const fixedOptions: TablePillCellOptions = {
- type: TableCellDisplayMode.Pill,
- colorMode: 'fixed',
- color: '#FF00FF',
- };
-
- render();
- expect(screen.getByText('test-value')).toBeInTheDocument();
});
- it('should use auto color when colorMode is auto', () => {
- const autoOptions: TablePillCellOptions = {
- type: TableCellDisplayMode.Pill,
- colorMode: 'auto',
- };
-
- render();
- expect(screen.getByText('test-value')).toBeInTheDocument();
+ it('JSON array values', () => {
+ expectHTML(
+ render(),
+ `
+ value1
+ value2
+ value3
+ `
+ );
});
- });
-});
-describe('inferPills', () => {
- // These tests verify the pill parsing logic handles various input formats correctly.
- // They ensure the function can extract pill values from different data structures.
-
- it('should return empty array for null/undefined values', () => {
- expect(inferPills(null)).toEqual([]);
- expect(inferPills(undefined)).toEqual([]);
- expect(inferPills('')).toEqual([]);
+ // TODO: handle null values?
});
- it('should parse single values', () => {
- expect(inferPills('test')).toEqual(['test']);
- expect(inferPills('"quoted"')).toEqual(['quoted']);
- expect(inferPills("'quoted'")).toEqual(['quoted']);
- });
-
- it('should parse CSV strings', () => {
- expect(inferPills('value1,value2,value3')).toEqual(['value1', 'value2', 'value3']);
- expect(inferPills(' value1 , value2 , value3 ')).toEqual(['value1', 'value2', 'value3']);
- expect(inferPills('value1, ,value3')).toEqual(['value1', 'value3']);
- });
-
- it('should parse JSON arrays', () => {
- expect(inferPills('["item1","item2","item3"]')).toEqual(['item1', 'item2', 'item3']);
- expect(inferPills('["item1", "item2", "item3"]')).toEqual(['item1', 'item2', 'item3']);
- expect(inferPills('["item1", null, "item3"]')).toEqual(['item1', 'item3']);
- });
+ describe('Color by value mappings', () => {
+ const field: Field = {
+ ...mockField,
+ config: {
+ ...mockField.config,
+ mappings: [
+ {
+ type: MappingType.ValueToText,
+ options: {
+ success: { color: '#00FF00' },
+ error: { color: '#FF0000' },
+ warning: { color: '#FFFF00' },
+ },
+ },
+ ],
+ },
+ display: (value: unknown) => ({
+ text: String(value),
+ color:
+ value === 'success' ? '#00FF00' : value === 'error' ? '#FF0000' : value === 'warning' ? '#FFFF00' : '#FF780A',
+ numeric: 0,
+ }),
+ };
+
+ const props = {
+ ...defaultProps,
+ field,
+ };
+
+ it('CSV values', () => {
+ expectHTML(
+ render(),
+ `
+ success
+ error
+ warning
+ unknown
+ `
+ );
+ });
- it('should handle mixed content', () => {
- // When JSON parsing fails, it falls back to CSV parsing
- expect(inferPills('["item1", "item2"],extra')).toEqual(['["item1"', '"item2"]', 'extra']);
- expect(inferPills('not-json,value')).toEqual(['not-json', 'value']);
+ // TODO: handle null values?
});
});
diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx
index aaa103c3dc7..c1ca23b7f69 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx
@@ -1,15 +1,19 @@
import { css } from '@emotion/css';
-import { Property } from 'csstype';
import { useMemo } from 'react';
-import { GrafanaTheme2, isDataFrame, classicColors, colorManipulator, Field } from '@grafana/data';
-import { TablePillCellOptions } from '@grafana/schema';
-
-import { useStyles2 } from '../../../../themes/ThemeContext';
+import {
+ GrafanaTheme2,
+ classicColors,
+ colorManipulator,
+ Field,
+ getColorByStringHash,
+ FALLBACK_COLOR,
+} from '@grafana/data';
+import { FieldColorModeId } from '@grafana/schema';
+
+import { useStyles2, useTheme2 } from '../../../../themes/ThemeContext';
import { TableCellRendererProps } from '../types';
-const DEFAULT_PILL_BG_COLOR = '#FF780A';
-
interface Pill {
value: string;
key: string;
@@ -17,9 +21,9 @@ interface Pill {
color: string;
}
-function createPills(pillValues: string[], cellOptions: TableCellRendererProps['cellOptions'], field: Field): Pill[] {
+function createPills(pillValues: string[], field: Field, theme: GrafanaTheme2): Pill[] {
return pillValues.map((pill, index) => {
- const bgColor = getPillColor(pill, cellOptions, field);
+ const bgColor = getPillColor(pill, field, theme);
const textColor = colorManipulator.getContrastRatio('#FFFFFF', bgColor) >= 4.5 ? '#FFFFFF' : '#000000';
return {
value: pill,
@@ -30,156 +34,73 @@ function createPills(pillValues: string[], cellOptions: TableCellRendererProps['
});
}
-export function PillCell({ value, field, justifyContent, cellOptions }: TableCellRendererProps) {
- const styles = useStyles2(getStyles, justifyContent);
+export function PillCell({ value, field }: TableCellRendererProps) {
+ const styles = useStyles2(getStyles);
+ const theme = useTheme2();
const pills: Pill[] = useMemo(() => {
- const pillValues = inferPills(value);
- return createPills(pillValues, cellOptions, field);
- }, [value, cellOptions, field]);
-
- if (pills.length === 0) {
- return
-
;
- }
-
- return (
-
-
- {pills.map((pill) => (
-
- {pill.value}
-
- ))}
-
-
- );
+ const pillValues = inferPills(String(value));
+ return createPills(pillValues, field, theme);
+ }, [value, field, theme]);
+
+ return pills.map((pill) => (
+
+ {pill.value}
+
+ ));
}
-export function inferPills(value: unknown): string[] {
- if (!value) {
- return [];
- }
+const SPLIT_RE = /\s*,\s*/;
+const TRANSPARENT = 'rgba(0,0,0,0)';
- // Handle DataFrame - not supported for pills
- if (isDataFrame(value)) {
+export function inferPills(value: string): string[] {
+ if (value === '') {
return [];
}
- // Handle different value types
- const stringValue = String(value);
-
- // Try to parse as JSON first
- try {
- const parsed = JSON.parse(stringValue);
- if (Array.isArray(parsed)) {
- // JSON array of strings
- return parsed
- .filter((item) => item != null && item !== '')
- .map(String)
- .map((text) => text.trim())
- .filter((item) => item !== '');
+ if (value[0] === '[') {
+ try {
+ return JSON.parse(value);
+ } catch {
+ return value.trim().split(SPLIT_RE);
}
- } catch {
- // Not valid JSON, continue with other parsing
- }
-
- // Handle CSV string
- if (stringValue.includes(',')) {
- return stringValue
- .split(',')
- .map((text) => text.trim())
- .filter((item) => item !== '');
}
- // Single value - strip quotes
- return [stringValue.replace(/["'`]/g, '').trim()];
+ return value.trim().split(SPLIT_RE);
}
-function isPillCellOptions(cellOptions: TableCellRendererProps['cellOptions']): cellOptions is TablePillCellOptions {
- return cellOptions?.type === 'pill';
-}
+function getPillColor(value: string, field: Field, theme: GrafanaTheme2): string {
+ const cfg = field.config;
-function getPillColor(pill: string, cellOptions: TableCellRendererProps['cellOptions'], field: Field): string {
- if (!isPillCellOptions(cellOptions)) {
- return getDeterministicColor(pill);
+ if (cfg.mappings?.length ?? 0 > 0) {
+ return field.display!(value).color ?? FALLBACK_COLOR;
}
- const colorMode = cellOptions.colorMode || 'auto';
-
- // Fixed color mode (highest priority)
- if (colorMode === 'fixed' && cellOptions.color) {
- return cellOptions.color;
+ if (cfg.color?.mode === FieldColorModeId.Fixed) {
+ return theme.visualization.getColorByName(cfg.color?.fixedColor ?? FALLBACK_COLOR);
}
- // Mapped color mode - use field's value mappings
- if (colorMode === 'mapped') {
- // Check if field has value mappings
- if (field.config.mappings && field.config.mappings.length > 0) {
- // Use the field's display processor to get the mapped value
- const displayValue = field.display!(pill);
- if (displayValue.color) {
- return displayValue.color;
- }
- }
- // Fallback to default color for unmapped values
- return cellOptions.color || DEFAULT_PILL_BG_COLOR;
- }
-
- // Auto mode - deterministic color assignment based on string hash
- if (colorMode === 'auto') {
- return getDeterministicColor(pill);
- }
-
- // Default color for unknown values or fallback
- return DEFAULT_PILL_BG_COLOR;
+ // TODO: instead of classicColors we need to pull colors from theme, same way as FieldColorModeId.PaletteClassicByName (see fieldColor.ts)
+ return getColorByStringHash(classicColors, value);
}
-function getDeterministicColor(text: string): string {
- // Create a simple hash of the string to get consistent colors
- let hash = 0;
- for (let i = 0; i < text.length; i++) {
- const char = text.charCodeAt(i);
- hash = (hash << 5) - hash + char;
- hash = hash & hash; // Convert to 32-bit integer
- }
-
- // Use absolute value and modulo to get a consistent index
- const colorValues = Object.values(classicColors);
- const index = Math.abs(hash) % colorValues.length;
-
- return colorValues[index];
-}
-
-const getStyles = (theme: GrafanaTheme2, justifyContent: Property.JustifyContent | undefined) => ({
- cell: css({
- display: 'flex',
- justifyContent: justifyContent || 'flex-start',
- alignItems: 'center',
- height: '100%',
- padding: theme.spacing(0.5),
- }),
- pillsContainer: css({
- display: 'flex',
- flexWrap: 'wrap',
- gap: theme.spacing(0.5),
- maxWidth: '100%',
- }),
+export const getStyles = (theme: GrafanaTheme2) => ({
pill: css({
display: 'inline-block',
padding: theme.spacing(0.25, 0.75),
+ marginInlineEnd: theme.spacing(0.5),
+ marginBlock: theme.spacing(0.5),
borderRadius: theme.shape.radius.default,
fontSize: theme.typography.bodySmall.fontSize,
lineHeight: theme.typography.bodySmall.lineHeight,
- fontWeight: theme.typography.fontWeightMedium,
whiteSpace: 'nowrap',
- textAlign: 'center',
- minWidth: 'fit-content',
}),
});
diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx
index 74c773f28ff..d1bdcdad4a2 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx
@@ -109,6 +109,12 @@ export function getCellRenderer(field: Field, cellOptions: TableCellOptions): Ta
if (cellType === TableCellDisplayMode.Auto) {
return getAutoRendererResult(field);
}
+
+ // TODO: add support boolean, enum, (maybe int). but for now just string fields
+ if (cellType === TableCellDisplayMode.Pill && field.type !== FieldType.string) {
+ return AUTO_RENDERER;
+ }
+
return CELL_RENDERERS[cellType] ?? AUTO_RENDERER;
}
diff --git a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
index dbe5dd3f1a0..5590dad8e3e 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
@@ -14,9 +14,18 @@ import {
SortColumn,
} from 'react-data-grid';
-import { DataHoverClearEvent, DataHoverEvent, Field, FieldType, GrafanaTheme2, ReducerID } from '@grafana/data';
+import {
+ DataHoverClearEvent,
+ DataHoverEvent,
+ FALLBACK_COLOR,
+ Field,
+ FieldType,
+ getDisplayProcessor,
+ GrafanaTheme2,
+ ReducerID,
+} from '@grafana/data';
import { t, Trans } from '@grafana/i18n';
-import { TableCellHeight } from '@grafana/schema';
+import { FieldColorModeId, TableCellHeight } from '@grafana/schema';
import { useStyles2, useTheme2 } from '../../../themes/ThemeContext';
import { ContextMenu } from '../../ContextMenu/ContextMenu';
@@ -272,11 +281,30 @@ export function TableNG(props: TableNGProps) {
let _rowHeight = 0;
f.forEach((field, i) => {
+ const cellOptions = getCellOptions(field);
+ const cellType = cellOptions.type;
+
+ // make sure we use mappings exclusively if they exist, ignore default thresholds mode
+ // we hack this by using the single color mode calculator
+ if (cellType === TableCellDisplayMode.Pill && (field.config.mappings?.length ?? 0 > 0)) {
+ field = {
+ ...field,
+ config: {
+ ...field.config,
+ color: {
+ ...field.config.color,
+ mode: FieldColorModeId.Fixed,
+ fixedColor: field.config.color?.fixedColor ?? FALLBACK_COLOR,
+ },
+ },
+ };
+ field.display = getDisplayProcessor({ field, theme });
+ }
+
const justifyContent = getTextAlign(field);
const footerStyles = getFooterStyles(justifyContent);
const displayName = getDisplayName(field);
const headerCellClass = getHeaderCellStyles(theme, justifyContent).headerCell;
- const cellOptions = getCellOptions(field);
const renderFieldCell = getCellRenderer(field, cellOptions);
const cellInspect = isCellInspectEnabled(field);
@@ -293,7 +321,6 @@ export function TableNG(props: TableNGProps) {
)
: undefined;
- const cellType = cellOptions.type;
const shouldOverflow = shouldTextOverflow(field);
const shouldWrap = shouldTextWrap(field);
const withTooltip = withDataLinksActionsTooltip(field, cellType);
diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.ts
index 90004837874..a99ec3edab7 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/utils.ts
+++ b/packages/grafana-ui/src/components/Table/TableNG/utils.ts
@@ -128,11 +128,14 @@ export function getMaxWrapCell(
* Returns true if text overflow handling should be applied to the cell.
*/
export function shouldTextOverflow(field: Field): boolean {
+ let type = getCellOptions(field).type;
+
return (
field.type === FieldType.string &&
// Tech debt: Technically image cells are of type string, which is misleading (kinda?)
// so we need to ensure we don't apply overflow hover states for type image
- getCellOptions(field).type !== TableCellDisplayMode.Image &&
+ type !== TableCellDisplayMode.Image &&
+ type !== TableCellDisplayMode.Pill &&
!shouldTextWrap(field) &&
!isCellInspectEnabled(field)
);
diff --git a/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx b/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx
index d8752c8e503..ee4d69c1add 100644
--- a/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx
+++ b/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx
@@ -10,7 +10,6 @@ import { AutoCellOptionsEditor } from './cells/AutoCellOptionsEditor';
import { BarGaugeCellOptionsEditor } from './cells/BarGaugeCellOptionsEditor';
import { ColorBackgroundCellOptionsEditor } from './cells/ColorBackgroundCellOptionsEditor';
import { ImageCellOptionsEditor } from './cells/ImageCellOptionsEditor';
-import { PillCellOptionsEditor } from './cells/PillCellOptionsEditor';
import { SparklineCellOptionsEditor } from './cells/SparklineCellOptionsEditor';
// The props that any cell type editor are expected
@@ -78,9 +77,6 @@ export const TableCellOptionEditor = ({ value, onChange }: Props) => {
{cellType === TableCellDisplayMode.Image && (
)}
- {cellType === TableCellDisplayMode.Pill && (
-
- )}
);
};
diff --git a/public/app/plugins/panel/table/table-new/cells/PillCellOptionsEditor.tsx b/public/app/plugins/panel/table/table-new/cells/PillCellOptionsEditor.tsx
deleted file mode 100644
index 0ff38f33ea9..00000000000
--- a/public/app/plugins/panel/table/table-new/cells/PillCellOptionsEditor.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { t } from '@grafana/i18n';
-import { TablePillCellOptions } from '@grafana/schema';
-import { Field, ColorPicker, RadioButtonGroup, Stack } from '@grafana/ui';
-
-import { TableCellEditorProps } from '../TableCellOptionEditor';
-
-const colorModeOptions: Array<{ value: 'auto' | 'fixed' | 'mapped'; label: string }> = [
- { value: 'auto', label: 'Auto' },
- { value: 'fixed', label: 'Fixed color' },
- { value: 'mapped', label: 'Value mapping' },
-];
-
-export const PillCellOptionsEditor = ({ cellOptions, onChange }: TableCellEditorProps) => {
- const colorMode = cellOptions.colorMode || 'auto';
-
- const onColorModeChange = (mode: 'auto' | 'fixed' | 'mapped') => {
- const updatedOptions = { ...cellOptions, colorMode: mode };
- onChange(updatedOptions);
- };
-
- const onColorChange = (color: string) => {
- const updatedOptions = { ...cellOptions, color };
- onChange(updatedOptions);
- };
-
- return (
-
-
-
-
-
- {colorMode === 'fixed' && (
-
-
-
- )}
-
- {colorMode === 'mapped' && (
-
-
-
- )}
-
- );
-};
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index ea3d5595fbb..c518ead9368 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -11871,14 +11871,6 @@
"name-show-table-footer": "Show table footer",
"name-show-table-header": "Show table header",
"name-wrap-header-text": "Wrap header text",
- "pill-cell-options-editor": {
- "description-color-mode": "Choose how colors are assigned to pills",
- "description-fixed-color": "All pills in this column will use this color",
- "description-value-mappings-info": "For Value Mappings either use the global table Value Mappings or the Field overrides Value Mappings. The default will fall back to the Color Scheme. ",
- "label-color-mode": "Color Mode",
- "label-fixed-color": "Fixed Color",
- "label-value-mappings-info": "Value Mappings"
- },
"placeholder-column-width": "auto",
"placeholder-fields": "All Numeric Fields"
},