Skip to content

Commit 1267703

Browse files
authored
fix: Render UI navigation items as links instead of buttons (#4970)
fix: Render navigation items as links instead of buttons Using link is semantically correct and improves accessibility, allows opening the linked pages in another tab etc. Use react-router-dom Links instead of plain anchors to prevent full page reloads when navigating. Signed-off-by: Harri Lehtola <[email protected]>
1 parent 8ac6a85 commit 1267703

File tree

2 files changed

+10
-24
lines changed

2 files changed

+10
-24
lines changed

ui/src/FeastUISansProviders.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ test("routes are reachable", async () => {
8989

9090
const routeRegExp = new RegExp(routeName, "i");
9191

92-
await user.click(screen.getByRole("button", { name: routeRegExp }));
92+
await user.click(screen.getByRole("link", { name: routeRegExp }));
9393

9494
// Should land on a page with the heading
9595
screen.getByRole("heading", {
@@ -112,7 +112,7 @@ test("features are reachable", async () => {
112112
await screen.findByText(/Explore this Project/i);
113113
const routeRegExp = new RegExp("Feature Views", "i");
114114

115-
await user.click(screen.getByRole("button", { name: routeRegExp }));
115+
await user.click(screen.getByRole("link", { name: routeRegExp }));
116116

117117
screen.getByRole("heading", {
118118
name: "Feature Views",

ui/src/pages/Sidebar.tsx

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useContext, useState } from "react";
22

33
import { EuiIcon, EuiSideNav, htmlIdGenerator } from "@elastic/eui";
4-
import { useNavigate, useParams } from "react-router-dom";
4+
import { Link, useParams } from "react-router-dom";
55
import { useMatchSubpath } from "../hooks/useMatchSubpath";
66
import useLoadRegistry from "../queries/useLoadRegistry";
77
import RegistryPathContext from "../contexts/RegistryPathContext";
@@ -19,8 +19,6 @@ const SideNav = () => {
1919

2020
const [isSideNavOpenOnMobile, setisSideNavOpenOnMobile] = useState(false);
2121

22-
const navigate = useNavigate();
23-
2422
const toggleOpenOnMobile = () => {
2523
setisSideNavOpenOnMobile(!isSideNavOpenOnMobile);
2624
};
@@ -57,57 +55,45 @@ const SideNav = () => {
5755

5856
const baseUrl = `${process.env.PUBLIC_URL || ""}/p/${projectName}`;
5957

60-
const sideNav = [
58+
const sideNav: React.ComponentProps<typeof EuiSideNav>['items'] = [
6159
{
6260
name: "Home",
6361
id: htmlIdGenerator("basicExample")(),
64-
onClick: () => {
65-
navigate(`${baseUrl}/`);
66-
},
62+
renderItem: props => <Link {...props} to={`${baseUrl}/`} />,
6763
items: [
6864
{
6965
name: dataSourcesLabel,
7066
id: htmlIdGenerator("dataSources")(),
7167
icon: <EuiIcon type={DataSourceIcon} />,
72-
onClick: () => {
73-
navigate(`${baseUrl}/data-source`);
74-
},
68+
renderItem: props => <Link {...props} to={`${baseUrl}/data-source`} />,
7569
isSelected: useMatchSubpath(`${baseUrl}/data-source`),
7670
},
7771
{
7872
name: entitiesLabel,
7973
id: htmlIdGenerator("entities")(),
8074
icon: <EuiIcon type={EntityIcon} />,
81-
onClick: () => {
82-
navigate(`${baseUrl}/entity`);
83-
},
75+
renderItem: props => <Link {...props} to={`${baseUrl}/entity`} />,
8476
isSelected: useMatchSubpath(`${baseUrl}/entity`),
8577
},
8678
{
8779
name: featureViewsLabel,
8880
id: htmlIdGenerator("featureView")(),
8981
icon: <EuiIcon type={FeatureViewIcon} />,
90-
onClick: () => {
91-
navigate(`${baseUrl}/feature-view`);
92-
},
82+
renderItem: props => <Link {...props} to={`${baseUrl}/feature-view`} />,
9383
isSelected: useMatchSubpath(`${baseUrl}/feature-view`),
9484
},
9585
{
9686
name: featureServicesLabel,
9787
id: htmlIdGenerator("featureService")(),
9888
icon: <EuiIcon type={FeatureServiceIcon} />,
99-
onClick: () => {
100-
navigate(`${baseUrl}/feature-service`);
101-
},
89+
renderItem: props => <Link {...props} to={`${baseUrl}/feature-service`} />,
10290
isSelected: useMatchSubpath(`${baseUrl}/feature-service`),
10391
},
10492
{
10593
name: savedDatasetsLabel,
10694
id: htmlIdGenerator("savedDatasets")(),
10795
icon: <EuiIcon type={DatasetIcon} />,
108-
onClick: () => {
109-
navigate(`${baseUrl}/data-set`);
110-
},
96+
renderItem: props => <Link {...props} to={`${baseUrl}/data-set`} />,
11197
isSelected: useMatchSubpath(`${baseUrl}/data-set`),
11298
},
11399
],

0 commit comments

Comments
 (0)