diff --git a/app/react/sidebar/EnvironmentSidebar.tsx b/app/react/sidebar/EnvironmentSidebar.tsx
index 47eb5aa6c..2ad4bf5fb 100644
--- a/app/react/sidebar/EnvironmentSidebar.tsx
+++ b/app/react/sidebar/EnvironmentSidebar.tsx
@@ -1,6 +1,6 @@
import { useCurrentStateAndParams, useRouter } from '@uirouter/react';
import { useEffect, useState } from 'react';
-import { X } from 'react-feather';
+import { X, Slash } from 'react-feather';
import {
PlatformType,
@@ -15,35 +15,56 @@ import { getPlatformIcon } from '../portainer/environments/utils/get-platform-ic
import { AzureSidebar } from './AzureSidebar';
import { DockerSidebar } from './DockerSidebar';
import { KubernetesSidebar } from './KubernetesSidebar';
-import { SidebarSection } from './SidebarSection';
+import { SidebarSection, SidebarSectionTitle } from './SidebarSection';
import { useSidebarState } from './useSidebarState';
export function EnvironmentSidebar() {
const { query: currentEnvironmentQuery, clearEnvironment } =
useCurrentEnvironment();
const environment = currentEnvironmentQuery.data;
- if (!environment) {
+
+ const { isOpen } = useSidebarState();
+
+ if (!isOpen && !environment) {
return null;
}
+ return (
+
+ {environment ? (
+
+ ) : (
+
+
+ Environment:
+
+ None selected
+
+
+ )}
+
+ );
+}
+
+interface ContentProps {
+ environment: Environment;
+ onClear: () => void;
+}
+
+function Content({ environment, onClear }: ContentProps) {
const platform = getPlatformType(environment.Type);
const Sidebar = getSidebar(platform);
return (
-
-
(
-
- )}
- >
+ }
+ aria-label={environment.Name}
+ showTitleWhenOpen
+ >
+
-
-
+
+
);
function getSidebar(platform: PlatformType) {
@@ -86,38 +107,38 @@ function useCurrentEnvironment() {
}
interface TitleProps {
- className: string;
environment: Environment;
onClear(): void;
}
-function Title({ className, environment, onClear }: TitleProps) {
+function Title({ environment, onClear }: TitleProps) {
const { isOpen } = useSidebarState();
+
const EnvironmentIcon = getPlatformIcon(environment.Type);
if (!isOpen) {
return (
-
+
-
+
);
}
return (
-
-
-
Environment
-
-
{environment.Name}
+
+
+
+ {environment.Name}
+
-
-
-
+
+
);
}
diff --git a/app/react/sidebar/Header.tsx b/app/react/sidebar/Header.tsx
index 24f48d1f8..3040e293e 100644
--- a/app/react/sidebar/Header.tsx
+++ b/app/react/sidebar/Header.tsx
@@ -18,7 +18,7 @@ export function Header({ logo }: Props) {
toggle()}
- className="w-6 h-6 flex justify-center items-center text-gray-4 be:text-gray-5 border-0 rounded text-sm be:bg-gray-10 bg-blue-11 hover:text-white be:hover:text-white"
+ className="w-6 h-6 flex justify-center items-center text-gray-4 be:text-gray-5 border-0 rounded text-sm bg-blue-11 hover:bg-blue-10 be:bg-gray-10 be:hover:bg-gray-8 transition-colors duration-200 hover:text-white be:hover:text-white"
aria-label="Toggle Sidebar"
title="Toggle Sidebar"
>
diff --git a/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx b/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx
index 92838e4c2..0c85a82fd 100644
--- a/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx
+++ b/app/react/sidebar/KubernetesSidebar/KubernetesSidebar.tsx
@@ -19,7 +19,11 @@ export function KubernetesSidebar({ environmentId }: Props) {
return (
<>
- {isOpen && }
+ {isOpen && (
+
+
+
+ )}
-
- {!!icon && (
- svg]:w-4')} />
- )}
- {isOpen && {label}}
-
+ {!!icon && (
+ svg]:w-4')} />
+ )}
+ {isOpen && {label}}
+
+
);
}
@@ -73,7 +81,7 @@ function useSrefActive(
options: TransitionOptions = {},
ignorePaths: string[] = []
) {
- const { state } = useCurrentStateAndParams();
+ const { state: { name: stateName = '' } = {} } = useCurrentStateAndParams();
const anchorProps = useUiRouterSrefActive(
to,
params || {},
@@ -81,7 +89,7 @@ function useSrefActive(
options
);
- const className = ignorePaths.includes(state.name || '')
+ const className = ignorePaths.some((path) => stateName.includes(path))
? ''
: anchorProps.className;
diff --git a/app/react/sidebar/SidebarItem/Wrapper.tsx b/app/react/sidebar/SidebarItem/Wrapper.tsx
index 56c2c59fa..af852ca6f 100644
--- a/app/react/sidebar/SidebarItem/Wrapper.tsx
+++ b/app/react/sidebar/SidebarItem/Wrapper.tsx
@@ -19,7 +19,6 @@ export function Wrapper({
className,
'text-gray-3 min-h-8 [&>a]:text-inherit [&>a]:hover:text-inherit [&>a]:hover:no-underline'
)}
- title={label}
aria-label={label}
// eslint-disable-next-line react/jsx-props-no-spreading
{...ariaProps}
diff --git a/app/react/sidebar/SidebarSection.tsx b/app/react/sidebar/SidebarSection.tsx
index 77750588f..9de673618 100644
--- a/app/react/sidebar/SidebarSection.tsx
+++ b/app/react/sidebar/SidebarSection.tsx
@@ -3,28 +3,50 @@ import { PropsWithChildren, ReactNode } from 'react';
import { useSidebarState } from './useSidebarState';
interface Props {
- title: string;
- renderTitle?: (className: string) => ReactNode;
+ title: ReactNode;
+ showTitleWhenOpen?: boolean;
+ 'aria-label'?: string;
}
export function SidebarSection({
title,
- renderTitle,
children,
+ showTitleWhenOpen,
+ 'aria-label': ariaLabel,
}: PropsWithChildren) {
- const { isOpen } = useSidebarState();
- const titleClassName =
- 'ml-3 text-sm text-gray-3 be:text-gray-6 transition-all duration-500 ease-in-out';
-
return (
- {renderTitle
- ? renderTitle(titleClassName)
- : isOpen &&
{title}}
+
+ {title}
+
-
);
}
+
+interface TitleProps {
+ showWhenOpen?: boolean;
+}
+
+export function SidebarSectionTitle({
+ showWhenOpen,
+ children,
+}: PropsWithChildren) {
+ const { isOpen } = useSidebarState();
+
+ if (!isOpen && !showWhenOpen) {
+ return null;
+ }
+
+ return (
+
+ {children}
+
+ );
+}