Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "stage-ui",
"author": "Script Heads",
"version": "0.7.58",
"version": "0.7.63",
"license": "MIT",
"private": true,
"workspaces": [
Expand Down
36 changes: 33 additions & 3 deletions packages/core/control/Button/PolymorphicButton.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
/* eslint-disable react/button-has-type */
/* eslint-disable react/destructuring-assignment */
import React, {
ComponentProps,
forwardRef,
ForwardRefRenderFunction,
HTMLProps,
MouseEvent,
PropsWithoutRef,
ReactChild,
ReactNode,
Ref,
Expand All @@ -28,21 +31,41 @@ type PropsToOmit<E extends PossibleElementType, P> = keyof (AsProp<E> & P)

type PolymorphicRef<E extends PossibleElementType> = React.ComponentPropsWithRef<E>['ref']

type Props<E extends PossibleElementType> = ButtonTypes.PolymorphicProps &
type Props<E extends PossibleElementType> = ButtonTypes.PolymorphicProps<E> &
AsProp<E> &
Omit<React.ComponentPropsWithoutRef<E>, PropsToOmit<E, ButtonTypes.PolymorphicProps>>
Omit<React.ComponentPropsWithoutRef<E>, PropsToOmit<E, ButtonTypes.PolymorphicProps<E>>>

const PolymorphicButtonComponent = <E extends PossibleElementType = 'button'>(
props: Props<E>,
ref: PolymorphicRef<E>,
) => {
let { leftChild, rightChild, children, as = 'button', style, ...restProps } = props
let {
leftChild,
rightChild,
children,
as = 'button',
style,
disabled,
onClick,
...restProps
} = props
const { classes, attributes, events, styleProps } = useSystem(
'PolymorphicButton',
props,
createClasses,
)

const handleOnClick = (e: MouseEvent<PropsWithoutRef<ComponentProps<E>>>) => {
if (disabled) {
e.preventDefault()
return
}
if (onClick) {
onClick?.(e)
return
}
}

return jsx(as, {
...attributes,
...events,
Expand All @@ -56,7 +79,14 @@ const PolymorphicButtonComponent = <E extends PossibleElementType = 'button'>(
</>
),
ref,

onClick: handleOnClick,

...restProps,

...(disabled && {
tabIndex: -1,
}),
})
}

Expand Down
19 changes: 8 additions & 11 deletions packages/core/control/Button/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ import { colorProp } from '@stage-ui/system'

import Types from './types'

const styles: Stage.CreateClasses<Types.Classes, Types.Props | Types.PolymorphicProps> = (
theme,
props,
) => {
const {
size = 'm',
decoration = 'filled',
shape = 'rounded',
disabled,
uppercase,
} = props
const styles: Stage.CreateClasses<
Types.Classes,
Types.Props | Types.PolymorphicProps<any>
> = (theme, props) => {
const { size = 'm', decoration = 'filled', shape = 'rounded' } = props
const disabled = 'disabled' in props ? props.disabled : undefined
const uppercase = 'uppercase' in props ? props.uppercase : undefined

const color = colorProp(props.color, theme) || theme.color.primary
const isDark = color.contrast(theme.color.onPrimary) > 2.4

Expand Down
102 changes: 50 additions & 52 deletions packages/core/control/Button/types.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,60 @@
import React from 'react'
import React, { ComponentPropsWithoutRef } from 'react'

declare namespace ButtonTypes {
type Decoration = 'filled' | 'outline' | 'text' | 'plain'
type Shape = 'square' | 'rounded' | 'round'
type Type = 'submit' | 'reset' | 'button'
type ChildAlign = 'left' | 'right'
interface Props extends Stage.AllProps<HTMLButtonElement, Classes> {

interface SharedProps {
/**
* Specifies that the button should have input focus when the page loads
* Sizes of button
* @display Sizes
* @link /props/#size
* @default m
*/
autoFocus?: boolean
size?: Stage.Sizes
/**
* Defines how button look
* @default filled
*/
decoration?: Decoration
/**
* Shape of button
* @default rounded
*/
shape?: Shape

/**
* Color of button
*/
color?: Stage.ColorProp

/**
* same as label
*/
children?: React.ReactNode
/**
* Place for items to the right of children
*/
rightChild?: React.ReactNode
/**
* Place for items to the left of children
*/
leftChild?: React.ReactNode

/**
* Prevents the user from interacting with the button
*/
disabled?: boolean
}

interface Props extends Stage.AllProps<HTMLButtonElement, Classes>, SharedProps {
/**
* Specifies that the button should have input focus when the page loads
*/
autoFocus?: boolean

/**
* The <form> element to associate the button with
*/
Expand Down Expand Up @@ -53,47 +94,16 @@ declare namespace ButtonTypes {
*/
value?: string | string[] | number

/**
* Sizes of button
* @display Sizes
* @link /props/#size
* @default m
*/
size?: Stage.Sizes
/**
* Defines how button look
* @default filled
*/
decoration?: Decoration
/**
* Shape of button
* @default rounded
*/
shape?: Shape
/**
* Make button's text uppercase
*/
uppercase?: boolean
/**
* Color of button
*/
color?: Stage.ColorProp

/**
* Button's label
*/
label?: React.ReactNode
/**
* same as label
*/
children?: React.ReactNode
/**
* Place for items to the right of children
*/
rightChild?: React.ReactNode
/**
* Place for items to the left of children
*/
leftChild?: React.ReactNode

/**
* Async onClick
*/
Expand All @@ -105,21 +115,9 @@ declare namespace ButtonTypes {
loadingComponent?: React.ReactNode
}

interface PolymorphicProps
extends Pick<
Props,
| 'leftChild'
| 'rightChild'
| 'type'
| 'size'
| 'shape'
| 'disabled'
| 'uppercase'
| 'decoration'
| 'color'
| 'children'
| 'style'
> {}
interface PolymorphicProps<E extends React.ElementType>
extends Stage.AllProps<React.ComponentPropsWithoutRef<E>, Classes>,
SharedProps {}

type Classes = {
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@stage-ui/core",
"description": "Flexible UI components library declared by your own Design System.",
"version": "0.7.58",
"version": "0.7.63",
"license": "MIT",
"homepage": "https://stageui.shds.io/",
"bugs": "https://github.com/script-heads/stage-ui/issues",
Expand Down
2 changes: 1 addition & 1 deletion packages/icons/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@stage-ui/icons",
"description": "Flexible UI components library declared by your own Design System.",
"version": "0.7.58",
"version": "0.7.63",
"license": "MIT",
"homepage": "https://stageui.shds.io/",
"bugs": "https://github.com/script-heads/stage-ui/issues",
Expand Down
2 changes: 1 addition & 1 deletion packages/system/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@stage-ui/system",
"description": "Flexible UI components library declared by your own Design System.",
"version": "0.7.58",
"version": "0.7.63",
"license": "MIT",
"homepage": "https://stageui.shds.io/",
"bugs": "https://github.com/script-heads/stage-ui/issues",
Expand Down
83 changes: 70 additions & 13 deletions packages/testbed/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,77 @@
import { light } from './theme'
import { DatePicker, Modal, modal, Viewport } from '@stage-ui/core'
import {
Button,
DatePicker,
Drop,
Modal,
modal,
PolymorphicButton,
ReactFocusTrap,
TextField,
Viewport,
} from '@stage-ui/core'
import ReactDOM from 'react-dom'
import { useState } from 'react'
import { useState, useEffect, useRef, HTMLProps } from 'react'
import LinkTypes from '@stage-ui/core/content/Link/types'
import ButtonTypes from '@stage-ui/core/control/Button/types'

const App: React.FC = () => {
const handleOpen = () => {
modal({
preventEscapeClose: true,
render: () => {
return <>123</>
},
overlayClose: false,
})
}

return null
const [open, setOpen] = useState(false)
const debouncedOpen = useDebounce(open, 1000)
const targetRef = useRef(null)

const linkProps: ButtonTypes.PolymorphicProps<'a'> = {}
return (
<div>
<button onClick={() => setOpen(true)}> focus </button>

<div ref={targetRef}>123</div>

<PolymorphicButton
disabled
as="a"
href={''}
leftChild={
<img
src="https://ismart-files.storage.yandexcloud.net/image_1_6c2cab5b4a.svg"
alt="yandex"
/>
}
style={(t) => ({
cursor: 'pointer',
textDecoration: 'none !important',
width: '100%',
fontSize: '1.125rem',
color: `${t.color.gray[900].string()} !important`,
'&:hover': {
backgroundColor: t.color.gray[100].string(),
},
})}
borderColor="border"
decoration="outline"
size="xl"
{...linkProps}
>
Продолжить с Яндекс ID
</PolymorphicButton>
</div>
)
}

export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)

useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value)
}, delay)

return () => {
clearTimeout(handler)
}
}, [value, delay])

return debouncedValue
}

ReactDOM.render(
Expand Down