chore: update state icons and colors (#2126)

* chore: update state icons and colors

* chore: update icons
This commit is contained in:
Aaryan Khandelwal 2023-09-11 11:45:28 +05:30 committed by GitHub
parent ad8a011bb9
commit 5b228bd1eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 351 additions and 460 deletions

View File

@ -44,7 +44,6 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mod
{mode === "full" && (
<div className="flex justify-between gap-2 pb-3">
<h6 className="flex items-center gap-2 font-medium">
{/* {getStateGroupIcon(issue.state_detail.group, "16", "16", issue.state_detail.color)} */}
{issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
</h6>
<div className="flex items-center gap-2">

View File

@ -1,7 +1,7 @@
// icons
import { PlayIcon } from "@heroicons/react/24/outline";
// types
import { IDefaultAnalyticsResponse } from "types";
import { IDefaultAnalyticsResponse, TStateGroups } from "types";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
@ -27,7 +27,7 @@ export const AnalyticsDemand: React.FC<Props> = ({ defaultAnalytics }) => (
<span
className="h-2 w-2 rounded-full"
style={{
backgroundColor: STATE_GROUP_COLORS[group.state_group],
backgroundColor: STATE_GROUP_COLORS[group.state_group as TStateGroups],
}}
/>
<h6 className="capitalize">{group.state_group}</h6>
@ -42,7 +42,7 @@ export const AnalyticsDemand: React.FC<Props> = ({ defaultAnalytics }) => (
className="absolute top-0 left-0 h-1 rounded duration-300"
style={{
width: `${percentage}%`,
backgroundColor: STATE_GROUP_COLORS[group.state_group],
backgroundColor: STATE_GROUP_COLORS[group.state_group as TStateGroups],
}}
/>
</div>

View File

@ -9,7 +9,7 @@ import { CustomSearchSelect, CustomSelect, ToggleSwitch } from "components/ui";
import { SelectMonthModal } from "components/automation";
// icons
import { ChevronDownIcon, Squares2X2Icon } from "@heroicons/react/24/outline";
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// services
import stateService from "services/state.service";
// constants
@ -46,7 +46,7 @@ export const AutoCloseAutomation: React.FC<Props> = ({ projectDetails, handleCha
query: state.name,
content: (
<div className="flex items-center gap-2">
{getStateGroupIcon(state.group, "16", "16", state.color)}
<StateGroupIcon stateGroup={state.group} color={state.color} height="16px" width="16px" />
{state.name}
</div>
),
@ -140,14 +140,19 @@ export const AutoCloseAutomation: React.FC<Props> = ({ projectDetails, handleCha
label={
<div className="flex items-center gap-2">
{selectedOption ? (
getStateGroupIcon(selectedOption.group, "16", "16", selectedOption.color)
<StateGroupIcon
stateGroup={selectedOption.group}
color={selectedOption.color}
height="16px"
width="16px"
/>
) : currentDefaultState ? (
getStateGroupIcon(
currentDefaultState.group,
"16",
"16",
currentDefaultState.color
)
<StateGroupIcon
stateGroup={currentDefaultState.group}
color={currentDefaultState.color}
height="16px"
width="16px"
/>
) : (
<Squares2X2Icon className="h-3.5 w-3.5 text-custom-text-200" />
)}

View File

@ -1,22 +1,24 @@
import { useRouter } from "next/router";
import React, { Dispatch, SetStateAction, useCallback } from "react";
import { useRouter } from "next/router";
import useSWR, { mutate } from "swr";
// cmdk
import { Command } from "cmdk";
// ui
import { Spinner } from "components/ui";
// helpers
import { getStatesList } from "helpers/state.helper";
// services
import issuesService from "services/issues.service";
import stateService from "services/state.service";
// ui
import { Spinner } from "components/ui";
// icons
import { CheckIcon, StateGroupIcon } from "components/icons";
// helpers
import { getStatesList } from "helpers/state.helper";
// types
import { ICurrentUserResponse, IIssue } from "types";
// fetch keys
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY, STATES_LIST } from "constants/fetch-keys";
// icons
import { CheckIcon, getStateGroupIcon } from "components/icons";
type Props = {
setIsPaletteOpen: Dispatch<SetStateAction<boolean>>;
@ -82,7 +84,12 @@ export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, use
className="focus:outline-none"
>
<div className="flex items-center space-x-3">
{getStateGroupIcon(state.group, "16", "16", state.color)}
<StateGroupIcon
stateGroup={state.group}
color={state.color}
height="16px"
width="16px"
/>
<p>{state.name}</p>
</div>
<div>{state.id === issue.state && <CheckIcon className="h-3 w-3" />}</div>

View File

@ -2,7 +2,7 @@ import React from "react";
// icons
import { XMarkIcon } from "@heroicons/react/24/outline";
import { getPriorityIcon, getStateGroupIcon } from "components/icons";
import { getPriorityIcon, StateGroupIcon } from "components/icons";
// ui
import { Avatar } from "components/ui";
// helpers
@ -71,12 +71,10 @@ export const FiltersList: React.FC<Props> = ({
}}
>
<span>
{getStateGroupIcon(
state?.group ?? "backlog",
"12",
"12",
state?.color
)}
<StateGroupIcon
stateGroup={state?.group ?? "backlog"}
color={state?.color}
/>
</span>
<span>{state?.name ?? ""}</span>
<span
@ -105,7 +103,9 @@ export const FiltersList: React.FC<Props> = ({
backgroundColor: `${STATE_GROUP_COLORS[group]}20`,
}}
>
<span>{getStateGroupIcon(group, "16", "16")}</span>
<span>
<StateGroupIcon stateGroup={group} color={undefined} />
</span>
<span>{group}</span>
<span
className="cursor-pointer"

View File

@ -15,6 +15,7 @@ import {
TAssigneesDistribution,
TCompletionChartDistribution,
TLabelsDistribution,
TStateGroups,
} from "types";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
@ -215,7 +216,7 @@ export const SidebarProgressStats: React.FC<Props> = ({
<span
className="block h-3 w-3 rounded-full "
style={{
backgroundColor: STATE_GROUP_COLORS[group],
backgroundColor: STATE_GROUP_COLORS[group as TStateGroups],
}}
/>
<span className="text-xs capitalize">{group}</span>

View File

@ -1,7 +1,7 @@
// components
import { SingleBoard } from "components/core/views/board-view/single-board";
// icons
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
// types
@ -82,8 +82,14 @@ export const AllBoards: React.FC<Props> = ({
className="flex items-center justify-between gap-2 rounded bg-custom-background-90 p-2 shadow"
>
<div className="flex items-center gap-2">
{currentState &&
getStateGroupIcon(currentState.group, "16", "16", currentState.color)}
{currentState && (
<StateGroupIcon
stateGroup={currentState.group}
color={currentState.color}
height="16px"
width="16px"
/>
)}
<h4 className="text-sm capitalize">
{selectedGroup === "state"
? addSpaceIfCamelCase(currentState?.name ?? "")

View File

@ -13,14 +13,16 @@ import useProjects from "hooks/use-projects";
import { Avatar, Icon } from "components/ui";
// icons
import { PlusIcon } from "@heroicons/react/24/outline";
import { getPriorityIcon, getStateGroupIcon } from "components/icons";
import { StateGroupIcon, getPriorityIcon } from "components/icons";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
import { renderEmoji } from "helpers/emoji.helper";
// types
import { IIssueViewProps, IState } from "types";
import { IIssueViewProps, IState, TStateGroups } from "types";
// fetch-keys
import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
type Props = {
currentState?: IState | null;
@ -97,11 +99,24 @@ export const BoardHeader: React.FC<Props> = ({
switch (selectedGroup) {
case "state":
icon =
currentState && getStateGroupIcon(currentState.group, "16", "16", currentState.color);
icon = currentState && (
<StateGroupIcon
stateGroup={currentState.group}
color={currentState.color}
height="16px"
width="16px"
/>
);
break;
case "state_detail.group":
icon = getStateGroupIcon(groupTitle as any, "16", "16");
icon = (
<StateGroupIcon
stateGroup={groupTitle as TStateGroups}
color={STATE_GROUP_COLORS[groupTitle as TStateGroups]}
height="16px"
width="16px"
/>
);
break;
case "priority":
icon = getPriorityIcon(groupTitle, "text-lg");

View File

@ -15,7 +15,7 @@ import { SingleListIssue } from "components/core";
import { Avatar, CustomMenu } from "components/ui";
// icons
import { PlusIcon } from "@heroicons/react/24/outline";
import { getPriorityIcon, getStateGroupIcon } from "components/icons";
import { StateGroupIcon, getPriorityIcon } from "components/icons";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
import { renderEmoji } from "helpers/emoji.helper";
@ -26,10 +26,13 @@ import {
IIssueLabels,
IIssueViewProps,
IState,
TStateGroups,
UserAuth,
} from "types";
// fetch-keys
import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
type Props = {
currentState?: IState | null;
@ -111,11 +114,24 @@ export const SingleList: React.FC<Props> = ({
switch (selectedGroup) {
case "state":
icon =
currentState && getStateGroupIcon(currentState.group, "16", "16", currentState.color);
icon = currentState && (
<StateGroupIcon
stateGroup={currentState.group}
color={currentState.color}
height="16px"
width="16px"
/>
);
break;
case "state_detail.group":
icon = getStateGroupIcon(groupTitle as any, "16", "16");
icon = (
<StateGroupIcon
stateGroup={groupTitle as TStateGroups}
color={STATE_GROUP_COLORS[groupTitle as TStateGroups]}
height="16px"
width="16px"
/>
);
break;
case "priority":
icon = getPriorityIcon(groupTitle, "text-lg");

View File

@ -28,7 +28,7 @@ import {
TriangleExclamationIcon,
AlarmClockIcon,
LayerDiagonalIcon,
CompletedStateIcon,
StateGroupIcon,
} from "components/icons";
import { StarIcon } from "@heroicons/react/24/outline";
// components
@ -385,8 +385,8 @@ export const ActiveCycleDetails: React.FC = () => {
<LayerDiagonalIcon className="h-4 w-4 flex-shrink-0" />
{cycle.total_issues} issues
</div>
<div className="flex gap-2">
<CompletedStateIcon width={16} height={16} color="#438AF3" />
<div className="flex items-center gap-2">
<StateGroupIcon stateGroup="completed" height="14px" width="14px" />
{cycle.completed_issues} issues
</div>
</div>

View File

@ -1,21 +0,0 @@
import React from "react";
import type { Props } from "./types";
export const BacklogStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "rgb(var(--color-text-200))",
}) => (
<svg
width={width}
height={height}
className={className}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="10" cy="10" r="9" stroke={color} strokeLinecap="round" strokeDasharray="4 4" />
</svg>
);

View File

@ -1,78 +0,0 @@
import React from "react";
import type { Props } from "./types";
export const CancelledStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#f2655a",
}) => (
<svg
width={width}
height={height}
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 84.36 84.36"
>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M20.45,7.69a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M76.67,20.45a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M63.92,76.67a39.78,39.78,0,0,1-43.44-.53"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M7.69,63.92a39.75,39.75,0,0,1,.54-43.44"
/>
<circle className="cls-2" fill={color} cx="42.18" cy="42.18" r="31.04" />
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M32.64,32.44q9.54,9.75,19.09,19.48"
/>
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M32.64,51.92,51.73,32.44"
/>
</g>
</g>
</svg>
);

View File

@ -1,69 +0,0 @@
import React from "react";
import type { Props } from "./types";
export const CompletedStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#438af3",
}) => (
<svg
width={width}
height={height}
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 84.36 84.36"
>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M20.45,7.69a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M76.67,20.45a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M63.92,76.67a39.78,39.78,0,0,1-43.44-.53"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M7.69,63.92a39.75,39.75,0,0,1,.54-43.44"
/>
<circle className="cls-2" fill={color} cx="42.18" cy="42.18" r="31.04" />
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M30.45,43.75l6.61,6.61L53.92,34"
/>
</g>
</g>
</svg>
);

View File

@ -1,6 +1,7 @@
export * from "./module";
export * from "./state";
export * from "./alarm-clock-icon";
export * from "./attachment-icon";
export * from "./backlog-state-icon";
export * from "./blocked-icon";
export * from "./blocker-icon";
export * from "./bolt-icon";
@ -8,12 +9,10 @@ export * from "./calendar-before-icon";
export * from "./calendar-after-icon";
export * from "./calendar-month-icon";
export * from "./cancel-icon";
export * from "./cancelled-state-icon";
export * from "./clipboard-icon";
export * from "./color-pallette-icon";
export * from "./comment-icon";
export * from "./completed-cycle-icon";
export * from "./completed-state-icon";
export * from "./current-cycle-icon";
export * from "./cycle-icon";
export * from "./discord-icon";
@ -23,11 +22,9 @@ export * from "./ellipsis-horizontal-icon";
export * from "./external-link-icon";
export * from "./github-icon";
export * from "./heartbeat-icon";
export * from "./started-state-icon";
export * from "./layer-diagonal-icon";
export * from "./lock-icon";
export * from "./menu-icon";
export * from "./module";
export * from "./pencil-scribble-icon";
export * from "./plus-icon";
export * from "./person-running-icon";
@ -36,11 +33,8 @@ export * from "./question-mark-circle-icon";
export * from "./setting-icon";
export * from "./signal-cellular-icon";
export * from "./stacked-layers-icon";
export * from "./started-state-icon";
export * from "./state-group-icon";
export * from "./tag-icon";
export * from "./tune-icon";
export * from "./unstarted-state-icon";
export * from "./upcoming-cycle-icon";
export * from "./user-group-icon";
export * from "./user-icon-circle";

View File

@ -1,77 +0,0 @@
import React from "react";
import type { Props } from "./types";
export const StartedStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#fbb040",
}) => (
<svg
width={width}
height={height}
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 83.36 83.36"
>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M20,7.19a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M76.17,20a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M63.42,76.17A39.78,39.78,0,0,1,20,75.64"
/>
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M7.19,63.42A39.75,39.75,0,0,1,7.73,20"
/>
<path
className="cls-2"
fill={color}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M42.32,41.21q9.57-14.45,19.13-28.9a35.8,35.8,0,0,0-39.09,0Z"
/>
<path
className="cls-2"
fill={color}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M42.32,41.7,61.45,70.6a35.75,35.75,0,0,1-39.09,0Z"
/>
</g>
</g>
</svg>
);

View File

@ -1,66 +0,0 @@
import {
BacklogStateIcon,
CancelledStateIcon,
CompletedStateIcon,
StartedStateIcon,
UnstartedStateIcon,
} from "components/icons";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
export const getStateGroupIcon = (
stateGroup: "backlog" | "unstarted" | "started" | "completed" | "cancelled",
width = "20",
height = "20",
color?: string
) => {
switch (stateGroup) {
case "backlog":
return (
<BacklogStateIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["backlog"]}
className="flex-shrink-0"
/>
);
case "unstarted":
return (
<UnstartedStateIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["unstarted"]}
className="flex-shrink-0"
/>
);
case "started":
return (
<StartedStateIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["started"]}
className="flex-shrink-0"
/>
);
case "completed":
return (
<CompletedStateIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["completed"]}
className="flex-shrink-0"
/>
);
case "cancelled":
return (
<CancelledStateIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["cancelled"]}
className="flex-shrink-0"
/>
);
default:
return <></>;
}
};

View File

@ -0,0 +1,24 @@
type Props = {
width?: string;
height?: string;
className?: string;
color?: string;
};
export const StateGroupBacklogIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#a3a3a3",
}) => (
<svg
height={height}
width={width}
className={className}
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="6" cy="6" r="5.6" stroke={color} stroke-width="0.8" stroke-dasharray="4 4" />
</svg>
);

View File

@ -0,0 +1,34 @@
type Props = {
width?: string;
height?: string;
className?: string;
color?: string;
};
export const StateGroupCancelledIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#ef4444",
}) => (
<svg
height={height}
width={width}
className={className}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_4052_100277)">
<path
d="M8 8.84L10.58 11.42C10.7 11.54 10.84 11.6 11 11.6C11.16 11.6 11.3 11.54 11.42 11.42C11.54 11.3 11.6 11.16 11.6 11C11.6 10.84 11.54 10.7 11.42 10.58L8.84 8L11.42 5.42C11.54 5.3 11.6 5.16 11.6 5C11.6 4.84 11.54 4.7 11.42 4.58C11.3 4.46 11.16 4.4 11 4.4C10.84 4.4 10.7 4.46 10.58 4.58L8 7.16L5.42 4.58C5.3 4.46 5.16 4.4 5 4.4C4.84 4.4 4.7 4.46 4.58 4.58C4.46 4.7 4.4 4.84 4.4 5C4.4 5.16 4.46 5.3 4.58 5.42L7.16 8L4.58 10.58C4.46 10.7 4.4 10.84 4.4 11C4.4 11.16 4.46 11.3 4.58 11.42C4.7 11.54 4.84 11.6 5 11.6C5.16 11.6 5.3 11.54 5.42 11.42L8 8.84ZM8 16C6.90667 16 5.87333 15.79 4.9 15.37C3.92667 14.95 3.07667 14.3767 2.35 13.65C1.62333 12.9233 1.05 12.0733 0.63 11.1C0.21 10.1267 0 9.09333 0 8C0 6.89333 0.21 5.85333 0.63 4.88C1.05 3.90667 1.62333 3.06 2.35 2.34C3.07667 1.62 3.92667 1.05 4.9 0.63C5.87333 0.21 6.90667 0 8 0C9.10667 0 10.1467 0.21 11.12 0.63C12.0933 1.05 12.94 1.62 13.66 2.34C14.38 3.06 14.95 3.90667 15.37 4.88C15.79 5.85333 16 6.89333 16 8C16 9.09333 15.79 10.1267 15.37 11.1C14.95 12.0733 14.38 12.9233 13.66 13.65C12.94 14.3767 12.0933 14.95 11.12 15.37C10.1467 15.79 9.10667 16 8 16ZM8 14.8C9.89333 14.8 11.5 14.1367 12.82 12.81C14.14 11.4833 14.8 9.88 14.8 8C14.8 6.10667 14.14 4.5 12.82 3.18C11.5 1.86 9.89333 1.2 8 1.2C6.12 1.2 4.51667 1.86 3.19 3.18C1.86333 4.5 1.2 6.10667 1.2 8C1.2 9.88 1.86333 11.4833 3.19 12.81C4.51667 14.1367 6.12 14.8 8 14.8Z"
fill={color}
/>
</g>
<defs>
<clipPath id="clip0_4052_100277">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
);

View File

@ -0,0 +1,27 @@
type Props = {
width?: string;
height?: string;
className?: string;
color?: string;
};
export const StateGroupCompletedIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#16a34a",
}) => (
<svg
height={height}
width={width}
className={className}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6.80486 9.80731L4.84856 7.85103C4.73197 7.73443 4.58542 7.67478 4.4089 7.67208C4.23238 7.66937 4.08312 7.72902 3.96113 7.85103C3.83913 7.97302 3.77814 8.12093 3.77814 8.29474C3.77814 8.46855 3.83913 8.61645 3.96113 8.73844L6.27206 11.0494C6.42428 11.2016 6.60188 11.2777 6.80486 11.2777C7.00782 11.2777 7.18541 11.2016 7.33764 11.0494L12.0227 6.36435C12.1393 6.24776 12.1989 6.10121 12.2016 5.92469C12.2043 5.74817 12.1447 5.59891 12.0227 5.47692C11.9007 5.35493 11.7528 5.29393 11.579 5.29393C11.4051 5.29393 11.2572 5.35493 11.1353 5.47692L6.80486 9.80731ZM8.00141 16C6.89494 16 5.85491 15.79 4.88132 15.3701C3.90772 14.9502 3.06082 14.3803 2.34064 13.6604C1.62044 12.9405 1.05028 12.094 0.63017 11.1208C0.210057 10.1477 0 9.10788 0 8.00141C0 6.89494 0.209966 5.85491 0.629896 4.88132C1.04983 3.90772 1.61972 3.06082 2.33958 2.34064C3.05946 1.62044 3.90598 1.05028 4.87915 0.630171C5.8523 0.210058 6.89212 0 7.99859 0C9.10506 0 10.1451 0.209966 11.1187 0.629897C12.0923 1.04983 12.9392 1.61972 13.6594 2.33959C14.3796 3.05946 14.9497 3.90598 15.3698 4.87915C15.7899 5.8523 16 6.89212 16 7.99859C16 9.10506 15.79 10.1451 15.3701 11.1187C14.9502 12.0923 14.3803 12.9392 13.6604 13.6594C12.9405 14.3796 12.094 14.9497 11.1208 15.3698C10.1477 15.7899 9.10788 16 8.00141 16ZM8 14.7369C9.88071 14.7369 11.4737 14.0842 12.779 12.779C14.0842 11.4737 14.7369 9.88071 14.7369 8C14.7369 6.11929 14.0842 4.52631 12.779 3.22104C11.4737 1.91577 9.88071 1.26314 8 1.26314C6.11929 1.26314 4.52631 1.91577 3.22104 3.22104C1.91577 4.52631 1.26314 6.11929 1.26314 8C1.26314 9.88071 1.91577 11.4737 3.22104 12.779C4.52631 14.0842 6.11929 14.7369 8 14.7369Z"
fill={color}
/>
</svg>
);

View File

@ -0,0 +1,6 @@
export * from "./backlog";
export * from "./cancelled";
export * from "./completed";
export * from "./started";
export * from "./state-group-icon";
export * from "./unstarted";

View File

@ -0,0 +1,25 @@
type Props = {
width?: string;
height?: string;
className?: string;
color?: string;
};
export const StateGroupStartedIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#f59e0b",
}) => (
<svg
height={height}
width={width}
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 12 12"
fill="none"
>
<circle cx="6" cy="6" r="5.6" stroke={color} stroke-width="0.8" />
<circle cx="6" cy="6" r="3.35" stroke={color} stroke-width="0.8" stroke-dasharray="2.4 2.4" />
</svg>
);

View File

@ -0,0 +1,74 @@
// icons
import {
StateGroupBacklogIcon,
StateGroupCancelledIcon,
StateGroupCompletedIcon,
StateGroupStartedIcon,
StateGroupUnstartedIcon,
} from "components/icons";
// types
import { TStateGroups } from "types";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
type Props = {
className?: string;
color?: string;
height?: string;
stateGroup: TStateGroups;
width?: string;
};
export const StateGroupIcon: React.FC<Props> = ({
className = "",
color,
height = "12px",
width = "12px",
stateGroup,
}) => {
if (stateGroup === "backlog")
return (
<StateGroupBacklogIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["backlog"]}
className={`flex-shrink-0 ${className}`}
/>
);
else if (stateGroup === "cancelled")
return (
<StateGroupCancelledIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["cancelled"]}
className={`flex-shrink-0 ${className}`}
/>
);
else if (stateGroup === "completed")
return (
<StateGroupCompletedIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["completed"]}
className={`flex-shrink-0 ${className}`}
/>
);
else if (stateGroup === "started")
return (
<StateGroupStartedIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["started"]}
className={`flex-shrink-0 ${className}`}
/>
);
else
return (
<StateGroupUnstartedIcon
width={width}
height={height}
color={color ?? STATE_GROUP_COLORS["unstarted"]}
className={`flex-shrink-0 ${className}`}
/>
);
};

