mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-09 06:55:47 +01:00
fixed active state of sub navigation items, which are using activeWhenMatch
This commit is contained in:
committed by
René Pfeuffer
parent
91aca71591
commit
dcac6b3f22
@@ -40777,6 +40777,68 @@ exports[`Storyshots Modal|Modal Default 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Navigation|Secondary Active when match 1`] = `
|
||||
<div
|
||||
className="SecondaryNavigationstories__Columns-fdxo4w-0 iEPunq columns"
|
||||
>
|
||||
<div
|
||||
className="column is-3"
|
||||
>
|
||||
<aside
|
||||
className="SecondaryNavigation__SectionContainer-sc-8p1rgi-0 cpLxdt menu"
|
||||
>
|
||||
<div>
|
||||
<p
|
||||
className="SecondaryNavigation__MenuLabel-sc-8p1rgi-2 bzrEDi menu-label"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="SecondaryNavigation__Icon-sc-8p1rgi-1 djTcfn is-medium"
|
||||
color="info"
|
||||
>
|
||||
<i
|
||||
className="fas fa-caret-right"
|
||||
/>
|
||||
</i>
|
||||
Hitchhiker
|
||||
</p>
|
||||
<ul
|
||||
className="menu-list"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
className=""
|
||||
href="/42"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-puzzle-piece fa-fw"
|
||||
/>
|
||||
|
||||
Puzzle 42
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
className="is-active"
|
||||
href="/heart-of-gold"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-star fa-fw"
|
||||
/>
|
||||
|
||||
Heart Of Gold
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Navigation|Secondary Default 1`] = `
|
||||
<div
|
||||
className="SecondaryNavigationstories__Columns-fdxo4w-0 iEPunq columns"
|
||||
|
||||
@@ -27,6 +27,7 @@ import { Link, useRouteMatch } from "react-router-dom";
|
||||
import { RoutingProps } from "./RoutingProps";
|
||||
import { FC } from "react";
|
||||
import useMenuContext from "./MenuContext";
|
||||
import useActiveMatch from "./useActiveMatch";
|
||||
|
||||
type Props = RoutingProps & {
|
||||
label: string;
|
||||
@@ -34,11 +35,8 @@ type Props = RoutingProps & {
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
const NavLink: FC<Props> = ({ to, activeOnlyWhenExact, icon, label, title }) => {
|
||||
const match = useRouteMatch({
|
||||
path: to,
|
||||
exact: activeOnlyWhenExact
|
||||
});
|
||||
const NavLink: FC<Props> = ({ to, activeWhenMatch, activeOnlyWhenExact, icon, label, title }) => {
|
||||
const active = useActiveMatch({to, activeWhenMatch, activeOnlyWhenExact});
|
||||
|
||||
const context = useMenuContext();
|
||||
const collapsed = context.isCollapsed();
|
||||
@@ -54,7 +52,7 @@ const NavLink: FC<Props> = ({ to, activeOnlyWhenExact, icon, label, title }) =>
|
||||
|
||||
return (
|
||||
<li title={collapsed ? title : undefined}>
|
||||
<Link className={classNames(!!match ? "is-active" : "", collapsed ? "has-text-centered" : "")} to={to}>
|
||||
<Link className={classNames(active ? "is-active" : "", collapsed ? "has-text-centered" : "")} to={to}>
|
||||
{showIcon}
|
||||
{collapsed ? null : label}
|
||||
</Link>
|
||||
|
||||
@@ -86,4 +86,18 @@ storiesOf("Navigation|Secondary", module)
|
||||
</SecondaryNavigation>
|
||||
</BinderContext.Provider>
|
||||
);
|
||||
});
|
||||
})
|
||||
.add("Active when match", () =>
|
||||
withRoute("/hog")(
|
||||
<SecondaryNavigation label="Hitchhiker">
|
||||
<SecondaryNavigationItem to="/42" icon="fas fa-puzzle-piece" label="Puzzle 42" title="Puzzle 42" />
|
||||
<SecondaryNavigationItem
|
||||
activeWhenMatch={route => route.location.pathname === "/hog"}
|
||||
to="/heart-of-gold"
|
||||
icon="fas fa-star"
|
||||
label="Heart Of Gold"
|
||||
title="Heart Of Gold"
|
||||
/>
|
||||
</SecondaryNavigation>
|
||||
)
|
||||
);
|
||||
|
||||
@@ -22,10 +22,11 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import React, { FC, useContext } from "react";
|
||||
import { Link, useRouteMatch } from "react-router-dom";
|
||||
import { Link, useRouteMatch, useLocation } from "react-router-dom";
|
||||
import classNames from "classnames";
|
||||
import useMenuContext, { MenuContext } from "./MenuContext";
|
||||
import { RoutingProps } from "./RoutingProps";
|
||||
import useActiveMatch from "./useActiveMatch";
|
||||
|
||||
type Props = RoutingProps & {
|
||||
label: string;
|
||||
@@ -33,18 +34,19 @@ type Props = RoutingProps & {
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
const SubNavigation: FC<Props> = ({ to, activeOnlyWhenExact, icon, title, label, children }) => {
|
||||
const SubNavigation: FC<Props> = ({ to, activeOnlyWhenExact, activeWhenMatch, icon, title, label, children }) => {
|
||||
const context = useMenuContext();
|
||||
const collapsed = context.isCollapsed();
|
||||
|
||||
const parents = to.split("/");
|
||||
parents.splice(-1, 1);
|
||||
const parent = parents.join("/");
|
||||
|
||||
const match = useRouteMatch({
|
||||
path: parent,
|
||||
exact: activeOnlyWhenExact
|
||||
});
|
||||
|
||||
const context = useMenuContext();
|
||||
const collapsed = context.isCollapsed();
|
||||
const active = useActiveMatch({
|
||||
to: parent,
|
||||
activeOnlyWhenExact,
|
||||
activeWhenMatch
|
||||
})
|
||||
|
||||
let defaultIcon = "fas fa-cog";
|
||||
if (icon) {
|
||||
@@ -52,13 +54,13 @@ const SubNavigation: FC<Props> = ({ to, activeOnlyWhenExact, icon, title, label,
|
||||
}
|
||||
|
||||
let childrenList = null;
|
||||
if (match && !collapsed) {
|
||||
if (active && !collapsed) {
|
||||
childrenList = <ul className="sub-menu">{children}</ul>;
|
||||
}
|
||||
|
||||
return (
|
||||
<li title={collapsed ? title : undefined}>
|
||||
<Link className={classNames(match != null ? "is-active" : "", collapsed ? "has-text-centered" : "")} to={to}>
|
||||
<Link className={classNames(active ? "is-active" : "", collapsed ? "has-text-centered" : "")} to={to}>
|
||||
<i className={classNames(defaultIcon, "fa-fw")} /> {collapsed ? "" : label}
|
||||
</Link>
|
||||
{childrenList}
|
||||
|
||||
48
scm-ui/ui-components/src/navigation/useActiveMatch.ts
Normal file
48
scm-ui/ui-components/src/navigation/useActiveMatch.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import {useLocation, useRouteMatch} from "react-router-dom";
|
||||
import {RoutingProps} from "./RoutingProps";
|
||||
|
||||
const useActiveMatch = ({to, activeOnlyWhenExact, activeWhenMatch}: RoutingProps) => {
|
||||
const match = useRouteMatch({
|
||||
path: to,
|
||||
exact: activeOnlyWhenExact
|
||||
});
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
const isActiveWhenMatch = () => {
|
||||
if (activeWhenMatch) {
|
||||
return activeWhenMatch({
|
||||
location
|
||||
});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return !!match || isActiveWhenMatch();
|
||||
};
|
||||
|
||||
export default useActiveMatch;
|
||||
Reference in New Issue
Block a user