From a62d8562e632bbcc13431564dc8d408b55e98573 Mon Sep 17 00:00:00 2001 From: christophidesp Date: Thu, 10 Sep 2026 18:10:34 +0300 Subject: [PATCH 1/9] theming and table component --- src/components/select/index.js | 2 +- src/components/table/body/header/cell.js | 2 +- src/components/table/body/header/index.js | 2 +- src/components/table/header/index.js | 7 +++-- src/components/table/index.d.ts | 1 + src/components/table/table.js | 4 +++ src/components/tabs/styled.js | 13 ++++----- src/components/templates/mixins/background.js | 6 +++- .../templates/mixins/background.test.js | 12 ++++++++ src/theme/dark/colors.js | 20 +++++++------ src/theme/default/colors.js | 29 ++++++++++--------- src/theme/index.test.js | 9 ++++++ 12 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/components/select/index.js b/src/components/select/index.js index 98dd5f46d..af102fc86 100644 --- a/src/components/select/index.js +++ b/src/components/select/index.js @@ -240,7 +240,7 @@ const makeCustomStyles = (theme, { minWidth, ...providedStyles } = {}) => ({ color: getOptionColor(theme, state), backgroundColor: getOptionBackground(theme, state), ":hover": { - backgroundColor: theme.colors.secondaryHighlight, + backgroundColor: theme.colors.menuItemHover, color: theme.colors.text, }, fontSize, diff --git a/src/components/table/body/header/cell.js b/src/components/table/body/header/cell.js index c65469dee..927a8df14 100644 --- a/src/components/table/body/header/cell.js +++ b/src/components/table/body/header/cell.js @@ -123,7 +123,7 @@ const BodyHeaderCell = ({ style={enableColumnReordering ? sortableStyle : undefined} flex={getColumnFlex(column, header, table.getState().columnSizing?.[column.id] != null)} width={`${header.subHeaders.length ? header.subHeaders.reduce((s, h) => s + h.column.getSize(), 0) : column.getSize()}px`} - height={{ min: "45px" }} + height="40px" position="relative" {...(column.getCanSort() && coloredSortedColumn && diff --git a/src/components/table/body/header/index.js b/src/components/table/body/header/index.js index 33e9dcab7..e64e1747e 100644 --- a/src/components/table/body/header/index.js +++ b/src/components/table/body/header/index.js @@ -38,7 +38,7 @@ const HeaderGroup = ({ id, headers, testPrefix, rowReverse, enableColumnReorderi id={id} data-testid={`netdata-table-headRow${testPrefix}`} flex - background="mainBackground" + background="panelBg" rowReverse={rowReverse} > {headers.map((header, index) => ( diff --git a/src/components/table/header/index.js b/src/components/table/header/index.js index 7896ff493..2a816d642 100644 --- a/src/components/table/header/index.js +++ b/src/components/table/header/index.js @@ -43,11 +43,12 @@ const Header = ({ data-noprint width="100%" zIndex={10} - background="mainBackground" + background="panelBgGrad" + position="relative" gap={1} alignItems="center" - padding={[2, 3]} - round={{ side: "top", size: 1 }} + padding={[2, 4]} + border={{ side: "bottom", color: "border" }} flexWrap {...tableMeta.bulkActionsStyles} > diff --git a/src/components/table/index.d.ts b/src/components/table/index.d.ts index ce2229836..5e28fefeb 100644 --- a/src/components/table/index.d.ts +++ b/src/components/table/index.d.ts @@ -140,6 +140,7 @@ export type TableProps = { enableColumnVisibility?: boolean enableColumnPinning?: boolean enableGroupByControl?: boolean + bordered?: boolean headerActionsBeforeChildren?: boolean headerChildren?: ReactNode onGlobalSearchChange?: (value: any) => void diff --git a/src/components/table/table.js b/src/components/table/table.js index 99eba7fc8..3f4e285ed 100644 --- a/src/components/table/table.js +++ b/src/components/table/table.js @@ -45,6 +45,7 @@ const filterFns = { const emptyArray = [] const tableDefaultProps = { + bordered: true, coloredSortedColumn: true, enableColumnPinning: false, enableColumnReordering: false, @@ -73,6 +74,7 @@ const tableDefaultProps = { const Table = memo(props => { const { + bordered = tableDefaultProps.bordered, bulkActions, headerChildren, headerActionsBeforeChildren = tableDefaultProps.headerActionsBeforeChildren, @@ -319,6 +321,8 @@ const Table = memo(props => { ref={ref} className={className} width={width} + border={bordered ? { side: "all", color: "border" } : undefined} + round={1} >
({ ` const colorsByFlavour = { - success: { background: "menuItemSelected", borderColor: "border", color: "menuItem" }, - warning: { background: "warningSemi", borderColor: "border", color: "menuItem" }, - error: { background: "errorSemi", borderColor: "border", color: "menuItem" }, - default: { background: "modalBackground", borderColor: "border", color: "menuItem" }, + success: { background: "tabActiveBackground", borderColor: "border", color: "tabItem" }, + warning: { background: "warningSemi", borderColor: "border", color: "tabItem" }, + error: { background: "errorSemi", borderColor: "border", color: "tabItem" }, + default: { background: "modalBackground", borderColor: "border", color: "tabItem" }, } const activeColorsByFlavour = { success: { ...colorsByFlavour.success, borderColor: "primary", color: "primary" }, warning: { ...colorsByFlavour.warning, borderColor: "warning", color: "warning" }, error: { ...colorsByFlavour.error, borderColor: "error", color: "error" }, - default: { background: "menuItemSelected", borderColor: "accent", color: "primary" }, + default: { background: "tabActiveBackground", borderColor: "accent", color: "primary" }, } const hoverColorsByFlavour = { @@ -100,9 +100,8 @@ export const StyledTab = styled(Flex).attrs(props => ({ pointer-events: ${({ disabled }) => (disabled ? "none" : "auto")}; - margin-bottom: -1px; - ${colors} + ` export const StyledTabMenu = styled(Flex)` diff --git a/src/components/templates/mixins/background.js b/src/components/templates/mixins/background.js index 05067a3cb..dbbf09861 100644 --- a/src/components/templates/mixins/background.js +++ b/src/components/templates/mixins/background.js @@ -7,5 +7,9 @@ export default ({ theme, background, backgroundOpacity }) => { ? getRgbColor(background, backgroundOpacity)({ theme }) : getColor(background)({ theme }) - return value && `background-color: ${value};` + if (!value) return value + + return typeof value === "string" && value.startsWith("linear-gradient") + ? `background: ${value};` + : `background-color: ${value};` } diff --git a/src/components/templates/mixins/background.test.js b/src/components/templates/mixins/background.test.js index 99afe8a5d..24d6e289e 100644 --- a/src/components/templates/mixins/background.test.js +++ b/src/components/templates/mixins/background.test.js @@ -11,6 +11,18 @@ it("renders color", () => { ) }) +it("renders gradient", () => { + expect(background({ theme, background: "panelBgGrad" })).toBe( + `background: ${theme.colors.panelBgGrad};` + ) +}) + +it("renders unresolved color path", () => { + expect(background({ theme, background: ["invalid", "path"] })).toBe( + `background-color: invalid,path;` + ) +}) + it("renders invalid color", () => { expect(background({ theme, background: "invalid" })).toBe(`background-color: invalid;`) }) diff --git a/src/theme/dark/colors.js b/src/theme/dark/colors.js index dcbbf1a7e..069a15161 100644 --- a/src/theme/dark/colors.js +++ b/src/theme/dark/colors.js @@ -18,8 +18,10 @@ const appColors = { modalTabsBackground: rawColors.neutral.grey20, modalBackground: rawColors.neutral.grey30, modalInfoBackground: rawColors.neutral.grey50, - menuItemSelected: rawColors.green.green30, - menuItemHover: rawColors.green.green10, + menuItemSelected: rawColors.neutral.grey30, + menuItemHover: rawColors.neutral.grey40, + tabActiveBackground: rawColors.green.green30, + tabItem: rawColors.neutral.grey155, scrollBarTrack: rawColors.neutral.grey25, scrollBarThumb: rawColors.neutral.grey50, scrollBarThumbHover: rawColors.neutral.grey100, @@ -100,6 +102,7 @@ const appColors = { key: rawColors.neutral.iron, panel: rawColors.neutral.limedSpruce, panelBg: rawColors.neutral.grey25, + panelBgGrad: `linear-gradient(to right, ${rawColors.neutral.grey25} 0%, ${rawColors.neutral.grey15} 50%, ${rawColors.neutral.grey25} 100%)`, mainChartBg: rawColors.neutral.grey25, mainChartHeaderBg: rawColors.neutral.grey35, mainChartBorder: rawColors.neutral.grey25, @@ -119,8 +122,8 @@ const appColors = { dateTimePickerChipBg: rawColors.violet.violet20, dateTimePickerChipAccent: rawColors.violet.violet120, // Input colors - inputBg: rawColors.neutral.grey55, - inputBorder: rawColors.neutral.grey65, + inputBg: rawColors.neutral.grey30, + inputBorder: rawColors.neutral.grey45, inputBorderHover: rawColors.neutral.grey85, inputBorderFocus: rawColors.neutral.grey85, // Badges @@ -140,12 +143,11 @@ const appColors = { idleClear: rawColors.green.green20, // Table - dropdownTable: rawColors.neutral.eerieBlack, - tableRowBgHover: rawColors.neutral.grey35, + tableRowBgHover: rawColors.neutral.grey25, tableRowBg: rawColors.neutral.grey25, - tableRowBg2: rawColors.neutral.grey20, - tableRowBg2Hover: rawColors.neutral.grey35, - columnHighlight: rawColors.green.green30, + tableRowBg2: rawColors.neutral.grey25, + tableRowBg2Hover: rawColors.neutral.grey25, + columnHighlight: rawColors.neutral.grey35, // Progress Bare progressBg: rawColors.neutral.bluebayoux, diff --git a/src/theme/default/colors.js b/src/theme/default/colors.js index 59fc2f145..21c8b6ded 100644 --- a/src/theme/default/colors.js +++ b/src/theme/default/colors.js @@ -4,22 +4,24 @@ const appColors = { primary: rawColors.green.green100, accent: rawColors.green.chateau, main: rawColors.neutral.limedSpruce, - border: rawColors.neutral.grey185, - borderSecondary: rawColors.neutral.grey180, + border: rawColors.neutral.grey180, + borderSecondary: rawColors.neutral.grey175, disabled: rawColors.neutral.grey160, disabledBackground: rawColors.neutral.grey160, dropdown: rawColors.neutral.white, dropdownShadow: rawColors.shadows.dropdownLight, elementBackground: rawColors.neutral.blackhaze, elementBackgroundHover: rawColors.neutral.white, - mainBackground: rawColors.neutral.grey195, + mainBackground: rawColors.neutral.white, mainBackgroundDisabled: rawColors.neutral.blackhaze, modalHeaderBackground: rawColors.neutral.grey185, modalTabsBackground: rawColors.neutral.grey190, modalBackground: rawColors.neutral.grey195, modalInfoBackground: rawColors.neutral.blackhaze, - menuItemSelected: rawColors.green.green196, - menuItemHover: rawColors.green.green190, + menuItemSelected: rawColors.neutral.grey180, + menuItemHover: rawColors.neutral.grey185, + tabActiveBackground: rawColors.transparent.full, + tabItem: rawColors.neutral.grey100, scrollBarTrack: rawColors.neutral.grey190, scrollBarThumb: rawColors.neutral.grey170, scrollBarThumbHover: rawColors.neutral.grey150, @@ -49,7 +51,7 @@ const appColors = { successBackground: rawColors.green.green50, successText: rawColors.green.green100, - warning: rawColors.yellow.yellow80, + warning: rawColors.yellow.yellow70, warningLite: rawColors.yellow.yellow190, warningSemi: rawColors.yellow.yellow190, warningBackground: rawColors.yellow.yellow160, @@ -97,7 +99,8 @@ const appColors = { placeholder: rawColors.neutral.grey140, key: rawColors.neutral.regentgrey, panel: rawColors.neutral.limedSpruce, - panelBg: rawColors.neutral.grey190, + panelBg: rawColors.neutral.grey195, + panelBgGrad: `linear-gradient(to right, ${rawColors.neutral.grey195} 0%, ${rawColors.neutral.white} 50%, ${rawColors.neutral.grey195} 100%)`, mainChartBg: rawColors.neutral.blackhaze, mainChartHeaderBg: rawColors.neutral.grey190, mainChartBorder: rawColors.neutral.grey185, @@ -109,7 +112,7 @@ const appColors = { spaceHovered: rawColors.neutral.grey180, hoverHighlight: rawColors.green.green70, menuItem: rawColors.neutral.grey120, - topBarBg: rawColors.neutral.grey190, + topBarBg: rawColors.neutral.grey195, elevationLevelOne: rawColors.neutral.grey185, // Date picker @@ -119,8 +122,8 @@ const appColors = { dateTimePickerChipAccent: rawColors.violet.violet130, // Input colors - inputBg: rawColors.neutral.grey190, - inputBorder: rawColors.neutral.grey185, + inputBg: rawColors.neutral.white, + inputBorder: rawColors.neutral.grey180, inputBorderHover: rawColors.neutral.grey165, inputBorderFocus: rawColors.neutral.grey165, @@ -142,11 +145,11 @@ const appColors = { // Table dropdownTable: rawColors.neutral.white, - tableRowBg: rawColors.neutral.grey190, + tableRowBg: rawColors.neutral.grey195, tableRowBgHover: rawColors.neutral.grey180, tableRowBg2: rawColors.neutral.grey195, - tableRowBg2Hover: rawColors.neutral.grey185, - columnHighlight: rawColors.green.green190, + tableRowBg2Hover: rawColors.neutral.grey180, + columnHighlight: rawColors.neutral.grey190, // IconButton iconColor: rawColors.neutral.limedSpruce, diff --git a/src/theme/index.test.js b/src/theme/index.test.js index 850407273..794548682 100644 --- a/src/theme/index.test.js +++ b/src/theme/index.test.js @@ -11,4 +11,13 @@ describe("theme colors", () => { expect(DefaultTheme.colors.mapSearchHighlight).toBe(rawColors.blue.blue100) expect(DarkTheme.colors.mapSearchHighlight).toBe(rawColors.blue.blue150) }) + + it("owns a horizontal panel background gradient in both themes", () => { + expect(DefaultTheme.colors.panelBgGrad).toBe( + `linear-gradient(to right, ${rawColors.neutral.white} 0%, ${rawColors.neutral.grey195} 50%, ${rawColors.neutral.white} 100%)` + ) + expect(DarkTheme.colors.panelBgGrad).toBe( + `linear-gradient(to right, ${rawColors.neutral.grey15} 0%, ${rawColors.neutral.grey25} 50%, ${rawColors.neutral.grey15} 100%)` + ) + }) }) From aff7c50d049e36858c4371f289b4d1d6df6f0853 Mon Sep 17 00:00:00 2001 From: christophidesp Date: Mon, 14 Sep 2026 16:37:40 +0300 Subject: [PATCH 2/9] set global padding for tabs, update warning color --- src/components/tabs/styled.js | 2 +- src/theme/dark/colors.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/tabs/styled.js b/src/components/tabs/styled.js index 96e436608..98647aac2 100644 --- a/src/components/tabs/styled.js +++ b/src/components/tabs/styled.js @@ -14,7 +14,7 @@ export const StyledTabs = styled(Flex).attrs(props => ({ flexWrap: false, justifyContent: "start", alignItems: "center", - padding: [0, 0.5], + padding: [0, 4], flex: false, border: !props.noDefaultBorder && { side: "bottom", diff --git a/src/theme/dark/colors.js b/src/theme/dark/colors.js index 069a15161..f1f7a391e 100644 --- a/src/theme/dark/colors.js +++ b/src/theme/dark/colors.js @@ -53,7 +53,7 @@ const appColors = { successBackground: rawColors.green.green50, successText: rawColors.green.green100, - warning: rawColors.yellow.yellow80, + warning: rawColors.yellow.yellow60, warningLite: rawColors.yellow.yellow190, warningSemi: rawColors.yellow.yellow20, warningBackground: rawColors.yellow.yellow60, From 0d49da10b11c93fdcbbc0b238c7d61c28cdd1740 Mon Sep 17 00:00:00 2001 From: christophidesp Date: Wed, 16 Sep 2026 16:32:23 +0300 Subject: [PATCH 3/9] update dropdown color and borders, add columns icon --- src/components/drops/drop/index.js | 7 ++- src/components/drops/menu/dropdown.js | 1 + src/components/icon/assets/columns.svg | 4 ++ src/components/icon/iconsList.js | 2 + src/components/table/body/row.js | 19 ++++--- .../header/actions/columnVisibility/index.js | 55 ++++++++++++++----- src/components/table/header/actions/index.js | 2 + .../table/header/actions/useActions.js | 2 +- .../table/headerActionsOrder.test.js | 34 ++++++++++++ src/components/table/index.d.ts | 1 + src/components/table/table.js | 2 + src/theme/dark/colors.js | 2 +- 12 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 src/components/icon/assets/columns.svg diff --git a/src/components/drops/drop/index.js b/src/components/drops/drop/index.js index 8c7fe8252..c8c615c27 100644 --- a/src/components/drops/drop/index.js +++ b/src/components/drops/drop/index.js @@ -39,8 +39,13 @@ const Drop = ({ dataDrop = "drop-content", ref: parentRef, backdropProps = {}, - ...rest + ...props }) => { + const rest = + props.background === "dropdown" && props.border === undefined + ? { border: { side: "all", size: "1px", type: "solid", color: "border" }, ...props } + : props + const [ref, setRef] = useForwardRef(parentRef) const updatePosition = useMakeUpdatePosition( diff --git a/src/components/drops/menu/dropdown.js b/src/components/drops/menu/dropdown.js index 88474a3eb..b61f33dd9 100644 --- a/src/components/drops/menu/dropdown.js +++ b/src/components/drops/menu/dropdown.js @@ -79,6 +79,7 @@ const Dropdown = ({ as="ul" role="listbox" background="dropdown" + border={{ side: "all", size: "1px", type: "solid", color: "border" }} hideShadow={hideShadow} padding={[0]} margin={[1, 0]} diff --git a/src/components/icon/assets/columns.svg b/src/components/icon/assets/columns.svg new file mode 100644 index 000000000..1a27976bf --- /dev/null +++ b/src/components/icon/assets/columns.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/icon/iconsList.js b/src/components/icon/iconsList.js index 363587ab7..4b065f74d 100644 --- a/src/components/icon/iconsList.js +++ b/src/components/icon/iconsList.js @@ -78,6 +78,7 @@ import cluster_spaces from "./assets/cluster_spaces.svg" import code from "./assets/code.svg" import collapse from "./assets/collapse.svg" import collect from "./assets/collect.svg" +import columns from "./assets/columns.svg" import community from "./assets/community.svg" import connection_to_cloud from "./assets/connection_to_cloud.svg" import connectivityStatusLive from "./assets/connectivity_status_live.svg" @@ -563,6 +564,7 @@ export const iconsList = { code, collapse, collect, + columns, community, connection_to_cloud, connectivityStatusLive, diff --git a/src/components/table/body/row.js b/src/components/table/body/row.js index ec5bac586..abaf7d111 100644 --- a/src/components/table/body/row.js +++ b/src/components/table/body/row.js @@ -138,7 +138,7 @@ const rerenderSelector = state => ({ const StyledRow = styled(Flex)` &:hover .row-content { - background: ${getColor("mainBackgroundHover")}; + background: ${getColor("tableRowBgHover")}; } ` @@ -148,9 +148,13 @@ const DirectStyledRow = styled(Flex).attrs({ background: "mainBackground", border: { side: "bottom" }, })` + .row-content { + background-color: ${getColor("mainBackground")}; + } + &:hover, &:hover .row-content { - background: ${getColor("mainBackgroundHover")}; + background-color: ${getColor("tableRowBgHover")}; } ` @@ -216,7 +220,6 @@ const TableRow = ({ borderRight: `1px solid ${getColor("border")({ theme })}`, zIndex: zIndex || 10, flex: `0 0 ${table.getLeftTotalSize()}px`, - backgroundColor: getColor("mainBackground")({ theme }), }} > {row.getLeftVisibleCells().map((cell, index) => ( @@ -239,7 +242,6 @@ const TableRow = ({ display: "flex", width: `${table.getCenterTotalSize()}px`, flex: "1 0 auto", - backgroundColor: getColor("mainBackground")({ theme }), }} > {row.getCenterVisibleCells().map((cell, index) => ( @@ -266,7 +268,6 @@ const TableRow = ({ zIndex: zIndex || 10, flex: `0 0 ${table.getRightTotalSize()}px`, flexDirection: "row-reverse", - backgroundColor: getColor("mainBackground")({ theme }), }} > {row.getRightVisibleCells().map((cell, index) => ( @@ -296,7 +297,7 @@ const TableRow = ({ flex={false} background="mainBackground" _hover={{ - background: "mainBackgroundHover", + background: "tableRowBgHover", }} className="row-content" > @@ -318,7 +319,7 @@ const TableRow = ({ flex="grow" background="mainBackground" _hover={{ - background: "mainBackgroundHover", + background: "tableRowBgHover", }} className="row-content" > @@ -346,7 +347,7 @@ const TableRow = ({ flex={false} background="mainBackground" _hover={{ - background: "mainBackgroundHover", + background: "tableRowBgHover", }} rowReverse className="row-content" @@ -383,7 +384,7 @@ const TableRow = ({ flex: true, column: true, background: "mainBackground", - _hover: { background: "mainBackgroundHover" }, + _hover: { background: "tableRowBgHover" }, border: { side: "bottom" }, })} > diff --git a/src/components/table/header/actions/columnVisibility/index.js b/src/components/table/header/actions/columnVisibility/index.js index 7f2ea28bd..c657415bd 100644 --- a/src/components/table/header/actions/columnVisibility/index.js +++ b/src/components/table/header/actions/columnVisibility/index.js @@ -1,5 +1,7 @@ import React, { useRef, useMemo } from "react" import useToggle from "@/hooks/useToggle" +import Tooltip from "@/components/drops/tooltip" +import { Button } from "@/components/button" import BulkAction from "../action" import ColumnsMenu from "./columnsMenu" import { supportedBulkActions } from "../useActions" @@ -14,6 +16,7 @@ const excludedById = { const ColumnVisibilityAction = ({ alwaysEnabled, + buttonFlavour, columnPinning = {}, dataGa, enableColumnPinning, @@ -34,6 +37,7 @@ const ColumnVisibilityAction = ({ const actionRef = useRef() const disabled = typeof isDisabled === "function" ? isDisabled() : isDisabled const visible = typeof isVisible === "function" ? isVisible() : isVisible + const triggerDisabled = (!alwaysEnabled && selectedRows?.length < 1) || disabled const columnGroups = useMemo(() => { const groups = [] @@ -99,20 +103,43 @@ const ColumnVisibilityAction = ({ return ( <> - handleAction(selectedRows, table)} - tooltipText={tooltipText} - disabled={(!alwaysEnabled && selectedRows?.length < 1) || disabled} - background="elementBackground" - selectedRows={selectedRows} - dataGa={dataGa} - {...rest} - /> + {buttonFlavour === "hollow" ? ( + visible !== false && ( + +