Skip to content

Commit

Permalink
♻️ Ny utility composeEventHandlers (#2610)
Browse files Browse the repository at this point in the history
* 💄 Synket prettier

* ✨ ComposeEventHandlers

* ♻️ Button composeEvent

* ♻️ chips composeEvent

* ♻️ copybutton composeEvent

* ♻️ composeEventhandlers dropdown

* ♻️ composeEventhandlers react-more, stepper

* ♻️ composeEventhandlers expandablerow

* ⚰️ Fjernet deprecated prop fra tooltip

* ♻️ composeEventhandlers searchbutton

* 📝 Changeset

* Update @navikt/core/react/src/util/composeEventHandlers.ts

Co-authored-by: Halvor Haugan <[email protected]>

* 🔥 Fjernet as unknown as event i composeEventhandler

* ♻️ Forenklet if-tester, la tilbake kommentarer 📝

* 📝 Oppdatert jsdoc

---------

Co-authored-by: Halvor Haugan <[email protected]>
  • Loading branch information
KenAJoh and HalvorHaugan authored Jan 12, 2024
1 parent 2fedeab commit f707b22
Show file tree
Hide file tree
Showing 23 changed files with 157 additions and 137 deletions.
5 changes: 5 additions & 0 deletions .changeset/happy-ducks-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@navikt/ds-react": minor
---

Intern state: Komponenter respekterer nå `e.preventDefault()` bedre når event overskrives internt i komponent.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function transformer(file: JSCodeshift, api) {

const jsImport = root.find(j.ImportDeclaration).filter((x) => {
return ["@navikt/ds-tokens/dist/tokens"].includes(
x.node.source.value as string
x.node.source.value as string,
);
});

Expand All @@ -36,7 +36,7 @@ export default function transformer(file: JSCodeshift, api) {
let foundName: string = "";

getImportSpecifier(j, root, name, "@navikt/ds-tokens/dist/tokens").forEach(
(x) => (foundName = x.node.imported.name)
(x) => (foundName = x.node.imported.name),
);

if (name === foundName) {
Expand All @@ -45,15 +45,15 @@ export default function transformer(file: JSCodeshift, api) {
j,
root,
name,
"@navikt/ds-tokens/dist/tokens"
"@navikt/ds-tokens/dist/tokens",
) || name;

renameImportSpecifier(
j,
root,
name,
out,
"@navikt/ds-tokens/dist/tokens"
"@navikt/ds-tokens/dist/tokens",
);

let code = root.toSource(getLineTerminator(file.source));
Expand Down
8 changes: 4 additions & 4 deletions @navikt/aksel/src/codemod/utils/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface TestT {

export function check(
dirName: string,
{ fixture, migration, extension = "js", options = {} }: TestT
{ fixture, migration, extension = "js", options = {} }: TestT,
) {
describe(migration, () => {
it(fixture, async () => {
Expand All @@ -22,7 +22,7 @@ export function check(
const source = fs.readFileSync(inputPath, "utf8");
const expected = fs.readFileSync(
path.join(fixtureDir, `${fixture}.output.${extension}`),
"utf8"
"utf8",
);
// Assumes transform is one level up from tests directory
const module = await import(path.join(dirName, "..", migration));
Expand All @@ -34,11 +34,11 @@ export function check(
expect(
await prettier.format(output, {
parser: parser === "js" ? "typescript" : parser,
})
}),
).toBe(
await prettier.format(expected, {
parser: parser === "js" ? "typescript" : parser,
})
}),
);
});
});
Expand Down
6 changes: 2 additions & 4 deletions @navikt/core/react/src/accordion/AccordionHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { ChevronDownIcon } from "@navikt/aksel-icons";
import { Heading } from "../typography";
import { composeEventHandlers } from "../util/composeEventHandlers";
import { AccordionContext } from "./AccordionContext";
import { AccordionItemContext } from "./AccordionItem";

Expand Down Expand Up @@ -30,10 +31,7 @@ const AccordionHeader = forwardRef<HTMLButtonElement, AccordionHeaderProps>(
ref={ref}
{...rest}
className={cl("navds-accordion__header", className)}
onClick={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
itemContext.toggleOpen();
onClick && onClick(e);
}}
onClick={composeEventHandlers(onClick, itemContext.toggleOpen)}
aria-expanded={itemContext.open}
type="button"
>
Expand Down
4 changes: 2 additions & 2 deletions @navikt/core/react/src/accordion/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const AccordionItemContext =
const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(
(
{ children, className, open, defaultOpen = false, onOpenChange, ...rest },
ref
ref,
) => {
const [_open, _setOpen] = useControllableState({
defaultValue: defaultOpen,
Expand Down Expand Up @@ -78,7 +78,7 @@ const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(
</AccordionItemContext.Provider>
</div>
);
}
},
);

export default AccordionItem;
19 changes: 8 additions & 11 deletions @navikt/core/react/src/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { forwardRef, useRef, useState } from "react";
import { Loader } from "../loader";
import { Label } from "../typography";
import { OverridableComponent, omit, useClientLayoutEffect } from "../util";
import { composeEventHandlers } from "../util/composeEventHandlers";
import { useMergeRefs } from "../util/hooks/useMergeRefs";

export interface ButtonProps
Expand Down Expand Up @@ -99,22 +100,18 @@ export const Button: OverridableComponent<ButtonProps, HTMLButtonElement> =
const filterProps: React.ButtonHTMLAttributes<HTMLButtonElement> =
disabled ?? widthOverride ? omit(rest, ["href"]) : rest;

const handleKeyUp = (e: React.KeyboardEvent<HTMLButtonElement>) => {
if (e.key === " " && !disabled && !widthOverride) {
e.currentTarget.click();
}
};

return (
<Component
{...(Component !== "button" ? { role: "button" } : {})}
{...filterProps}
ref={mergedRef}
onKeyUp={(e: React.KeyboardEvent<HTMLButtonElement>) => {
filterProps.onKeyUp?.(e);
if (
e.key === " " &&
!disabled &&
!widthOverride &&
!e.isDefaultPrevented()
) {
e.currentTarget.click();
}
}}
onKeyUp={composeEventHandlers(filterProps.onKeyUp, handleKeyUp)}
className={cl(
className,
"navds-button",
Expand Down
7 changes: 3 additions & 4 deletions @navikt/core/react/src/chips/Removable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cl from "clsx";
import React, { forwardRef } from "react";
import { XMarkIcon } from "@navikt/aksel-icons";
import { composeEventHandlers } from "../util/composeEventHandlers";

export interface RemovableChipsProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
Expand Down Expand Up @@ -33,6 +34,7 @@ export const RemovableChips = forwardRef<
removeLabel = "slett",
onDelete,
type = "button",
onClick,
...rest
},
ref,
Expand All @@ -48,10 +50,7 @@ export const RemovableChips = forwardRef<
`navds-chips__removable--${variant}`,
)}
aria-label={`${children} ${removeLabel}`}
onClick={(e) => {
onDelete?.();
rest?.onClick?.(e);
}}
onClick={composeEventHandlers(onClick, onDelete)}
>
<span className="navds-chips__chip-text">{children}</span>
<span className="navds-chips__removable-icon">
Expand Down
9 changes: 4 additions & 5 deletions @navikt/core/react/src/copybutton/CopyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
} from "react";
import { CheckmarkIcon, FilesIcon } from "@navikt/aksel-icons";
import { Label } from "../typography";
import { composeEventHandlers } from "../util/composeEventHandlers";
import copy from "../util/copy";

export interface CopyButtonProps
Expand Down Expand Up @@ -97,6 +98,7 @@ export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
title = "Kopier",
activeTitle = "Kopiert",
iconPosition = "left",
onClick,
...rest
},
ref,
Expand All @@ -110,14 +112,11 @@ export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
};
}, []);

const handleClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => {
const handleClick = () => {
timeoutRef.current && clearTimeout(timeoutRef.current);
copy(copyText);
setActive(true);
onActiveChange?.(true);
rest.onClick?.(event);

timeoutRef.current = window.setTimeout(() => {
setActive(false);
Expand Down Expand Up @@ -160,7 +159,7 @@ export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
"navds-copybutton--active": active,
},
)}
onClick={handleClick}
onClick={composeEventHandlers(onClick, handleClick)}
>
<span className="navds-copybutton__content">
{iconPosition === "left" && copyIcon}
Expand Down
44 changes: 22 additions & 22 deletions @navikt/core/react/src/dropdown/Menu/GroupedList/GroupedItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { OverridableComponent } from "../../../util";
import { composeEventHandlers } from "../../../util/composeEventHandlers";
import { DropdownContext } from "../../context";

export interface GroupedItemProps
Expand All @@ -14,28 +15,27 @@ export interface GroupedItemProps
export const GroupedItem: OverridableComponent<
GroupedItemProps,
HTMLButtonElement
> = forwardRef(({ as: Component = "button", className, ...rest }, ref) => {
const context = useContext(DropdownContext);
> = forwardRef(
({ as: Component = "button", className, onClick, ...rest }, ref) => {
const context = useContext(DropdownContext);

return (
<dd className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
context?.onSelect?.(event);
rest?.onClick?.(event);
}}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</dd>
);
});
return (
<dd className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={composeEventHandlers(onClick, context?.onSelect)}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</dd>
);
},
);

