Skip to content

Commit

Permalink
Merge branch 'main' into guoda-convert-panel-to-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
guoda-puidokaite committed Nov 13, 2024
2 parents cbbbde0 + c9190d0 commit 2029083
Show file tree
Hide file tree
Showing 51 changed files with 1,428 additions and 486 deletions.
5 changes: 5 additions & 0 deletions .changeset/nice-moons-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudoperators/juno-ui-components": minor
---

Migrate NativeSelect, NativeSelectionOption and NativeSelectOptionGroup components to TypeScript
5 changes: 5 additions & 0 deletions .changeset/shaggy-pots-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudoperators/juno-ui-components": minor
---

Migrate Form, FormRow and FormSection components to TypeScript
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import React, { useState, useEffect } from "react"
import PropTypes from "prop-types"
import { NativeSelect } from "../NativeSelect/NativeSelect.component"
import { NativeSelectOption } from "../NativeSelectOption/NativeSelectOption.component"
import { NativeSelect } from "../../deprecated_js/NativeSelect/NativeSelect.component"
import { NativeSelectOption } from "../../deprecated_js/NativeSelectOption/NativeSelectOption.component"
import { TextInput } from "../../deprecated_js/TextInput/TextInput.component"
import { Icon } from "../../deprecated_js/Icon/Icon.component"

Expand Down
36 changes: 0 additions & 36 deletions packages/ui-components/src/components/Form/Form.component.js

This file was deleted.

47 changes: 47 additions & 0 deletions packages/ui-components/src/components/Form/Form.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { ReactNode, FormHTMLAttributes } from "react"

const formBaseStyles = `
jn-mb-8
`

const formTitleStyles = `
jn-text-2xl
jn-font-bold
jn-mb-4
`

export interface FormProps extends FormHTMLAttributes<HTMLFormElement> {
/**
* Title for the form.
*/
title?: string

/**
* Additional CSS classes to apply to the form for custom styling.
*/
className?: string

/**
* Content to render inside the form.
* This can include FormSections, FormGroups, and other form elements.
*/
children?: ReactNode
}

