Skip to content

Commit

Permalink
Merge pull request #13 from glassonion1/feature/as_to_aschild
Browse files Browse the repository at this point in the history
Deprecate the as property and introduce the asChild property.
  • Loading branch information
Taisuke Fujita authored Dec 5, 2024
2 parents 5738106 + e060e24 commit 6741650
Show file tree
Hide file tree
Showing 15 changed files with 595 additions and 298 deletions.
8 changes: 4 additions & 4 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
"preview": "vite preview"
},
"dependencies": {
"@sakura-ui/core": "^0.2.17",
"@sakura-ui/core": "^0.3.0-beta.1",
"@sakura-ui/forms": "^0.2.1",
"@sakura-ui/tailwind-theme-plugin": "^0.2.1",
"clsx": "^2.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"tailwindcss": "^3.4.11",
"clsx": "^2.1.0"
"tailwindcss": "^3.4.11"
},
"devDependencies": {
"@types/react": "^18.3.5",
Expand All @@ -25,6 +25,6 @@
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"typescript": "^5.4.5",
"vite": "^5.3.5"
"vite": "^5.4.11"
}
}
68 changes: 23 additions & 45 deletions examples/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -476,85 +476,63 @@ const Home = () => {
<div className="my-4">
<H2>Link Buttons</H2>
<Button className="mr-2">Normal button</Button>
<Button
as="a"
className="mr-2"
href="https://google.com"
target="_blank"
>
Link button
<Button className="mr-2" asChild>
<a href="https://google.com">Link button</a>
</Button>
<IconButton
as="a"
className="mr-2"
target="_blank"
icon="open_in_new"
iconLayout="right"
variant="secondary"
asChild
>
Link icon button
<a href="https://google.com" target="_blank">
Link icon button
</a>
</IconButton>
<Button
as="a"
size="md"
className="mr-2"
href="https://google.com"
target="_blank"
variant="secondary"
>
Link button
<Button size="md" className="mr-2" variant="secondary" asChild>
<a href="https://google.com">Link button</a>
</Button>
<IconButton
as="a"
size="md"
className="mr-2"
target="_blank"
icon="open_in_new"
iconLayout="right"
asChild
>
Link icon button
<a href="https://google.com" target="_blank">
Link icon button
</a>
</IconButton>
</div>
<div className="my-4">
<Button
as="a"
size="md"
className="mr-2"
href="https://google.com"
target="_blank"
>
Link button
<Button size="md" className="mr-2" asChild>
<a href="https://google.com">Link button</a>
</Button>
<IconButton
as="a"
size="sm"
className="mr-2"
target="_blank"
icon="open_in_new"
iconLayout="right"
variant="secondary"
asChild
>
Link icon button
<a href="https://google.com" target="_blank">
Link icon button
</a>
</IconButton>
<Button
as="a"
size="sm"
className="mr-2"
href="https://google.com"
target="_blank"
variant="secondary"
>
Link button
<Button size="sm" className="mr-2" variant="secondary" asChild>
<a href="https://google.com">Link button</a>
</Button>
<IconButton
as="a"
size="xs"
className="mr-2"
target="_blank"
icon="open_in_new"
iconLayout="right"
>
Link icon button
<a href="https://google.com" target="_blank">
Link icon button
</a>
</IconButton>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sakura-ui/core",
"version": "0.2.17",
"version": "0.3.0-beta.1",
"description": "",
"keywords": [
"react",
Expand Down
18 changes: 13 additions & 5 deletions packages/core/src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
import { type ComponentWithAs, cx, forwardRef } from '@sakura-ui/helper'
import React, { type ComponentProps } from 'react'
import { cx } from '@sakura-ui/helper'
import {
type ButtonVariant,
type ButtonSize,
base,
getVariantStyle,
getSizeStyle
} from './buttonStyle'
import { Slot } from './Slot'

export interface ButtonProps {
export type ButtonProps = {
className?: string
variant?: ButtonVariant
size?: ButtonSize
}
} & (
| ({ asChild?: false } & ComponentProps<'button'>)
| { asChild: true; children: React.ReactNode }
)

export const Button: ComponentWithAs<'button', ButtonProps> = forwardRef(
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const {
as: Component = 'button',
asChild,
variant = 'solid-fill',
size = 'lg',
className,
children,
...restProps
} = props

const Component = asChild ? Slot : 'button'

return (
<Component
className={cx(
Expand Down
13 changes: 2 additions & 11 deletions packages/core/src/components/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,10 @@ import { cx } from '@sakura-ui/helper'
export interface IconProps extends React.ComponentPropsWithRef<'span'> {
opticalSize?: 16 | 20 | 24 | 40 | 44 | 48
altText?: string
/** @deprecated instead of using this property, set the text to children. */
icon?: string
}

export const Icon = React.forwardRef<HTMLElement, IconProps>((props, ref) => {
const {
className,
icon,
altText = '',
opticalSize = 24,
children,
...rest
} = props
const { className, altText = '', opticalSize = 24, children, ...rest } = props

const size = {
16: '!text-[16px]',
Expand Down Expand Up @@ -61,7 +52,7 @@ export const Icon = React.forwardRef<HTMLElement, IconProps>((props, ref) => {
{...rest}
ref={ref}
>
{icon ?? children}
{children}
</span>
<span className="sr-only">{altText}</span>
</>
Expand Down
59 changes: 35 additions & 24 deletions packages/core/src/components/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import { type ComponentWithAs, cx, forwardRef } from '@sakura-ui/helper'
import React, { type ComponentProps } from 'react'
import { cx } from '@sakura-ui/helper'
import {
base,
getVariantStyle,
getSizeStyle,
type ButtonVariant,
type ButtonSize
} from './buttonStyle'
import { Slot } from './Slot'

export interface IconButtonProps {
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 const IconButton: ComponentWithAs<'button', IconButtonProps> =
forwardRef((props, ref) => {
export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
(props, ref) => {
const {
as: Component = 'button',
asChild,
variant = 'solid-fill',
size = 'lg',
iconLayout = 'left',
Expand All @@ -29,6 +35,8 @@ export const IconButton: ComponentWithAs<'button', IconButtonProps> =
...restProps
} = props

const Component = asChild ? Slot : 'button'

const styleFontSize = `${size === 'xs' ? 'scale-105' : 'scale-125'}`

const styleIcon = `
Expand Down Expand Up @@ -58,25 +66,28 @@ export const IconButton: ComponentWithAs<'button', IconButtonProps> =
{...restProps}
ref={ref}
>
{iconLayout === 'left' && (
<span
className={cx(styleIcon, styleFontSize)}
aria-hidden={ariaHidden}
>
{icon}
</span>
)}
{children && <span className="mx-1">{children}</span>}
{iconLayout === 'right' && (
<span
className={cx(styleIcon, styleFontSize)}
aria-hidden={ariaHidden}
>
{icon}
</span>
)}
<span>
{iconLayout === 'left' && (
<span
className={cx(styleIcon, styleFontSize)}
aria-hidden={ariaHidden}
>
{icon}
</span>
)}
{children && <span className="mx-1">{children}</span>}
{iconLayout === 'right' && (
<span
className={cx(styleIcon, styleFontSize)}
aria-hidden={ariaHidden}
>
{icon}
</span>
)}
</span>
</Component>
)
})
}
)

IconButton.displayName = 'IconButton'
49 changes: 26 additions & 23 deletions packages/core/src/components/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import {
type ComponentWithAs,
cx,
forwardRef,
styleUnderline,
styleFocusRoundedWithBg
} from '@sakura-ui/helper'
import React, { type ComponentProps } from 'react'
import { cx, styleUnderline, styleFocusRoundedWithBg } from '@sakura-ui/helper'
import { Icon } from './Icon'
import { Slot } from './Slot'

// biome-ignore lint/suspicious/noEmptyInterface:
export interface LinkProps {}
export type LinkProps = {
className?: string
} & (
| ({ asChild?: false } & ComponentProps<'a'>)
| {
asChild: true
children: React.ReactNode
}
)

export const Link: ComponentWithAs<'a', LinkProps> = forwardRef(
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
(props, ref) => {
const { as: Component = 'a', href, className, children, ...rest } = props
const { asChild, className, children, ...rest } = props

const Component = asChild ? Slot : 'a'

// Make lines break at each word
const style = `
Expand All @@ -26,11 +31,19 @@ export const Link: ComponentWithAs<'a', LinkProps> = forwardRef(
[overflow-wrap:anywhere]
`

if (href?.startsWith('http') || props.target === '_blank') {
// This assumes the use of next/link or gatsby-link.
if (asChild) {
return (
<Component className={cx(style, className)} {...rest} ref={ref}>
{children}
</Component>
)
}

if (props.href?.startsWith('http') || props.target === '_blank') {
return (
<Component
className={cx(style, className)}
href={href}
target="_blank"
rel="noopener noreferrer"
{...rest}
Expand All @@ -43,16 +56,6 @@ export const Link: ComponentWithAs<'a', LinkProps> = forwardRef(
</Component>
)
}
return (
<Component
className={cx(style, className)}
href={href}
{...rest}
ref={ref}
>
{children}
</Component>
)
}
)

Expand Down
Loading

0 comments on commit 6741650

Please sign in to comment.