Common front-end components for Web using the Tesseract design system, written for React. https://make.modal.sh/tesseract/web/react/common
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

82 rivejä
2.0 KiB

  1. import * as React from 'react'
  2. import * as PropTypes from 'prop-types'
  3. import * as FeatherIcon from 'react-feather'
  4. import styled from 'styled-components'
  5. import { pascalCase, pascalCaseTransformMerge } from 'pascal-case'
  6. import splitValueAndUnit from '../../services/splitValueAndUnit'
  7. const Label = styled('span')({
  8. position: 'absolute',
  9. left: -999999,
  10. width: 1,
  11. height: 1,
  12. ':empty': {
  13. display: 'none',
  14. },
  15. })
  16. const StyledIcon = styled('svg')({
  17. stroke: 'currentColor',
  18. strokeLinecap: 'round',
  19. display: 'inline-block',
  20. verticalAlign: 'middle',
  21. })
  22. const propTypes = {
  23. /**
  24. * Name of the icon to display.
  25. */
  26. name: PropTypes.string.isRequired,
  27. /**
  28. * Width of the icon's strokes.
  29. */
  30. weight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  31. /**
  32. * Size of the icon. This controls both the width and the height.
  33. */
  34. size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  35. /**
  36. * Describe of what the component represents.
  37. */
  38. label: PropTypes.string,
  39. }
  40. type Props = PropTypes.InferProps<typeof propTypes>
  41. const Icon: React.FC<Props> = ({ name, weight = '0.125rem', size = '1.5rem', label = name }) => {
  42. const iconName = pascalCase(name, { transform: pascalCaseTransformMerge })
  43. const { [iconName as keyof typeof FeatherIcon]: TheIcon = null } = FeatherIcon
  44. const { magnitude: sizeValue, unit: sizeUnit } = splitValueAndUnit(size)
  45. const { magnitude: weightValue } = splitValueAndUnit(weight)
  46. const factor = weightValue * (3 / 2)
  47. if (TheIcon !== null) {
  48. return (
  49. <span>
  50. <StyledIcon
  51. as={TheIcon}
  52. size={undefined}
  53. color={undefined}
  54. strokeLinecap={undefined}
  55. strokeWidth={undefined}
  56. style={{
  57. width: size!,
  58. height: size!,
  59. strokeWidth: `${factor / sizeValue}${sizeUnit}`,
  60. }}
  61. aria-label={label!}
  62. />
  63. <Label aria-hidden="true">{label}</Label>
  64. </span>
  65. )
  66. }
  67. return null
  68. }
  69. Icon.propTypes = propTypes
  70. Icon.displayName = 'Icon'
  71. export default Icon