mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: icons tab interaction
This commit is contained in:
parent
41e812a811
commit
bc60e7cb7f
@ -1,12 +1,13 @@
|
||||
export * from "./avatar";
|
||||
export * from "./breadcrumbs";
|
||||
export * from "./badge";
|
||||
export * from "./breadcrumbs";
|
||||
export * from "./button";
|
||||
export * from "./control-link";
|
||||
export * from "./dropdowns";
|
||||
export * from "./form-fields";
|
||||
export * from "./icons";
|
||||
export * from "./progress";
|
||||
export * from "./spinners";
|
||||
export * from "./tabs";
|
||||
export * from "./tooltip";
|
||||
export * from "./loader";
|
||||
export * from "./control-link";
|
||||
|
84
packages/ui/src/tabs/icon-tabs.tsx
Normal file
84
packages/ui/src/tabs/icon-tabs.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
import React from "react";
|
||||
// tooltip
|
||||
import { Tooltip } from "../tooltip";
|
||||
// helpers
|
||||
import { cn } from "../../helpers";
|
||||
|
||||
export type TIconTabsProps = {
|
||||
buttonClassName?: string;
|
||||
containerClassName?: string;
|
||||
hideTooltip?: boolean;
|
||||
iconClassName?: string;
|
||||
iconsList: {
|
||||
key: string;
|
||||
title: string;
|
||||
icon: any;
|
||||
}[];
|
||||
onSelect: (key: string) => void;
|
||||
overlayClassName?: string;
|
||||
selectedKey: string | undefined;
|
||||
};
|
||||
|
||||
export const IconTabs: React.FC<TIconTabsProps> = (props) => {
|
||||
const {
|
||||
buttonClassName,
|
||||
containerClassName,
|
||||
hideTooltip = false,
|
||||
iconClassName,
|
||||
iconsList,
|
||||
onSelect,
|
||||
overlayClassName,
|
||||
selectedKey,
|
||||
} = props;
|
||||
|
||||
const selectedTabIndex = iconsList.findIndex((icon) => icon.key === selectedKey);
|
||||
|
||||
return (
|
||||
<div className={cn("relative flex items-center rounded-[5px] bg-custom-background-80 p-[2px]", containerClassName)}>
|
||||
<div
|
||||
className={cn(
|
||||
"absolute z-0 bg-custom-background-100 top-1/2 rounded-[3px] transition-all duration-500 ease-in-out",
|
||||
{
|
||||
// right shadow
|
||||
"shadow-[2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== iconsList.length - 1,
|
||||
// left shadow
|
||||
"shadow-[-2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== 0,
|
||||
},
|
||||
overlayClassName
|
||||
)}
|
||||
style={{
|
||||
height: "calc(100% - 4px)",
|
||||
width: `calc((100% - 4px)/${iconsList.length})`,
|
||||
transform: `translate(${selectedTabIndex * 100}%, -50%)`,
|
||||
}}
|
||||
/>
|
||||
{iconsList.map((icon) => (
|
||||
<Tooltip key={icon.key} tooltipContent={icon.title} disabled={hideTooltip}>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"relative grid h-[22px] w-7 place-items-center overflow-hidden rounded-[3px] transition-all z-[1] text-custom-text-200",
|
||||
{
|
||||
"text-custom-text-100": selectedKey == icon.key,
|
||||
},
|
||||
buttonClassName
|
||||
)}
|
||||
onClick={() => onSelect(icon.key)}
|
||||
>
|
||||
<icon.icon
|
||||
size={14}
|
||||
strokeWidth={2}
|
||||
className={cn(
|
||||
"h-3.5 w-3.5 text-custom-text-200",
|
||||
{
|
||||
"text-custom-text-100": selectedKey == icon.key,
|
||||
},
|
||||
iconClassName
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
1
packages/ui/src/tabs/index.ts
Normal file
1
packages/ui/src/tabs/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./icon-tabs";
|
@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
// ui
|
||||
import { Tooltip } from "@plane/ui";
|
||||
import { IconTabs } from "@plane/ui";
|
||||
// types
|
||||
import { TIssueLayouts } from "@plane/types";
|
||||
// constants
|
||||
@ -17,26 +16,10 @@ export const LayoutSelection: React.FC<Props> = (props) => {
|
||||
const { layouts, onChange, selectedLayout } = props;
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 rounded bg-custom-background-80 p-1">
|
||||
{ISSUE_LAYOUTS.filter((l) => layouts.includes(l.key)).map((layout) => (
|
||||
<Tooltip key={layout.key} tooltipContent={layout.title}>
|
||||
<button
|
||||
type="button"
|
||||
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${
|
||||
selectedLayout == layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""
|
||||
}`}
|
||||
onClick={() => onChange(layout.key)}
|
||||
>
|
||||
<layout.icon
|
||||
size={14}
|
||||
strokeWidth={2}
|
||||
className={`h-3.5 w-3.5 ${
|
||||
selectedLayout == layout.key ? "text-custom-text-100" : "text-custom-text-200"
|
||||
}`}
|
||||
<IconTabs
|
||||
iconsList={ISSUE_LAYOUTS.filter((l) => layouts.includes(l.key))}
|
||||
onSelect={(key) => onChange(key as TIssueLayouts)}
|
||||
selectedKey={selectedLayout}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -131,11 +131,11 @@ export const ISSUE_LAYOUTS: {
|
||||
title: string;
|
||||
icon: any;
|
||||
}[] = [
|
||||
{ key: "list", title: "List Layout", icon: List },
|
||||
{ key: "kanban", title: "Kanban Layout", icon: Kanban },
|
||||
{ key: "calendar", title: "Calendar Layout", icon: Calendar },
|
||||
{ key: "spreadsheet", title: "Spreadsheet Layout", icon: Sheet },
|
||||
{ key: "gantt_chart", title: "Gantt Chart Layout", icon: GanttChartSquare },
|
||||
{ key: "list", title: "List layout", icon: List },
|
||||
{ key: "kanban", title: "Kanban layout", icon: Kanban },
|
||||
{ key: "calendar", title: "Calendar layout", icon: Calendar },
|
||||
{ key: "spreadsheet", title: "Spreadsheet layout", icon: Sheet },
|
||||
{ key: "gantt_chart", title: "Gantt Chart layout", icon: GanttChartSquare },
|
||||
];
|
||||
|
||||
export const ISSUE_LIST_FILTERS = [
|
||||
|
Loading…
Reference in New Issue
Block a user