docs: create docs workspace (#5174)
* docs: migrate ui docs to docs universe * created yarn workspace * added eslint and tsconfig configurations * fix eslint configurations * fixed eslint configurations * shared tailwind configurations * added shared ui package * added more shared components * migrating more components * made details components shared * move InlineCode component * moved InputText * moved Loading component * Moved Modal component * moved Select components * Moved Tooltip component * moved Search components * moved ColorMode provider * Moved Notification components and providers * used icons package * use UI colors in api-reference * moved Navbar component * used Navbar and Search in UI docs * added Feedback to UI docs * general enhancements * fix color mode * added copy colors file from ui-preset * added features and enhancements to UI docs * move Sidebar component and provider * general fixes and preparations for deployment * update docusaurus version * adjusted versions * fix output directory * remove rootDirectory property * fix yarn.lock * moved code component * added vale for all docs MD and MDX * fix tests * fix vale error * fix deployment errors * change ignore commands * add output directory * fix docs test * general fixes * content fixes * fix announcement script * added changeset * fix vale checks * added nofilter option * fix vale error
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { Text } from "@medusajs/ui"
|
||||
import { allDocs } from "contentlayer/generated"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { Mdx } from "@/components/mdx-components"
|
||||
import { siteConfig } from "@/config/site"
|
||||
import { Metadata } from "next"
|
||||
|
||||
interface DocPageProps {
|
||||
params: {
|
||||
slug: string[]
|
||||
}
|
||||
}
|
||||
|
||||
async function getDocFromParams({ params }: DocPageProps) {
|
||||
const slug = params.slug?.join("/") || ""
|
||||
|
||||
const doc = allDocs.find((doc) => doc.slugAsParams === slug)
|
||||
|
||||
if (!doc) {
|
||||
null
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: DocPageProps): Promise<Metadata> {
|
||||
const doc = await getDocFromParams({ params })
|
||||
|
||||
if (!doc) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const title = `${doc.title} - ${siteConfig.name}`
|
||||
|
||||
return {
|
||||
title: title,
|
||||
description: doc.description,
|
||||
metadataBase: new URL(
|
||||
process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateStaticParams(): Promise<
|
||||
DocPageProps["params"][]
|
||||
> {
|
||||
return allDocs.map((doc) => ({
|
||||
slug: doc.slugAsParams.split("/"),
|
||||
}))
|
||||
}
|
||||
|
||||
export default async function DocPage({ params }: DocPageProps) {
|
||||
const doc = await getDocFromParams({ params })
|
||||
|
||||
if (!doc) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<h1 className="h1-docs text-medusa-fg-base dark:text-medusa-fg-base-dark mb-2">
|
||||
{doc.title}
|
||||
</h1>
|
||||
<Text
|
||||
className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark mb-6"
|
||||
size="large"
|
||||
>
|
||||
{doc.description}
|
||||
</Text>
|
||||
<div>
|
||||
<Mdx code={doc.body.code} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
@@ -0,0 +1,34 @@
|
||||
import { MetadataRoute } from "next"
|
||||
|
||||
import { docsConfig } from "@/config/docs"
|
||||
import { absoluteUrl } from "@/lib/absolute-url"
|
||||
import { SidebarItemType } from "docs-ui"
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const now = new Date()
|
||||
|
||||
const items: Array<{
|
||||
url: string
|
||||
lastModified?: string | Date
|
||||
}> = []
|
||||
|
||||
function pushItems(newItems: SidebarItemType[]) {
|
||||
newItems.forEach((item) => {
|
||||
if (item.path) {
|
||||
items.push({
|
||||
url: absoluteUrl(item.path),
|
||||
lastModified: now,
|
||||
})
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
pushItems(item.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pushItems(docsConfig.sidebar.top)
|
||||
pushItems(docsConfig.sidebar.bottom)
|
||||
|
||||
return items
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
@@ -0,0 +1,52 @@
|
||||
import type { Metadata } from "next"
|
||||
import { Inter, Roboto_Mono } from "next/font/google"
|
||||
|
||||
import { Navbar } from "@/components/navbar"
|
||||
import { Providers } from "@/providers"
|
||||
|
||||
import { siteConfig } from "@/config/site"
|
||||
import "../styles/globals.css"
|
||||
import { Sidebar } from "docs-ui"
|
||||
|
||||
const inter = Inter({ subsets: ["latin"], variable: "--inter" })
|
||||
const robotoMono = Roboto_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-roboto-mono",
|
||||
})
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: siteConfig.name,
|
||||
description: siteConfig.description,
|
||||
metadataBase: new URL(
|
||||
process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"
|
||||
),
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" className="h-full w-full">
|
||||
<head />
|
||||
<body
|
||||
className={` bg-docs-bg dark:bg-docs-bg-dark h-screen w-full ${inter.variable} ${robotoMono.variable}`}
|
||||
>
|
||||
<Providers>
|
||||
<div className="w-full">
|
||||
<Navbar />
|
||||
<div className="max-w-xxl grid w-full grid-cols-1 px-6 lg:mx-auto lg:grid-cols-[280px_1fr]">
|
||||
<Sidebar expandItems={true} />
|
||||
<div className="relative flex w-full flex-1 items-start justify-center px-4 pb-8 pt-16 md:px-8 lg:px-16 lg:py-[112px]">
|
||||
<main className="h-full w-full lg:max-w-[720px] lg:px-px">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
User-Agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://docs.medusajs.com/ui/assets/sitemap.xml
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<sitemap>
|
||||
<loc>https://docs.medusajs.com/ui/assets/sitemap.xml</loc>
|
||||
</sitemap>
|
||||
<sitemap>
|
||||
<loc>https://docs.medusajs.com/sitemap-docs.xml</loc>
|
||||
</sitemap>
|
||||
</sitemapindex>
|
||||
@@ -0,0 +1,171 @@
|
||||
"use client"
|
||||
|
||||
import { Copy, clx } from "@medusajs/ui"
|
||||
import React from "react"
|
||||
import { useColorMode } from "docs-ui"
|
||||
import { colors as allColors } from "../config/colors"
|
||||
|
||||
type Color = {
|
||||
name: string
|
||||
code: string
|
||||
}
|
||||
|
||||
type ColorsTable = {
|
||||
backgrounds: Color[]
|
||||
foregrounds: Color[]
|
||||
borders: Color[]
|
||||
buttons: Color[]
|
||||
code: Color[]
|
||||
tags: Color[]
|
||||
}
|
||||
|
||||
const PREFIXES: { [k: string]: keyof ColorsTable } = {
|
||||
"--bg": "backgrounds",
|
||||
"--fg": "foregrounds",
|
||||
"--border": "borders",
|
||||
"--button": "buttons",
|
||||
"--code": "code",
|
||||
"--tag": "tags",
|
||||
}
|
||||
|
||||
interface ColorBlockProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
colour: Color
|
||||
}
|
||||
|
||||
const ColorBlock = ({ colour, className, ...props }: ColorBlockProps) => {
|
||||
const [mounted, setMounted] = React.useState(false)
|
||||
|
||||
React.useEffect(() => setMounted(true), [])
|
||||
|
||||
if (!mounted) {
|
||||
return (
|
||||
<div className="flex w-fit flex-row items-center gap-x-2">
|
||||
<div
|
||||
className={
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark h-[48px] w-[48px] rounded-lg border p-1"
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={clx(
|
||||
"bg-medusa-bg-component dark:bg-medusa-bg-component-dark h-full w-full animate-pulse rounded-[4px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col items-start">
|
||||
<div className="bg-medusa-bg-component dark:bg-medusa-bg-component-dark h-[20px] w-[85px] animate-pulse rounded-sm" />
|
||||
<div className="bg-medusa-bg-subtle dark:bg-medusa-bg-subtle-dark h-[20px] w-[120px] animate-pulse rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<div
|
||||
className={
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark h-[48px] w-[48px] rounded-lg border p-1"
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={clx("h-full w-full rounded-[4px]", className)}
|
||||
style={{ background: colour.code }}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col items-start">
|
||||
<p className="txt-compact-xsmall-plus text-medusa-fg-base dark:text-medusa-fg-base-dark text-start">
|
||||
{cssVarToTailwindClass(colour.name)}
|
||||
</p>
|
||||
<p className="txt-compact-xsmall text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark">
|
||||
{colour.code}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const cssVarToTailwindClass = (name: string) => {
|
||||
if (name.startsWith("--bg") || name.startsWith("--button")) {
|
||||
return name.replace("-", "bg-ui")
|
||||
}
|
||||
|
||||
if (name.startsWith("--fg")) {
|
||||
return name.replace("-", "text-ui")
|
||||
}
|
||||
|
||||
if (name.startsWith("--border")) {
|
||||
return name.replace("-", "border-ui")
|
||||
}
|
||||
|
||||
if (name.startsWith("--tag") || name.startsWith("--code")) {
|
||||
if (name.includes("bg")) {
|
||||
return name.replace("-", "bg-ui")
|
||||
}
|
||||
if (name.includes("border")) {
|
||||
return name.replace("-", "border-ui")
|
||||
}
|
||||
if (name.includes("icon") || name.includes("text")) {
|
||||
return name.replace("-", "text-ui")
|
||||
}
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
const Colors = () => {
|
||||
const { colorMode } = useColorMode()
|
||||
|
||||
const colors: ColorsTable = {
|
||||
backgrounds: [],
|
||||
foregrounds: [],
|
||||
borders: [],
|
||||
buttons: [],
|
||||
code: [],
|
||||
tags: [],
|
||||
}
|
||||
|
||||
for (const [tag, value] of Object.entries(allColors[colorMode])) {
|
||||
const prefix = tag.match(/(--[a-zA-Z]+)/gi)
|
||||
if (prefix && Object.keys(PREFIXES).includes(prefix[0])) {
|
||||
if (!tag.includes("gradient")) {
|
||||
colors[PREFIXES[prefix[0]]].push({
|
||||
name: tag,
|
||||
code: value as string,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [, section] of Object.entries(colors)) {
|
||||
section.sort((a, b) => {
|
||||
return a.name < b.name ? -1 : 1
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{Object.entries(colors).map(([section, colors]) => (
|
||||
<div className="mb-16" key={`colours-section-${section}`}>
|
||||
<h2 className="h2-docs mb-4 mt-10 text-medusa-fg-base dark:text-medusa-fg-base-dark">
|
||||
{section.charAt(0).toUpperCase() + section.slice(1)}
|
||||
</h2>
|
||||
<hr className="mb-4" />
|
||||
<div className="xs:grid-cols-2 mb-8 grid grid-cols-1 gap-4 gap-y-10 sm:grid-cols-3 ">
|
||||
{colors.map((colour) => (
|
||||
<Copy
|
||||
content={cssVarToTailwindClass(colour.name)}
|
||||
key={`colours-section-${section}-${colour.name}`}
|
||||
>
|
||||
<ColorBlock colour={colour} />
|
||||
</Copy>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { Colors }
|
||||
@@ -0,0 +1,72 @@
|
||||
"use client"
|
||||
|
||||
import { Spinner } from "@medusajs/icons"
|
||||
import * as React from "react"
|
||||
import { ExampleRegistry } from "../registries/example-registry"
|
||||
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/tabs"
|
||||
import { Feedback } from "./feedback"
|
||||
import clsx from "clsx"
|
||||
import { CodeBlock } from "docs-ui"
|
||||
|
||||
interface ComponentExampleProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
name: string
|
||||
}
|
||||
|
||||
export function ComponentExample({
|
||||
children,
|
||||
name,
|
||||
...props
|
||||
}: ComponentExampleProps) {
|
||||
const Preview = React.useMemo(() => {
|
||||
const Component = ExampleRegistry[name]?.component
|
||||
|
||||
if (!Component) {
|
||||
return <p>Component {name} not found in registry</p>
|
||||
}
|
||||
|
||||
return <Component />
|
||||
}, [name])
|
||||
|
||||
const CodeElement = children as React.ReactElement
|
||||
const Code = CodeElement.props.code
|
||||
|
||||
return (
|
||||
<div className="relative my-4 flex flex-col space-y-2" {...props}>
|
||||
<Tabs defaultValue="preview" className="relative mr-auto w-full">
|
||||
<div className="flex flex-col items-center justify-between pb-3">
|
||||
<TabsList className="">
|
||||
<TabsTrigger value="preview">Preview</TabsTrigger>
|
||||
<TabsTrigger value="code">Code</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="preview" className="relative">
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-docs-bg border-medusa-border-base flex max-h-[400px] min-h-[400px]",
|
||||
"dark:bg-docs-bg-dark dark:border-medusa-border-base-dark",
|
||||
"w-full items-center justify-center overflow-auto rounded-md border px-10 py-5"
|
||||
)}
|
||||
>
|
||||
<React.Suspense
|
||||
fallback={
|
||||
<div className="text-medusa-fg-muted dark:text-medusa-fg-muted-dark flex items-center text-sm">
|
||||
<Spinner className="animate-spin" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{Preview}
|
||||
</React.Suspense>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="code" className="relative ">
|
||||
<CodeBlock source={Code} lang="tsx" />
|
||||
</TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
<Feedback
|
||||
title={`example ${name}`}
|
||||
question="Was this example helpful?"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Spinner } from "@medusajs/icons"
|
||||
import { Container } from "@medusajs/ui"
|
||||
import * as React from "react"
|
||||
|
||||
import { PropRegistry } from "@/registries/prop-registry"
|
||||
import { Feedback } from "./feedback"
|
||||
|
||||
type ComponentPropsProps = {
|
||||
component: string
|
||||
}
|
||||
|
||||
const ComponentProps = ({ component }: ComponentPropsProps) => {
|
||||
const Props = React.useMemo(() => {
|
||||
const Table = PropRegistry[component]?.table
|
||||
|
||||
if (!Table) {
|
||||
return (
|
||||
<div className="flex min-h-[200px] w-full items-center justify-center">
|
||||
<p className="txt-compact-small">
|
||||
No API reference found for{" "}
|
||||
<span className="txt-compact-small-plus">{component}</span>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return <Table />
|
||||
}, [component])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container className="mb-6 mt-8 overflow-hidden p-0">
|
||||
<React.Suspense
|
||||
fallback={
|
||||
<div className="text-medusa-fg-muted dark:text-medusa-fg-muted-dark flex flex-1 items-center justify-center">
|
||||
<Spinner className="animate-spin" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{Props}
|
||||
</React.Suspense>
|
||||
</Container>
|
||||
<Feedback title={`props of ${component}`} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export { ComponentProps }
|
||||
@@ -0,0 +1,34 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Feedback as UiFeedback,
|
||||
FeedbackProps as UiFeedbackProps,
|
||||
formatReportLink,
|
||||
} from "docs-ui"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { absoluteUrl } from "@/lib/absolute-url"
|
||||
import clsx from "clsx"
|
||||
|
||||
export type FeedbackProps = {
|
||||
title: string
|
||||
} & Partial<UiFeedbackProps>
|
||||
|
||||
export const Feedback = ({ title, ...props }: FeedbackProps) => {
|
||||
const pathname = usePathname()
|
||||
|
||||
return (
|
||||
<UiFeedback
|
||||
event="survey"
|
||||
pathName={absoluteUrl(pathname)}
|
||||
reportLink={formatReportLink("UI Docs", title)}
|
||||
extraData={{
|
||||
section: title,
|
||||
}}
|
||||
{...props}
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
props.className
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { BorderedIcon } from "docs-ui"
|
||||
import { basePathUrl } from "@/lib/base-path-url"
|
||||
|
||||
export const FigmaIcon = () => {
|
||||
return <BorderedIcon icon={basePathUrl("/images/figma.png")} />
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import { InformationCircleSolid } from "@medusajs/icons"
|
||||
import { Table, Tooltip } from "@medusajs/ui"
|
||||
|
||||
import { HookData, HookDataMap } from "@/types/hooks"
|
||||
import { EnumType, FunctionType, ObjectType } from "@/types/props"
|
||||
|
||||
const HookTable = ({ props }: { props: HookDataMap }) => {
|
||||
return (
|
||||
<Table>
|
||||
<Table.Header className="border-t-0">
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>Value</Table.HeaderCell>
|
||||
<Table.HeaderCell>Type</Table.HeaderCell>
|
||||
<Table.HeaderCell>Description</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body className="border-b-0 [&_tr:last-child]:border-b-0">
|
||||
{/* eslint-disable-next-line react/prop-types */}
|
||||
{props.map((propData, index) => (
|
||||
<Row key={index} {...propData} />
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
}
|
||||
|
||||
const Row = ({ value, type, description }: HookData) => {
|
||||
const isEnum = (t: unknown): t is EnumType => {
|
||||
return (t as EnumType).type !== undefined && (t as EnumType).type === "enum"
|
||||
}
|
||||
|
||||
const isObject = (t: unknown): t is ObjectType => {
|
||||
return (
|
||||
(t as ObjectType).type !== undefined &&
|
||||
(t as ObjectType).type === "object"
|
||||
)
|
||||
}
|
||||
|
||||
const isFunction = (t: unknown): t is FunctionType => {
|
||||
return (
|
||||
(t as FunctionType).type !== undefined &&
|
||||
(t as FunctionType).type === "function"
|
||||
)
|
||||
}
|
||||
|
||||
const isComplexType = isEnum(type) || isObject(type) || isFunction(type)
|
||||
|
||||
return (
|
||||
<Table.Row className="code-body">
|
||||
<Table.Cell>{value}</Table.Cell>
|
||||
<Table.Cell>
|
||||
{!isComplexType && type.toString()}
|
||||
{isEnum(type) && (
|
||||
<Tooltip
|
||||
content={type.values.map((v) => `"${v}"`).join(" | ")}
|
||||
className="font-mono"
|
||||
>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span>enum</span>
|
||||
<InformationCircleSolid className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isObject(type) && (
|
||||
<Tooltip
|
||||
content={<pre>{type.shape}</pre>}
|
||||
className="font-mono"
|
||||
maxWidth={500}
|
||||
>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span>{type.name}</span>
|
||||
<InformationCircleSolid className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isFunction(type) && (
|
||||
<Tooltip
|
||||
content={<pre>{type.signature}</pre>}
|
||||
className="font-mono"
|
||||
maxWidth={500}
|
||||
>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span>function</span>
|
||||
<InformationCircleSolid className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{description}</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
}
|
||||
|
||||
export { HookTable }
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Spinner } from "@medusajs/icons"
|
||||
import { Container } from "@medusajs/ui"
|
||||
import * as React from "react"
|
||||
|
||||
import { HookRegistry } from "@/registries/hook-registry"
|
||||
import { Feedback } from "./feedback"
|
||||
|
||||
type HookValuesProps = {
|
||||
hook: string
|
||||
}
|
||||
|
||||
const HookValues = ({ hook }: HookValuesProps) => {
|
||||
const Props = React.useMemo(() => {
|
||||
const Table = HookRegistry[hook]?.table
|
||||
|
||||
if (!Table) {
|
||||
return (
|
||||
<div className="flex min-h-[200px] w-full items-center justify-center">
|
||||
<p className="txt-compact-small">
|
||||
No API reference found for{" "}
|
||||
<span className="txt-compact-small-plus">{hook}</span>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return <Table />
|
||||
}, [hook])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container className="mb-6 mt-8 overflow-hidden p-0">
|
||||
<React.Suspense
|
||||
fallback={
|
||||
<div className="text-medusa-fg-muted dark:text-medusa-fg-muted-dark flex flex-1 items-center justify-center">
|
||||
<Spinner className="animate-spin" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{Props}
|
||||
</React.Suspense>
|
||||
</Container>
|
||||
<Feedback title={`props of ${hook}`} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export { HookValues }
|
||||
@@ -0,0 +1,94 @@
|
||||
"use client"
|
||||
|
||||
import * as Icons from "@medusajs/icons"
|
||||
import { Container, Input, Text, Tooltip } from "@medusajs/ui"
|
||||
import clsx from "clsx"
|
||||
import * as React from "react"
|
||||
|
||||
const iconNames = Object.keys(Icons).filter((name) => name !== "default")
|
||||
|
||||
const IconSearch = React.memo(function IconSearch() {
|
||||
const [query, setQuery] = React.useState<string | undefined>("")
|
||||
|
||||
return (
|
||||
<div className="mt-8 flex flex-col gap-y-2">
|
||||
<Input
|
||||
type="search"
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
/>
|
||||
<Container>
|
||||
<SearchResults query={query} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const SearchResults = ({ query = "" }: { query?: string }) => {
|
||||
const cleanQuery = escapeStringRegexp(query.trim().replace(/\s/g, " "))
|
||||
const results = iconNames.filter((name) =>
|
||||
new RegExp(`\\b${cleanQuery}`, "gi").test(name)
|
||||
)
|
||||
|
||||
if (results.length === 0) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"text-medusa-text-muted dark:text-medusa-text-muted-dark",
|
||||
"flex min-h-[300px] items-center justify-center"
|
||||
)}
|
||||
>
|
||||
<Text>
|
||||
No results found for{" "}
|
||||
<Text weight={"plus"} asChild>
|
||||
<span>{query}</span>
|
||||
</Text>
|
||||
</Text>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid w-full grid-cols-4 gap-8 md:grid-cols-6 lg:grid-cols-8">
|
||||
{results.map((name) => {
|
||||
return (
|
||||
<div
|
||||
key={name}
|
||||
className="flex h-full w-full items-center justify-center"
|
||||
>
|
||||
<Tooltip content={name}>
|
||||
<div
|
||||
className={clsx(
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark",
|
||||
"flex h-10 w-10 items-center justify-center rounded-lg border"
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Icon named {name}</span>
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-medusa-bg-component text-medusa-fg-base",
|
||||
"dark:bg-medusa-bg-component-dark dark:text-medusa-fg-base-dark",
|
||||
"flex h-8 w-8 items-center justify-center rounded-[4px]"
|
||||
)}
|
||||
>
|
||||
{React.createElement(Icons[name as keyof typeof Icons])}
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// https://github.com/sindresorhus/escape-string-regexp/blob/main/index.js
|
||||
function escapeStringRegexp(string: unknown) {
|
||||
if (typeof string !== "string") {
|
||||
throw new TypeError("Expected a string")
|
||||
}
|
||||
|
||||
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d")
|
||||
}
|
||||
|
||||
export { IconSearch }
|
||||
@@ -0,0 +1,150 @@
|
||||
"use client"
|
||||
|
||||
import { Text, clx } from "@medusajs/ui"
|
||||
import { useMDXComponent } from "next-contentlayer/hooks"
|
||||
import * as React from "react"
|
||||
|
||||
import { Colors } from "@/components/colors"
|
||||
import { ComponentExample } from "@/components/component-example"
|
||||
import { ComponentProps } from "@/components/component-props"
|
||||
import { HookValues } from "@/components/hook-values"
|
||||
import { IconSearch } from "@/components/icon-search"
|
||||
import { PackageInstall } from "@/components/package-install"
|
||||
import { Feedback } from "@/components/feedback"
|
||||
import { FigmaIcon } from "@/components/figma-icon"
|
||||
import clsx from "clsx"
|
||||
import { NextLink, Card, BorderedIcon, CodeMdx, CodeBlock } from "docs-ui"
|
||||
|
||||
interface MdxProps {
|
||||
code: string
|
||||
}
|
||||
|
||||
const components = {
|
||||
h1: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => {
|
||||
return (
|
||||
<h1
|
||||
className={clx(
|
||||
"h1-docs text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
h2: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => {
|
||||
return (
|
||||
<h2
|
||||
className={clx(
|
||||
"h2-docs mb-4 mt-16 text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
h3: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => {
|
||||
return (
|
||||
<h3
|
||||
className={clx(
|
||||
"h3-docs mb-2 mt-10 text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
p: ({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => {
|
||||
return (
|
||||
<Text
|
||||
className={clx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark mb-docs_1.5",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
a: ({
|
||||
className,
|
||||
href,
|
||||
...props
|
||||
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
|
||||
const isInternal = href && href?.startsWith("/")
|
||||
|
||||
if (isInternal) {
|
||||
return <NextLink className={className} href={href} {...props} />
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
className={clx(
|
||||
"txt-medium text-medusa-fg-interactive hover:text-medusa-fg-interactive-hover",
|
||||
"dark:text-medusa-fg-interactive-dark dark:hover:text-medusa-fg-interactive-hover-dark",
|
||||
className
|
||||
)}
|
||||
href={href}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
code: CodeMdx,
|
||||
ul: ({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLUListElement>) => {
|
||||
return (
|
||||
<ul
|
||||
{...props}
|
||||
className={clsx("list-disc px-docs_1 mb-docs_1.5", className)}
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
)
|
||||
},
|
||||
li: ({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLElement>) => {
|
||||
return (
|
||||
<li
|
||||
className={clx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<Text>{children}</Text>
|
||||
</li>
|
||||
)
|
||||
},
|
||||
hr: ({ className, ...props }: React.HTMLAttributes<HTMLHRElement>) => {
|
||||
return <hr className={clx("mb-4", className)} {...props} />
|
||||
},
|
||||
HookValues,
|
||||
ComponentProps,
|
||||
CodeBlock,
|
||||
ComponentExample,
|
||||
PackageInstall,
|
||||
IconSearch,
|
||||
Feedback,
|
||||
Colors,
|
||||
Card,
|
||||
BorderedIcon,
|
||||
FigmaIcon,
|
||||
}
|
||||
|
||||
const Mdx = ({ code }: MdxProps) => {
|
||||
const Component = useMDXComponent(code)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Component components={components} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { Mdx }
|
||||
@@ -0,0 +1,26 @@
|
||||
"use client"
|
||||
|
||||
import { docsConfig } from "@/config/docs"
|
||||
import { Navbar as UiNavbar, useSidebar } from "docs-ui"
|
||||
import { basePathUrl } from "@/lib/base-path-url"
|
||||
|
||||
const Navbar = () => {
|
||||
const { mobileSidebarOpen, setMobileSidebarOpen } = useSidebar()
|
||||
|
||||
return (
|
||||
<UiNavbar
|
||||
logo={{
|
||||
light: basePathUrl("/images/logo-icon.png"),
|
||||
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||
}}
|
||||
items={docsConfig.mainNav}
|
||||
mobileMenuButton={{
|
||||
setMobileSidebarOpen,
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
className="!z-[99]"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Navbar }
|
||||
@@ -0,0 +1,35 @@
|
||||
import { clx } from "@medusajs/ui"
|
||||
import { CodeTabs } from "docs-ui"
|
||||
|
||||
type PackageInstallProps = {
|
||||
packageName: string
|
||||
devDependency?: boolean
|
||||
version?: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
const PackageInstall = ({
|
||||
packageName,
|
||||
devDependency = false,
|
||||
version,
|
||||
className,
|
||||
}: PackageInstallProps) => {
|
||||
const pkg = `${packageName}${version ? `@${version}` : ""}`
|
||||
|
||||
const yarn = `yarn add ${devDependency ? "-D " : ""}${pkg}`
|
||||
const npm = `npm install ${pkg} ${devDependency ? "--save-dev" : "--save"}`
|
||||
const pnpm = `pnpm add ${devDependency ? "-D " : ""}${pkg}`
|
||||
|
||||
return (
|
||||
<CodeTabs
|
||||
tabs={[
|
||||
{ code: { lang: "bash", source: yarn }, label: "npm", value: "npm" },
|
||||
{ code: { lang: "bash", source: npm }, label: "yarn", value: "yarn" },
|
||||
{ code: { lang: "bash", source: pnpm }, label: "pnpm", value: "pnpm" },
|
||||
]}
|
||||
className={clx("my-4", className)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { PackageInstall }
|
||||
@@ -0,0 +1,129 @@
|
||||
"use client"
|
||||
|
||||
import { InformationCircleSolid } from "@medusajs/icons"
|
||||
import { Table, Tooltip } from "@medusajs/ui"
|
||||
|
||||
import {
|
||||
EnumType,
|
||||
FunctionType,
|
||||
ObjectType,
|
||||
PropData,
|
||||
PropDataMap,
|
||||
} from "@/types/props"
|
||||
|
||||
type PropTableProps = {
|
||||
props: PropDataMap
|
||||
}
|
||||
|
||||
const PropTable = ({ props }: PropTableProps) => {
|
||||
return (
|
||||
<Table>
|
||||
<Table.Header className="border-t-0">
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>Prop</Table.HeaderCell>
|
||||
<Table.HeaderCell>Type</Table.HeaderCell>
|
||||
<Table.HeaderCell className="text-right">Default</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body className="border-b-0 [&_tr:last-child]:border-b-0">
|
||||
{/* eslint-disable-next-line react/prop-types */}
|
||||
{props.map((propData, index) => (
|
||||
<Row key={index} {...propData} />
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
}
|
||||
|
||||
const Row = ({ prop, type, defaultValue }: PropData) => {
|
||||
const isEnum = (t: unknown): t is EnumType => {
|
||||
return (t as EnumType).type !== undefined && (t as EnumType).type === "enum"
|
||||
}
|
||||
|
||||
const isObject = (t: unknown): t is ObjectType => {
|
||||
return (
|
||||
(t as ObjectType).type !== undefined &&
|
||||
(t as ObjectType).type === "object"
|
||||
)
|
||||
}
|
||||
|
||||
const isFunction = (t: unknown): t is FunctionType => {
|
||||
return (
|
||||
(t as FunctionType).type !== undefined &&
|
||||
(t as FunctionType).type === "function"
|
||||
)
|
||||
}
|
||||
|
||||
const defaultValueRenderer = (
|
||||
v: string | number | boolean | null | undefined
|
||||
) => {
|
||||
if (v === undefined) {
|
||||
return "-"
|
||||
}
|
||||
|
||||
if (typeof v === "boolean") {
|
||||
return v ? "true" : "false"
|
||||
}
|
||||
|
||||
if (v === null) {
|
||||
return "null"
|
||||
}
|
||||
|
||||
if (typeof v === "string") {
|
||||
return `"${v}"`
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
const isComplexType = isEnum(type) || isObject(type) || isFunction(type)
|
||||
|
||||
return (
|
||||
<Table.Row className="code-body">
|
||||
<Table.Cell>{prop}</Table.Cell>
|
||||
<Table.Cell>
|
||||
{!isComplexType && type.toString()}
|
||||
{isEnum(type) && (
|
||||
<Tooltip
|
||||
content={type.values.map((v) => `"${v}"`).join(" | ")}
|
||||
className="font-mono"
|
||||
>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span>enum</span>
|
||||
<InformationCircleSolid className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isObject(type) && (
|
||||
<Tooltip
|
||||
content={<pre>{type.shape}</pre>}
|
||||
className="font-mono"
|
||||
maxWidth={500}
|
||||
>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span>{type.name}</span>
|
||||
<InformationCircleSolid className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isFunction(type) && (
|
||||
<Tooltip
|
||||
content={<pre>{type.signature}</pre>}
|
||||
className="font-mono"
|
||||
maxWidth={500}
|
||||
>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span>function</span>
|
||||
<InformationCircleSolid className="text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Table.Cell>
|
||||
<Table.Cell className="text-right">
|
||||
{defaultValueRenderer(defaultValue)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
}
|
||||
|
||||
export { PropTable }
|
||||
@@ -0,0 +1,57 @@
|
||||
"use client"
|
||||
|
||||
import { clx } from "@medusajs/ui"
|
||||
import * as Primitives from "@radix-ui/react-scroll-area"
|
||||
import clsx from "clsx"
|
||||
|
||||
type ScrollbarProps = React.ComponentProps<typeof Primitives.Scrollbar>
|
||||
|
||||
const Scrollbar = (props: ScrollbarProps) => {
|
||||
return (
|
||||
<Primitives.Scrollbar
|
||||
className={clsx(
|
||||
"bg-medusa-bg-base dark:bg-medusa-bg-base-dark flex touch-none select-none p-0.5 transition-colors ease-out",
|
||||
"data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
type ThumbProps = React.ComponentProps<typeof Primitives.Thumb>
|
||||
|
||||
const Thumb = ({ className, ...props }: ThumbProps) => {
|
||||
return (
|
||||
<Primitives.Thumb
|
||||
className={clx(
|
||||
"bg-medusa-bg-component dark:bg-medusa-bg-component-dark relative flex-1 rounded-[10px] before:absolute before:left-1/2 before:top-1/2 before:h-full",
|
||||
"before:min-h-[44px] before:w-full before:min-w-[44px] before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
type ScrollAreaProps = React.ComponentProps<typeof Primitives.Root>
|
||||
|
||||
const ScrollArea = ({ children, className }: ScrollAreaProps) => {
|
||||
return (
|
||||
<Primitives.Root
|
||||
className={clx("h-full w-full overflow-hidden", className)}
|
||||
>
|
||||
<Primitives.Viewport className="h-full w-full">
|
||||
{children}
|
||||
</Primitives.Viewport>
|
||||
<Scrollbar orientation="vertical">
|
||||
<Thumb />
|
||||
</Scrollbar>
|
||||
<Scrollbar orientation="horizontal">
|
||||
<Thumb />
|
||||
</Scrollbar>
|
||||
<Primitives.Corner />
|
||||
</Primitives.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export { ScrollArea }
|
||||
@@ -0,0 +1,59 @@
|
||||
"use client"
|
||||
|
||||
import { clx } from "@medusajs/ui"
|
||||
import * as Primitives from "@radix-ui/react-tabs"
|
||||
import * as React from "react"
|
||||
|
||||
const Tabs = Primitives.Root
|
||||
|
||||
const TabsList = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.List>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.List>
|
||||
// eslint-disable-next-line react/prop-types
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Primitives.List
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"inline-flex h-10 w-full items-end justify-start rounded-none bg-transparent p-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsList.displayName = "TabsList"
|
||||
|
||||
const TabsTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.Trigger>
|
||||
// eslint-disable-next-line react/prop-types
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Primitives.Trigger
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"text-medusa-fg-subtle txt-compact-small-plus rounded-full px-3 py-1.5 transition-all",
|
||||
"data-[state=active]:shadow-card-rest dark:data-[state=active]:shadow-card-rest-dark data-[state=active]:text-medusa-fg-base",
|
||||
"dark:text-medusa-fg-subtle-dark dark:data-[state=active]:text-medusa-fg-base-dark",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsTrigger.displayName = "TabsTrigger"
|
||||
|
||||
const TabsContent = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.Content>
|
||||
// eslint-disable-next-line react/prop-types
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Primitives.Content
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"w-full rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 data-[state=active]:mt-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsContent.displayName = "TabsContent"
|
||||
|
||||
export { Tabs, TabsContent, TabsList, TabsTrigger }
|
||||
@@ -0,0 +1,204 @@
|
||||
export const colors = {
|
||||
dark: {
|
||||
"--bg-highlight-hover": "rgba(30, 58, 138, 1)",
|
||||
"--border-danger": "rgba(190, 18, 60, 1)",
|
||||
"--border-interactive": "rgba(96, 165, 250, 1)",
|
||||
"--bg-highlight": "rgba(23, 37, 84, 1)",
|
||||
"--fg-interactive-hover": "rgba(59, 130, 246, 1)",
|
||||
"--fg-error": "rgba(251, 113, 133, 1)",
|
||||
"--bg-interactive": "rgba(96, 165, 250, 1)",
|
||||
"--border-error": "rgba(244, 63, 94, 1)",
|
||||
"--button-danger": "rgba(159, 18, 57, 1)",
|
||||
"--button-danger-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-danger-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--bg-overlay": "rgba(10, 10, 10, 0.7)",
|
||||
"--fg-interactive": "rgba(96, 165, 250, 1)",
|
||||
"--fg-on-inverted": "rgba(10, 10, 10, 1)",
|
||||
"--button-danger-pressed": "rgba(159, 18, 57, 1)",
|
||||
"--button-danger-pressed-gradient-from": "rgba(255, 255, 255, 0)",
|
||||
"--button-danger-pressed-gradient-to": "rgba(255, 255, 255, 1)",
|
||||
"--button-neutral-pressed": "rgba(38, 38, 38, 1)",
|
||||
"--button-neutral-pressed-gradient-from": "rgba(255, 255, 255, 0)",
|
||||
"--button-neutral-pressed-gradient-to": "rgba(255, 255, 255, 1)",
|
||||
"--tag-red-border": "rgba(136, 19, 55, 1)",
|
||||
"--tag-red-bg": "rgba(76, 5, 25, 1)",
|
||||
"--button-transparent-hover": "rgba(38, 38, 38, 1)",
|
||||
"--tag-blue-text": "rgba(96, 165, 250, 1)",
|
||||
"--button-inverted": "rgba(238, 238, 238, 1)",
|
||||
"--button-inverted-gradient-from": "rgba(0, 0, 0, 0)",
|
||||
"--button-inverted-gradient-to": "rgba(0, 0, 0, 1)",
|
||||
"--tag-orange-text": "rgba(251, 191, 36, 1)",
|
||||
"--tag-green-text": "rgba(52, 211, 153, 1)",
|
||||
"--button-transparent": "rgba(0, 0, 0, 0)",
|
||||
"--button-transparent-pressed": "rgba(48, 48, 48, 1)",
|
||||
"--tag-neutral-bg": "rgba(48, 48, 48, 1)",
|
||||
"--code-text-subtle": "rgba(110, 110, 110, 1)",
|
||||
"--code-bg-base": "rgba(30, 30, 30, 1)",
|
||||
"--tag-orange-border": "rgba(120, 53, 15, 1)",
|
||||
"--border-base": "rgba(48, 48, 48, 1)",
|
||||
"--bg-component": "rgba(38, 38, 38, 1)",
|
||||
"--code-text-base": "rgba(238, 238, 238, 1)",
|
||||
"--tag-green-border": "rgba(6, 78, 59, 1)",
|
||||
"--bg-base": "rgba(23, 23, 23, 1)",
|
||||
"--fg-on-color": "rgba(238, 238, 238, 1)",
|
||||
"--tag-red-text": "rgba(251, 113, 133, 1)",
|
||||
"--tag-green-bg-hover": "rgba(6, 78, 59, 1)",
|
||||
"--tag-purple-bg-hover": "rgba(76, 29, 149, 1)",
|
||||
"--tag-red-bg-hover": "rgba(136, 19, 55, 1)",
|
||||
"--border-strong": "rgba(55, 55, 55, 1)",
|
||||
"--fg-subtle": "rgba(163, 163, 163, 1)",
|
||||
"--fg-base": "rgba(238, 238, 238, 1)",
|
||||
"--code-border": "rgba(48, 48, 48, 1)",
|
||||
"--border-transparent": "rgba(238, 238, 238, 0)",
|
||||
"--tag-orange-icon": "rgba(245, 158, 11, 1)",
|
||||
"--tag-purple-bg": "rgba(46, 16, 100, 1)",
|
||||
"--bg-base-hover": "rgba(38, 38, 38, 1)",
|
||||
"--bg-subtle-hover": "rgba(23, 23, 23, 1)",
|
||||
"--tag-blue-bg": "rgba(23, 37, 84, 1)",
|
||||
"--fg-disabled": "rgba(63, 63, 63, 1)",
|
||||
"--bg-subtle": "rgba(10, 10, 10, 1)",
|
||||
"--tag-green-bg": "rgba(2, 44, 34, 1)",
|
||||
"--bg-subtle-pressed": "rgba(38, 38, 38, 1)",
|
||||
"--tag-blue-border": "rgba(30, 58, 138, 1)",
|
||||
"--fg-muted": "rgba(110, 110, 110, 1)",
|
||||
"--tag-purple-border": "rgba(76, 29, 149, 1)",
|
||||
"--tag-blue-bg-hover": "rgba(30, 42, 138, 1)",
|
||||
"--code-bg-header": "rgba(23, 23, 23, 1)",
|
||||
"--border-loud": "rgba(238, 238, 238, 1)",
|
||||
"--bg-base-pressed": "rgba(48, 48, 48, 1)",
|
||||
"--tag-orange-bg": "rgba(69, 26, 3, 1)",
|
||||
"--bg-disabled": "rgba(38, 38, 38, 1)",
|
||||
"--tag-orange-bg-hover": "rgba(120, 53, 15, 1)",
|
||||
"--code-icon": "rgba(74, 74, 74, 1)",
|
||||
"--bg-field-hover": "rgba(48, 48, 48, 1)",
|
||||
"--bg-field": "rgba(38, 38, 38, 1)",
|
||||
"--button-neutral": "rgba(38, 38, 38, 1)",
|
||||
"--button-neutral-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-neutral-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--button-inverted-pressed": "rgba(238, 238, 238, 1)",
|
||||
"--button-inverted-pressed-gradient-from": "rgba(0, 0, 0, 1)",
|
||||
"--button-inverted-pressed-gradient-to": "rgba(0, 0, 0, 0)",
|
||||
"--button-neutral-hover": "rgba(38, 38, 38, 1)",
|
||||
"--button-neutral-hover-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-neutral-hover-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--button-inverted-hover": "rgba(238, 238, 238, 1)",
|
||||
"--button-inverted-hover-gradient-from": "rgba(0, 0, 0, 0)",
|
||||
"--button-inverted-hover-gradient-to": "rgba(0, 0, 0, 1)",
|
||||
"--button-danger-hover": "rgba(159, 18, 57, 1)",
|
||||
"--button-danger-hover-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-danger-hover-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--bg-switch-off-hover": "rgba(74, 74, 74, 1)",
|
||||
"--bg-switch-off": "rgba(55, 55, 55, 1)",
|
||||
"--tag-neutral-bg-hover": "rgba(63, 63, 63, 1)",
|
||||
"--tag-neutral-border": "rgba(63, 63, 63, 1)",
|
||||
"--tag-blue-icon": "rgba(59, 130, 246, 1)",
|
||||
"--tag-red-icon": "rgba(244, 63, 94, 1)",
|
||||
"--tag-neutral-icon": "rgba(129, 129, 129, 1)",
|
||||
"--tag-purple-icon": "rgba(139, 92, 246, 1)",
|
||||
"--tag-purple-text": "rgba(167, 139, 250, 1)",
|
||||
"--tag-neutral-text": "rgba(163, 163, 163, 1)",
|
||||
"--tag-green-icon": "rgba(16, 185, 129, 1)",
|
||||
},
|
||||
light: {
|
||||
"--code-text-base": "rgba(249, 250, 251, 1)",
|
||||
"--tag-green-bg": "rgba(209, 250, 229, 1)",
|
||||
"--border-strong": "rgba(209, 213, 219, 1)",
|
||||
"--border-interactive": "rgba(59, 130, 246, 1)",
|
||||
"--bg-highlight": "rgba(239, 246, 255, 1)",
|
||||
"--bg-base-hover": "rgba(249, 250, 251, 1)",
|
||||
"--tag-neutral-bg": "rgba(243, 244, 246, 1)",
|
||||
"--tag-red-bg": "rgba(255, 228, 230, 1)",
|
||||
"--tag-orange-bg": "rgba(254, 244, 199, 1)",
|
||||
"--bg-base": "rgba(255, 255, 255, 1)",
|
||||
"--border-base": "rgba(229, 231, 235, 1)",
|
||||
"--tag-green-icon": "rgba(5, 150, 105, 1)",
|
||||
"--tag-purple-bg-hover": "rgba(221, 214, 254, 1)",
|
||||
"--tag-blue-border": "rgba(191, 219, 254, 1)",
|
||||
"--tag-orange-icon": "rgba(217, 119, 6, 1)",
|
||||
"--tag-purple-bg": "rgba(237, 233, 254, 1)",
|
||||
"--bg-subtle": "rgba(249, 250, 251, 1)",
|
||||
"--tag-purple-text": "rgba(109, 40, 217, 1)",
|
||||
"--tag-blue-bg": "rgba(219, 234, 254, 1)",
|
||||
"--tag-blue-icon": "rgba(37, 99, 235, 1)",
|
||||
"--bg-component": "rgba(241, 243, 245, 1)",
|
||||
"--border-error": "rgba(225, 29, 72, 1)",
|
||||
"--bg-field-hover": "rgba(243, 244, 246, 1)",
|
||||
"--bg-field": "rgba(249, 250, 251, 1)",
|
||||
"--border-loud": "rgba(3, 7, 18, 1)",
|
||||
"--fg-on-inverted": "rgba(255, 255, 255, 1)",
|
||||
"--fg-on-color": "rgba(255, 255, 255, 1)",
|
||||
"--button-danger-pressed": "rgba(225, 29, 72, 1)",
|
||||
"--button-danger-pressed-gradient-from": "rgba(255, 255, 255, 0)",
|
||||
"--button-danger-pressed-gradient-to": "rgba(255, 255, 255, 1)",
|
||||
"--button-transparent": "rgba(255, 255, 255, 0)",
|
||||
"--bg-interactive": "rgba(59, 130, 246, 1)",
|
||||
"--fg-interactive-hover": "rgba(37, 99, 235, 1)",
|
||||
"--fg-interactive": "rgba(59, 130, 246, 1)",
|
||||
"--fg-error": "rgba(225, 29, 72, 1)",
|
||||
"--border-danger": "rgba(190, 18, 60, 1)",
|
||||
"--border-transparent": "rgba(3, 7, 18, 0)",
|
||||
"--bg-overlay": "rgba(3, 7, 18, 0.4)",
|
||||
"--fg-base": "rgba(3, 7, 18, 1)",
|
||||
"--fg-disabled": "rgba(209, 213, 219, 1)",
|
||||
"--bg-subtle-pressed": "rgba(229, 231, 235, 1)",
|
||||
"--fg-subtle": "rgba(75, 85, 99, 1)",
|
||||
"--fg-muted": "rgba(156, 163, 175, 1)",
|
||||
"--bg-base-pressed": "rgba(243, 244, 246, 1)",
|
||||
"--bg-subtle-hover": "rgba(243, 244, 246, 1)",
|
||||
"--tag-neutral-border": "rgba(229, 231, 235, 1)",
|
||||
"--tag-green-bg-hover": "rgba(167, 243, 208, 1)",
|
||||
"--tag-blue-bg-hover": "rgba(191, 219, 254, 1)",
|
||||
"--tag-red-icon": "rgba(225, 29, 72, 1)",
|
||||
"--tag-neutral-text": "rgba(75, 85, 99, 1)",
|
||||
"--tag-red-bg-hover": "rgba(254, 205, 211, 1)",
|
||||
"--tag-red-text": "rgba(190, 18, 60, 1)",
|
||||
"--tag-purple-icon": "rgba(124, 58, 237, 1)",
|
||||
"--tag-blue-text": "rgba(29, 78, 216, 1)",
|
||||
"--tag-orange-bg-hover": "rgba(253, 230, 138, 1)",
|
||||
"--tag-neutral-bg-hover": "rgba(229, 231, 235, 1)",
|
||||
"--tag-purple-border": "rgba(221, 214, 254, 1)",
|
||||
"--tag-orange-text": "rgba(180, 83, 9, 1)",
|
||||
"--tag-neutral-icon": "rgba(107, 114, 128, 1)",
|
||||
"--tag-orange-border": "rgba(253, 230, 138, 1)",
|
||||
"--tag-red-border": "rgba(254, 205, 211, 1)",
|
||||
"--tag-green-border": "rgba(167, 243, 208, 1)",
|
||||
"--tag-green-text": "rgba(4, 120, 87, 1)",
|
||||
"--bg-disabled": "rgba(243, 244, 246, 1)",
|
||||
"--button-transparent-hover": "rgba(249, 250, 251, 1)",
|
||||
"--button-transparent-pressed": "rgba(243, 244, 246, 1)",
|
||||
"--bg-switch-off-hover": "rgba(229, 231, 235, 1)",
|
||||
"--bg-switch-off-hover-gradient-from": "rgba(3, 7, 18, 0)",
|
||||
"--bg-switch-off-hover-gradient-to": "rgba(3, 7, 18, 1)",
|
||||
"--bg-highlight-hover": "rgba(219, 234, 254, 1)",
|
||||
"--code-bg-base": "rgba(17, 24, 39, 1)",
|
||||
"--code-bg-header": "rgba(31, 41, 55, 1)",
|
||||
"--code-text-subtle": "rgba(156, 163, 175, 1)",
|
||||
"--code-border": "rgba(55, 65, 81, 1)",
|
||||
"--code-icon": "rgba(107, 114, 128, 1)",
|
||||
"--button-inverted": "rgba(10, 10, 10, 1)",
|
||||
"--button-inverted-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-inverted-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--button-neutral-pressed": "rgba(255, 255, 255, 1)",
|
||||
"--button-neutral-pressed-gradient-from": "rgba(10, 10, 10, 1)",
|
||||
"--button-neutral-pressed-gradient-to": "rgba(10, 10, 10, 0)",
|
||||
"--button-inverted-pressed": "rgba(10, 10, 10, 1)",
|
||||
"--button-inverted-pressed-gradient-from": "rgba(255, 255, 255, 0)",
|
||||
"--button-inverted-pressed-gradient-to": "rgba(255, 255, 255, 1)",
|
||||
"--button-inverted-hover": "rgba(10, 10, 10, 1)",
|
||||
"--button-inverted-hover-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-inverted-hover-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--button-neutral": "rgba(255, 255, 255, 1)",
|
||||
"--button-neutral-gradient-from": "rgba(10, 10, 10, 0)",
|
||||
"--button-neutral-gradient-to": "rgba(10, 10, 10, 1)",
|
||||
"--button-neutral-hover": "rgba(255, 255, 255, 1)",
|
||||
"--button-neutral-hover-gradient-from": "rgba(10, 10, 10, 0)",
|
||||
"--button-neutral-hover-gradient-to": "rgba(10, 10, 10, 1)",
|
||||
"--button-danger": "rgba(225, 29, 72, 1)",
|
||||
"--button-danger-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-danger-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--button-danger-hover": "rgba(225, 29, 72, 1)",
|
||||
"--button-danger-hover-gradient-from": "rgba(255, 255, 255, 1)",
|
||||
"--button-danger-hover-gradient-to": "rgba(255, 255, 255, 0)",
|
||||
"--bg-switch-off": "rgba(229, 231, 235, 1)",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
import { NavbarLinkProps, SidebarSectionItemsType } from "docs-ui"
|
||||
|
||||
type DocsConfig = {
|
||||
mainNav: NavbarLinkProps[]
|
||||
sidebar: SidebarSectionItemsType
|
||||
}
|
||||
|
||||
export const docsConfig: DocsConfig = {
|
||||
mainNav: [
|
||||
{
|
||||
label: "Docs",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `${process.env.NEXT_PUBLIC_DOCS_URL}`,
|
||||
},
|
||||
{
|
||||
label: "User Guide",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `${process.env.NEXT_PUBLIC_DOCS_URL}/user-guide`,
|
||||
},
|
||||
{
|
||||
label: "Store API",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `${process.env.NEXT_PUBLIC_DOCS_URL}/api/store`,
|
||||
},
|
||||
{
|
||||
label: "Admin API",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `${process.env.NEXT_PUBLIC_DOCS_URL}/api/admin`,
|
||||
},
|
||||
{
|
||||
label: "UI",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `${process.env.NEXT_PUBLIC_DOCS_URL}/ui`,
|
||||
activeValuePattern: new RegExp("/ui"),
|
||||
},
|
||||
],
|
||||
sidebar: {
|
||||
top: [
|
||||
{
|
||||
title: "Getting Started",
|
||||
children: [
|
||||
{
|
||||
title: "Introduction",
|
||||
path: "/",
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Installation",
|
||||
children: [
|
||||
{
|
||||
title: "Medusa Admin Extension",
|
||||
path: "/installation/medusa-admin-extension",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Standalone Project",
|
||||
path: "/installation/standalone-project",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
bottom: [
|
||||
{
|
||||
title: "Colors",
|
||||
children: [
|
||||
{
|
||||
title: "Overview",
|
||||
path: "/colors/overview",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Icons",
|
||||
children: [
|
||||
{
|
||||
title: "Overview",
|
||||
path: "/icons/overview",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Components",
|
||||
children: [
|
||||
{
|
||||
title: "Avatar",
|
||||
path: "/components/avatar",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Badge",
|
||||
path: "/components/badge",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Button",
|
||||
path: "/components/button",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Calendar",
|
||||
path: "/components/calendar",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Checkbox",
|
||||
path: "/components/checkbox",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Code Block",
|
||||
path: "/components/code-block",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Command",
|
||||
path: "/components/command",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Container",
|
||||
path: "/components/container",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Copy",
|
||||
path: "/components/copy",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Date Picker",
|
||||
path: "/components/date-picker",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Drawer",
|
||||
path: "/components/drawer",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Dropdown Menu",
|
||||
path: "/components/dropdown-menu",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Focus Modal",
|
||||
path: "/components/focus-modal",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Heading",
|
||||
path: "/components/heading",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Input",
|
||||
path: "/components/input",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Kbd",
|
||||
path: "/components/kbd",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Label",
|
||||
path: "/components/label",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Prompt",
|
||||
path: "/components/prompt",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Radio Group",
|
||||
path: "/components/radio-group",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Select",
|
||||
path: "/components/select",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Switch",
|
||||
path: "/components/switch",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Table",
|
||||
path: "/components/table",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Text",
|
||||
path: "/components/text",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Textarea",
|
||||
path: "/components/textarea",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Toast",
|
||||
path: "/components/toast",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Tooltip",
|
||||
path: "/components/tooltip",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Hooks",
|
||||
children: [
|
||||
{
|
||||
title: "usePrompt",
|
||||
path: "/hooks/use-prompt",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "useToast",
|
||||
path: "/hooks/use-toast",
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "useToggleState",
|
||||
path: "/hooks/use-toggle-state",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Utils",
|
||||
children: [
|
||||
{
|
||||
title: "clx",
|
||||
path: "/utils/clx",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
mobile: [
|
||||
{
|
||||
title: "Docs",
|
||||
path: `${process.env.NEXT_PUBLIC_DOCS_URL}`,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "User Guide",
|
||||
path: `${process.env.NEXT_PUBLIC_DOCS_URL}/user-guide`,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Store API",
|
||||
path: `${process.env.NEXT_PUBLIC_DOCS_URL}/api/store`,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Admin API",
|
||||
path: `${process.env.NEXT_PUBLIC_DOCS_URL}/api/admin`,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "UI",
|
||||
path: `${process.env.NEXT_PUBLIC_DOCS_URL}/ui`,
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
type SiteConfig = {
|
||||
name: string
|
||||
url: string
|
||||
ogImage: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export const siteConfig: SiteConfig = {
|
||||
name: "Medusa UI",
|
||||
url: `${process.env.NEXT_PUBLIC_DOCS_URL}/ui`,
|
||||
ogImage: `${process.env.NEXT_PUBLIC_DOCS_URL}/ui/images/medusa-og.png`,
|
||||
description: "Primitives for building Medusa applications.",
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: "Colors"
|
||||
description: "The color system used in Medusa UI"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
---
|
||||
|
||||
These are most of the colors used in Medusa UI and across Medusa Admin. Use the theme
|
||||
switcher in the navbar to see how the colours react in light/dark themes.
|
||||
|
||||
You can click on any of the blocks to copy the Tailwind class name.
|
||||
|
||||
<Colors />
|
||||
|
||||
<Feedback title={"Colors"} />
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "Avatar"
|
||||
description: "An image element with a fallback for representing the user."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="avatar-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Avatar } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Avatar
|
||||
src="https://avatars.githubusercontent.com/u/10656202?v=4"
|
||||
fallback="M"
|
||||
/>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Avatar](https://www.radix-ui.com/primitives/docs/components/avatar) primitive.
|
||||
|
||||
<ComponentProps component="avatar" />
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Badge"
|
||||
description: "Displays a badge"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="badge-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Badge } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Badge>Badge</Badge>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="badge" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Grey
|
||||
|
||||
<ComponentExample name="badge-grey" />
|
||||
|
||||
### Red
|
||||
|
||||
<ComponentExample name="badge-red" />
|
||||
|
||||
### Green
|
||||
|
||||
<ComponentExample name="badge-green" />
|
||||
|
||||
### Blue
|
||||
|
||||
<ComponentExample name="badge-blue" />
|
||||
|
||||
### Orange
|
||||
|
||||
<ComponentExample name="badge-orange" />
|
||||
|
||||
### Purple
|
||||
|
||||
<ComponentExample name="badge-purple" />
|
||||
|
||||
### Small
|
||||
|
||||
<ComponentExample name="badge-small" />
|
||||
|
||||
### Large
|
||||
|
||||
<ComponentExample name="badge-large" />
|
||||
|
||||
### Rounded
|
||||
|
||||
<ComponentExample name="badge-rounded" />
|
||||
|
||||
### Icon
|
||||
|
||||
<ComponentExample name="badge-icon" />
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "Button"
|
||||
description: "Displays a button component"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="button-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Button } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Button>Button</Button>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `button` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="button" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Primary
|
||||
|
||||
<ComponentExample name="button-primary" />
|
||||
|
||||
### Secondary
|
||||
|
||||
<ComponentExample name="button-secondary" />
|
||||
|
||||
### Transparent
|
||||
|
||||
<ComponentExample name="button-transparent" />
|
||||
|
||||
### Danger
|
||||
|
||||
<ComponentExample name="button-danger" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentExample name="button-disabled" />
|
||||
|
||||
### With Icon
|
||||
|
||||
<ComponentExample name="button-with-icon" />
|
||||
|
||||
### Icon Only
|
||||
|
||||
<ComponentExample name="button-icon-only" />
|
||||
|
||||
### Loading
|
||||
|
||||
<ComponentExample name="button-loading" />
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "Calendar"
|
||||
description: "A calendar component that allows picking of a single date or a range of dates."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="calendar-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Calendar } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Calendar />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [react-date-picker](https://www.npmjs.com/package/react-date-picker) package.
|
||||
|
||||
<ComponentProps component="calendar" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Single Date
|
||||
|
||||
<ComponentExample name="calendar-single" />
|
||||
|
||||
### Range
|
||||
|
||||
<ComponentExample name="calendar-range" />
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "Checkbox"
|
||||
description: "A control that allows the user to toggle between checked and not checked."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="checkbox-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Checkbox } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Checkbox />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Checkbox](https://www.radix-ui.com/primitives/docs/components/checkbox) primitive.
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Default
|
||||
|
||||
<ComponentExample name="checkbox-default" />
|
||||
|
||||
### Checked
|
||||
|
||||
<ComponentExample name="checkbox-checked" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentExample name="checkbox-disabled" />
|
||||
|
||||
### Indeterminate
|
||||
|
||||
<ComponentExample name="checkbox-indeterminate" />
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: "Code Block"
|
||||
description: "Allows you to render highlighted code snippets"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="code-block-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { CodeBlock } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<CodeBlock
|
||||
snippets={[
|
||||
{
|
||||
language: "tsx",
|
||||
label: "Label",
|
||||
code: "import { useProduct } from \"medusa-react\"",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<CodeBlock.Header />
|
||||
<CodeBlock.Body />
|
||||
</CodeBlock>
|
||||
```
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
### CodeBlock
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="code-block" />
|
||||
|
||||
### CodeBlock.Header
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="code-block-header" />
|
||||
|
||||
### CodeBlock.Header.Meta
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
### CodeBlock.Body
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="code-block-body" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Single snippet
|
||||
|
||||
If you want to only show a code sample for one language or API, you can choose to hide the snippet labels:
|
||||
|
||||
<ComponentExample name="code-block-single" />
|
||||
|
||||
### No Header
|
||||
|
||||
You could also choose to omit the header entirely:
|
||||
|
||||
<ComponentExample name="code-block-no-header" />
|
||||
|
||||
### No Line Numbers
|
||||
|
||||
<ComponentExample name="code-block-no-lines" />
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: "Command"
|
||||
description: "Renders an unhighlighted code block, useful for one-liners or endpoints"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="command-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Command } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Command>
|
||||
<code>yarn add @medusajs/ui</code>
|
||||
</Command>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: "Container"
|
||||
description: "A box used to organise content."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="container-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Container } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Container>Container</Container>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### In a layout
|
||||
|
||||
<ComponentExample name="container-layout" />
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: "Copy"
|
||||
description: "Displays a tooltipped button that puts string contents into the user's clipboard."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="copy-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Copy } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Copy content="yarn add @medusajs/ui" />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `button` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="copy" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### With custom display
|
||||
|
||||
<ComponentExample name="copy-custom-display" />
|
||||
|
||||
### As child
|
||||
|
||||
Using the `asChild` prop, you can render the `<Copy/>` as it's child. This is useful if you want to render a custom button, to prevent rendering a button inside a button.
|
||||
|
||||
<ComponentExample name="copy-as-child" />
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: "Date Picker"
|
||||
description: "A date picker component with range and presets."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="date-picker-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { DatePicker } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<DatePicker />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Calendar](/components/calendar) component and [Radix UI Popover](https://www.radix-ui.com/primitives/docs/components/popover).
|
||||
|
||||
<ComponentProps component="date-picker" />
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Single
|
||||
|
||||
<ComponentExample name="date-picker-single" />
|
||||
|
||||
### Single with time
|
||||
|
||||
<ComponentExample name="date-picker-single-time" />
|
||||
|
||||
### Single with presets
|
||||
|
||||
<ComponentExample name="date-picker-single-presets" />
|
||||
|
||||
### Single with presets and time
|
||||
|
||||
<ComponentExample name="date-picker-single-presets-time" />
|
||||
|
||||
### Range
|
||||
|
||||
<ComponentExample name="date-picker-range" />
|
||||
|
||||
### Range with time
|
||||
|
||||
<ComponentExample name="date-picker-range-time" />
|
||||
|
||||
### Range with presets
|
||||
|
||||
<ComponentExample name="date-picker-range-presets" />
|
||||
|
||||
### Range with presets and time
|
||||
|
||||
<ComponentExample name="date-picker-range-presets-time" />
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: "Drawer"
|
||||
description: "A triggerable drawer that overlaps whatever page it's on."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="drawer-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Drawer } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Drawer>
|
||||
<Drawer.Trigger>Trigger</Drawer.Trigger>
|
||||
<Drawer.Content>
|
||||
<Drawer.Header>
|
||||
<Drawer.Title>Drawer Title</Drawer.Title>
|
||||
</Drawer.Header>
|
||||
<Drawer.Body>Body</Drawer.Body>
|
||||
<Drawer.Footer>Footer</Drawer.Footer>
|
||||
</Drawer.Content>
|
||||
</Drawer>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Dialog](https://www.radix-ui.com/primitives/docs/components/dialog) primitives.
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: "Dropdown Menu"
|
||||
description: "Displays a menu to the user—such as a set of actions or functions—triggered by a button."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="dropdown-menu-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { DropdownMenu } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger>Trigger</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content>
|
||||
<DropdownMenu.Item>Edit</DropdownMenu.Item>
|
||||
<DropdownMenu.Item>Add</DropdownMenu.Item>
|
||||
<DropdownMenu.Item>Delete</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Dropdown Menu](https://www.radix-ui.com/primitives/docs/components/dropdown-menu) primitive.
|
||||
|
||||
### DropdownMenu.Shortcut
|
||||
|
||||
This component is based on the `span` element and supports all props of this element.
|
||||
|
||||
### DropdownMenu.Hint
|
||||
|
||||
This component is based on the `span` element and supports all props of this element.
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Sorting
|
||||
|
||||
Implementing collection sorting choices using a Dropdown Menu:
|
||||
|
||||
<ComponentExample name="dropdown-menu-sorting" />
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "Focus Modal"
|
||||
description: "A modal component that spans the whole screen"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="focus-modal-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { FocusModal } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<FocusModal>
|
||||
<FocusModal.Trigger>Trigger</FocusModal.Trigger>
|
||||
<FocusModal.Content>
|
||||
<FocusModal.Header>Title</FocusModal.Header>
|
||||
<FocusModal.Body>Content</FocusModal.Body>
|
||||
</FocusModal.Content>
|
||||
</FocusModal>
|
||||
```
|
||||
|
||||
### API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Dialog](https://www.radix-ui.com/primitives/docs/components/dialog) primitives.
|
||||
|
||||
### FocusModal.Header
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
### FocusModal.Body
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: "Heading"
|
||||
description: "Text component used for page titles and other headers"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="heading-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Heading } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Heading>A Title</Heading>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `heading` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="heading" />
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "Input"
|
||||
description: "Renders a form input field"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="input-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Input } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Input placeholder="Placeholder" id="input-id" />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `input` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="input" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Password
|
||||
|
||||
<ComponentExample name="input-password" />
|
||||
|
||||
### Search
|
||||
|
||||
<ComponentExample name="input-search" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentExample name="input-disabled" />
|
||||
|
||||
### Small
|
||||
|
||||
<ComponentExample name="input-small" />
|
||||
|
||||
### Error state
|
||||
|
||||
You can leverage the native `aria-invalid` property to show an error state on your input:
|
||||
|
||||
<ComponentExample name="input-error" />
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: "Kbd"
|
||||
description: "Renders a badge-styled kbd element"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="kbd-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Kbd } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Kbd>Ctrl + Shift + A</Kbd>
|
||||
```
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `kbd` element and supports all props of this element.
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: "Label"
|
||||
description: "Renders an accessible label associated with controls."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="label-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Label } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Label>Label</Label>
|
||||
```
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Label](https://www.radix-ui.com/primitives/docs/components/label) primitive.
|
||||
|
||||
<ComponentProps component="label" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Base Regular
|
||||
|
||||
<ComponentExample name="label-base-regular" />
|
||||
|
||||
### Base Plus
|
||||
|
||||
<ComponentExample name="label-base-plus" />
|
||||
|
||||
### Large Regular
|
||||
|
||||
<ComponentExample name="label-large-regular" />
|
||||
|
||||
### Large Plus
|
||||
|
||||
<ComponentExample name="label-large-plus" />
|
||||
|
||||
### Small Regular
|
||||
|
||||
<ComponentExample name="label-small-regular" />
|
||||
|
||||
### Small Plus
|
||||
|
||||
<ComponentExample name="label-small-plus" />
|
||||
|
||||
### X-Small Regular
|
||||
|
||||
<ComponentExample name="label-xsmall-regular" />
|
||||
|
||||
### X-Small Plus
|
||||
|
||||
<ComponentExample name="label-xsmall-plus" />
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "Prompt"
|
||||
description: "Displays a dialog triggered by a button"
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="prompt-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Prompt } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Prompt>
|
||||
<Prompt.Trigger>Trigger</Prompt.Trigger>
|
||||
<Prompt.Content>
|
||||
<Prompt.Header>
|
||||
<Prompt.Title>Title</Prompt.Title>
|
||||
<Prompt.Description>Description</Prompt.Description>
|
||||
</Prompt.Header>
|
||||
<Prompt.Footer>
|
||||
<Prompt.Cancel>Cancel</Prompt.Cancel>
|
||||
<Prompt.Action>Delete</Prompt.Action>
|
||||
</Prompt.Footer>
|
||||
</Prompt.Content>
|
||||
</Prompt>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Alert Dialog](https://www.radix-ui.com/primitives/docs/components/alert-dialog) primitives.
|
||||
|
||||
### Prompt.Header
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
### Prompt.Footer
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: "Radio Group"
|
||||
description: "A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="radio-group-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { RadioGroup } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<RadioGroup>
|
||||
<RadioGroup.Item value="1" id="radio_1" />
|
||||
<RadioGroup.Item value="2" id="radio_2" />
|
||||
<RadioGroup.Item value="3" id="radio_3" />
|
||||
</RadioGroup>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Radio Group](https://www.radix-ui.com/primitives/docs/components/radio-group) primitives.
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### With Descriptions
|
||||
|
||||
<ComponentExample name="radio-group-descriptions" />
|
||||
|
||||
### With a disabled item
|
||||
|
||||
<ComponentExample name="radio-group-disabled" />
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: "Select"
|
||||
description: "Displays a list of options for the user to pick from—triggered by a button."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="select-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Select } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Select>
|
||||
<Select.Trigger>
|
||||
<Select.Value placeholder="Placeholder" />
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{items.map((item) => (
|
||||
<Select.Item key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on [Radix UI Select](https://www.radix-ui.com/primitives/docs/components/dropdown-menu).
|
||||
|
||||
### Select
|
||||
|
||||
Contains all the parts of the select component.
|
||||
|
||||
<ComponentProps component="select" />
|
||||
|
||||
### Select.Trigger
|
||||
|
||||
The trigger that toggles the select.
|
||||
|
||||
### Select.Value
|
||||
|
||||
Displays the selected value, or a placeholder if no value is selected.
|
||||
|
||||
<ComponentProps component="select-value" />
|
||||
|
||||
### Select.Group
|
||||
|
||||
Groups multiple items together.
|
||||
|
||||
### Select.Label
|
||||
|
||||
Used to label a group of items.
|
||||
|
||||
### Select.Item
|
||||
|
||||
An item in the select.
|
||||
|
||||
<ComponentProps component="select-item" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Small
|
||||
|
||||
<ComponentExample name="select-small" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentExample name="select-disabled" />
|
||||
|
||||
### Grouped Items
|
||||
|
||||
<ComponentExample name="select-grouped-items" />
|
||||
|
||||
### Controlled
|
||||
|
||||
<ComponentExample name="select-controlled" />
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "Switch"
|
||||
description: "A control that allows the user to toggle between checked and not checked."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="switch-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Switch } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Switch />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Switch](https://www.radix-ui.com/primitives/docs/components/switch) primitive.
|
||||
|
||||
<ComponentProps component="switch" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Small
|
||||
|
||||
<ComponentExample name="switch-small" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentExample name="switch-disabled" />
|
||||
|
||||
### Checked
|
||||
|
||||
<ComponentExample name="switch-checked" />
|
||||
|
||||
### Checked Disabled
|
||||
|
||||
<ComponentExample name="switch-checked-disabled" />
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "Table"
|
||||
description: "A Table component for displaying data."
|
||||
---
|
||||
|
||||
<ComponentExample name="table-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Table } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>#</Table.HeaderCell>
|
||||
<Table.HeaderCell>Customer</Table.HeaderCell>
|
||||
<Table.HeaderCell>Email</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.Cell>1</Table.Cell>
|
||||
<Table.Cell>Emil Larsson</Table.Cell>
|
||||
<Table.Cell>emil2738@gmail.com</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `table` element and its various children, and supports all props of those elements.
|
||||
|
||||
- `Table`: `table`
|
||||
- `Table.Header`: `thead`
|
||||
- `Table.Row`: `tr`
|
||||
- `Table.HeaderCell`: `th`
|
||||
- `Table.Body`: `tbody`
|
||||
- `Table.Cell`: `td`
|
||||
|
||||
### Pagination
|
||||
|
||||
This component is based on the `div` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="table-pagination" />
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "Text"
|
||||
description: "Displays basic text."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="text-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Text } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Text>Text</Text>
|
||||
```
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `p` element and supports all props of this element.
|
||||
|
||||
<ComponentProps component="text" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### All variations
|
||||
|
||||
<ComponentExample name="text-examples" />
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "Textarea"
|
||||
description: "Displays a form textarea."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="textarea-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Textarea } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Textarea />
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the `textarea` element and supports all props of this element.
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: "Toast"
|
||||
description: "A succinct message that is displayed temporarily."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="toaster-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
Add the Toaster component somewhere in your tree
|
||||
|
||||
```tsx
|
||||
import { Toaster } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Toaster />
|
||||
```
|
||||
|
||||
The `useToast` hook returns a `toast` function that you can use to display a toast.
|
||||
|
||||
```tsx
|
||||
import { useToast } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
const { toast } = useToast()
|
||||
|
||||
return (
|
||||
|
||||
<Button
|
||||
onClick={() =>
|
||||
toast({
|
||||
title: "Toast title",
|
||||
description: "Toast body",
|
||||
})
|
||||
}
|
||||
>
|
||||
Trigger
|
||||
</Button>
|
||||
)
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
This component is based on the [Radix UI Toast](https://www.radix-ui.com/primitives/docs/components/toast) primitives.
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Warning
|
||||
|
||||
<ComponentExample name="toaster-warning" />
|
||||
|
||||
### Error
|
||||
|
||||
<ComponentExample name="toaster-error" />
|
||||
|
||||
### Success
|
||||
|
||||
<ComponentExample name="toaster-success" />
|
||||
|
||||
### Loading
|
||||
|
||||
<ComponentExample name="toaster-loading" />
|
||||
|
||||
### With Action
|
||||
|
||||
<ComponentExample name="toaster-with-action" />
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: "Tooltip"
|
||||
description: "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it."
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentExample name="tooltip-demo" />
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import { Tooltip } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
|
||||
```tsx
|
||||
<Tooltip content="Tooltip content">Trigger</Tooltip>
|
||||
```
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
This component is based on the [Radix UI Tooltip](https://www.radix-ui.com/primitives/docs/components/tooltip) primitive.
|
||||
|
||||
<ComponentProps component="tooltip" />
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "usePrompt"
|
||||
description: ""
|
||||
component: true
|
||||
---
|
||||
|
||||
This hook can be used to prompt the user for confirmation of an action.
|
||||
|
||||
## Usage
|
||||
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { usePrompt } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
const dialog = usePrompt()
|
||||
const actionFunction = async () => {
|
||||
const confirmed = await dialog({
|
||||
title: "Are you sure?",
|
||||
description: "Please confirm this action",
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
### Call Signature
|
||||
|
||||
`usePrompt()`
|
||||
|
||||
### usePrompt return
|
||||
|
||||
<HookValues hook="usePrompt" />
|
||||
|
||||
### PromptProps
|
||||
|
||||
<HookValues hook="PromptProps" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
### Basic
|
||||
|
||||
<ComponentExample name="use-prompt-demo" />
|
||||
|
||||
### With Verification
|
||||
|
||||
<ComponentExample name="use-prompt-verification" />
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "useToast"
|
||||
description: ""
|
||||
component: true
|
||||
---
|
||||
|
||||
|
||||
This hook is used to display and manage toasts. To learn how to make it usable and to see some examples, please check the [Toast component page](/components/toast).
|
||||
|
||||
```tsx
|
||||
import { useToast } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
### Call Signature
|
||||
|
||||
`useToast()`
|
||||
|
||||
### useToast return
|
||||
|
||||
<HookValues hook="useToast" />
|
||||
|
||||
### ToasterToast
|
||||
|
||||
Important type used when pushing or retrieving toasts. This extends the [Radix UI Toast Root](https://www.radix-ui.com/primitives/docs/components/toast#root) primitive type.
|
||||
|
||||
<HookValues hook="ToasterToast" />
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "useToggleState"
|
||||
description: ""
|
||||
component: true
|
||||
---
|
||||
|
||||
|
||||
This is a simple hook that can be used to keep track of a boolean value and toggle between its two states.
|
||||
|
||||
It can be useful to, for example, display or hide the same `FocusModal` component
|
||||
via multiple triggers, for example, in a table.
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import { useToggleState } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
```tsx
|
||||
const [state, open, close, toggle] = useToggleState()
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
---
|
||||
|
||||
### Call Signature
|
||||
|
||||
`useToggleState(initial: boolean = false)`
|
||||
|
||||
### Returns
|
||||
|
||||
<HookValues hook="useToggleState" />
|
||||
|
||||
## Examples
|
||||
|
||||
---
|
||||
|
||||
<ComponentExample name="use-toggle-state-demo" />
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: "Icons"
|
||||
description: "React components for Medusa UI icons."
|
||||
---
|
||||
|
||||
## Overview
|
||||
---
|
||||
|
||||
Below is a list of all the icons available in the Medusa UI design system.
|
||||
|
||||
<IconSearch />
|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
The icons are available as an [npm package](https://www.npmjs.com/package/@medusajs/icons). To install the package run:
|
||||
|
||||
<PackageInstall packageName="@medusajs/icons" />
|
||||
|
||||
## Usage
|
||||
---
|
||||
|
||||
```tsx
|
||||
import { Sun, Moon } from "@medusajs/icons"
|
||||
```
|
||||
|
||||
<Feedback title={"Icons"} />
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "Introduction"
|
||||
description: "Primitives for building Medusa applications."
|
||||
---
|
||||
|
||||
Welcome to Medusa UI, a React implementation of the Medusa design system.
|
||||
It is a collection of components, hooks, utility functions, icons, and [Tailwind CSS](https://tailwindcss.com/) classes that can be used to build
|
||||
a consistent user interface across the Medusa Admin and other Medusa applications.
|
||||
|
||||
<Card
|
||||
title="Medusa UI"
|
||||
text="Colors, type, icons and components"
|
||||
href="https://www.figma.com/community/file/1278648465968635936/Medusa-UI"
|
||||
icon={
|
||||
<FigmaIcon />
|
||||
}
|
||||
/>
|
||||
|
||||
## Packages
|
||||
|
||||
---
|
||||
|
||||
Medusa UI is split into multiple packages. Each package is published to npm
|
||||
and can be installed separately.
|
||||
|
||||
- `@medusajs/ui` - React components, hooks, and utility functions used
|
||||
in Medusa UI.
|
||||
- `@medusajs/ui-preset` - Tailwind CSS preset containing all the classes
|
||||
used in Medusa UI.
|
||||
- `@medusajs/icons` - Icons used in Medusa UI.
|
||||
|
||||
## About
|
||||
|
||||
---
|
||||
|
||||
At its core, Medusa UI is a styled and slightly opinionated implementation of [Radix Primitives](https://www.radix-ui.com/primitives).
|
||||
Our team have also referenced the fantastic [shadcn/ui](https://ui.shadcn.com/) for inspiration in certain implementations.
|
||||
|
||||
Our team strongly believe in keeping the components simple and
|
||||
composable, much like Medusa's foundation. This allows you to build whatever you need. Our team have tried to avoid overloading
|
||||
the component API and, instead, leveraged the native HTML API, which gets implemented
|
||||
and respected accordingly, and passed to the underlying elements.
|
||||
|
||||
<Feedback title={"Introduction"} />
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: "Installation"
|
||||
description: "How to install and setup Medusa UI."
|
||||
---
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: "Medusa Admin Extension"
|
||||
description: "How to install and use Medusa UI for building Admin extensions."
|
||||
---
|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
The `@medusajs/ui` package is a already installed as a dependency of the `@medusajs/admin` package. Due to this you can simply import the package and use it in your local Admin extensions.
|
||||
|
||||
If you are building a Admin extension as part of a Medusa plugin, you can install the package as a dependency of your plugin.
|
||||
|
||||
<PackageInstall packageName="@medusajs/ui" />
|
||||
|
||||
## Configuration
|
||||
---
|
||||
|
||||
The configuration of the UI package is handled by the `@medusajs/admin` package. Therefore, you do not need to any additional configuration to use the UI package in your Admin extensions.
|
||||
|
||||
<Feedback title={"Install in Medusa Admin Extension"} />
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "Standalone Project"
|
||||
description: "How to install and use Medusa UI in a standalone project."
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
---
|
||||
|
||||
Medusa UI is a React UI library and while it's intended for usage within Medusa projects, it can also be used in any React project.
|
||||
|
||||
### Install Medusa UI
|
||||
|
||||
Install the React UI library with the following command:
|
||||
|
||||
<PackageInstall packageName="@medusajs/ui" />
|
||||
|
||||
### Configuring Tailwind CSS
|
||||
|
||||
The components are styled using Tailwind CSS, and in order to use them, you will need to install Tailwind CSS in your project as well.
|
||||
For more information on how to install Tailwind CSS, please refer to the [Tailwind CSS documentation](https://tailwindcss.com/docs/installation).
|
||||
|
||||
All of the classes used for Medusa UI are shipped as a Tailwind CSS customization.
|
||||
You can install it with the following command:
|
||||
|
||||
<PackageInstall packageName="@medusajs/ui-preset" devDependency />
|
||||
|
||||
After you have installed Tailwind CSS and the Medusa UI preset, you need to add the following to your `tailwind.config.js`file:
|
||||
|
||||
```tsx
|
||||
module.exports = {
|
||||
presets: [require("@medusajs/ui-preset")],
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
In order for the styles to be applied correctly to the components, you will also need to ensure that
|
||||
`@medusajs/ui` is included in the content field of your `tailwind.config.js` file:
|
||||
|
||||
```tsx
|
||||
module.exports = {
|
||||
content: [
|
||||
// ...
|
||||
"./node_modules/@medusajs/ui/dist/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
If you are working within a monorepo, you may need to add the path to the `@medusajs/ui` package in your `tailwind.config.js` like so:
|
||||
|
||||
```tsx
|
||||
const path = require("path")
|
||||
|
||||
const uiPath = path.resolve(
|
||||
require.resolve("@medusajs/ui"),
|
||||
"../..",
|
||||
"\*_/_.{js,jsx,ts,tsx}"
|
||||
)
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
// ...
|
||||
uiPath,
|
||||
],
|
||||
// ...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Start building
|
||||
|
||||
---
|
||||
|
||||
You are now ready to start building your application with Medusa UI. You can import the components like so:
|
||||
|
||||
```tsx
|
||||
import { Button, Drawer } from "@medusajs/ui"
|
||||
```
|
||||
|
||||
<Feedback title={"Install in Standalone Project"} />
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: "clx"
|
||||
description: "Utility function for working with classNames."
|
||||
---
|
||||
|
||||
## Usage
|
||||
---
|
||||
|
||||
The `clx` function is a utility function for working with classNames. It is built using [clsx](https://www.npmjs.com/package/clsx) and [tw-merge](https://www.npmjs.com/package/tw-merge) and is intended to be used with [Tailwind CSS](https://tailwindcss.com/).
|
||||
|
||||
```tsx
|
||||
import { clx } from "@medusajs/ui"
|
||||
|
||||
type BoxProps = {
|
||||
className?: string
|
||||
children: React.ReactNode
|
||||
mt?: "sm" | "md" | "lg"
|
||||
}
|
||||
|
||||
const Box = ({ className, children }: BoxProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clx(
|
||||
"flex items-center justify-center",
|
||||
{
|
||||
"mt-4": mt === "sm",
|
||||
"mt-8": mt === "md",
|
||||
"mt-12": mt === "lg",
|
||||
},
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
In the above example the utility is used to apply a base style, a margin top that is dependent on the `mt` prop and a custom className.
|
||||
The Box component accepts a `className` prop that is merged with the other classNames, and the underlying usage of `tw-merge` ensures that all Tailwind CSS classes are merged without style conflicts.
|
||||
|
||||
<Feedback title={"clx"} />
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Avatar } from "@medusajs/ui"
|
||||
|
||||
export default function AvatarDemo() {
|
||||
return (
|
||||
<Avatar
|
||||
src="https://avatars.githubusercontent.com/u/10656202?v=4"
|
||||
fallback="M"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeBlue() {
|
||||
return <Badge color="blue">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeDemo() {
|
||||
return <Badge>Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeGreen() {
|
||||
return <Badge color="green">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeGrey() {
|
||||
return <Badge color="grey">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { BuildingTax } from "@medusajs/icons"
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeIcon() {
|
||||
return (
|
||||
<Badge type="icon">
|
||||
<BuildingTax />
|
||||
</Badge>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeLarge() {
|
||||
return <Badge size="large">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeOrange() {
|
||||
return <Badge color="orange">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgePurple() {
|
||||
return <Badge color="purple">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeRed() {
|
||||
return <Badge color="red">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeRounded() {
|
||||
return <Badge type="rounded">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Badge } from "@medusajs/ui"
|
||||
|
||||
export default function BadgeSmall() {
|
||||
return <Badge size="small">Badge</Badge>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonDanger() {
|
||||
return <Button variant="danger">Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonDemo() {
|
||||
return <Button>Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonDisabled() {
|
||||
return <Button disabled={true}>Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { PlusMini } from "@medusajs/icons"
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonIconOnly() {
|
||||
return (
|
||||
<Button format="icon">
|
||||
<PlusMini />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonLoading() {
|
||||
return <Button isLoading={true}>Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonPrimary() {
|
||||
return <Button>Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonSecondary() {
|
||||
return <Button variant="secondary">Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonTransparent() {
|
||||
return <Button variant="transparent">Button</Button>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { PlusMini } from "@medusajs/icons"
|
||||
import { Button } from "@medusajs/ui"
|
||||
|
||||
export default function ButtonWithIcon() {
|
||||
return (
|
||||
<Button>
|
||||
Button <PlusMini />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Calendar } from "@medusajs/ui"
|
||||
import * as React from "react"
|
||||
|
||||
export default function CalendarDemo() {
|
||||
const [date, setDate] = React.useState<Date | undefined>()
|
||||
|
||||
return <Calendar selected={date} onSelect={setDate} />
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Calendar } from "@medusajs/ui"
|
||||
import * as React from "react"
|
||||
import type { DateRange } from "react-day-picker"
|
||||
|
||||
export default function CalendarRange() {
|
||||
const [dates, setDates] = React.useState<DateRange | undefined>()
|
||||
|
||||
const setDateRange = (range: DateRange | undefined) => {
|
||||
setDates(range)
|
||||
}
|
||||
|
||||
return <Calendar selected={dates} onSelect={setDateRange} mode="range" />
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Calendar } from "@medusajs/ui"
|
||||
import * as React from "react"
|
||||
|
||||
export default function CalendarSingle() {
|
||||
const [date, setDate] = React.useState<Date | undefined>()
|
||||
|
||||
return <Calendar selected={date} onSelect={setDate} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Checkbox, Label } from "@medusajs/ui"
|
||||
|
||||
export default function CheckboxChecked() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="billing-shipping-checked" checked={true} />
|
||||
<Label htmlFor="billing-shipping-checked">
|
||||
Billing address same as shipping address
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Checkbox, Label } from "@medusajs/ui"
|
||||
|
||||
export default function CheckboxDefault() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="billing-shipping-default" />
|
||||
<Label htmlFor="billing-shipping-default">
|
||||
Billing address same as shipping address
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Checkbox, Label } from "@medusajs/ui"
|
||||
|
||||
export default function CheckboxDemo() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="billing-shipping" />
|
||||
<Label htmlFor="billing-shipping">
|
||||
Billing address same as shipping address
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Checkbox, Label } from "@medusajs/ui"
|
||||
|
||||
export default function CheckboxDisabled() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="billing-shipping-disabled" disabled={true} />
|
||||
<Label htmlFor="billing-shipping-disabled">
|
||||
Billing address same as shipping address
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Checkbox, Label } from "@medusajs/ui"
|
||||
|
||||
export default function CheckboxIndeterminate() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox id="billing-shipping-indeterminate" checked={"indeterminate"} />
|
||||
<Label htmlFor="billing-shipping-indeterminate">
|
||||
Billing address same as shipping address
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { CodeBlock, Label } from "@medusajs/ui"
|
||||
|
||||
const snippets = [
|
||||
{
|
||||
label: "cURL",
|
||||
language: "markdown",
|
||||
code: `curl -H 'x-publishable-key: YOUR_API_KEY' 'http://localhost:9000/store/products/PRODUCT_ID'`,
|
||||
},
|
||||
{
|
||||
label: "Medusa JS Client",
|
||||
language: "jsx",
|
||||
code: `// Install the JS Client in your storefront project: @medusajs/medusa-js\n\nimport Medusa from "@medusajs/medusa-js"\n\nconst medusa = new Medusa({ publishableApiKey: "YOUR_API_KEY"})\nconst product = await medusa.products.retrieve("PRODUCT_ID")\nconsole.log(product.id)`,
|
||||
},
|
||||
{
|
||||
label: "Medusa React",
|
||||
language: "tsx",
|
||||
code: `// Install the React SDK and required dependencies in your storefront project:\n// medusa-react @tanstack/react-query @medusajs/medusa\n\nimport { useProduct } from "medusa-react"\n\nconst { product } = useProduct("PRODUCT_ID")\nconsole.log(product.id)`,
|
||||
},
|
||||
]
|
||||
|
||||
export default function CodeBlockDemo() {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<CodeBlock snippets={snippets}>
|
||||
<CodeBlock.Header>
|
||||
<CodeBlock.Header.Meta>
|
||||
<Label weight={"plus"}>/product-detail.js</Label>
|
||||
</CodeBlock.Header.Meta>
|
||||
</CodeBlock.Header>
|
||||
<CodeBlock.Body />
|
||||
</CodeBlock>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { CodeBlock } from "@medusajs/ui"
|
||||
|
||||
const snippets = [
|
||||
{
|
||||
label: "Medusa React",
|
||||
language: "tsx",
|
||||
code: `import { useProduct } from "medusa-react"\n\nconst { product } = useProduct("PRODUCT_ID")\nconsole.log(product.id)`,
|
||||
},
|
||||
]
|
||||
|
||||
export default function CodeBlockNoHeader() {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<CodeBlock snippets={snippets}>
|
||||
<CodeBlock.Body />
|
||||
</CodeBlock>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { CodeBlock, Label } from "@medusajs/ui"
|
||||
|
||||
const snippets = [
|
||||
{
|
||||
label: "Medusa React",
|
||||
language: "tsx",
|
||||
code: `import { useProduct } from "medusa-react"\n\nconst { product } = useProduct("PRODUCT_ID")\nconsole.log(product.id)`,
|
||||
},
|
||||
]
|
||||
|
||||
export default function CodeBlockNoLines() {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<CodeBlock snippets={snippets}>
|
||||
<CodeBlock.Header>
|
||||
<CodeBlock.Header.Meta>
|
||||
<Label weight={"plus"}>/product-detail.js</Label>
|
||||
</CodeBlock.Header.Meta>
|
||||
</CodeBlock.Header>
|
||||
<CodeBlock.Body hideLineNumbers={true} />
|
||||
</CodeBlock>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { CodeBlock, Label } from "@medusajs/ui"
|
||||
|
||||
const snippets = [
|
||||
{
|
||||
label: "Medusa React",
|
||||
language: "tsx",
|
||||
code: `import { useProduct } from "medusa-react"\n\nconst { product } = useProduct("PRODUCT_ID")\nconsole.log(product.id)`,
|
||||
},
|
||||
]
|
||||
|
||||
export default function CodeBlockSingle() {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<CodeBlock snippets={snippets}>
|
||||
<CodeBlock.Header hideLabels={true}>
|
||||
<CodeBlock.Header.Meta>
|
||||
<Label weight={"plus"}>/product-detail.js</Label>
|
||||
</CodeBlock.Header.Meta>
|
||||
</CodeBlock.Header>
|
||||
<CodeBlock.Body />
|
||||
</CodeBlock>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Badge, Command } from "@medusajs/ui"
|
||||
|
||||
export default function CommandDemo() {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<Command>
|
||||
<Badge color="green">Get</Badge>
|
||||
<code>localhost:9000/store/products</code>
|
||||
<Command.Copy
|
||||
content="localhost:9000/store/products"
|
||||
className="ml-auto"
|
||||
/>
|
||||
</Command>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Container } from "@medusajs/ui"
|
||||
|
||||
export default function ContainerDemo() {
|
||||
return <Container>Content</Container>
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Container, Heading } from "@medusajs/ui"
|
||||
|
||||
export default function ContainerLayout() {
|
||||
return (
|
||||
<div className="flex h-full w-full">
|
||||
<div className="border-ui-border-base w-full max-w-[216px] border-r p-4">
|
||||
<Heading level="h3">Menubar</Heading>
|
||||
</div>
|
||||
<div className="flex w-full flex-col gap-y-2 px-8 pb-8 pt-6">
|
||||
<Container>
|
||||
<Heading>Section 1</Heading>
|
||||
</Container>
|
||||
<Container>
|
||||
<Heading>Section 2</Heading>
|
||||
</Container>
|
||||
<Container>
|
||||
<Heading>Section 3</Heading>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { PlusMini } from "@medusajs/icons"
|
||||
import { Button, Copy, Text } from "@medusajs/ui"
|
||||
|
||||
export default function CopyAsChild() {
|
||||
return (
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Text>Copy command</Text>
|
||||
<Copy content="yarn add @medusajs/ui" asChild>
|
||||
<Button format="icon" size="small" className="text-ui-fg-on-inverted">
|
||||
<PlusMini />
|
||||
</Button>
|
||||
</Copy>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Code, Copy } from "@medusajs/ui"
|
||||
|
||||
export default function CopyDemo() {
|
||||
return (
|
||||
<Copy content="yarn add @medusajs/ui">
|
||||
<Code>yarn add @medusajs/ui</Code>
|
||||
</Copy>
|
||||
)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user