Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/prs/angular/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { Feat3241Component } from "../routes/features/feat3241/feat3241.componen
import { FeatV2IconsComponent } from "../routes/features/featV2Icons/feat-v2-icons.component";
import { Feat3137Component } from "../routes/features/feat3137/feat3137.component";
import { Feat3306Component } from "../routes/features/feat3306/feat3306.component";
import { Feat3340Component } from "../routes/features/feat3340/feat3340.component";

export const appRoutes: Route[] = [
{ path: "everything", component: EverythingComponent },
Expand Down Expand Up @@ -128,4 +129,5 @@ export const appRoutes: Route[] = [
{ path: "features/3137", component: Feat3137Component },
{ path: "features/1908", component: Feat1908Component },
{ path: "features/3306", component: Feat3306Component },
{ path: "features/3340", component: Feat3340Component },
];
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<h1>Feature 3340: Work Side Menu Item Click Handling</h1>

<p>
This demonstrates handling click events on items within a
<code>goabx-work-side-menu</code> component.
</p>

<p>
Total item clicks:
<strong>{{ itemClicks }}</strong>
</p>

<goabx-work-side-menu
heading="Menu heading"
url="#"
[primaryContent]="primaryTemplate"
[open]="true"
>
</goabx-work-side-menu>

<ng-template #primaryTemplate>
<goabx-work-side-menu-item label="Menu item 1" icon="star" (click)="onItemClick()" />
<goabx-work-side-menu-item label="Menu item 2" icon="star" (click)="onItemClick()" />
<goabx-work-side-menu-item label="Menu item 3" icon="star" (click)="onItemClick()" />
</ng-template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { CommonModule } from "@angular/common";
import { Component } from "@angular/core";
import {
GoabxWorkSideMenu,
GoabxWorkSideMenuGroup,
GoabxWorkSideMenuItem,
} from "@abgov/angular-components";

@Component({
standalone: true,
selector: "abgov-feat3340",
templateUrl: "./feat3340.component.html",
styleUrls: ["./feat3340.component.css"],
imports: [
CommonModule,
GoabxWorkSideMenu,
GoabxWorkSideMenuGroup,
GoabxWorkSideMenuItem,
],
})
export class Feat3340Component {
itemClicks = 0;

onItemClick(): void {
this.itemClicks += 1;
}
}
1 change: 1 addition & 0 deletions apps/prs/react/src/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export function App() {
<Link to="/features/v2-icons">v2 header icons</Link>
<Link to="/features/3137">3137 Work Side Menu Group</Link>
<Link to="/features/3306">3306 Custom slug value for tabs</Link>
<Link to="/features/3340">3340 Work Side Menu Item Click</Link>
</GoabSideMenuGroup>
<GoabSideMenuGroup heading="Everything">
<Link to="/everything">A</Link>
Expand Down
2 changes: 2 additions & 0 deletions apps/prs/react/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import { Feat3241Route } from "./routes/features/feat3241";
import { FeatV2IconsRoute } from "./routes/features/featV2Icons";
import { Feat3137Route } from "./routes/features/feat3137";
import Feat3306Route from "./routes/features/feat3306";
import Feat3340Route from "./routes/features/feat3340";

const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);

Expand Down Expand Up @@ -142,6 +143,7 @@ root.render(
<Route path="features/3137" element={<Feat3137Route />} />
<Route path="features/1908" element={<Feat1908Route />} />
<Route path="features/3306" element={<Feat3306Route />} />
<Route path="features/3340" element={<Feat3340Route />} />
</Route>
</Routes>
</BrowserRouter>
Expand Down
63 changes: 63 additions & 0 deletions apps/prs/react/src/routes/features/feat3340.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useCallback, useMemo, useState } from "react";
import { GoabButton, GoabContainer, GoabText } from "@abgov/react-components";
import {
GoabxWorkSideMenu,
GoabxWorkSideMenuGroup,
GoabxWorkSideMenuItem,
} from "@abgov/react-components/experimental";

export function Feat3340Route() {
const [itemClicks, setItemClicks] = useState(0);

const onItemClick = function () {
console.log("Menu item clicked");
setItemClicks((prev) => prev + 1);
};
return (
<div
style={{
display: "flex",
flexDirection: "column",
gap: "var(--goa-spacing-xl)",
}}
>
<h1>Feature 3340: Work Side Menu Item Click Handling</h1>

<p>
This demonstrates handling click events on items within a
<code>goabx-work-side-menu</code> component.
</p>

<GoabText as="p" size="body-m">
Total item clicks: <strong>{itemClicks}</strong>
</GoabText>

<GoabxWorkSideMenu
heading="Menu heading"
url="#"
open={true}
primaryContent={
<>
<GoabxWorkSideMenuItem
label="Menu item 1"
icon="star"
onClick={onItemClick}
/>
<GoabxWorkSideMenuItem
label="Menu item 2"
icon="star"
onClick={onItemClick}
/>
<GoabxWorkSideMenuItem
label="Menu item 3"
icon="star"
onClick={onItemClick}
/>
</>
}
/>
</div>
);
}

export default Feat3340Route;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
CUSTOM_ELEMENTS_SCHEMA,
Component,
Input,
Output,
EventEmitter,
OnInit,
ChangeDetectorRef,
} from "@angular/core";
Expand All @@ -23,6 +25,7 @@ import { CommonModule } from "@angular/common";
[attr.icon]="icon"
[attr.testid]="testId"
[attr.type]="type"
(_click)="_onClick()"
>
<ng-content />
</goa-work-side-menu-item>
Expand All @@ -31,14 +34,16 @@ import { CommonModule } from "@angular/common";
})
export class GoabxWorkSideMenuItem implements OnInit {
@Input({ required: true }) label!: string;
@Input({ required: true }) url!: string;
@Input() url?: string;
@Input() badge?: string;
@Input() current?: boolean;
@Input() divider?: boolean;
@Input() icon?: string;
@Input() testId?: string;
@Input() type?: GoabWorkSideMenuItemType = "normal";

@Output() onClick = new EventEmitter();

isReady = false;

constructor(private cdr: ChangeDetectorRef) {}
Expand All @@ -51,4 +56,8 @@ export class GoabxWorkSideMenuItem implements OnInit {
this.cdr.detectChanges();
}, 0);
}

