Morphin
Introduction
Button
Chip
Input
Searchbar
Sidebar

Button

Mn Button uses Tamagui button and add ablility to add loading state and shaped button (square)

Code

import { Separator, XStack, YStack } from 'tamagui'
import { MnButton } from 'yourpath/ui'

const DemoButton = () => {
  return (
    <>
      <YStack
        minHeight={250}
        overflow="hidden"
        margin="$3"
        padding="$2"
        justifyContent="space-between"
      >
        <XStack gap={'$4'}>
          <MnButton loading>Loading</MnButton>
          <MnButton size={'$10'}>Normal Button</MnButton>
          <MnButton size={'$10'} circular>
            A
          </MnButton>
        </XStack>

        <XStack gap={'$2'}>
          <XStack gap={'$4'}>
            <MnButton size={'$1'} circular>
              A
            </MnButton>
            <MnButton size={'$2'} circular>
              B
            </MnButton>
            <MnButton size={'$3'} circular>
              C
            </MnButton>

            <MnButton size={'$4'} circular>
              D
            </MnButton>
            <MnButton size={'$5'} circular>
              E
            </MnButton>
            <MnButton size={'$6'} circular>
              F
            </MnButton>
          </XStack>

          <XStack gap={'$4'}>
            <MnButton size={'$6'} square>
              F
            </MnButton>
            <MnButton size={'$5'} square>
              E
            </MnButton>
            <MnButton size={'$4'} square>
              D
            </MnButton>
            <MnButton size={'$3'} square>
              C
            </MnButton>
            <MnButton size={'$2'} square>
              B
            </MnButton>
            <MnButton size={'$1'} square>
              A
            </MnButton>
          </XStack>
        </XStack>
      </YStack>
    </>
  )
}

export default DemoButton

Props

MnButton
Prop NameTypeDescription
loadingbooleanRender a right (default) icon inside the button
loadingIconIconProps (default is spinner)Render a right (default) loading icon inside the button
loadingIconAligment"left" | "right"Render a right or left (default) loading icon inside the button
squarebooleanIf true than renders square button
extendsButton (ButtonProps) = MnButton (MnButtonProps)It extends all the props from Button

Button Code

import { SizeTokens, styled, TokensParsed } from '@tamagui/web'
import { FunctionComponent } from 'react'
import { Button, ButtonProps, getTokens, Spinner } from 'tamagui'

type InputComponentIconProps = { color?: any; size?: any }
type IconProp = JSX.Element | FunctionComponent<InputComponentIconProps> | null

export interface IMnButtonProps extends ButtonProps {
  loading?: boolean
  loadingIcon?: IconProp
  loadingIconAligment?: 'left' | 'right'
  square?: boolean
}

export const getSquareShapeSize = (size, { tokens }) => {
  const width = tokens.size[size] ?? size
  const height = tokens.size[size] ?? size

  return {
    width,
    height,
    minWidth: width,
    maxWidth: width,
    maxHeight: height,
    minHeight: height,
    padding: 0,
  }
}

const getShapeSize = ({
  size,
  tokens,
  shape,
}: {
  size: number | SizeTokens | undefined
  tokens: TokensParsed
  shape?: 'square'
}) => {
  if (!shape) {
    return {}
  }

  return getSquareShapeSize(size, {
    tokens,
  })
}

export const MnButton = (props: IMnButtonProps) => {
  const {
    loading = false,
    loadingIcon = Spinner,
    loadingIconAligment,
    children,
    square = false,
    ...rest
  } = props

  const size = props.size || (props.unstyled ? undefined : '$true')

  const tokens = getTokens({ prefixed: true })
  const shapeSize = getShapeSize({
    size,
    tokens,
    shape: square ? 'square' : undefined,
  })

  return (
    // @ts-ignore
    <Button
      size={size}
      {...rest}
      disabled={loading}
      {...(loading
        ? loadingIconAligment === 'left'
          ? { left: Spinner, opacity: 0.5 }
          : { iconAfter: Spinner, opacity: 0.5 }
        : {})}
      {...(square && shapeSize)}
    >
      {children}
    </Button>
  )
}