snapshot of https://github.com/makeplane/plane.git @ d868349a55de79979eb8b98701bf1702c67ad634 (2026-09-15)
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
This commit is contained in:
162
apps/web/core/components/sidebar/sidebar-item.tsx
Normal file
162
apps/web/core/components/sidebar/sidebar-item.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import Link from "next/link";
|
||||
import { cn } from "@plane/utils";
|
||||
|
||||
// ============================================================================
|
||||
// TYPES
|
||||
// ============================================================================
|
||||
|
||||
interface AppSidebarItemData {
|
||||
href?: string;
|
||||
label?: string;
|
||||
icon?: React.ReactNode;
|
||||
isActive?: boolean;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
showLabel?: boolean;
|
||||
}
|
||||
|
||||
interface AppSidebarItemProps {
|
||||
variant?: "link" | "button";
|
||||
item?: AppSidebarItemData;
|
||||
}
|
||||
|
||||
interface AppSidebarItemLabelProps {
|
||||
highlight?: boolean;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
interface AppSidebarItemIconProps {
|
||||
icon?: React.ReactNode;
|
||||
highlight?: boolean;
|
||||
}
|
||||
|
||||
interface AppSidebarLinkItemProps {
|
||||
href?: string;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface AppSidebarButtonItemProps {
|
||||
children: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// STYLES
|
||||
// ============================================================================
|
||||
|
||||
const styles = {
|
||||
base: "group flex flex-col gap-0.5 items-center justify-center text-tertiary",
|
||||
icon: "flex items-center justify-center gap-2 size-8 rounded-md text-tertiary",
|
||||
iconActive: "bg-layer-transparent-selected text-secondary !text-icon-primary",
|
||||
iconInactive: "group-hover:text-icon-secondary group-hover:bg-layer-transparent-hover !text-icon-tertiary",
|
||||
label: "text-11 font-medium",
|
||||
labelActive: "text-secondary",
|
||||
labelInactive: "group-hover:text-secondary text-tertiary",
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
// SUB-COMPONENTS
|
||||
// ============================================================================
|
||||
|
||||
function AppSidebarItemLabel({ highlight = false, label }: AppSidebarItemLabelProps) {
|
||||
if (!label) return null;
|
||||
|
||||
return (
|
||||
<span
|
||||
className={cn(styles.label, {
|
||||
[styles.labelActive]: highlight,
|
||||
[styles.labelInactive]: !highlight,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function AppSidebarItemIcon({ icon, highlight }: AppSidebarItemIconProps) {
|
||||
if (!icon) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(styles.icon, {
|
||||
[styles.iconActive]: highlight,
|
||||
[styles.iconInactive]: !highlight,
|
||||
})}
|
||||
>
|
||||
{icon}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AppSidebarLinkItem({ href, children, className }: AppSidebarLinkItemProps) {
|
||||
if (!href) return null;
|
||||
|
||||
return (
|
||||
<Link href={href} className={cn(styles.base, className)}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function AppSidebarButtonItem({ children, onClick, disabled = false, className }: AppSidebarButtonItemProps) {
|
||||
return (
|
||||
<button className={cn(styles.base, className)} onClick={onClick} disabled={disabled} type="button">
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// MAIN COMPONENT
|
||||
// ============================================================================
|
||||
|
||||
export type AppSidebarItemComponent = React.FC<AppSidebarItemProps> & {
|
||||
Label: React.FC<AppSidebarItemLabelProps>;
|
||||
Icon: React.FC<AppSidebarItemIconProps>;
|
||||
Link: React.FC<AppSidebarLinkItemProps>;
|
||||
Button: React.FC<AppSidebarButtonItemProps>;
|
||||
};
|
||||
|
||||
function AppSidebarItem({ variant = "link", item }: AppSidebarItemProps) {
|
||||
if (!item) return null;
|
||||
|
||||
const { icon, isActive, label, href, onClick, disabled, showLabel = true } = item;
|
||||
|
||||
const commonItems = (
|
||||
<>
|
||||
<AppSidebarItemIcon icon={icon} highlight={isActive} />
|
||||
{showLabel && <AppSidebarItemLabel highlight={isActive} label={label} />}
|
||||
</>
|
||||
);
|
||||
|
||||
if (variant === "link") {
|
||||
return <AppSidebarLinkItem href={href}>{commonItems}</AppSidebarLinkItem>;
|
||||
}
|
||||
|
||||
return (
|
||||
<AppSidebarButtonItem onClick={onClick} disabled={disabled}>
|
||||
{commonItems}
|
||||
</AppSidebarButtonItem>
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// COMPOUND COMPONENT ASSIGNMENT
|
||||
// ============================================================================
|
||||
|
||||
AppSidebarItem.Label = AppSidebarItemLabel;
|
||||
AppSidebarItem.Icon = AppSidebarItemIcon;
|
||||
AppSidebarItem.Link = AppSidebarLinkItem;
|
||||
AppSidebarItem.Button = AppSidebarButtonItem;
|
||||
|
||||
export { AppSidebarItem };
|
||||
export type { AppSidebarItemData, AppSidebarItemProps };
|
||||
Reference in New Issue
Block a user