/**
* A Form component used to encapsulate FormSections and/or FormGroups.
* Can be used to build complex forms with structured sections.
*/
export const Form: React.FC<FormProps> = ({ title = "", className = "", children, ...props }) => {
return (
<form className={`juno-form ${formBaseStyles} ${className}`} {...props}>
{title ? <h1 className={`juno-form-heading ${formTitleStyles}`}>{title}</h1> : null}
{children}
</form>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,31 @@
*/

import React from "react"
import PropTypes from "prop-types"
import { Form } from "./index.js"
import { FormRow } from "../FormRow/index.js"
import { FormSection } from "../FormSection/index.js"
import { FormHint } from "../../deprecated_js/FormHint/index.js"
import { TextInput } from "../../deprecated_js/TextInput/index.js"
import { Select } from "../../deprecated_js/Select/index.js"
import { SelectOption } from "../../deprecated_js/SelectOption/index.js"
import { Switch } from "../../deprecated_js/Switch/Switch.component"
import { Textarea } from "../../deprecated_js/Textarea/index.js"
import { Button } from "../../deprecated_js/Button/index.js"
import { ButtonRow } from "../../deprecated_js/ButtonRow/index.js"
import { IntroBox } from "../IntroBox/index.ts"
import { PortalProvider } from "../../deprecated_js/PortalProvider/PortalProvider.component"
import { Meta, StoryFn } from "@storybook/react"

import { Form, FormProps } from "./Form.component"
import { FormRow } from "../FormRow/FormRow.component"
import { FormHint } from "../FormHint/FormHint.component"
import { FormSection } from "../FormSection/FormSection.component"

import { Select } from "../Select/Select.component"
import { SelectOption } from "../SelectOption/SelectOption.component"

import { Textarea } from "../Textarea/Textarea.component"
import { TextInput } from "../TextInput/TextInput.component"

import { Button } from "../Button/Button.component"
import { ButtonRow } from "../ButtonRow/ButtonRow.component"

import { Radio } from "../Radio/Radio.component"
import { RadioGroup } from "../RadioGroup/RadioGroup.component"

import { Checkbox } from "../Checkbox/Checkbox.component"
import { CheckboxGroup } from "../CheckboxGroup/CheckboxGroup.component"

import { PortalProvider } from "../PortalProvider/PortalProvider.component"
import { IntroBox } from "../IntroBox/IntroBox.component"
import { Switch } from "../Switch/Switch.component"

export default {
title: "Forms/Form",
Expand All @@ -30,27 +41,27 @@ export default {
},
children: {
control: false,
table: {
type: { summary: "ReactNode" },
},
},
},
decorators: [
(Story) => (
(Story: StoryFn) => (
<div className="jn-pb-12" style={{ minHeight: "250px" }}>
<PortalProvider>
<Story />
</PortalProvider>
</div>
),
],
}
} as Meta<typeof Form>

const Template = ({ children, ...args }) => <Form {...args}>{children}</Form>
Template.propTypes = {
children: PropTypes.node,
}
// eslint-disable-next-line react/prop-types
const Template: StoryFn<FormProps> = ({ children, ...args }) => <Form {...args}>{children}</Form>

export const Default = {
render: Template,

args: {
title: "A Simple Form",
children: [
Expand All @@ -73,7 +84,6 @@ export const Default = {

export const ComplexForm = {
render: Template,

args: {
title: "A Complex Form",
children: [
Expand Down Expand Up @@ -101,6 +111,16 @@ export const ComplexForm = {
</FormRow>
</FormSection>,
<FormSection title="Second Section of the Form" key="fs-2">
<RadioGroup name="color-radios" label="In case you are not sure, select your true favorite color:">
<Radio key="r-1" id="color-red" label="Red" value="red" />
<Radio key="r-2" id="color-blue" label="Blue" value="blue" />
<Radio key="r-3" id="color-green" label="Green" value="green" />
<Radio key="r-4" id="color-yellow" label="Yellow" value="yellow" />
</RadioGroup>
<CheckboxGroup name="all-about-red" label="What is your opinion towards the color Red?">
<Checkbox key="c-1" id="overrated" label="Red is vastly overrated" value="overrated" />
<Checkbox key="c-2" id="blackisred" label="Black is better" value="blackisbetter" />
</CheckboxGroup>
<FormRow key="fr-4">
<Textarea
label="Your Message"
Expand Down
43 changes: 0 additions & 43 deletions packages/ui-components/src/components/Form/Form.test.js

This file was deleted.

84 changes: 84 additions & 0 deletions packages/ui-components/src/components/Form/Form.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
* SPDX-License-Identifier: Apache-2.0
*/

import * as React from "react"
import { render, screen } from "@testing-library/react"
import { describe, expect, test } from "vitest"

import { Form } from "./Form.component"

describe("Form Component Tests", () => {
describe("Basic Rendering", () => {
test("renders a Form", () => {
render(<Form data-testid="my-form" />)
expect(screen.getByTestId("my-form")).toBeInTheDocument()
})

test("renders a title", () => {
render(<Form data-testid="my-form" title="My Form" />)
expect(screen.getByTestId("my-form")).toBeInTheDocument()
expect(screen.getByRole("heading")).toHaveClass("juno-form-heading")
expect(screen.getByRole("heading")).toHaveTextContent("My Form")
})

test("renders without any props", () => {
const { container } = render(<Form />)
expect(container.firstChild).toBeInTheDocument()
expect(container.firstChild).toHaveClass("juno-form")
})

test("renders with falsy values as title", () => {
render(<Form data-testid="my-form" title={""} />)
expect(screen.queryByRole("heading")).not.toBeInTheDocument()
})
})

describe("Props Handling", () => {
test("renders a custom className", () => {
render(<Form data-testid="my-form" className="my-custom-class" />)
expect(screen.getByTestId("my-form")).toBeInTheDocument()
expect(screen.getByTestId("my-form")).toHaveClass("my-custom-class")
})

test("renders all props as passed", () => {
render(<Form data-testid="23" data-lolol={true} />)
expect(screen.getByTestId("23")).toBeInTheDocument()
expect(screen.getByTestId("23")).toHaveAttribute("data-lolol")
})

test("applies default styles", () => {
const { container } = render(<Form />)
expect(container.firstChild).toHaveClass("juno-form")
expect(container.firstChild).toHaveClass("jn-mb-8")
})
})

describe("Children Rendering", () => {
test("renders children as passed", () => {
render(
<Form data-testid="my-form">
<button></button>
</Form>
)
expect(screen.getByRole("button")).toBeInTheDocument()
})

test("renders multiple children", () => {
render(
<Form data-testid="my-form">
<button>Button 1</button>
<button>Button 2</button>
</Form>
)
expect(screen.getByText("Button 1")).toBeInTheDocument()
expect(screen.getByText("Button 2")).toBeInTheDocument()
})

test("renders with no children", () => {
render(<Form data-testid="my-form" />)
expect(screen.getByTestId("my-form").childElementCount).toBe(0)
})
})
})
Loading

0 comments on commit 2029083

Please sign in to comment.