From 2a756088f14e6ca73cc36f56bb68ad2bd1327c01 Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Fri, 25 Oct 2024 11:02:52 -0400 Subject: [PATCH] Fleet UI: Accessibility button actions, tabbing (#22916) --- .../ActionsDropdown/ActionsDropdown.tests.tsx | 92 +++++++ .../ActionsDropdown/ActionsDropdown.tsx | 252 ++++++++++++++++++ .../components/ActionsDropdown/_styles.scss | 6 + frontend/components/ActionsDropdown/index.ts | 1 + .../components/FileUploader/FileUploader.tsx | 22 +- frontend/components/Modal/Modal.tsx | 2 +- .../DropdownCell/DropdownCell.tests.tsx | 33 --- .../DataTable/DropdownCell/DropdownCell.tsx | 37 --- .../DataTable/DropdownCell/_styles.scss | 87 ------ .../DataTable/DropdownCell/index.ts | 1 - .../TeamsDropdown/TeamsDropdown.tsx | 1 + frontend/components/buttons/Button/Button.tsx | 9 +- .../components/buttons/Button/_styles.scss | 7 +- .../buttons/DropdownButton/_styles.scss | 2 +- .../DropdownOptionTooltipWrapper/_styles.scss | 5 +- .../PackQueriesTableConfig.tsx | 10 +- .../components/top_nav/UserMenu/UserMenu.tsx | 2 +- .../components/top_nav/UserMenu/_styles.scss | 16 ++ .../SoftwarePackageCard.tsx | 16 +- .../Integrations/IntegrationsTableConfig.tsx | 10 +- .../AppleBusinessManagerTableConfig.tsx | 4 +- .../components/VppTable/VppTableConfig.tsx | 4 +- .../components/IdpSection/IdpSection.tsx | 1 + .../UsersPage/UsersPageTableConfig.tsx | 10 +- .../TeamManagementPage/TeamTableConfig.tsx | 2 +- .../UsersTable/UsersTableConfig.tsx | 10 +- .../HostStatusWebhookPreviewModal.tsx | 2 +- .../CustomLabelGroupHeading.tsx | 2 +- .../components/FilterPill/_styles.scss | 5 - .../LabelFilterSelect/LabelFilterSelect.tsx | 16 +- .../DeleteHostModal/DeleteHostModal.tsx | 8 +- .../HostActionsDropdown.tests.tsx | 18 +- .../HostActionsDropdown.tsx | 7 +- .../RunScriptModal/ScriptsTableConfig.tsx | 8 +- .../Software/HostSoftwareTableConfig.tsx | 4 +- frontend/styles/var/colors.ts | 5 + frontend/styles/var/mixins.scss | 7 + frontend/styles/var/padding.ts | 19 ++ 38 files changed, 503 insertions(+), 240 deletions(-) create mode 100644 frontend/components/ActionsDropdown/ActionsDropdown.tests.tsx create mode 100644 frontend/components/ActionsDropdown/ActionsDropdown.tsx create mode 100644 frontend/components/ActionsDropdown/_styles.scss create mode 100644 frontend/components/ActionsDropdown/index.ts delete mode 100644 frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tests.tsx delete mode 100644 frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tsx delete mode 100644 frontend/components/TableContainer/DataTable/DropdownCell/_styles.scss delete mode 100644 frontend/components/TableContainer/DataTable/DropdownCell/index.ts create mode 100644 frontend/styles/var/padding.ts diff --git a/frontend/components/ActionsDropdown/ActionsDropdown.tests.tsx b/frontend/components/ActionsDropdown/ActionsDropdown.tests.tsx new file mode 100644 index 0000000000..a1f7a71c14 --- /dev/null +++ b/frontend/components/ActionsDropdown/ActionsDropdown.tests.tsx @@ -0,0 +1,92 @@ +import React from "react"; +import { screen } from "@testing-library/react"; +import { renderWithSetup } from "test/test-utils"; + +import ActionsDropdown from "./ActionsDropdown"; + +const DROPDOWN_OPTIONS = [ + { disabled: false, label: "Edit", value: "edit-query" }, + { disabled: false, label: "Show query", value: "show-query" }, + { disabled: true, label: "Delete", value: "delete-query" }, +]; +const PLACEHOLDER = "Actions"; +const ON_CHANGE = (value: string) => { + console.log(value); +}; + +describe("Actions dropdown", () => { + it("renders dropdown placeholder and options", async () => { + const { user } = renderWithSetup( + + ); + + await user.click(screen.getByText("Actions")); + + expect(screen.queryAllByText(/edit/i)[1]).toBeInTheDocument(); // Aria shows Edit twice since it's focused + expect(screen.queryByText(/show query/i)).toBeInTheDocument(); + expect(screen.queryByText(/delete/i)).toBeInTheDocument(); + }); + + it("renders dropdown as disabled when disabled prop is true", () => { + renderWithSetup( + + ); + expect(screen.getByRole("combobox")).toBeDisabled(); + }); + + it("calls onChange with correct value when an option is selected", async () => { + const mockOnChange = jest.fn(); + const { user } = renderWithSetup( + + ); + + await user.click(screen.getByText("Actions")); + await user.click(screen.getByText("Edit")); + + expect(mockOnChange).toHaveBeenCalledWith("edit-query"); + }); + + it("renders disabled option as non-selectable", async () => { + const { user } = renderWithSetup( + + ); + + await user.click(screen.getByText("Actions")); + const deleteOption = screen.getByText("Delete"); + + expect(deleteOption).toHaveAttribute("aria-disabled", "true"); + }); + + it("closes the dropdown when clicking outside", async () => { + const { user } = renderWithSetup( + + ); + + await user.click(screen.getByText("Actions")); + expect(screen.getByText("Edit")).toBeVisible(); + + await user.click(document.body); + expect(screen.queryByText(/edit/i)).not.toBeInTheDocument(); + }); +}); diff --git a/frontend/components/ActionsDropdown/ActionsDropdown.tsx b/frontend/components/ActionsDropdown/ActionsDropdown.tsx new file mode 100644 index 0000000000..9e068bf735 --- /dev/null +++ b/frontend/components/ActionsDropdown/ActionsDropdown.tsx @@ -0,0 +1,252 @@ +import React from "react"; +import Select, { + StylesConfig, + DropdownIndicatorProps, + OptionProps, + components, +} from "react-select-5"; + +import { PADDING } from "styles/var/padding"; +import { COLORS } from "styles/var/colors"; +import classnames from "classnames"; + +import { IDropdownOption } from "interfaces/dropdownOption"; + +import Icon from "components/Icon"; +import DropdownOptionTooltipWrapper from "components/forms/fields/Dropdown/DropdownOptionTooltipWrapper"; + +const baseClass = "actions-dropdown"; + +interface IActionsDropdownProps { + options: IDropdownOption[]; + placeholder: string; + onChange: (value: string) => void; + disabled?: boolean; + isSearchable?: boolean; + className?: string; + menuAlign?: "right" | "left" | "default"; +} + +const getOptionBackgroundColor = (state: any) => { + return state.isSelected || state.isFocused + ? COLORS["ui-vibrant-blue-10"] + : "transparent"; +}; + +const getLeftMenuAlign = (menuAlign: "right" | "left" | "default") => { + switch (menuAlign) { + case "right": + return "auto"; + case "left": + return "0"; + default: + return "-12px"; + } +}; + +const getRightMenuAlign = (menuAlign: "right" | "left" | "default") => { + switch (menuAlign) { + case "right": + return "0"; + default: + return "undefined"; + } +}; + +const CustomDropdownIndicator = ( + props: DropdownIndicatorProps +) => { + const { isFocused, selectProps } = props; + // no access to hover state here from react-select so that is done in the scss + // file of ActionsDropdown. + const color = + isFocused || selectProps.menuIsOpen + ? "core-fleet-blue" + : "core-fleet-black"; + + return ( + + + + ); +}; + +const CustomOption: React.FC> = (props) => { + const { innerProps, innerRef, data, isDisabled } = props; + + const optionContent = ( +
+ {data.label} + {data.helpText && ( + {data.helpText} + )} +
+ ); + + return ( + + {data.tooltipContent ? ( + + {optionContent} + + ) : ( + optionContent + )} + + ); +}; + +const ActionsDropdown = ({ + options, + placeholder, + onChange, + disabled, + isSearchable = false, + className, + menuAlign = "default", +}: IActionsDropdownProps): JSX.Element => { + const dropdownClassnames = classnames(baseClass, className); + + const handleChange = (newValue: IDropdownOption | null) => { + if (newValue) { + onChange(newValue.value.toString()); + } + }; + + const customStyles: StylesConfig = { + container: (provided) => ({ + ...provided, + width: "80px", + }), + control: (provided, state) => ({ + ...provided, + display: "flex", + flexDirection: "row", + width: "max-content", + padding: "8px 0", + backgroundColor: "initial", + border: 0, + boxShadow: "none", + cursor: "pointer", + "&:hover": { + boxShadow: "none", + ".actions-dropdown-select__placeholder": { + color: COLORS["core-vibrant-blue-over"], + }, + ".actions-dropdown-select__indicator path": { + stroke: COLORS["core-vibrant-blue-over"], + }, + }, + "&:active .actions-dropdown-select__indicator path": { + stroke: COLORS["core-vibrant-blue-down"], + }, + // TODO: Figure out a way to apply separate &:focus-visible styling + // Currently only relying on &:focus styling for tabbing through app + ...(state.menuIsOpen && { + ".actions-dropdown-select__indicator svg": { + transform: "rotate(180deg)", + transition: "transform 0.25s ease", + }, + }), + }), + placeholder: (provided, state) => ({ + ...provided, + color: state.isFocused + ? COLORS["core-fleet-blue"] + : COLORS["core-fleet-black"], + fontSize: "14px", + lineHeight: "normal", + paddingLeft: 0, + marginTop: "1px", + }), + dropdownIndicator: (provided) => ({ + ...provided, + display: "flex", + padding: "2px", + svg: { + transition: "transform 0.25s ease", + }, + }), + menu: (provided) => ({ + ...provided, + boxShadow: "0 2px 6px rgba(0, 0, 0, 0.1)", + borderRadius: "4px", + zIndex: 6, + overflow: "hidden", + border: 0, + marginTop: 0, + minWidth: "158px", + maxHeight: "220px", + position: "absolute", + left: getLeftMenuAlign(menuAlign), + right: getRightMenuAlign(menuAlign), + animation: "fade-in 150ms ease-out", + }), + menuList: (provided) => ({ + ...provided, + padding: PADDING["pad-small"], + }), + valueContainer: (provided) => ({ + ...provided, + padding: 0, + }), + option: (provided, state) => ({ + ...provided, + padding: "10px 8px", + fontSize: "14px", + backgroundColor: getOptionBackgroundColor(state), + "&:hover": { + backgroundColor: state.isDisabled + ? "transparent" + : COLORS["ui-vibrant-blue-10"], + }, + "&:active": { + backgroundColor: state.isDisabled + ? "transparent" + : COLORS["ui-vibrant-blue-10"], + }, + ...(state.isDisabled && { + color: COLORS["ui-fleet-black-50"], + fontStyle: "italic", + // pointerEvents: "none", // Prevents any mouse interaction + }), + }), + }; + + return ( +
+ + options={options} + placeholder={placeholder} + onChange={handleChange} + isDisabled={disabled} + isSearchable={isSearchable} + styles={customStyles} + components={{ + DropdownIndicator: CustomDropdownIndicator, + IndicatorSeparator: () => null, + Option: CustomOption, + SingleValue: () => null, // Doesn't replace placeholder text with selected text + // Note: react-select doesn't support skipping disabled options when keyboarding through + }} + controlShouldRenderValue={false} // Doesn't change placeholder text to selected text + isOptionSelected={() => false} // Hides any styling on selected option + className={dropdownClassnames} + classNamePrefix={`${baseClass}-select`} + isOptionDisabled={(option) => !!option.disabled} + /> +
+ ); +}; + +export default ActionsDropdown; diff --git a/frontend/components/ActionsDropdown/_styles.scss b/frontend/components/ActionsDropdown/_styles.scss new file mode 100644 index 0000000000..ba8549808d --- /dev/null +++ b/frontend/components/ActionsDropdown/_styles.scss @@ -0,0 +1,6 @@ +// All styling in customStyles part of react-select-5 +.actions-dropdown-select__control { + &:focus-visible { + background-color: $core-fleet-blue; + } +} diff --git a/frontend/components/ActionsDropdown/index.ts b/frontend/components/ActionsDropdown/index.ts new file mode 100644 index 0000000000..92d81527a2 --- /dev/null +++ b/frontend/components/ActionsDropdown/index.ts @@ -0,0 +1 @@ +export { default } from "./ActionsDropdown"; diff --git a/frontend/components/FileUploader/FileUploader.tsx b/frontend/components/FileUploader/FileUploader.tsx index 6ba3bfa42f..9951ae3509 100644 --- a/frontend/components/FileUploader/FileUploader.tsx +++ b/frontend/components/FileUploader/FileUploader.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useRef } from "react"; import classnames from "classnames"; import Button from "components/buttons/Button"; @@ -74,18 +74,32 @@ export const FileUploader = ({ fileDetails, }: IFileUploaderProps) => { const [isFileSelected, setIsFileSelected] = useState(!!fileDetails); + const fileInputRef = useRef(null); const classes = classnames(baseClass, className, { [`${baseClass}__file-preview`]: isFileSelected, }); const buttonVariant = buttonType === "button" ? "brand" : "text-icon"; + const triggerFileInput = () => { + fileInputRef.current?.click(); + }; + const onFileSelect = (e: React.ChangeEvent) => { const files = e.target.files; onFileUpload(files); setIsFileSelected(true); - e.target.value = ""; + if (fileInputRef.current) { + fileInputRef.current.value = ""; + } + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + e.preventDefault(); + triggerFileInput(); + } }; const renderGraphics = () => { @@ -113,6 +127,9 @@ export const FileUploader = ({ variant={buttonVariant} isLoading={isLoading} disabled={disabled} + customOnKeyDown={handleKeyDown} + tabIndex={0} + onClick={triggerFileInput} > {title} {!disableClosingModal && (
-
diff --git a/frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tests.tsx b/frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tests.tsx deleted file mode 100644 index 8c0c988525..0000000000 --- a/frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tests.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import { screen } from "@testing-library/react"; -import { renderWithSetup } from "test/test-utils"; - -import DropdownCell from "./DropdownCell"; - -const DROPDOWN_OPTIONS = [ - { disabled: false, label: "Edit", value: "edit-query" }, - { disabled: false, label: "Show query", value: "show-query" }, - { disabled: true, label: "Delete", value: "delete-query" }, -]; -const PLACEHOLDER = "Actions"; -const ON_CHANGE = (value: string) => { - console.log(value); -}; - -describe("Dropdown cell", () => { - it("renders dropdown placeholder and options", async () => { - const { user } = renderWithSetup( - - ); - - await user.click(screen.getByText("Actions")); - - expect(screen.getByText(/edit/i)).toBeInTheDocument(); - expect(screen.getByText(/show query/i)).toBeInTheDocument(); - expect(screen.getByText(/delete/i)).toBeInTheDocument(); - }); -}); diff --git a/frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tsx b/frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tsx deleted file mode 100644 index 6eb4fad3ea..0000000000 --- a/frontend/components/TableContainer/DataTable/DropdownCell/DropdownCell.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from "react"; - -// ignore TS error for now until these are rewritten in ts. -// @ts-ignore -import Dropdown from "components/forms/fields/Dropdown"; - -import { IDropdownOption } from "interfaces/dropdownOption"; - -const baseClass = "dropdown-cell"; - -interface IDropdownCellProps { - options: IDropdownOption[]; - placeholder: string; - onChange: (value: string) => void; - disabled?: boolean; -} - -const DropdownCell = ({ - options, - placeholder, - onChange, - disabled, -}: IDropdownCellProps): JSX.Element => { - return ( -
- -
- ); -}; - -export default DropdownCell; diff --git a/frontend/components/TableContainer/DataTable/DropdownCell/_styles.scss b/frontend/components/TableContainer/DataTable/DropdownCell/_styles.scss deleted file mode 100644 index eaf1d1c3c2..0000000000 --- a/frontend/components/TableContainer/DataTable/DropdownCell/_styles.scss +++ /dev/null @@ -1,87 +0,0 @@ -.dropdown-cell { - width: 80px; - - .form-field { - margin: 0; - } - - .Select { - position: relative; - border: 0; - height: auto; - - &.is-focused, - &:hover { - border: 0; - } - - &.is-focused:not(.is-open) { - .Select-control { - background-color: initial; - } - } - - &.is-disabled { - .Select-control { - .Select-placeholder { - @include disabled; - } - } - } - - .Select-control { - display: flex; - background-color: initial; - height: auto; - justify-content: space-between; - border: 0; - cursor: pointer; - - &:hover { - box-shadow: none; - } - - &:hover .Select-placeholder { - color: $core-vibrant-blue; - } - - .Select-placeholder { - color: $core-fleet-black; - font-size: 14px; - line-height: normal; - padding-left: 0; - margin-top: 1px; - } - - .Select-input { - height: auto; - } - - .Select-arrow-zone { - display: flex; - } - } - - .Select-menu-outer { - margin-top: $pad-xsmall; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); - border-radius: $border-radius; - z-index: 6; - overflow: hidden; - border: 0; - width: 188px; - left: unset; - top: unset; - max-height: 220px; - padding: $pad-small; - position: absolute; - left: -12px; - } - - &.is-open { - .Select-control .Select-placeholder { - color: $core-vibrant-blue; - } - } - } -} diff --git a/frontend/components/TableContainer/DataTable/DropdownCell/index.ts b/frontend/components/TableContainer/DataTable/DropdownCell/index.ts deleted file mode 100644 index d2a9324aa2..0000000000 --- a/frontend/components/TableContainer/DataTable/DropdownCell/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./DropdownCell"; diff --git a/frontend/components/TeamsDropdown/TeamsDropdown.tsx b/frontend/components/TeamsDropdown/TeamsDropdown.tsx index 31f2400d3d..f96a0a77d2 100644 --- a/frontend/components/TeamsDropdown/TeamsDropdown.tsx +++ b/frontend/components/TeamsDropdown/TeamsDropdown.tsx @@ -85,6 +85,7 @@ const TeamsDropdown = ({ onChange={onChange} onOpen={onOpen} onClose={onClose} + tabIndex={0} /> ); } diff --git a/frontend/components/buttons/Button/Button.tsx b/frontend/components/buttons/Button/Button.tsx index 44b28fc4db..48ee81ad00 100644 --- a/frontend/components/buttons/Button/Button.tsx +++ b/frontend/components/buttons/Button/Button.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { Children } from "react"; import classnames from "classnames"; import Spinner from "components/Spinner"; @@ -35,6 +35,7 @@ export interface IButtonProps { tabIndex?: number; type?: "button" | "submit" | "reset"; title?: string; + /** Default: "brand" */ variant?: ButtonVariant; onClick?: | ((value?: any) => void) @@ -44,6 +45,7 @@ export interface IButtonProps { | React.KeyboardEvent ) => void); isLoading?: boolean; + customOnKeyDown?: (e: React.KeyboardEvent) => void; } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -57,7 +59,7 @@ class Button extends React.Component { static defaultProps = { size: "", type: "button", - variant: "default", + variant: "brand", }; componentDidMount(): void { @@ -115,6 +117,7 @@ class Button extends React.Component { title, variant, isLoading, + customOnKeyDown, } = this.props; const fullClassName = classnames( baseClass, @@ -136,7 +139,7 @@ class Button extends React.Component { className={fullClassName} disabled={disabled} onClick={handleClick} - onKeyDown={handleKeyDown} + onKeyDown={customOnKeyDown || handleKeyDown} tabIndex={tabIndex} type={type} title={title} diff --git a/frontend/components/buttons/Button/_styles.scss b/frontend/components/buttons/Button/_styles.scss index f38badbcce..ca6fc09598 100644 --- a/frontend/components/buttons/Button/_styles.scss +++ b/frontend/components/buttons/Button/_styles.scss @@ -301,8 +301,13 @@ $base-class: "button"; color: $core-vibrant-blue-down; } - &:focus { + &:focus-visible { + color: $core-vibrant-blue-over; + border: 1px; + border-radius: 2px; // Visble when tabbing + background: var(--Core-White, #fff); outline: none; + box-shadow: 0px 0px 0px 2px #fff, 0px 0px 0px 4px #d9d9fe; } &:hover, diff --git a/frontend/components/buttons/DropdownButton/_styles.scss b/frontend/components/buttons/DropdownButton/_styles.scss index 18f6d59871..d22bb4e208 100644 --- a/frontend/components/buttons/DropdownButton/_styles.scss +++ b/frontend/components/buttons/DropdownButton/_styles.scss @@ -1,5 +1,5 @@ .dropdown-button { - padding: 8px 24px 8px 0; + padding: 8px 0; &__wrapper { display: flex; position: relative; diff --git a/frontend/components/forms/fields/Dropdown/DropdownOptionTooltipWrapper/_styles.scss b/frontend/components/forms/fields/Dropdown/DropdownOptionTooltipWrapper/_styles.scss index c617631615..7fcd24ad33 100644 --- a/frontend/components/forms/fields/Dropdown/DropdownOptionTooltipWrapper/_styles.scss +++ b/frontend/components/forms/fields/Dropdown/DropdownOptionTooltipWrapper/_styles.scss @@ -1,4 +1,7 @@ -.Select > .Select-menu-outer { +// Used with old react-select dropdown and +// New react-select-5 ActionsDropdown.tsx +.Select > .Select-menu-outer, +.actions-dropdown { .is-disabled * { color: $ui-fleet-black-50; } diff --git a/frontend/components/queries/PackQueriesTable/PackQueriesTable/PackQueriesTableConfig.tsx b/frontend/components/queries/PackQueriesTable/PackQueriesTable/PackQueriesTableConfig.tsx index b93aea08df..089302eedc 100644 --- a/frontend/components/queries/PackQueriesTable/PackQueriesTable/PackQueriesTableConfig.tsx +++ b/frontend/components/queries/PackQueriesTable/PackQueriesTable/PackQueriesTableConfig.tsx @@ -12,7 +12,7 @@ import { IScheduledQuery } from "interfaces/scheduled_query"; import { IDropdownOption } from "interfaces/dropdownOption"; import Checkbox from "components/forms/fields/Checkbox"; -import DropdownCell from "components/TableContainer/DataTable/DropdownCell"; +import ActionsDropdown from "components/ActionsDropdown"; import HeaderCell from "components/TableContainer/DataTable/HeaderCell/HeaderCell"; import PerformanceImpactCell from "components/TableContainer/DataTable/PerformanceImpactCell"; import TextCell from "components/TableContainer/DataTable/TextCell"; @@ -54,7 +54,7 @@ interface IPerformanceImpactCellProps extends IRowProps { }; } -interface IDropdownCellProps extends IRowProps { +interface IActionsDropdownProps extends IRowProps { cell: { value: IDropdownOption[]; }; @@ -68,7 +68,7 @@ interface IDataColumn { Cell: | ((props: ICellProps) => JSX.Element) | ((props: IPerformanceImpactCellProps) => JSX.Element) - | ((props: IDropdownCellProps) => JSX.Element); + | ((props: IActionsDropdownProps) => JSX.Element); disableHidden?: boolean; disableSortBy?: boolean; } @@ -182,8 +182,8 @@ const generateTableHeaders = ( Header: "", disableSortBy: true, accessor: "actions", - Cell: (cellProps: IDropdownCellProps) => ( - ( + actionSelectHandler(value, cellProps.row.original) diff --git a/frontend/components/top_nav/UserMenu/UserMenu.tsx b/frontend/components/top_nav/UserMenu/UserMenu.tsx index 0cae736a32..b1228abc25 100644 --- a/frontend/components/top_nav/UserMenu/UserMenu.tsx +++ b/frontend/components/top_nav/UserMenu/UserMenu.tsx @@ -71,7 +71,7 @@ const UserMenu = ({ return (
- + void; } -const ActionsDropdown = ({ +const SoftwareActionsDropdown = ({ isSoftwarePackage, onDownloadClick, onDeleteClick, @@ -207,16 +206,17 @@ const ActionsDropdown = ({ return (
-
); @@ -353,7 +353,7 @@ const SoftwarePackageCard = ({
)} {showActions && ( - JSX.Element) - | ((props: IDropdownCellProps) => JSX.Element); + | ((props: IActionsDropdownProps) => JSX.Element); disableHidden?: boolean; disableSortBy?: boolean; sortType?: string; @@ -98,8 +98,8 @@ const generateTableHeaders = ( Header: "", disableSortBy: true, accessor: "actions", - Cell: (cellProps: IDropdownCellProps) => ( - ( + actionSelectHandler(value, cellProps.row.original) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx index d79e1d3eb1..03a633b599 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx @@ -6,7 +6,7 @@ import { IHeaderProps, IStringCellProps } from "interfaces/datatable_config"; import { IDropdownOption } from "interfaces/dropdownOption"; import HeaderCell from "components/TableContainer/DataTable/HeaderCell"; -import DropdownCell from "components/TableContainer/DataTable/DropdownCell"; +import ActionsDropdown from "components/ActionsDropdown"; import TextCell from "components/TableContainer/DataTable/TextCell"; import TooltipWrapper from "components/TooltipWrapper"; @@ -163,7 +163,7 @@ export const generateTableConfig = ( // but we don't use it. accessor: "id", Cell: (cellProps) => ( - actionSelectHandler(value, cellProps.row.original) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/VppTable/VppTableConfig.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/VppTable/VppTableConfig.tsx index 28e1e32cae..2a10c65bf7 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/VppTable/VppTableConfig.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/VppTable/VppTableConfig.tsx @@ -6,7 +6,7 @@ import { IHeaderProps, IStringCellProps } from "interfaces/datatable_config"; import { IDropdownOption } from "interfaces/dropdownOption"; import HeaderCell from "components/TableContainer/DataTable/HeaderCell"; -import DropdownCell from "components/TableContainer/DataTable/DropdownCell"; +import ActionsDropdown from "components/ActionsDropdown"; import TextCell from "components/TableContainer/DataTable/TextCell"; import RenewDateCell from "../../../components/RenewDateCell"; @@ -104,7 +104,7 @@ export const generateTableConfig = ( // but we don't use it. accessor: "id", Cell: (cellProps) => ( - actionSelectHandler(value, cellProps.row.original) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/IdpSection/IdpSection.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/IdpSection/IdpSection.tsx index a3f50e6e2f..6bc821b468 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/IdpSection/IdpSection.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/IdpSection/IdpSection.tsx @@ -114,6 +114,7 @@ const IdpSection = () => { disabled={!completedForm} onClick={onSubmit} className="button-wrap" + variant="brand" > Save diff --git a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/UsersPage/UsersPageTableConfig.tsx b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/UsersPage/UsersPageTableConfig.tsx index 20d166e251..6cb769b90d 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/UsersPage/UsersPageTableConfig.tsx +++ b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/UsersPage/UsersPageTableConfig.tsx @@ -1,7 +1,7 @@ import React from "react"; import ReactTooltip from "react-tooltip"; import TextCell from "components/TableContainer/DataTable/TextCell/TextCell"; -import DropdownCell from "components/TableContainer/DataTable/DropdownCell"; +import ActionsDropdown from "components/ActionsDropdown"; import CustomLink from "components/CustomLink"; import { IUser, UserRole } from "interfaces/user"; import { ITeam } from "interfaces/team"; @@ -29,7 +29,7 @@ interface ICellProps extends IRowProps { }; } -interface IDropdownCellProps extends IRowProps { +interface IActionsDropdownProps extends IRowProps { cell: { value: IDropdownOption[]; }; @@ -41,7 +41,7 @@ interface IDataColumn { accessor: string; Cell: | ((props: ICellProps) => JSX.Element) - | ((props: IDropdownCellProps) => JSX.Element); + | ((props: IActionsDropdownProps) => JSX.Element); disableHidden?: boolean; disableSortBy?: boolean; sortType?: string; @@ -174,8 +174,8 @@ const generateColumnConfigs = ( Header: "", disableSortBy: true, accessor: "actions", - Cell: (cellProps: IDropdownCellProps) => ( - ( + actionSelectHandler(value, cellProps.row.original) diff --git a/frontend/pages/admin/TeamManagementPage/TeamTableConfig.tsx b/frontend/pages/admin/TeamManagementPage/TeamTableConfig.tsx index 55edae36d2..31a7de9ebe 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamTableConfig.tsx +++ b/frontend/pages/admin/TeamManagementPage/TeamTableConfig.tsx @@ -2,7 +2,7 @@ import React from "react"; import LinkCell from "components/TableContainer/DataTable/LinkCell"; import TextCell from "components/TableContainer/DataTable/TextCell"; -import DropdownCell from "components/TableContainer/DataTable/DropdownCell"; +import DropdownCell from "components/ActionsDropdown"; import { ITeam } from "interfaces/team"; import { IDropdownOption } from "interfaces/dropdownOption"; import PATHS from "router/paths"; diff --git a/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx b/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx index bb6788b012..482b0b491a 100644 --- a/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx +++ b/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx @@ -12,7 +12,7 @@ import { IDropdownOption } from "interfaces/dropdownOption"; import { generateRole, generateTeam, greyCell } from "utilities/helpers"; import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants"; import { COLORS } from "styles/var/colors"; -import DropdownCell from "../../../../../components/TableContainer/DataTable/DropdownCell"; +import ActionsDropdown from "../../../../../components/ActionsDropdown"; interface IHeaderProps { column: { @@ -33,7 +33,7 @@ interface ICellProps extends IRowProps { }; } -interface IDropdownCellProps extends IRowProps { +interface IActionsDropdownProps extends IRowProps { cell: { value: IDropdownOption[]; }; @@ -45,7 +45,7 @@ interface IDataColumn { accessor: string; Cell: | ((props: ICellProps) => JSX.Element) - | ((props: IDropdownCellProps) => JSX.Element); + | ((props: IActionsDropdownProps) => JSX.Element); disableHidden?: boolean; disableSortBy?: boolean; } @@ -200,8 +200,8 @@ const generateTableHeaders = ( Header: "", disableSortBy: true, accessor: "actions", - Cell: (cellProps: IDropdownCellProps) => ( - ( + actionSelectHandler(value, cellProps.row.original) diff --git a/frontend/pages/admin/components/HostStatusWebhookPreviewModal/HostStatusWebhookPreviewModal.tsx b/frontend/pages/admin/components/HostStatusWebhookPreviewModal/HostStatusWebhookPreviewModal.tsx index f46dfaf4ae..2a4885499c 100644 --- a/frontend/pages/admin/components/HostStatusWebhookPreviewModal/HostStatusWebhookPreviewModal.tsx +++ b/frontend/pages/admin/components/HostStatusWebhookPreviewModal/HostStatusWebhookPreviewModal.tsx @@ -54,7 +54,7 @@ const HostStatusWebhookPreviewModal = ({ />
-
diff --git a/frontend/pages/hosts/ManageHostsPage/components/CustomLabelGroupHeading/CustomLabelGroupHeading.tsx b/frontend/pages/hosts/ManageHostsPage/components/CustomLabelGroupHeading/CustomLabelGroupHeading.tsx index f6e564b216..729bd31bc6 100644 --- a/frontend/pages/hosts/ManageHostsPage/components/CustomLabelGroupHeading/CustomLabelGroupHeading.tsx +++ b/frontend/pages/hosts/ManageHostsPage/components/CustomLabelGroupHeading/CustomLabelGroupHeading.tsx @@ -30,7 +30,7 @@ const CustomLabelGroupHeading = ( const handleInputClick = ( event: React.MouseEvent ) => { - onClickLabelSearchInput(event); + onClickLabelSearchInput && onClickLabelSearchInput(event); inputRef.current?.focus(); event.stopPropagation(); }; diff --git a/frontend/pages/hosts/ManageHostsPage/components/FilterPill/_styles.scss b/frontend/pages/hosts/ManageHostsPage/components/FilterPill/_styles.scss index 8f4a9c76a3..a71973b863 100644 --- a/frontend/pages/hosts/ManageHostsPage/components/FilterPill/_styles.scss +++ b/frontend/pages/hosts/ManageHostsPage/components/FilterPill/_styles.scss @@ -17,11 +17,6 @@ padding: 0px; border: none; margin-left: 0; - - img { - padding: 0px; - margin: 0px; - } } .premium-icon-tip { diff --git a/frontend/pages/hosts/ManageHostsPage/components/LabelFilterSelect/LabelFilterSelect.tsx b/frontend/pages/hosts/ManageHostsPage/components/LabelFilterSelect/LabelFilterSelect.tsx index 355e87d665..40c0dcc9ed 100644 --- a/frontend/pages/hosts/ManageHostsPage/components/LabelFilterSelect/LabelFilterSelect.tsx +++ b/frontend/pages/hosts/ManageHostsPage/components/LabelFilterSelect/LabelFilterSelect.tsx @@ -24,12 +24,12 @@ declare module "react-select-5/dist/declarations/src/Select" { IsMulti extends boolean, Group extends GroupBase