Source

adminjs-design-system/src/atoms/input.tsx

  1. import styled, { css } from 'styled-components'
  2. import { rgba } from 'polished'
  3. import { space, SpaceProps, layout, LayoutProps, variant } from 'styled-system'
  4. import focusShadowStyle from '../utils/focus-shadow.style'
  5. import { cssClass } from '../utils/css-class'
  6. const borderlessCSS = css`
  7. padding: 0;
  8. border-color: transparent;
  9. border-width: 0 0 1px 0;
  10. color: ${({ theme }) => theme.colors.grey100};
  11. &:focus {
  12. box-shadow: none;
  13. border-bottom: 1px solid ${({ theme }): string => theme.colors.inputBorder};
  14. }
  15. &:hover {
  16. cursor: pointer;
  17. }
  18. `
  19. const sizeVariants = variant({
  20. prop: 'variant',
  21. variants: {
  22. default: {
  23. fontSize: 'default',
  24. lineHeight: 'lg',
  25. },
  26. sm: {
  27. fontSize: 'sm',
  28. lineHeight: 'default',
  29. },
  30. lg: {
  31. fontSize: 'lg',
  32. lineHeight: 'xl',
  33. },
  34. xl: {
  35. fontSize: 'xl',
  36. lineHeight: 'xxl',
  37. },
  38. xxl: {
  39. fontSize: 'h1',
  40. fontWeight: 'light',
  41. lineHeight: 'x4',
  42. },
  43. },
  44. })
  45. /**
  46. * Input CSS Styles which can be reused in another input component with styled-components
  47. *
  48. * ### Usage:
  49. *
  50. * ```
  51. * import { InputCSS } from '@adminjs/design-system'
  52. *
  53. * const MyStyledInput = styled.input`
  54. * ${InputCSS}
  55. * `
  56. * ```
  57. * @memberof Input
  58. * @alias InputCSS
  59. */
  60. export const InputCSS = css<InputProps>`
  61. box-sizing: border-box;
  62. color: ${({ theme }): string => theme.colors.grey80};
  63. background: transparent;
  64. border: 1px solid ${({ theme }): string => theme.colors.inputBorder};
  65. font-size: ${({ theme }): string => theme.fontSizes.default};
  66. line-height: ${({ theme }): string => theme.lineHeights.lg};
  67. font-family: ${({ theme }): string => theme.font};
  68. outline: none;
  69. &:hover {
  70. border-color: ${({ theme }): string => theme.colors.grey60};
  71. }
  72. &:focus {
  73. border-color: ${({ theme }): string => theme.colors.primary100};
  74. ${({ theme }): string => `box-shadow: ${focusShadowStyle(theme)}`};
  75. }
  76. &:disabled {
  77. color: ${({ theme }): string => rgba(theme.colors.grey80, 0.5)};
  78. border-color: ${({ theme }): string => rgba(theme.colors.inputBorder, 0.5)};
  79. }
  80. ${({ borderless }): any => (borderless ? borderlessCSS : '')};
  81. ${sizeVariants};
  82. `
  83. /**
  84. * Prop Types of an Input component.
  85. * Apart from variant it extends all {@link LayoutProps} and {@link SpaceProps}
  86. *
  87. * @memberof Input
  88. * @alias InputProps
  89. * @property {string} [...] Other props from {@link LayoutProps}, {@link SpaceProps}
  90. */
  91. export type InputProps = SpaceProps & LayoutProps & {
  92. borderless?: boolean;
  93. variant?: 'sm' | 'lg' | 'xl' | 'default' | 'xxl';
  94. }
  95. /**
  96. * @classdesc
  97. *
  98. * <img src="components/input.png" />
  99. *
  100. * Wrapped `input` html element.
  101. *
  102. * ### Usage
  103. *
  104. * ```javascript
  105. * import { Input, InputProps, InputCSS } from '@adminjs/design-system'
  106. * ```
  107. *
  108. * @component
  109. * @subcategory Atoms
  110. * @see InputProps
  111. * @see {@link https://storybook.adminjs.co/?path=/story/designsystem-atoms-input--default Storybook}
  112. * @hideconstructor
  113. * @example
  114. * return (
  115. * <Box p="xl">
  116. * <Label htmlFor="input1">Some example label</Label>
  117. * <Input id="input1" width={1/2} />
  118. * </Box>
  119. * )
  120. * @section design-system
  121. */
  122. const Input = styled.input<InputProps>`
  123. ${InputCSS};
  124. ${space};
  125. ${layout};
  126. `
  127. Input.defaultProps = {
  128. px: 'default',
  129. py: 'sm',
  130. className: cssClass('Input'),
  131. }
  132. export { Input }
  133. export default Input