feat(ui,dashboard): Move InlineTip to UI package (#11462)
This commit is contained in:
committed by
GitHub
parent
63f0774569
commit
b53ea77658
6
.changeset/seven-nails-sleep.md
Normal file
6
.changeset/seven-nails-sleep.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/ui": patch
|
||||||
|
"@medusajs/dashboard": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(ui,dashboard): Move InlineTip to UI package
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import { clx } from "@medusajs/ui"
|
|
||||||
import { ComponentPropsWithoutRef, forwardRef } from "react"
|
|
||||||
import { useTranslation } from "react-i18next"
|
|
||||||
|
|
||||||
interface InlineTipProps extends ComponentPropsWithoutRef<"div"> {
|
|
||||||
/**
|
|
||||||
* The label to display in the tip.
|
|
||||||
*/
|
|
||||||
label?: string
|
|
||||||
/**
|
|
||||||
* The variant of the tip.
|
|
||||||
*/
|
|
||||||
variant?: "tip" | "warning"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A component for rendering inline tips. Useful for providing additional information or context.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```tsx
|
|
||||||
* <InlineTip label="Info">
|
|
||||||
* This is an info tip.
|
|
||||||
* </InlineTip>
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* TODO: Move to `@medusajs/ui` package.
|
|
||||||
*/
|
|
||||||
export const InlineTip = forwardRef<HTMLDivElement, InlineTipProps>(
|
|
||||||
({ variant = "tip", label, className, children, ...props }, ref) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
const labelValue =
|
|
||||||
label || (variant === "warning" ? t("general.warning") : t("general.tip"))
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
role="presentation"
|
|
||||||
className={clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
|
|
||||||
"bg-ui-tag-orange-icon": variant === "warning",
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<div className="text-pretty">
|
|
||||||
<strong className="txt-small-plus text-ui-fg-base">
|
|
||||||
{labelValue}:
|
|
||||||
</strong>{" "}
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
InlineTip.displayName = "InlineTip"
|
|
||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
Heading,
|
Heading,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
InlineTip,
|
||||||
clx,
|
clx,
|
||||||
toast,
|
toast,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
@@ -21,7 +22,6 @@ import { FetchError } from "@medusajs/js-sdk"
|
|||||||
import { ComponentPropsWithoutRef, forwardRef } from "react"
|
import { ComponentPropsWithoutRef, forwardRef } from "react"
|
||||||
import { ConditionalTooltip } from "../../common/conditional-tooltip"
|
import { ConditionalTooltip } from "../../common/conditional-tooltip"
|
||||||
import { Form } from "../../common/form"
|
import { Form } from "../../common/form"
|
||||||
import { InlineTip } from "../../common/inline-tip"
|
|
||||||
import { Skeleton } from "../../common/skeleton"
|
import { Skeleton } from "../../common/skeleton"
|
||||||
import { RouteDrawer, useRouteModal } from "../../modals"
|
import { RouteDrawer, useRouteModal } from "../../modals"
|
||||||
import { KeyboundForm } from "../../utilities/keybound-form"
|
import { KeyboundForm } from "../../utilities/keybound-form"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Input, Switch } from "@medusajs/ui"
|
import { InlineTip, Input, Switch } from "@medusajs/ui"
|
||||||
import { ComponentType } from "react"
|
import { ComponentType } from "react"
|
||||||
import { ControllerRenderProps, UseFormReturn } from "react-hook-form"
|
import { ControllerRenderProps, UseFormReturn } from "react-hook-form"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
import { Form } from "../../../components/common/form"
|
import { Form } from "../../../components/common/form"
|
||||||
import { InlineTip } from "../../../components/common/inline-tip"
|
|
||||||
import { FormField } from "../../types"
|
import { FormField } from "../../types"
|
||||||
import { FormFieldType } from "./types"
|
import { FormFieldType } from "./types"
|
||||||
import { getFieldType } from "./utils"
|
import { getFieldType } from "./utils"
|
||||||
@@ -86,6 +86,8 @@ const FormExtensionFieldComponent = ({
|
|||||||
component,
|
component,
|
||||||
placeholder,
|
placeholder,
|
||||||
}: FormExtensionFieldComponentProps) => {
|
}: FormExtensionFieldComponentProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
if (component) {
|
if (component) {
|
||||||
const Component = component
|
const Component = component
|
||||||
|
|
||||||
@@ -104,7 +106,7 @@ const FormExtensionFieldComponent = ({
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return (
|
return (
|
||||||
<InlineTip variant="warning">
|
<InlineTip variant="warning" label={t("general.warning")}>
|
||||||
The field type does not support rendering a fallback component. Please
|
The field type does not support rendering a fallback component. Please
|
||||||
provide a component prop.
|
provide a component prop.
|
||||||
</InlineTip>
|
</InlineTip>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
import { HttpTypes } from "@medusajs/types"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import { Button, Heading, Input, toast } from "@medusajs/ui"
|
import { Button, Heading, InlineTip, Input, toast } from "@medusajs/ui"
|
||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { InlineTip } from "../../../../../components/common/inline-tip"
|
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
StackedFocusModal,
|
StackedFocusModal,
|
||||||
@@ -118,7 +117,7 @@ export function CreateServiceZoneForm({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InlineTip>
|
<InlineTip label={t("general.tip")}>
|
||||||
{t("stockLocations.serviceZones.fields.tip")}
|
{t("stockLocations.serviceZones.fields.tip")}
|
||||||
</InlineTip>
|
</InlineTip>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { HttpTypes } from "@medusajs/types"
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import { Button, Input, toast } from "@medusajs/ui"
|
import { Button, InlineTip, Input, toast } from "@medusajs/ui"
|
||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
import { Form } from "../../../../../components/common/form"
|
import { Form } from "../../../../../components/common/form"
|
||||||
import { InlineTip } from "../../../../../components/common/inline-tip"
|
|
||||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||||
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||||
import { useUpdateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
import { useUpdateFulfillmentSetServiceZone } from "../../../../../hooks/api/fulfillment-sets"
|
||||||
@@ -83,7 +82,9 @@ export const EditServiceZoneForm = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<InlineTip>{t("stockLocations.serviceZones.fields.tip")}</InlineTip>
|
<InlineTip label={t("general.tip")}>
|
||||||
|
{t("stockLocations.serviceZones.fields.tip")}
|
||||||
|
</InlineTip>
|
||||||
</div>
|
</div>
|
||||||
</RouteDrawer.Body>
|
</RouteDrawer.Body>
|
||||||
<RouteDrawer.Footer>
|
<RouteDrawer.Footer>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
Hint,
|
Hint,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
InlineTip,
|
||||||
Input,
|
Input,
|
||||||
Label,
|
Label,
|
||||||
Text,
|
Text,
|
||||||
@@ -21,7 +22,6 @@ import {
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
import { Form } from "../../../../../../../components/common/form"
|
import { Form } from "../../../../../../../components/common/form"
|
||||||
import { InlineTip } from "../../../../../../../components/common/inline-tip"
|
|
||||||
import { SortableList } from "../../../../../../../components/common/sortable-list"
|
import { SortableList } from "../../../../../../../components/common/sortable-list"
|
||||||
import { SwitchBox } from "../../../../../../../components/common/switch-box"
|
import { SwitchBox } from "../../../../../../../components/common/switch-box"
|
||||||
import { ChipInput } from "../../../../../../../components/inputs/chip-input"
|
import { ChipInput } from "../../../../../../../components/inputs/chip-input"
|
||||||
@@ -522,7 +522,7 @@ export const ProductCreateVariantsSection = ({
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
{variants.fields.length > 0 && (
|
{variants.fields.length > 0 && (
|
||||||
<InlineTip variant="tip">
|
<InlineTip label={t("general.tip")}>
|
||||||
{t("products.create.variants.productVariants.tip")}
|
{t("products.create.variants.productVariants.tip")}
|
||||||
</InlineTip>
|
</InlineTip>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { render, screen } from "@testing-library/react"
|
||||||
|
import * as React from "react"
|
||||||
|
import { InlineTip } from "./inline-tip"
|
||||||
|
|
||||||
|
describe("InlineTip", () => {
|
||||||
|
it("renders a InlineTip", () => {
|
||||||
|
render(<InlineTip label="Test">This is a test</InlineTip>)
|
||||||
|
expect(screen.getByText("This is a test")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("renders a InlineTip with a warning variant", () => {
|
||||||
|
render(
|
||||||
|
<InlineTip variant="warning" label="Test">
|
||||||
|
This is a test
|
||||||
|
</InlineTip>
|
||||||
|
)
|
||||||
|
expect(screen.getByText("This is a test")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("renders a InlineTip with an error variant", () => {
|
||||||
|
render(
|
||||||
|
<InlineTip variant="error" label="Test">
|
||||||
|
This is a test
|
||||||
|
</InlineTip>
|
||||||
|
)
|
||||||
|
expect(screen.getByText("This is a test")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("renders a InlineTip with a success variant", () => {
|
||||||
|
render(
|
||||||
|
<InlineTip variant="success" label="Test">
|
||||||
|
This is a test
|
||||||
|
</InlineTip>
|
||||||
|
)
|
||||||
|
expect(screen.getByText("This is a test")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import type { Meta, StoryObj } from "@storybook/react"
|
||||||
|
import * as React from "react"
|
||||||
|
import { InlineTip } from "./inline-tip"
|
||||||
|
|
||||||
|
const meta: Meta<typeof InlineTip> = {
|
||||||
|
title: "Components/InlineTip",
|
||||||
|
component: InlineTip,
|
||||||
|
parameters: {
|
||||||
|
layout: "centered",
|
||||||
|
},
|
||||||
|
render: (args) => {
|
||||||
|
return (
|
||||||
|
<div className="flex max-w-md">
|
||||||
|
<InlineTip {...args} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof InlineTip>
|
||||||
|
|
||||||
|
export const Info: Story = {
|
||||||
|
args: {
|
||||||
|
variant: "info",
|
||||||
|
label: "Info",
|
||||||
|
children:
|
||||||
|
"You can always install the storefront at a later point. Medusa is a headless backend, so it operates without a storefront by default. You can connect any storefront to it. The Next.js Starter storefront is a good option to use, but you can also build your own storefront later on.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Warning: Story = {
|
||||||
|
args: {
|
||||||
|
variant: "warning",
|
||||||
|
label: "Warning",
|
||||||
|
children:
|
||||||
|
"If you have multiple storage plugins configured, the last plugin declared in the medusa-config.js file will be used.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Error: Story = {
|
||||||
|
args: {
|
||||||
|
variant: "error",
|
||||||
|
label: "Don'ts",
|
||||||
|
children:
|
||||||
|
"Don’t use data models if you want to store simple key-value pairs related to a Medusa data model. Instead, use the metadata field that modles have, which is an object of custom key-value pairs.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Success: Story = {
|
||||||
|
args: {
|
||||||
|
variant: "success",
|
||||||
|
label: "Do's",
|
||||||
|
children:
|
||||||
|
"Use data models when you want to store data related to your customization in the database.",
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { clx } from "@/utils/clx"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
interface InlineTipProps extends React.ComponentPropsWithoutRef<"div"> {
|
||||||
|
/**
|
||||||
|
* The label to display in the tip.
|
||||||
|
*/
|
||||||
|
label: string
|
||||||
|
/**
|
||||||
|
* The variant of the tip.
|
||||||
|
* @default "info"
|
||||||
|
*/
|
||||||
|
variant?: "info" | "warning" | "error" | "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component is based on the `div` element and supports all of its props.
|
||||||
|
*/
|
||||||
|
export const InlineTip = React.forwardRef<HTMLDivElement, InlineTipProps>(
|
||||||
|
({ variant = "info", label, className, children, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={clx(
|
||||||
|
"bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
role="presentation"
|
||||||
|
className={clx("bg-ui-tag-neutral-icon h-full w-1 rounded-full", {
|
||||||
|
"bg-ui-tag-orange-icon": variant === "warning",
|
||||||
|
"bg-ui-tag-red-icon": variant === "error",
|
||||||
|
"bg-ui-tag-green-icon": variant === "success",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<div className="text-pretty">
|
||||||
|
<strong className="txt-small-plus text-ui-fg-base">{label}:</strong>{" "}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
InlineTip.displayName = "InlineTip"
|
||||||
@@ -22,6 +22,7 @@ export { Hint } from "./components/hint"
|
|||||||
export { I18nProvider } from "./components/i18n-provider"
|
export { I18nProvider } from "./components/i18n-provider"
|
||||||
export { IconBadge } from "./components/icon-badge"
|
export { IconBadge } from "./components/icon-badge"
|
||||||
export { IconButton } from "./components/icon-button"
|
export { IconButton } from "./components/icon-button"
|
||||||
|
export { InlineTip } from "./components/inline-tip"
|
||||||
export { Input } from "./components/input"
|
export { Input } from "./components/input"
|
||||||
export { Kbd } from "./components/kbd"
|
export { Kbd } from "./components/kbd"
|
||||||
export { Label } from "./components/label"
|
export { Label } from "./components/label"
|
||||||
|
|||||||
Reference in New Issue
Block a user