Skip to content

Commit

Permalink
chore(ui): introduce TS version of TextBox and dependencies (#289)
Browse files Browse the repository at this point in the history
* chore(ui): Add TS version of TextArea, Label and FormHint

* fix(ui): fix FormHint TS types

* fix(ui): playbook naming fix

* fix(ui): playbook stories fix

* fix(ui): fix textarea story

* fix(ui): format and naming fix

---------

Co-authored-by: [email protected] <[email protected]>
  • Loading branch information
gjaskiewicz and [email protected] authored Sep 2, 2024
1 parent cba3173 commit 4a212b7
Show file tree
Hide file tree
Showing 19 changed files with 966 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import React, { useState, useEffect, useMemo, createContext, useId } from "react"
import PropTypes from "prop-types"
import { Label } from "../Label/index.js"
import { Label } from "../Label/index"
import { Icon } from "../Icon/index"
import { FormHint } from "../FormHint/index"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const FormHint = ({ children = null, text = "", variant = "help", classNa
)
}

FormHint.displayName = "FormHint Js"

FormHint.propTypes = {
/** The children to render as a hint associated with a form element */
children: PropTypes.node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import PropTypes from "prop-types"
import { FormHint } from "./index.js"

export default {
title: "Forms/FormHint",
title: "Forms/FormHint (JS, deprecated)",
component: FormHint,
argTypes: {
children: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { ReactNode } from "react"

const baseStyles = `
jn-text-xs
jn-mt-1
`

type FormHintVariant = "help" | "error" | "success"

const variantStyles = (variant: FormHintVariant) => {
switch (variant) {
case "success":
return "jn-text-theme-success"
case "error":
return "jn-text-theme-error"
default:
return "jn-text-theme-light"
}
}

export const FormHint = ({ children = null, text = "", variant = "help", className, ...props }: FormHintProps) => {
return (
<div
className={`
juno-form-hint
juno-form-hint-${variant}
${baseStyles}
${variantStyles(variant)}
${className}
`}
{...props}
>
{children || text}
</div>
)
}

FormHint.displayName = "FormHint"

export interface FormHintProps {
/** The children to render as a hint associated with a form element */
children?: ReactNode
/** The text to render. If both children and text are passed, children will rendered */
text?: ReactNode | string
/** The variant of the the hint. Defaults to 'help'. */
variant?: FormHintVariant
/** Pass a custom className */
className?: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from "react"
import PropTypes from "prop-types"
import { FormHint } from "./index"

export default {
title: "Forms/FormHint",
component: FormHint,
argTypes: {
children: {
control: false,
},
},
}

type TemplateProps = {
children: React.ReactNode
}

const Template = ({ children, ...args }: TemplateProps) => <FormHint {...args}>{children}</FormHint>
Template.propTypes = {
children: PropTypes.node,
}

export const Default = {
render: Template,

args: {
text: "A simple hint to be associated with a form input",
},
}

export const WithChildren = {
render: Template,

args: {
children: (
<>
A FormHint with a <a href="#">Link</a>.
</>
),
},
}

export const WithTextAsChildren = {
render: Template,

args: {
text: (
<>
A FormHint with a <a href="#">Link</a>.
</>
),
},
}

export const ErrorVariant = {
render: Template,

args: {
variant: "error",
text: "A FormHint containing an error or invalidation message",
},
}

export const SuccessVariant = {
render: Template,

args: {
variant: "success",
text: "A FormHint containg a success or validation message",
},
}
72 changes: 72 additions & 0 deletions packages/ui-components/src/components/FormHintTs/FormHint.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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 { FormHint } from "./index"

describe("FormHint", () => {
test("renders a FormHint", () => {
render(<FormHint data-testid="my-form-hint" />)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
})

test("renders children as passed", () => {
render(
<FormHint data-testid="my-form-hint">
<button></button>
</FormHint>
)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
expect(screen.getByRole("button")).toBeInTheDocument()
})

test("renders a text as passed", () => {
render(<FormHint data-testid="my-form-hint" text="My form-related message" />)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
expect(screen.getByTestId("my-form-hint")).toHaveTextContent("My form-related message")
})

test("renders children if both children and text have been passed", () => {
render(
<FormHint data-testid="my-form-hint" text="123">
<>abc</>
</FormHint>
)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
expect(screen.getByTestId("my-form-hint")).toHaveTextContent("abc")
expect(screen.getByTestId("my-form-hint")).not.toHaveTextContent("123")
})

test("renders a help message by default", () => {
render(<FormHint data-testid="my-form-hint" />)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
expect(screen.getByTestId("my-form-hint")).toHaveClass("juno-form-hint-help")
})

test("renders an error message as passed", () => {
render(<FormHint data-testid="my-form-hint" variant="error" />)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
expect(screen.getByTestId("my-form-hint")).toHaveClass("juno-form-hint-error")
})

test("renders a success message as passed", () => {
render(<FormHint data-testid="my-form-hint" variant="success" />)
expect(screen.getByTestId("my-form-hint")).toBeInTheDocument()
expect(screen.getByTestId("my-form-hint")).toHaveClass("juno-form-hint-success")
})

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

test("renders all props as passed", () => {
render(<FormHint data-testid="23" data-lolol={true} />)
expect(screen.getByTestId("23")).toBeInTheDocument()
expect(screen.getByTestId("23")).toHaveAttribute("data-lolol")
})
})
6 changes: 6 additions & 0 deletions packages/ui-components/src/components/FormHintTs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { FormHint } from "./FormHint.component"
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const Label = React.forwardRef(
}
)

Label.displayName = "Label"
Label.displayName = "Label (JS)"

Label.propTypes = {
/** Pass a string of text to be rendered as contents. Required. */
Expand Down
4 changes: 2 additions & 2 deletions packages/ui-components/src/components/Label/Label.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Label } from "./index.js"
import { Label } from "./index"

export default {
title: "Forms/Label",
title: "Forms/Label (JS, deprecated)",
component: Label,
argTypes: {},
}
Expand Down
109 changes: 109 additions & 0 deletions packages/ui-components/src/components/LabelTs/Label.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from "react"

const labelstyles = `
jn-text-theme-high
jn-text-base
jn-transform
jn-origin-top-left
jn-transition-all
jn-duration-100
jn-ease-in-out
jn-z-10
`

const floatingStyles = `
jn-absolute
`

const minimizedStyles = `
jn-scale-75
-jn-translate-y-[0.4375rem]
`

const requiredstyles = `
jn-inline-block
jn-w-1
jn-h-1
jn-rounded-full
jn-align-top
jn-ml-1
jn-mt-2
jn-bg-theme-required
`

const disabledstyles = `
jn-opacity-50
jn-cursor-not-allowed
`

/**
* A re-usable Label component
*/

export const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
(
{
text = "",
htmlFor = undefined,
required = false,
className = "",
disabled = false,
floating = false,
minimized = false,
...props
},
forwardedRef
) => {
return (
<label
className={`
juno-label
${labelstyles}
${floating ? "juno-label-floating " + floatingStyles : ""}
${minimized ? "juno-label-minimized " + minimizedStyles : ""}
${disabled ? "juno-label-disabled " + disabledstyles : ""}
${className}
`}
htmlFor={htmlFor}
ref={forwardedRef}
{...props}
>
{text}
{required ? (
<span
className={`
juno-required
${requiredstyles}
`}
></span>
) : (
""
)}
</label>
)
}
)

Label.displayName = "Label"

export interface LabelProps {
/** Pass a string of text to be rendered as contents. Required. */
text?: string
/** An Id of an input element to associate the label with */
htmlFor?: string
/** Required */
required?: boolean
/** Pass a className */
className?: string
/** Label for a disabled input */
disabled?: boolean
/** Whether the label is floating */
floating?: boolean
/** Whether the label is minimized. Requires `floating` set to TRUE, otherwise it will have no effect. */
minimized?: boolean
}
Loading

0 comments on commit 4a212b7

Please sign in to comment.