Skip to content

Commit 11eabd6

Browse files
feat(ui): allow the button type to be overwritten (#1541)
* feat(ui): allow the button type to be overwritten * refactor(ui): replace hardcoded values with tailwind predefined * fix(greenhouse): failing tests due to async/mock timing issue * chore(ci): generate changeset * fix(ui): after merge changes * chore(ui): update btn props jsdoc
1 parent 06ae262 commit 11eabd6

4 files changed

Lines changed: 44 additions & 14 deletions

File tree

.changeset/few-paws-glow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cloudoperators/juno-ui-components": patch
3+
---
4+
5+
Added customizable type property for the button component.

packages/ui-components/src/components/AppShell/AppShell.component.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const AppShell = ({
4141
<>
4242
{topNavigation && <HeaderContainer fullWidth={fullWidthOrDefault}>{topNavigation}</HeaderContainer>}
4343
<MainContainer>
44-
<MainContainerInner fullWidth={fullWidthOrDefault} className={`${topNavigation ? "jn:mt-[3.875rem]" : ""}`}>
44+
<MainContainerInner fullWidth={fullWidthOrDefault} className={`${topNavigation ? "jn:mt-15.5" : ""}`}>
4545
{sideNavigation}
4646
<ContentContainer>{children}</ContentContainer>
4747
</MainContainerInner>
@@ -55,7 +55,7 @@ export const AppShell = ({
5555
</HeaderContainer>
5656
{/* Wrap everything except page header and footer and navigations in a main container. Add top margin to MainContainerInner as we are not in embedded mode here. */}
5757
<MainContainer>
58-
<MainContainerInner fullWidth={fullWidthOrDefault} className="jn:mt-[3.875rem]">
58+
<MainContainerInner fullWidth={fullWidthOrDefault} className="jn:mt-15.5">
5959
{sideNavigation}
6060
<ContentContainer>{children}</ContentContainer>
6161
</MainContainerInner>

packages/ui-components/src/components/Button/Button.component.tsx

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
2+
* SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and Juno contributors
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import React, { forwardRef, HTMLProps, LegacyRef, MouseEventHandler, ReactNode, MouseEvent } from "react"
6+
import React, {
7+
forwardRef,
8+
HTMLProps,
9+
MouseEventHandler,
10+
ReactNode,
11+
MouseEvent,
12+
ButtonHTMLAttributes,
13+
Ref,
14+
} from "react"
715
import { Icon } from "../Icon/index"
816
import { KnownIcons } from "../Icon/Icon.component"
917
import { Spinner } from "../Spinner/index"
@@ -38,24 +46,24 @@ const btnDefaultBase = `
3846
`
3947

4048
const btnSmallDefaultPadding = `
41-
jn:py-[0.3125rem]
49+
jn:py-1.25
4250
jn:px-[0.5rem]
4351
`
4452

4553
const btnSmallSubduedPadding = `
4654
jn:py-[0.25rem]
47-
jn:px-[0.4375rem]
55+
jn:px-1.75
4856
`
4957

5058
// default size padding
5159
const btnDefaultPadding = `
52-
jn:py-[0.4375rem]
53-
jn:px-[0.625rem]
60+
jn:py-1.75
61+
jn:px-2.5
5462
`
5563

5664
const btnDefaultSubduedPadding = `
57-
jn:py-[0.375rem]
58-
jn:px-[0.5625rem]
65+
jn:py-1.5
66+
jn:px-2.25
5967
`
6068

6169
const defaultButtonColors = `
@@ -166,6 +174,7 @@ export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPr
166174
{
167175
label,
168176
title,
177+
type = "button",
169178
variant = "default",
170179
size = "default",
171180
disabled,
@@ -183,7 +192,7 @@ export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPr
183192
const titleValue = title || label || ""
184193

185194
const buttonIcon = progress ? (
186-
<Spinner size={size === "small" ? "1.125rem" : "1.5rem"} color={`${spinnerColorClass(variant)}`} />
195+
<Spinner size={size === "small" ? "1.125rem" : "1.5rem"} color={spinnerColorClass(variant)} />
187196
) : icon ? (
188197
<Icon
189198
icon={icon}
@@ -213,9 +222,9 @@ export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPr
213222
${className}`}
214223
disabled={disabled || undefined}
215224
onClick={handleClick}
216-
ref={ref as LegacyRef<HTMLButtonElement>}
225+
ref={ref as Ref<HTMLButtonElement>}
217226
{...(props as HTMLProps<HTMLButtonElement>)}
218-
type="button"
227+
type={type}
219228
title={titleValue}
220229
>
221230
{buttonIcon}
@@ -240,7 +249,7 @@ export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPr
240249
`}
241250
disabled={disabled}
242251
onClick={onClick}
243-
ref={ref as LegacyRef<HTMLAnchorElement>}
252+
ref={ref as Ref<HTMLAnchorElement>}
244253
{...(props as HTMLProps<HTMLAnchorElement>)}
245254
title={titleValue}
246255
>
@@ -312,6 +321,12 @@ export interface ButtonProps extends Omit<HTMLProps<HTMLAnchorElement> | HTMLPro
312321
*/
313322
onClick?: MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>
314323

324+
/**
325+
* Button type.
326+
* @default "button"
327+
*/
328+
type?: ButtonHTMLAttributes<HTMLButtonElement>["type"]
329+
315330
/**
316331
* Indicates whether the button's action is in progress.
317332
* @default false

packages/ui-components/src/components/Button/Button.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ describe("Button", () => {
132132
expect(screen.getByRole("button")).toHaveAttribute("data-lolol")
133133
})
134134

135+
test("defaults to type button", () => {
136+
render(<Button label="Default type" />)
137+
expect(screen.getByRole("button", { name: "Default type" })).toHaveAttribute("type", "button")
138+
})
139+
140+
test("allows overriding type", () => {
141+
render(<Button label="Submit" type="submit" />)
142+
expect(screen.getByRole("button", { name: "Submit" })).toHaveAttribute("type", "submit")
143+
})
144+
135145
test("renders an icon with the defined button title", () => {
136146
render(<Button title="customTitle" icon="default" />)
137147
expect(screen.getByRole("img")).toBeInTheDocument()

0 commit comments

Comments
 (0)