export default GroupedItem;
44 changes: 22 additions & 22 deletions @navikt/core/react/src/dropdown/Menu/List/Item.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { OverridableComponent } from "../../../util";
import { composeEventHandlers } from "../../../util/composeEventHandlers";
import { DropdownContext } from "../../context";

export interface ListItemProps extends React.ButtonHTMLAttributes<HTMLElement> {
Expand All @@ -11,28 +12,27 @@ export interface ListItemProps extends React.ButtonHTMLAttributes<HTMLElement> {
}

export const ListItem: OverridableComponent<ListItemProps, HTMLButtonElement> =
forwardRef(({ as: Component = "button", className, ...rest }, ref) => {
const context = useContext(DropdownContext);
forwardRef(
({ as: Component = "button", className, onClick, ...rest }, ref) => {
const context = useContext(DropdownContext);

return (
<li className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
context?.onSelect?.(event);
rest?.onClick?.(event);
}}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</li>
);
});
return (
<li className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={composeEventHandlers(onClick, context?.onSelect)}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</li>
);
},
);

export default ListItem;
16 changes: 10 additions & 6 deletions @navikt/core/react/src/dropdown/Toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { composeEventHandlers } from "../util/composeEventHandlers";
import { DropdownContext } from "./context";

export interface ToggleProps
Expand All @@ -21,6 +22,13 @@ export const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(

const { setAnchorEl, handleToggle, isOpen } = context;

const handleClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => {
setAnchorEl(e.currentTarget);
handleToggle(!isOpen);
};

return (
<button
{...rest}
Expand All @@ -33,16 +41,12 @@ export const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(
ref.current = el;
}
}}
onClick={(e) => {
setAnchorEl(e.currentTarget);
handleToggle(!isOpen);
onClick && onClick(e);
}}
onClick={composeEventHandlers(onClick, handleClick)}
aria-expanded={isOpen}
className={cl("navds-dropdown__toggle", className)}
/>
);
}
},
);

export default Toggle;
6 changes: 2 additions & 4 deletions @navikt/core/react/src/form/search/SearchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { MagnifyingGlassIcon } from "@navikt/aksel-icons";
import { Button, ButtonProps } from "../../button";
import { composeEventHandlers } from "../../util/composeEventHandlers";
import { SearchContext } from "./context";

export interface SearchButtonProps
Expand Down Expand Up @@ -36,10 +37,7 @@ const SearchButton: SearchButtonType = forwardRef(
variant={variant === "secondary" ? "secondary" : "primary"}
className={cl("navds-search__button-search", className)}
disabled={context?.disabled ?? disabled}
onClick={(e) => {
handleClick();
onClick?.(e);
}}
onClick={composeEventHandlers(onClick, handleClick)}
icon={
<MagnifyingGlassIcon
{...(children ? { "aria-hidden": true } : { title: "Søk" })}
Expand Down
Loading

0 comments on commit f707b22

Please sign in to comment.