_onClick() {
this.onClick.emit();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type JSX } from "react";
import { useEffect, useRef, type JSX } from "react";
import { GoabWorkSideMenuItemType } from "@abgov/ui-components-common";
interface WCProps {
label: string;
url: string;
url?: string;
badge?: string;
current?: string;
divider?: string;
Expand All @@ -15,36 +15,68 @@ declare module "react" {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace JSX {
interface IntrinsicElements {
"goa-work-side-menu-item": WCProps & React.HTMLAttributes<HTMLElement>;
"goa-work-side-menu-item": WCProps &
React.HTMLAttributes<HTMLElement> & {
ref: React.RefObject<HTMLElement | null>;
};
}
}
}

export interface GoabWorkSideMenuItemProps {
label: string;
url: string;
url?: string;
badge?: string;
current?: boolean;
divider?: boolean;
icon?: string;
testId?: string;
type?: GoabWorkSideMenuItemType;
children?: React.ReactNode;
onCLick?: () => void;
}

export function GoabxWorkSideMenuItem(props: GoabWorkSideMenuItemProps): JSX.Element {
export function GoabxWorkSideMenuItem({
label,
url,
badge,
current,
divider,
icon,
testId,
type,
children,
onClick,
}: GoabWorkSideMenuItemProps): JSX.Element {
const el = useRef<HTMLElement>(null);

useEffect(() => {
if (!el.current) return;
if (!onClick) return;
const current = el.current;
const listener = () => {
onClick?.();
};

current.addEventListener("_click", listener);
return () => {
current.removeEventListener("_click", listener);
};
}, [el, onClick]);

return (
<goa-work-side-menu-item
label={props.label}
url={props.url}
badge={props.badge}
current={props.current ? "true" : undefined}
divider={props.divider ? "true" : undefined}
icon={props.icon}
testid={props.testId}
type={props.type}
ref={el}
label={label}
url={url}
badge={badge}
current={current ? "true" : undefined}
divider={divider ? "true" : undefined}
icon={icon}
testid={testId}
type={type}
>
{props.children}
{children}
</goa-work-side-menu-item>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/** The text label displayed for the menu item. */
export let label: string;
/** The URL the menu item links to. */
export let url: string;
export let url: string = "";

// optional
/** Badge text displayed alongside the menu item (e.g., notification count). */
Expand Down Expand Up @@ -61,8 +61,9 @@
// Functions
// *********

function handleClick() {
function handleClick(e: Event) {
dispatch(_rootEl, "_update", {}, { bubbles: true });
dispatch(_rootEl, "_click", {}, { bubbles: true });
}

function handleUpdateItem(e: CustomEvent) {
Expand Down Expand Up @@ -104,7 +105,8 @@
on:mouseenter={handleMouseEnter}
bind:this={_rootEl}
>
<a
<svelte:element
this={url ? "a" : "button"}
class="menu-item"
class:current
aria-current={current ? "page" : undefined}
Expand Down Expand Up @@ -138,7 +140,7 @@
{badge}
</div>
{/if}
</a>
</svelte:element>
</div>

<style>
Expand Down Expand Up @@ -196,6 +198,13 @@
margin-top: var(--goa-space-3xs);
}

button.menu-item {
border: none;
width: 100%;
text-align: left;
background-color: transparent;
}

/* Divider */
.divider {
padding-bottom: var(--goa-space-s);
Expand Down
Loading