diff --git a/biome.json b/biome.json
index be41be3..5215472 100644
--- a/biome.json
+++ b/biome.json
@@ -24,9 +24,6 @@
},
"security": {
"noDangerouslySetInnerHtml": "off"
- },
- "style": {
- "noNamespace": "error"
}
},
"ignore": [
diff --git a/examples/package.json b/examples/package.json
index a1bf377..e7036ab 100644
--- a/examples/package.json
+++ b/examples/package.json
@@ -8,23 +8,23 @@
"preview": "vite preview"
},
"dependencies": {
- "@sakura-ui/core": "^0.3.0",
- "@sakura-ui/forms": "^0.2.1",
- "@sakura-ui/tailwind-theme-plugin": "^0.2.1",
+ "@sakura-ui/core": "workspace:*",
+ "@sakura-ui/forms": "workspace:*",
+ "@sakura-ui/helper": "workspace:*",
+ "@sakura-ui/tailwind-theme-plugin": "workspace:*",
"clsx": "^2.1.0",
- "react": "^18.3.1",
- "react-dom": "^18.3.1",
+ "react": "catalog:",
+ "react-dom": "catalog:",
"react-router-dom": "^6.23.1",
- "tailwindcss": "^3.4.11"
+ "tailwindcss": "catalog:"
},
"devDependencies": {
- "@types/react": "^18.3.5",
- "@types/react-dom": "^18.3.0",
+ "@types/react": "catalog:",
+ "@types/react-dom": "catalog:",
"@types/react-router-dom": "^5.3.3",
"@vitejs/plugin-react-swc": "^3.7.0",
- "autoprefixer": "^10.4.19",
- "postcss": "^8.4.38",
- "typescript": "^5.4.5",
+ "autoprefixer": "catalog:",
+ "postcss": "catalog:",
"vite": "^5.4.11"
}
}
diff --git a/examples/src/pages/Forms.tsx b/examples/src/pages/Forms.tsx
index 8596a07..26af264 100644
--- a/examples/src/pages/Forms.tsx
+++ b/examples/src/pages/Forms.tsx
@@ -1,5 +1,6 @@
import React from 'react'
-import { H1, H2, Button } from '@sakura-ui/core'
+import clsx from 'clsx'
+import { H1, H2, Button, MenuButton, NavigationItem } from '@sakura-ui/core'
import {
CheckboxGroup,
Radio,
@@ -14,212 +15,156 @@ import {
} from '@sakura-ui/forms'
const Forms = () => {
+ const style = `
+ min-h-screen
+ text-sumi-900
+ text-base
+ `
+
+ const containerStyle = `
+ max-w-xs
+ sm:max-w-screen-sm
+ md:max-w-screen-md
+ lg:max-w-screen-lg
+ xl:max-w-[1120px]
+ mx-auto
+ `
+
+ const styleSp = 'hidden sm:block'
+
return (
-
-
SakuraUI Forms sample
-
-
-
Controlled forms
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+ SakuraUI Forms sample
+
+
Controlled forms
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Radio1
+
+
+ Radio2
+
+
+ Radio3
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Radio1
-
-
- Radio2
-
-
- Radio3
-
-
-
-
- Radio1
-
-
- Radio2
-
-
- Radio3
-
-
-
-
- Radio1
-
-
- Radio2
-
-
- Radio3
-
-
-
-
- Radio1
-
-
- Radio2
-
-
- Radio3
-
-
-
-
Radio1
@@ -230,7 +175,10 @@ const Forms = () => {
Radio3
-
+
Radio1
@@ -241,7 +189,10 @@ const Forms = () => {
Radio3
-
+
Radio1
@@ -252,91 +203,85 @@ const Forms = () => {
Radio3
-
-
- ) =>
- console.log(e.target.value)
- }
- />
- ) =>
- console.log(e.target.value)
- }
- />
- ) =>
- console.log(e.target.value)
- }
- />
-
-
-
- Checkbox1
-
-
- Checkbox2
-
-
- Checkbox3
-
-
-
-
- Checkbox1
-
-
- Checkbox2
-
-
- Checkbox3
-
-
-
-
- Checkbox1
-
-
- Checkbox2
-
-
- Checkbox3
-
-
-
-
+
+
+
+ Radio1
+
+
+ Radio2
+
+
+ Radio3
+
+
+
+
+ Radio1
+
+
+ Radio2
+
+
+ Radio3
+
+
+
+
+ Radio1
+
+
+ Radio2
+
+
+ Radio3
+
+
+
+
+ ) =>
+ console.log(e.target.value)
+ }
+ />
+ ) =>
+ console.log(e.target.value)
+ }
+ />
+ ) =>
+ console.log(e.target.value)
+ }
+ />
+
+
Checkbox1
@@ -347,7 +292,10 @@ const Forms = () => {
Checkbox3
-
+
Checkbox1
@@ -358,7 +306,10 @@ const Forms = () => {
Checkbox3
-
+
Checkbox1
@@ -369,186 +320,226 @@ const Forms = () => {
Checkbox3
-
-
- ) =>
- console.log(`${e.target.value}, ${e.target.checked}`)
- }
- />
- ) =>
- console.log(`${e.target.value}, ${e.target.checked}`)
- }
- />
- ) =>
- console.log(`${e.target.value}, ${e.target.checked}`)
- }
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
)
}
diff --git a/examples/src/pages/Home.tsx b/examples/src/pages/Home.tsx
index 084c3cc..c1f2690 100644
--- a/examples/src/pages/Home.tsx
+++ b/examples/src/pages/Home.tsx
@@ -72,10 +72,10 @@ const Home = () => {
diff --git a/examples/vite.config.ts b/examples/vite.config.mts
similarity index 100%
rename from examples/vite.config.ts
rename to examples/vite.config.mts
diff --git a/packages/core/package.json b/packages/core/package.json
index 286d125..f3c8001 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@sakura-ui/core",
- "version": "0.3.0",
+ "version": "0.3.1",
"description": "",
"keywords": [
"react",
diff --git a/packages/core/src/components/Button.tsx b/packages/core/src/components/Button.tsx
index 6f7e079..999428c 100644
--- a/packages/core/src/components/Button.tsx
+++ b/packages/core/src/components/Button.tsx
@@ -1,5 +1,4 @@
-import React, { type ComponentProps } from 'react'
-import { cx } from '@sakura-ui/helper'
+import { type ComponentWithAs, cx, forwardRef } from '@sakura-ui/helper'
import {
type ButtonVariant,
type ButtonSize,
@@ -7,21 +6,18 @@ import {
getVariantStyle,
getSizeStyle
} from './buttonStyle'
-import { Slot } from './Slot'
-export type ButtonProps = {
- className?: string
- variant?: ButtonVariant
- size?: ButtonSize
-} & (
- | ({ asChild?: false } & ComponentProps<'button'>)
- | { asChild: true; children: React.ReactNode }
-)
+export namespace Button {
+ export interface Props {
+ variant?: ButtonVariant
+ size?: ButtonSize
+ }
+}
-export const Button = React.forwardRef
(
+export const Button: ComponentWithAs<'button', Button.Props> = forwardRef(
(props, ref) => {
const {
- asChild,
+ as: Component = 'button',
variant = 'solid-fill',
size = 'lg',
className,
@@ -29,8 +25,6 @@ export const Button = React.forwardRef(
...restProps
} = props
- const Component = asChild ? Slot : 'button'
-
return (
{
+ as?: T
+ variant?: ButtonVariant
+ size?: ButtonSize
+ }
+}
+
+export const Button = (
+ props: Button.Props & Omit, keyof Button.Props>
+) => {
+ const {
+ as: Component = 'button',
+ variant = 'solid-fill',
+ size = 'lg',
+ className,
+ children,
+ ...restProps
+ } = props
+
+ return (
+
+ {children}
+
+ )
+}
+
+Button.displayName = 'Button'
diff --git a/packages/core/src/components/Card.tsx b/packages/core/src/components/Card.tsx
index c827bfa..d06235f 100644
--- a/packages/core/src/components/Card.tsx
+++ b/packages/core/src/components/Card.tsx
@@ -7,9 +7,11 @@ interface IdContextType {
const IdContext = React.createContext({ id: '' })
-export interface CardProps extends React.ComponentPropsWithoutRef<'article'> {}
+export namespace Card {
+ export interface Props extends React.ComponentPropsWithoutRef<'article'> {}
+}
-export const Card = (props: CardProps) => {
+export const Card = (props: Card.Props) => {
const { className, children, ...restProps } = props
const id = React.useId()
@@ -39,9 +41,11 @@ export const Card = (props: CardProps) => {
)
}
-export interface CardImgProps extends React.ComponentPropsWithoutRef<'img'> {}
+export namespace CardImg {
+ export interface Props extends React.ComponentPropsWithoutRef<'img'> {}
+}
-export const CardImg = (props: CardImgProps) => {
+export const CardImg = (props: CardImg.Props) => {
const { className, ...restProps } = props
const style = `
@@ -53,10 +57,11 @@ export const CardImg = (props: CardImgProps) => {
return
}
-export interface CardHeaderProps
- extends React.ComponentPropsWithoutRef<'div'> {}
+export namespace CardHeader {
+ export interface Props extends React.ComponentPropsWithoutRef<'div'> {}
+}
-export const CardHeader = (props: CardHeaderProps) => {
+export const CardHeader = (props: CardHeader.Props) => {
const { className, children, ...restProps } = props
const ctx = React.useContext(IdContext)
@@ -78,9 +83,11 @@ export const CardHeader = (props: CardHeaderProps) => {
)
}
-export interface CardBodyProps extends React.ComponentPropsWithoutRef<'div'> {}
+export namespace CardBody {
+ export interface Props extends React.ComponentPropsWithoutRef<'div'> {}
+}
-export const CardBody = (props: CardBodyProps) => {
+export const CardBody = (props: CardBody.Props) => {
const { className, children, ...restProps } = props
const ctx = React.useContext(IdContext)
@@ -101,10 +108,11 @@ export const CardBody = (props: CardBodyProps) => {
)
}
-export interface CardFooterProps
- extends React.ComponentPropsWithoutRef<'div'> {}
+export namespace CardFooter {
+ export interface Props extends React.ComponentPropsWithoutRef<'div'> {}
+}
-export const CardFooter = (props: CardFooterProps) => {
+export const CardFooter = (props: CardFooter.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/Code.tsx b/packages/core/src/components/Code.tsx
index 8c8b280..928e780 100644
--- a/packages/core/src/components/Code.tsx
+++ b/packages/core/src/components/Code.tsx
@@ -1,9 +1,11 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface CodeProps extends React.ComponentPropsWithoutRef<'code'> {}
+export namespace Code {
+ export interface Props extends React.ComponentPropsWithoutRef<'code'> {}
+}
-export const Code = (props: CodeProps) => {
+export const Code = (props: Code.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/Faq.tsx b/packages/core/src/components/Faq.tsx
index 476c39f..f936756 100644
--- a/packages/core/src/components/Faq.tsx
+++ b/packages/core/src/components/Faq.tsx
@@ -1,14 +1,16 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface FaqProps extends React.ComponentPropsWithoutRef<'dl'> {}
+export namespace Faq {
+ export interface Props extends React.ComponentPropsWithoutRef<'dl'> {}
+}
const headingStyle = `
text-h-med-m
sm:text-h-med
`
-export const Faq = (props: FaqProps) => {
+export const Faq = (props: Faq.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -31,9 +33,11 @@ export const Faq = (props: FaqProps) => {
)
}
-export interface QuestionProps extends React.ComponentPropsWithoutRef<'dt'> {}
+export namespace Question {
+ export interface Props extends React.ComponentPropsWithoutRef<'dt'> {}
+}
-export const Question = (props: QuestionProps) => {
+export const Question = (props: Question.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -54,9 +58,11 @@ export const Question = (props: QuestionProps) => {
)
}
-export interface AnswerProps extends React.ComponentPropsWithoutRef<'dd'> {}
+export namespace Answer {
+ export interface Props extends React.ComponentPropsWithoutRef<'dd'> {}
+}
-export const Answer = (props: AnswerProps) => {
+export const Answer = (props: Answer.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/Heading.tsx b/packages/core/src/components/Heading.tsx
index 1b8786a..a445b43 100644
--- a/packages/core/src/components/Heading.tsx
+++ b/packages/core/src/components/Heading.tsx
@@ -1,9 +1,11 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface HeadingProps extends React.ComponentPropsWithoutRef<'h1'> {}
+export namespace H1 {
+ export interface Props extends React.ComponentPropsWithoutRef<'h1'> {}
+}
-export const H1 = (props: HeadingProps) => {
+export const H1 = (props: H1.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -20,7 +22,11 @@ export const H1 = (props: HeadingProps) => {
)
}
-export const H2 = (props: HeadingProps) => {
+export namespace H2 {
+ export interface Props extends React.ComponentPropsWithoutRef<'h2'> {}
+}
+
+export const H2 = (props: H2.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -37,7 +43,11 @@ export const H2 = (props: HeadingProps) => {
)
}
-export const H3 = (props: HeadingProps) => {
+export namespace H3 {
+ export interface Props extends React.ComponentPropsWithoutRef<'h3'> {}
+}
+
+export const H3 = (props: H3.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -54,7 +64,11 @@ export const H3 = (props: HeadingProps) => {
)
}
-export const H4 = (props: HeadingProps) => {
+export namespace H4 {
+ export interface Props extends React.ComponentPropsWithoutRef<'h4'> {}
+}
+
+export const H4 = (props: H4.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -71,7 +85,11 @@ export const H4 = (props: HeadingProps) => {
)
}
-export const H5 = (props: HeadingProps) => {
+export namespace H5 {
+ export interface Props extends React.ComponentPropsWithoutRef<'h5'> {}
+}
+
+export const H5 = (props: H5.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -88,7 +106,11 @@ export const H5 = (props: HeadingProps) => {
)
}
-export const H6 = (props: HeadingProps) => {
+export namespace H6 {
+ export interface Props extends React.ComponentPropsWithoutRef<'h6'> {}
+}
+
+export const H6 = (props: H6.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/Icon.tsx b/packages/core/src/components/Icon.tsx
index 15f3e73..fd88cfe 100644
--- a/packages/core/src/components/Icon.tsx
+++ b/packages/core/src/components/Icon.tsx
@@ -1,12 +1,14 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface IconProps extends React.ComponentPropsWithRef<'span'> {
- opticalSize?: 16 | 20 | 24 | 40 | 44 | 48
- altText?: string
+export namespace Icon {
+ export interface Props extends React.ComponentPropsWithRef<'span'> {
+ opticalSize?: 16 | 20 | 24 | 40 | 44 | 48
+ altText?: string
+ }
}
-export const Icon = React.forwardRef((props, ref) => {
+export const Icon = React.forwardRef((props, ref) => {
const { className, altText = '', opticalSize = 24, children, ...rest } = props
const size = {
diff --git a/packages/core/src/components/IconButton.tsx b/packages/core/src/components/IconButton.tsx
index ecd525d..f0a1087 100644
--- a/packages/core/src/components/IconButton.tsx
+++ b/packages/core/src/components/IconButton.tsx
@@ -1,5 +1,4 @@
-import React, { type ComponentProps } from 'react'
-import { cx } from '@sakura-ui/helper'
+import { type ComponentWithAs, cx, forwardRef } from '@sakura-ui/helper'
import {
base,
getVariantStyle,
@@ -7,24 +6,21 @@ import {
type ButtonVariant,
type ButtonSize
} from './buttonStyle'
-import { Slot } from './Slot'
-export type IconButtonProps = {
- className?: string
- variant?: ButtonVariant
- size?: ButtonSize
- iconLayout?: 'left' | 'right'
- icon: string
- rounded?: string
-} & (
- | ({ asChild?: false } & ComponentProps<'button'>)
- | { asChild: true; children: React.ReactNode }
-)
+export namespace IconButton {
+ export interface Props {
+ variant?: ButtonVariant
+ size?: ButtonSize
+ iconLayout?: 'left' | 'right'
+ icon: string
+ rounded?: string
+ }
+}
-export const IconButton = React.forwardRef(
- (props, ref) => {
+export const IconButton: ComponentWithAs<'button', IconButton.Props> =
+ forwardRef((props, ref) => {
const {
- asChild,
+ as: Component = 'button',
variant = 'solid-fill',
size = 'lg',
iconLayout = 'left',
@@ -35,8 +31,6 @@ export const IconButton = React.forwardRef(
...restProps
} = props
- const Component = asChild ? Slot : 'button'
-
const styleFontSize = `${size === 'xs' ? 'scale-105' : 'scale-125'}`
const styleIcon = `
@@ -69,16 +63,16 @@ export const IconButton = React.forwardRef(
{iconLayout === 'left' && (
{icon}
)}
- {children && {children}}
+ {children}
{iconLayout === 'right' && (
{icon}
@@ -87,7 +81,6 @@ export const IconButton = React.forwardRef(
)
- }
-)
+ })
IconButton.displayName = 'IconButton'
diff --git a/packages/core/src/components/IconButton_19.tsx b/packages/core/src/components/IconButton_19.tsx
new file mode 100644
index 0000000..18b5a37
--- /dev/null
+++ b/packages/core/src/components/IconButton_19.tsx
@@ -0,0 +1,89 @@
+import React, { type ComponentProps } from 'react'
+import { cx } from '@sakura-ui/helper'
+import {
+ base,
+ getVariantStyle,
+ getSizeStyle,
+ type ButtonVariant,
+ type ButtonSize
+} from './buttonStyle'
+
+export namespace IconButton {
+ export interface Props {
+ as?: T
+ variant?: ButtonVariant
+ size?: ButtonSize
+ iconLayout?: 'left' | 'right'
+ icon: string
+ rounded?: string
+ }
+}
+
+export const IconButton = (
+ props: IconButton.Props &
+ Omit, keyof IconButton.Props>
+) => {
+ const {
+ as: Component = 'button',
+ variant = 'solid-fill',
+ size = 'lg',
+ iconLayout = 'left',
+ icon,
+ rounded,
+ className,
+ children,
+ ...restProps
+ } = props
+
+ const styleFontSize = `${size === 'xs' ? 'scale-105' : 'scale-125'}`
+
+ const styleIcon = `
+ inline-block
+ align-middle
+ mb-1
+ font-icon
+ font-light
+ leading-[0px]
+ antialiased
+ `
+
+ const styleRounded = `${rounded ? 'aspect-square !rounded-full !py-0' : ''}`
+
+ // When text is specified on a button, set the 'aria-hidden' attribute of the icon to true.
+ const ariaHidden = !!children
+
+ return (
+
+
+ {iconLayout === 'left' && (
+
+ {icon}
+
+ )}
+ {children && {children}}
+ {iconLayout === 'right' && (
+
+ {icon}
+
+ )}
+
+
+ )
+}
+
+IconButton.displayName = 'IconButton'
diff --git a/packages/core/src/components/LangSelector.tsx b/packages/core/src/components/LangSelector.tsx
index 1474995..1b16c53 100644
--- a/packages/core/src/components/LangSelector.tsx
+++ b/packages/core/src/components/LangSelector.tsx
@@ -1,27 +1,20 @@
import React from 'react'
-import {
- cx,
- mod,
- focusableSelector,
- styleClickable,
- styleFocusRoundedWithBg,
- styleHoverUnderline
-} from '@sakura-ui/helper'
+import { cx, mod, focusableSelector, Style } from '@sakura-ui/helper'
import { Language, LanguageMobile, KeyboadArrowDown } from '@/icons'
import { PopoverMenu, PopoverMenuItem } from './PopoverMenu'
-interface Lang {
- code: string
- title: string
- path: string
-}
-
-// Tailwind 3.4.5 or higher is required to use anchor-name.
-// https://github.com/tailwindlabs/tailwindcss/issues/13818
-export interface LangSelectorProps
- extends React.ComponentPropsWithRef<'button'> {
- current: string
- langs: Lang[]
+export namespace LangSelector {
+ interface Lang {
+ code: string
+ title: string
+ path: string
+ }
+ // Tailwind 3.4.5 or higher is required to use anchor-name.
+ // https://github.com/tailwindlabs/tailwindcss/issues/13818
+ export interface Props extends React.ComponentPropsWithRef<'button'> {
+ current: string
+ langs: Lang[]
+ }
}
export const LangSelector = ({
@@ -29,7 +22,7 @@ export const LangSelector = ({
langs,
className,
...restProps
-}: LangSelectorProps) => {
+}: LangSelector.Props) => {
const styleRoot = `
relative
group
@@ -46,10 +39,10 @@ export const LangSelector = ({
sm:py-3
text-base
leading-snug
- ${styleClickable}
- ${styleFocusRoundedWithBg}
+ ${Style.clickable}
+ ${Style.focusRoundedWithBg}
+ ${Style.hoverUnderline}
${styleAnchorName}
- ${styleHoverUnderline}
flex items-center
`
@@ -89,18 +82,18 @@ export const LangSelector = ({
}
}
- const handleToggle = () => {
- const focusable: HTMLElement | null | undefined =
- menuRef.current?.querySelector(focusableSelector)
- if (!focusable) return
- focusable.focus()
- }
-
React.useEffect(() => {
+ const handleToggle = () => {
+ const focusable: HTMLElement | null | undefined =
+ menuRef.current?.querySelector(focusableSelector)
+ if (!focusable) return
+ focusable.focus()
+ }
+
menuRef.current?.addEventListener('toggle', handleToggle)
return () => menuRef.current?.removeEventListener('toggle', handleToggle)
- }, [menuRef])
+ }, [])
return (
diff --git a/packages/core/src/components/Link.tsx b/packages/core/src/components/Link.tsx
index 6ed7ce7..3aa6749 100644
--- a/packages/core/src/components/Link.tsx
+++ b/packages/core/src/components/Link.tsx
@@ -1,23 +1,14 @@
-import React, { type ComponentProps } from 'react'
-import { cx, styleUnderline, styleFocusRoundedWithBg } from '@sakura-ui/helper'
+import { type ComponentWithAs, cx, forwardRef, Style } from '@sakura-ui/helper'
import { Icon } from './Icon'
-import { Slot } from './Slot'
-export type LinkProps = {
- className?: string
-} & (
- | ({ asChild?: false } & ComponentProps<'a'>)
- | {
- asChild: true
- children: React.ReactNode
- }
-)
+export namespace Link {
+ // biome-ignore lint/suspicious/noEmptyInterface: no error
+ export interface Props {}
+}
-export const Link = React.forwardRef
(
+export const Link: ComponentWithAs<'a', Link.Props> = forwardRef(
(props, ref) => {
- const { asChild, className, children, ...rest } = props
-
- const Component = asChild ? Slot : 'a'
+ const { as: Component = 'a', className, children, ...rest } = props
// Make lines break at each word
const style = `
@@ -25,21 +16,12 @@ export const Link = React.forwardRef(
text-blue-1000
active:text-orange-700
visited:text-magenta-900
- ${styleFocusRoundedWithBg}
- ${styleUnderline}
+ ${Style.focusRoundedWithBg}
+ ${Style.underline}
disabled:border-sumi-500
[overflow-wrap:anywhere]
`
- // This assumes the use of next/link or gatsby-link.
- if (asChild) {
- return (
-
- {children}
-
- )
- }
-
if (props.href?.startsWith('http') || props.target === '_blank') {
return (
(
)
}
+ return (
+
+ {children}
+
+ )
}
)
diff --git a/packages/core/src/components/LinkCard.tsx b/packages/core/src/components/LinkCard.tsx
index e02deba..f59a67b 100644
--- a/packages/core/src/components/LinkCard.tsx
+++ b/packages/core/src/components/LinkCard.tsx
@@ -1,16 +1,17 @@
import React from 'react'
-import { cx, styleFocusCard } from '@sakura-ui/helper'
+import { cx, Style } from '@sakura-ui/helper'
import { Card, CardHeader } from './Card'
import { Icon } from './Icon'
interface LinkContextType {
href: string
}
-
const LinkContext = React.createContext({ href: '' })
-export interface LinkCardProps extends React.ComponentProps<'article'> {
- href: string
+export namespace LinkCard {
+ export interface Props extends React.ComponentProps<'article'> {
+ href: string
+ }
}
export const LinkCard = ({
@@ -18,14 +19,14 @@ export const LinkCard = ({
className,
children,
...rest
-}: LinkCardProps) => {
+}: LinkCard.Props) => {
const styleLink = `
grid
outline-offset-4
rounded-2xl
sm:rounded-3xl
w-full h-full
- ${styleFocusCard}
+ ${Style.focusCard}
`
const styleHover = `
diff --git a/packages/core/src/components/Link_19.tsx b/packages/core/src/components/Link_19.tsx
new file mode 100644
index 0000000..b913383
--- /dev/null
+++ b/packages/core/src/components/Link_19.tsx
@@ -0,0 +1,51 @@
+import React from 'react'
+import { cx, Style } from '@sakura-ui/helper'
+import { Icon } from './Icon'
+
+export namespace Link {
+ export interface Props {
+ as?: T
+ }
+}
+
+export const Link = (
+ props: Link.Props & Omit, keyof Link.Props>
+) => {
+ const { as: Component = 'a', className, children, ...restProps } = props
+
+ // Make lines break at each word
+ const style = `
+ cursor-pointer
+ text-blue-1000
+ active:text-orange-700
+ visited:text-magenta-900
+ ${Style.focusRoundedWithBg}
+ ${Style.underline}
+ disabled:border-sumi-500
+ [overflow-wrap:anywhere]
+ `
+
+ if (restProps.href?.startsWith('http') || restProps.target === '_blank') {
+ return (
+
+ {children}
+
+ open_in_new
+
+
+ )
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+Link.displayName = 'Link'
diff --git a/packages/core/src/components/List.tsx b/packages/core/src/components/List.tsx
index 6482d07..598aeec 100644
--- a/packages/core/src/components/List.tsx
+++ b/packages/core/src/components/List.tsx
@@ -1,9 +1,11 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface UlProps extends React.ComponentPropsWithoutRef<'ul'> {}
+export namespace Ul {
+ export interface Props extends React.ComponentPropsWithoutRef<'ul'> {}
+}
-export const Ul = (props: UlProps) => {
+export const Ul = (props: Ul.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -19,9 +21,11 @@ export const Ul = (props: UlProps) => {
)
}
-export interface OlProps extends React.ComponentPropsWithoutRef<'ol'> {}
+export namespace Ol {
+ export interface Props extends React.ComponentPropsWithoutRef<'ol'> {}
+}
-export const Ol = (props: OlProps) => {
+export const Ol = (props: Ol.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/MenuButton.tsx b/packages/core/src/components/MenuButton.tsx
index fbf0a07..bfa0974 100644
--- a/packages/core/src/components/MenuButton.tsx
+++ b/packages/core/src/components/MenuButton.tsx
@@ -1,23 +1,17 @@
import React from 'react'
-import {
- cx,
- mod,
- focusableSelector,
- styleClickable,
- styleFocusRoundedWithBg,
- styleHoverUnderline
-} from '@sakura-ui/helper'
+import { cx, mod, focusableSelector, Style } from '@sakura-ui/helper'
import { Menu, MenuMobile, Close, CloseMobile } from '@/icons'
-export interface MenuButtonProps
- extends React.ComponentPropsWithRef<'button'> {}
+export namespace MenuButton {
+ export interface Props extends React.ComponentPropsWithRef<'button'> {}
+}
export const MenuButton = ({
className,
children,
onChange,
...rest
-}: MenuButtonProps) => {
+}: MenuButton.Props) => {
// leading 16px * 1.375(snug) + padding top 12px + padding bottom 12px + border * 2 = 48px
const styleMenuItem = `
w-fit
@@ -25,9 +19,9 @@ export const MenuButton = ({
sm:py-3
text-base
leading-snug
- ${styleClickable}
- ${styleHoverUnderline}
- ${styleFocusRoundedWithBg}
+ ${Style.clickable}
+ ${Style.hoverUnderline}
+ ${Style.focusRoundedWithBg}
`
const dialogRef = React.useRef(null)
diff --git a/packages/core/src/components/NavigationItem.tsx b/packages/core/src/components/NavigationItem.tsx
index 00555c2..bfb96c3 100644
--- a/packages/core/src/components/NavigationItem.tsx
+++ b/packages/core/src/components/NavigationItem.tsx
@@ -1,29 +1,19 @@
import React, { type ComponentProps } from 'react'
-import {
- cx,
- styleClickable,
- styleHoverUnderline,
- styleFocusRectWithBg
-} from '@sakura-ui/helper'
-import { Slot } from './Slot'
+import { cx, Style } from '@sakura-ui/helper'
-export type NavigationItemProps = {
- className?: string
-} & (
- | ({ asChild?: false } & ComponentProps<'a'>)
- | {
- asChild: true
- children: React.ReactNode
- }
-)
+export namespace NavigationItem {
+ export interface Props {
+ as?: T
+ }
+}
-export const NavigationItem = React.forwardRef<
- HTMLAnchorElement,
- NavigationItemProps
->((props, ref) => {
- const { asChild, className, children, ...rest } = props
+export const NavigationItem = (
+ props: NavigationItem.Props &
+ Omit, keyof NavigationItem.Props>
+) => {
+ const { as, className, children, ...rest } = props
- const Component = asChild ? Slot : 'a'
+ const Component = as || 'a'
// leading 16px * 1.375(snug) + padding top 12px + padding bottom 12px + border * 2 = 48px
const style = `
@@ -32,9 +22,9 @@ export const NavigationItem = React.forwardRef<
py-3
text-base
leading-snug
- ${styleClickable}
- ${styleHoverUnderline}
- ${styleFocusRectWithBg}
+ ${Style.clickable}
+ ${Style.hoverUnderline}
+ ${Style.focusRectWithBg}
`
return (
@@ -42,11 +32,10 @@ export const NavigationItem = React.forwardRef<
className={cx(style, className)}
rel="noopener noreferrer"
{...rest}
- ref={ref}
>
{children}
)
-})
+}
NavigationItem.displayName = 'NavigationItem'
diff --git a/packages/core/src/components/OverflowContainer.tsx b/packages/core/src/components/OverflowContainer.tsx
index fce1d7e..82c97ec 100644
--- a/packages/core/src/components/OverflowContainer.tsx
+++ b/packages/core/src/components/OverflowContainer.tsx
@@ -1,10 +1,11 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface OverflowContainerProps
- extends React.ComponentPropsWithoutRef<'div'> {}
+export namespace OverflowContainer {
+ export interface Props extends React.ComponentPropsWithoutRef<'div'> {}
+}
-export const OverflowContainer = (props: OverflowContainerProps) => {
+export const OverflowContainer = (props: OverflowContainer.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/PopoverMenu.tsx b/packages/core/src/components/PopoverMenu.tsx
index b9f421d..01266c0 100644
--- a/packages/core/src/components/PopoverMenu.tsx
+++ b/packages/core/src/components/PopoverMenu.tsx
@@ -1,9 +1,5 @@
import React from 'react'
-import {
- cx,
- styleHoverUnderline,
- styleFocusRectCondensedWithBg
-} from '@sakura-ui/helper'
+import { cx, Style } from '@sakura-ui/helper'
import { Icon } from './Icon'
export const PopoverMenu = React.forwardRef<
@@ -50,7 +46,7 @@ export const PopoverMenuItem = React.forwardRef<
items-center
gap-x-1.5
hover:bg-solid-grey-50
- ${styleFocusRectCondensedWithBg}
+ ${Style.focusRectCondensedWithBg}
`
const styleSelected = `
@@ -76,7 +72,7 @@ export const PopoverMenuItem = React.forwardRef<
>
check
- {children}
+ {children}
)
diff --git a/packages/core/src/components/Pre.tsx b/packages/core/src/components/Pre.tsx
index 05fc253..7421937 100644
--- a/packages/core/src/components/Pre.tsx
+++ b/packages/core/src/components/Pre.tsx
@@ -1,9 +1,11 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface PreProps extends React.ComponentPropsWithoutRef<'pre'> {}
+export namespace Pre {
+ export interface Props extends React.ComponentPropsWithoutRef<'pre'> {}
+}
-export const Pre = (props: PreProps) => {
+export const Pre = (props: Pre.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/Slot.tsx b/packages/core/src/components/Slot.tsx
deleted file mode 100644
index 3079a45..0000000
--- a/packages/core/src/components/Slot.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react'
-
-export interface SlotProps extends React.HTMLAttributes {
- children?: React.ReactNode
-}
-
-export const Slot = React.forwardRef((props, ref) => {
- const { children, ...restProps } = props
-
- if (React.isValidElement(children)) {
- return React.cloneElement(children, {
- ...restProps,
- ...children.props,
- className: `${restProps.className ?? ''} ${children.props.className ?? ''}`,
- ref
- })
- }
-
- if (React.Children.count(children) > 1) {
- React.Children.only(null)
- }
- return null
-})
diff --git a/packages/core/src/components/Table.tsx b/packages/core/src/components/Table.tsx
index c6c938d..6a5d09c 100644
--- a/packages/core/src/components/Table.tsx
+++ b/packages/core/src/components/Table.tsx
@@ -1,7 +1,9 @@
import React from 'react'
import { cx } from '@sakura-ui/helper'
-export interface TableProps extends React.ComponentPropsWithoutRef<'table'> {}
+export namespace Table {
+ export interface Props extends React.ComponentPropsWithoutRef<'table'> {}
+}
const styleBorder = `
border
@@ -9,7 +11,7 @@ const styleBorder = `
border-solid-grey-420
`
-export const Table = (props: TableProps) => {
+export const Table = (props: Table.Props) => {
const { className, children, ...restProps } = props
return (
@@ -19,10 +21,11 @@ export const Table = (props: TableProps) => {
)
}
-export interface CaptionProps
- extends React.ComponentPropsWithoutRef<'caption'> {}
+export namespace Caption {
+ export interface Props extends React.ComponentPropsWithoutRef<'caption'> {}
+}
-export const Caption = (props: CaptionProps) => {
+export const Caption = (props: Caption.Props) => {
const { className, children, ...restProps } = props
const style = 'text-left'
@@ -33,9 +36,11 @@ export const Caption = (props: CaptionProps) => {
)
}
-export interface TheadProps extends React.ComponentPropsWithoutRef<'thead'> {}
+export namespace Thead {
+ export interface Props extends React.ComponentPropsWithoutRef<'thead'> {}
+}
-export const Thead = (props: TheadProps) => {
+export const Thead = (props: Thead.Props) => {
const { className, children, ...restProps } = props
return (
@@ -45,9 +50,11 @@ export const Thead = (props: TheadProps) => {
)
}
-export interface TbodyProps extends React.ComponentPropsWithoutRef<'tbody'> {}
+export namespace Tbody {
+ export interface Props extends React.ComponentPropsWithoutRef<'tbody'> {}
+}
-export const Tbody = (props: TbodyProps) => {
+export const Tbody = (props: Tbody.Props) => {
const { className, children, ...restProps } = props
return (
@@ -57,9 +64,11 @@ export const Tbody = (props: TbodyProps) => {
)
}
-export interface ThProps extends React.ComponentPropsWithoutRef<'th'> {}
+export namespace Th {
+ export interface Props extends React.ComponentPropsWithoutRef<'th'> {}
+}
-export const Th = (props: ThProps) => {
+export const Th = (props: Th.Props) => {
const { className, children, ...restProps } = props
const style = `
@@ -75,9 +84,11 @@ export const Th = (props: ThProps) => {
)
}
-export interface TrProps extends React.ComponentPropsWithoutRef<'tr'> {}
+export namespace Tr {
+ export interface Props extends React.ComponentPropsWithoutRef<'tr'> {}
+}
-export const Tr = (props: TrProps) => {
+export const Tr = (props: Tr.Props) => {
const { className, children, ...restProps } = props
const style = ''
@@ -89,9 +100,11 @@ export const Tr = (props: TrProps) => {
)
}
-export interface TdProps extends React.ComponentPropsWithoutRef<'td'> {}
+export namespace Td {
+ export interface Props extends React.ComponentPropsWithoutRef<'td'> {}
+}
-export const Td = (props: TdProps) => {
+export const Td = (props: Td.Props) => {
const { className, children, ...restProps } = props
const style = `
diff --git a/packages/core/src/components/buttonStyle.ts b/packages/core/src/components/buttonStyle.ts
index 9719118..b9c57d7 100644
--- a/packages/core/src/components/buttonStyle.ts
+++ b/packages/core/src/components/buttonStyle.ts
@@ -1,9 +1,4 @@
-import {
- styleFocusRounded,
- styleFocusRoundedWithBg,
- styleHoverUnderline,
- styleUnderlineNoDeco
-} from '@sakura-ui/helper'
+import { Style } from '@sakura-ui/helper'
// Deprecated, replace to ButtonVariantV2
export type ButtonVariantV1 = 'primary' | 'secondary' | 'tertiary'
@@ -37,8 +32,8 @@ const solidFill = `
active:bg-blue-1200
disabled:bg-sumi-500
disabled:text-white
- ${styleHoverUnderline}
- ${styleFocusRounded}
+ ${Style.hoverUnderline}
+ ${Style.focusRounded}
`
const outline = `
@@ -50,8 +45,8 @@ const outline = `
active:bg-blue-300
disabled:bg-transparent
disabled:text-sumi-500
- ${styleHoverUnderline}
- ${styleFocusRounded}
+ ${Style.hoverUnderline}
+ ${Style.focusRounded}
`
const text = `
@@ -63,8 +58,8 @@ const text = `
active:bg-blue-300
disabled:bg-transparent
disabled:text-sumi-500
- ${styleUnderlineNoDeco}
- ${styleFocusRoundedWithBg}
+ ${Style.underlineNoDeco}
+ ${Style.focusRoundedWithBg}
`
const styles: { [key in ButtonVariant]: string } = {
diff --git a/packages/core/src/components/index.ts b/packages/core/src/components/index.ts
index d8924c7..c2545bc 100644
--- a/packages/core/src/components/index.ts
+++ b/packages/core/src/components/index.ts
@@ -1,39 +1,17 @@
-export { Button, type ButtonProps } from './Button'
-export { MenuButton, type MenuButtonProps } from './MenuButton'
+export { Button } from './Button'
+export { MenuButton } from './MenuButton'
export { Card, CardImg, CardHeader, CardBody, CardFooter } from './Card'
-export type {
- CardProps,
- CardImgProps,
- CardHeaderProps,
- CardBodyProps,
- CardFooterProps
-} from './Card'
export { LinkCard, LinkCardHeader } from './LinkCard'
-export type { LinkCardProps, LinkCardHeaderProps } from './LinkCard'
-export { Code, type CodeProps } from './Code'
+export { Code } from './Code'
export { Faq, Question, Answer } from './Faq'
-export type { FaqProps, QuestionProps, AnswerProps } from './Faq'
-export { H1, H2, H3, H4, H5, H6, type HeadingProps } from './Heading'
-export { Icon, type IconProps } from './Icon'
-export { IconButton, type IconButtonProps } from './IconButton'
-export { Link, type LinkProps } from './Link'
-export { Ol, Ul, type OlProps, type UlProps } from './List'
-export { NavigationItem, type NavigationItemProps } from './NavigationItem'
-export { Pre, type PreProps } from './Pre'
+export { H1, H2, H3, H4, H5, H6 } from './Heading'
+export { Icon } from './Icon'
+export { IconButton } from './IconButton'
+export { Link } from './Link'
+export { Ol, Ul } from './List'
+export { NavigationItem } from './NavigationItem'
+export { Pre } from './Pre'
export { Table, Caption, Thead, Tbody, Th, Tr, Td } from './Table'
-export type {
- TableProps,
- CaptionProps,
- TheadProps,
- TbodyProps,
- ThProps,
- TrProps,
- TdProps
-} from './Table'
-export {
- OverflowContainer,
- type OverflowContainerProps
-} from './OverflowContainer'
-export { LangSelector, type LangSelectorProps } from './LangSelector'
+export { OverflowContainer } from './OverflowContainer'
+export { LangSelector } from './LangSelector'
export { PopoverMenu, PopoverMenuItem } from './PopoverMenu'
-export { Slot } from './Slot'
diff --git a/packages/core/src/icons/Close.tsx b/packages/core/src/icons/Close.tsx
index 2e525a0..5c793a2 100644
--- a/packages/core/src/icons/Close.tsx
+++ b/packages/core/src/icons/Close.tsx
@@ -4,10 +4,10 @@ export const Close = (props: IconProps) => {
const { size, className, ...rest } = props
return (