View File

@ -0,0 +1,24 @@
type Props = {
width?: string;
height?: string;
className?: string;
color?: string;
};
export const StateGroupUnstartedIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#3a3a3a",
}) => (
<svg
height={height}
width={width}
className={className}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="8" cy="8" r="7.4" stroke={color} stroke-width="1.2" />
</svg>
);

View File

@ -1,59 +0,0 @@
import React from "react";
import type { Props } from "./types";
export const UnstartedStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "rgb(var(--color-text-200))",
}) => (
<svg
width={width}
height={height}
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 84.36 84.36"
>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M20.45,7.69a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M76.67,20.45a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M63.92,76.67a39.78,39.78,0,0,1-43.44-.53"
/>
<path
className="cls-1"
fill="none"
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M7.69,63.92a39.75,39.75,0,0,1,.54-43.44"
/>
</g>
</g>
</svg>
);

View File

@ -3,7 +3,7 @@ import { useRouter } from "next/router";
// ui
import { Tooltip } from "components/ui";
// icons
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// helpers
import { findTotalDaysInRange, renderShortDate } from "helpers/date-time.helper";
// types
@ -52,7 +52,7 @@ export const IssueGanttSidebarBlock = ({ data }: { data: IIssue }) => {
className="relative w-full flex items-center gap-2 h-full cursor-pointer"
onClick={() => router.push(`/${workspaceSlug}/projects/${data?.project}/issues/${data?.id}`)}
>
{getStateGroupIcon(data?.state_detail?.group, "14", "14", data?.state_detail?.color)}
<StateGroupIcon stateGroup={data?.state_detail?.group} color={data?.state_detail?.color} />
<div className="text-xs text-custom-text-300 flex-shrink-0">
{data?.project_detail?.identifier} {data?.sequence_id}
</div>

View File

@ -11,11 +11,11 @@ import { DateFilterModal } from "components/core";
// ui
import { MultiLevelDropdown } from "components/ui";
// icons
import { getPriorityIcon, getStateGroupIcon } from "components/icons";
import { StateGroupIcon, getPriorityIcon } from "components/icons";
// helpers
import { checkIfArraysHaveSameElements } from "helpers/array.helper";
// types
import { IIssueFilterOptions, IQuery } from "types";
import { IIssueFilterOptions, IQuery, TStateGroups } from "types";
// fetch-keys
import { WORKSPACE_LABELS } from "constants/fetch-keys";
// constants
@ -104,7 +104,7 @@ export const MyIssuesSelectFilters: React.FC<Props> = ({
id: key,
label: (
<div className="flex items-center gap-2">
{getStateGroupIcon(key as any, "16", "16")}{" "}
<StateGroupIcon stateGroup={key as TStateGroups} />
{GROUP_CHOICES[key as keyof typeof GROUP_CHOICES]}
</div>
),

View File

@ -2,7 +2,7 @@
import { observer } from "mobx-react-lite";
// headless ui
import { Disclosure } from "@headlessui/react";
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// hooks
import useToast from "hooks/use-toast";
import useUser from "hooks/use-user";
@ -66,7 +66,10 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({
{mode === "full" && (
<div className="flex justify-between gap-2 pb-3">
<h6 className="flex items-center gap-2 font-medium">
{getStateGroupIcon(issue.state_detail.group, "16", "16", issue.state_detail.color)}
<StateGroupIcon
stateGroup={issue.state_detail.group}
color={issue.state_detail.color}
/>
{issue.project_detail.identifier}-{issue.sequence_id}
</h6>
<div className="flex items-center gap-2">

View File

@ -10,7 +10,7 @@ import stateService from "services/state.service";
import { CustomSearchSelect } from "components/ui";
// icons
import { PlusIcon, Squares2X2Icon } from "@heroicons/react/24/outline";
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// helpers
import { getStatesList } from "helpers/state.helper";
// fetch keys
@ -41,7 +41,7 @@ export const IssueStateSelect: React.FC<Props> = ({ setIsOpen, value, onChange,
query: state.name,
content: (
<div className="flex items-center gap-2">
{getStateGroupIcon(state.group, "16", "16", state.color)}
<StateGroupIcon stateGroup={state.group} color={state.color} />
{state.name}
</div>
),
@ -58,9 +58,12 @@ export const IssueStateSelect: React.FC<Props> = ({ setIsOpen, value, onChange,
label={
<div className="flex items-center gap-2">
{selectedOption ? (
getStateGroupIcon(selectedOption.group, "16", "16", selectedOption.color)
<StateGroupIcon stateGroup={selectedOption.group} color={selectedOption.color} />
) : currentDefaultState ? (
getStateGroupIcon(currentDefaultState.group, "16", "16", currentDefaultState.color)
<StateGroupIcon
stateGroup={currentDefaultState.group}
color={currentDefaultState.color}
/>
) : (
<Squares2X2Icon className="h-3.5 w-3.5 text-custom-text-200" />
)}

View File

@ -9,7 +9,7 @@ import stateService from "services/state.service";
// ui
import { Spinner, CustomSelect } from "components/ui";
// icons
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// helpers
import { getStatesList } from "helpers/state.helper";
import { addSpaceIfCamelCase } from "helpers/string.helper";
@ -42,17 +42,12 @@ export const SidebarStateSelect: React.FC<Props> = ({ value, onChange, disabled
<button type="button" className="bg-custom-background-80 text-xs rounded px-2.5 py-0.5">
{selectedState ? (
<div className="flex items-center gap-1.5 text-left text-custom-text-100">
{getStateGroupIcon(
selectedState?.group ?? "backlog",
"14",
"14",
selectedState?.color ?? ""
)}
<StateGroupIcon stateGroup={selectedState.group} color={selectedState.color} />
{addSpaceIfCamelCase(selectedState?.name ?? "")}
</div>
) : inboxIssueId ? (
<div className="flex items-center gap-1.5 text-left text-custom-text-100">
{getStateGroupIcon("backlog", "14", "14", "#ff7700")}
<StateGroupIcon stateGroup="backlog" color="#ff7700" />
Triage
</div>
) : (
@ -71,7 +66,7 @@ export const SidebarStateSelect: React.FC<Props> = ({ value, onChange, disabled
states.map((state) => (
<CustomSelect.Option key={state.id} value={state.id}>
<>
{getStateGroupIcon(state.group, "16", "16", state.color)}
<StateGroupIcon stateGroup={state.group} color={state.color} />
{state.name}
</>
</CustomSelect.Option>

View File

@ -10,7 +10,7 @@ import trackEventServices from "services/track-event.service";
// ui
import { CustomSearchSelect, Tooltip } from "components/ui";
// icons
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// helpers
import { getStatesList } from "helpers/state.helper";
// types
@ -59,7 +59,7 @@ export const ViewStateSelect: React.FC<Props> = ({
query: state.name,
content: (
<div className="flex items-center gap-2">
{getStateGroupIcon(state.group, "16", "16", state.color)}
<StateGroupIcon stateGroup={state.group} color={state.color} />
{state.name}
</div>
),
@ -75,8 +75,9 @@ export const ViewStateSelect: React.FC<Props> = ({
>
<div className="flex items-center cursor-pointer w-full gap-2 text-custom-text-200">
<span className="h-3.5 w-3.5">
{selectedOption &&
getStateGroupIcon(selectedOption.group, "14", "14", selectedOption.color)}
{selectedOption && (
<StateGroupIcon stateGroup={selectedOption.group} color={selectedOption.color} />
)}
</span>
<span className="truncate">{selectedOption?.name ?? "State"}</span>
</div>

View File

@ -15,7 +15,7 @@ import {
PencilSquareIcon,
TrashIcon,
} from "@heroicons/react/24/outline";
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
import { groupBy, orderArrayBy } from "helpers/array.helper";
@ -162,7 +162,7 @@ export const SingleState: React.FC<Props> = ({
return (
<div className="group flex items-center justify-between gap-2 border-custom-border-200 bg-custom-background-100 p-5 first:rounded-t-[10px] last:rounded-b-[10px]">
<div className="flex items-center gap-3">
{getStateGroupIcon(state.group, "20", "20", state.color)}
<StateGroupIcon stateGroup={state.group} color={state.color} height="20px" width="20px" />
<div>
<h6 className="text-sm">{addSpaceIfCamelCase(state.name)}</h6>
<p className="text-xs text-custom-text-200">{state.description}</p>

View File

@ -13,7 +13,7 @@ import { DateFilterModal } from "components/core";
// ui
import { Avatar, MultiLevelDropdown } from "components/ui";
// icons
import { getPriorityIcon, getStateGroupIcon } from "components/icons";
import { StateGroupIcon, getPriorityIcon } from "components/icons";
// helpers
import { getStatesList } from "helpers/state.helper";
import { checkIfArraysHaveSameElements } from "helpers/array.helper";
@ -118,7 +118,8 @@ export const SelectFilters: React.FC<Props> = ({
id: state.id,
label: (
<div className="flex items-center gap-2">
{getStateGroupIcon(state.group, "16", "16", state.color)} {state.name}
<StateGroupIcon stateGroup={state.group} color={state.color} />
{state.name}
</div>
),
value: {

View File

@ -17,7 +17,7 @@ import stateService from "services/state.service";
import { STATES_LIST } from "constants/fetch-keys";
// components
import { getStateGroupIcon } from "components/icons";
import { StateGroupIcon } from "components/icons";
import { WebViewModal } from "./web-view-modal";
// helpers
@ -62,7 +62,7 @@ export const StateSelect: React.FC<Props> = (props) => {
label: state.name,
value: state.id,
checked: state.id === selectedState?.id,
icon: getStateGroupIcon(state.group, "16", "16", state.color),
icon: <StateGroupIcon stateGroup={state.group} color={state.color} />,
onClick: () => {
setIsOpen(false);
if (disabled) return;

View File

@ -1,9 +1,7 @@
// ui
import { PieGraph } from "components/ui";
// helpers
import { capitalizeFirstLetter } from "helpers/string.helper";
// types
import { IUserStateDistribution } from "types";
import { IUserStateDistribution, TStateGroups } from "types";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
@ -23,7 +21,7 @@ export const IssuesPieChart: React.FC<Props> = ({ groupedIssues }) => (
id: cell.state_group,
label: cell.state_group,
value: cell.state_count,
color: STATE_GROUP_COLORS[cell.state_group.toLowerCase()],
color: STATE_GROUP_COLORS[cell.state_group.toLowerCase() as TStateGroups],
})) ?? []
}
height="320px"

View File

@ -1,5 +1,7 @@
import { TStateGroups } from "types";
export const STATE_GROUP_COLORS: {
[key: string]: string;
[key in TStateGroups]: string;
} = {
backlog: "#d9d9d9",
unstarted: "#3f76ff",

View File

@ -3,7 +3,7 @@ import { BarDatum } from "@nivo/bar";
// helpers
import { capitalizeFirstLetter, generateRandomColor } from "helpers/string.helper";
// types
import { IAnalyticsData, IAnalyticsParams, IAnalyticsResponse } from "types";
import { IAnalyticsData, IAnalyticsParams, IAnalyticsResponse, TStateGroups } from "types";
// constants
import { STATE_GROUP_COLORS } from "constants/state";
import { MONTHS_LIST } from "constants/calendar";
@ -72,7 +72,8 @@ export const generateBarColor = (
if (params[type] === "state__name" || params[type] === "labels__name")
color = analytics?.extras?.colors.find((c) => c.name === value)?.color;
if (params[type] === "state__group") color = STATE_GROUP_COLORS[value.toLowerCase()];
if (params[type] === "state__group")
color = STATE_GROUP_COLORS[value.toLowerCase() as TStateGroups];
if (params[type] === "priority") {
const priority = value.toLowerCase();