change label filter dropdown icon match status dropdown and extend icon component (#8337)

This commit is contained in:
Gabriel Hernandez
2022-10-19 17:44:27 -05:00
committed by GitHub
parent bc32662a3e
commit 55bf0cea6a
10 changed files with 124 additions and 7 deletions
@@ -0,0 +1 @@
- updates label filter chevron icon to match the icon on the status filter dropdown
+15 -4
View File
@@ -1,22 +1,33 @@
import React from "react";
import React, { useMemo } from "react";
import { IconNames, ICON_MAP } from "components/icons";
import classnames from "classnames";
interface IIconProps {
name: IconNames;
color?: string;
className?: string;
}
const baseClass = "icon";
const Icon = ({ name, className }: IIconProps) => {
const Icon = ({ name, color, className }: IIconProps) => {
const classsNames = classnames(baseClass, className);
// createPassedProps creates a props object that we pass to the specific icon
// for values that are not null or undefined
const props = useMemo(() => {
const createPassedProps = () => {
return Object.assign({}, color === undefined ? undefined : { color });
};
return createPassedProps();
}, [color]);
const IconComponent = ICON_MAP[name];
return (
<div className={classsNames}>
<IconComponent />
<IconComponent {...props} />
</div>
);
};
+6
View File
@@ -0,0 +1,6 @@
.icon {
// we want to ensure the icon is always centered with these styles
display: flex;
align-items: center;
justify-content: center;
}
+20
View File
@@ -0,0 +1,20 @@
import React from "react";
interface IChevronDownProps {
color?: string;
}
const ChevronDown = ({ color = "#192147" }: IChevronDownProps) => {
return (
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="m8.751 10.891 4.144-4.297a.385.385 0 0 0 0-.528l-.927-.957a.345.345 0 0 0-.502 0L8.5 8.189l-2.966-3.08a.345.345 0 0 0-.502 0l-.927.957a.385.385 0 0 0 0 .528l4.144 4.297c.14.145.363.145.502 0Z"
fill={color}
/>
</svg>
);
};
export default ChevronDown;
+2
View File
@@ -7,6 +7,7 @@ import LowDiskSpaceHosts from "./LowDiskSpaceHosts";
import ApplePurple from "./ApplePurple";
import LinuxGreen from "./LinuxGreen";
import WindowsBlue from "./WindowsBlue";
import ChevronDown from "./ChevronDown";
// a mapping of the usable names of icons to the icon source.
export const ICON_MAP = {
@@ -22,6 +23,7 @@ export const ICON_MAP = {
"linux-green": LinuxGreen,
"missing-hosts": MissingHosts,
"low-disk-space-hosts": LowDiskSpaceHosts,
"chevron-down": ChevronDown,
};
export type IconNames = keyof typeof ICON_MAP;
+27
View File
@@ -15,6 +15,7 @@ should be discussed within the team and documented before merged.
- [Fleet API Calls](#fleet-api-calls)
- [Page Routing](#page-routing)
- [Styles](#styles)
- [Icons and Images](#icons)
- [Other](#other)
## Typing
@@ -260,6 +261,8 @@ const PageOrComponent = ({
Below are a few need-to-knows about what's available in Fleet's CSS:
### Modals
1) When creating a modal with a form inside, the action buttons (cancel, save, delete, etc.) should
@@ -281,6 +284,30 @@ suffice as long as we do not go more than two levels deep. Otherwise, if states
to be used across multiple unrelated components or 3+ levels from a parent,
then the [app's context](#react-context) should be used.
## Icons and Images
### Adding Icons
To add a new icon:
1. create a React component for the icon in `frontend/components/icons` directory. We will add the
SVG here.
2. download the icon source from Figma as an SVG file
3. run the downloaded file through an SVG optimizer such as
[SVGOMG](https://jakearchibald.github.io/svgomg/) or [SVG Optimizer](https://svgoptimizer.com/)
4. download the optimized SVG and place it in created file from step 1.
5. import the new icon in the `frontend/components/icons/index.ts` and add it the the `ICON_MAP`
object. The key will be the name the icon is accessible under.
The icon should now be available to use with the `Icon` component from the given key name.
```tsx
// using a new icon with the given key name 'chevron`
<Icon name="chevron" />
```
### File size
The recommend line limit per page/component is 500 lines. This is only a recommendation.
@@ -0,0 +1,29 @@
import React from "react";
import { DropdownIndicatorProps, components } from "react-select-5";
import { ILabel } from "interfaces/label";
import Icon from "components/Icon";
import { IEmptyOption, IGroupOption } from "../LabelFilterSelect/helpers";
const baseClass = "custom-dropdown-indicator";
const CustomDropdownIndicator = (
props: DropdownIndicatorProps<ILabel | IEmptyOption, false, IGroupOption>
) => {
const { isFocused, selectProps } = props;
// no access to hover state here from react-select so that is done in the scss
// file of LabelFilterSelect.
const color = isFocused || selectProps.menuIsOpen ? "#6a67fe" : undefined;
return (
<components.DropdownIndicator {...props} className={baseClass}>
<Icon
name="chevron-down"
color={color}
className={`${baseClass}__icon`}
/>
</components.DropdownIndicator>
);
};
export default CustomDropdownIndicator;
@@ -0,0 +1 @@
export { default } from "./CustomDropdownIndicator";
@@ -8,6 +8,7 @@ import { PLATFORM_LABEL_DISPLAY_NAMES } from "utilities/constants";
import CustomLabelGroupHeading from "../CustomLabelGroupHeading";
import { PLATFORM_TYPE_ICONS } from "./constants";
import { createDropdownOptions, IEmptyOption, IGroupOption } from "./helpers";
import CustomDropdownIndicator from "../CustomDropdownIndicator";
// Extending the react-select module to add custom props we need for our custom
// group heading. More info here:
@@ -27,6 +28,8 @@ declare module "react-select-5/dist/declarations/src/Select" {
}
}
const baseClass = "label-filter-select";
/** A custom option label to show in the dropdown. Only used in this dropdown
* component. You will find focus and blur handlers in this component to help
* solve the problem of changing focus between the select dropdown and the
@@ -53,8 +56,6 @@ const OptionLabel = (data: ILabel | IEmptyOption) => {
);
};
const baseClass = "label-filter-select";
interface ILabelFilterSelectProps {
labels: ILabel[];
selectedLabel: ILabel | null;
@@ -158,7 +159,10 @@ const LabelFilterSelect = ({
isSearchable={false}
getOptionLabel={getOptionLabel}
getOptionValue={getOptionValue}
components={{ GroupHeading: CustomLabelGroupHeading }}
components={{
GroupHeading: CustomLabelGroupHeading,
DropdownIndicator: CustomDropdownIndicator,
}}
labelQuery={labelQuery}
canAddNewLabels={canAddNewLabels}
onChange={handleChange}
@@ -1,6 +1,16 @@
.label-filter-select {
width: 175px;
&:hover {
// no access to hover state from react-select in JS so this is done here.
.custom-dropdown-indicator {
& path {
fill: $core-vibrant-blue
}
}
}
.label-filter-select__control {
border: 1px solid $ui-fleet-blue-15;
background-color: $ui-light-grey;
@@ -108,4 +118,10 @@
margin-right: $pad-small;
}
}
&__custom-dropdown-indicator {
&:hover {
cursor: pointer;
}
}
}