details.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import {useCallback, useEffect, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import Code from 'docs-ui/components/code';
  4. import BooleanField from 'sentry/components/forms/booleanField';
  5. import SelectField from 'sentry/components/forms/selectField';
  6. import space from 'sentry/styles/space';
  7. import {iconProps} from './data';
  8. import IconSample from './sample';
  9. import {ExtendedIconData} from './searchPanel';
  10. type Props = {
  11. icon: ExtendedIconData;
  12. };
  13. const Details = ({icon}: Props) => {
  14. // Editable icon props
  15. const [size, setSize] = useState(iconProps.size.default);
  16. const [direction, setDirection] = useState(
  17. icon.defaultProps?.direction ?? iconProps.direction.default
  18. );
  19. const [type, setType] = useState(icon.defaultProps?.type ?? iconProps.type.default);
  20. const [isCircled, setIsCircled] = useState(icon.defaultProps?.isCircled ?? false);
  21. const [isSolid, setIsSolid] = useState(icon.defaultProps?.isSolid ?? false);
  22. /**
  23. * Generate and update code sample based on prop states
  24. */
  25. const getCodeSample = useCallback(() => {
  26. return `<Icon${icon.name} color="gray500" size="${size}"${
  27. isCircled ? ' isCircled' : ' '
  28. }${isSolid ? ' isSolid' : ' '} />`;
  29. }, [icon.name, size, isCircled, isSolid]);
  30. const [codeSample, setCodeSample] = useState(getCodeSample());
  31. useEffect(() => void setCodeSample(getCodeSample()), [getCodeSample]);
  32. return (
  33. <Wrap>
  34. <SampleWrap>
  35. <IconSample
  36. name={icon.name}
  37. size={size}
  38. color="gray500"
  39. {...(icon.additionalProps?.includes('type') ? {type} : {})}
  40. {...(icon.additionalProps?.includes('direction') ? {direction} : {})}
  41. {...(isCircled ? {isCircled} : {})}
  42. {...(isSolid ? {isSolid} : {})}
  43. />
  44. </SampleWrap>
  45. <FieldContainer>
  46. <SelectField
  47. name="size"
  48. label="Size"
  49. defaultValue={iconProps.size.default}
  50. options={iconProps.size.options ?? []}
  51. onChange={(value: string) => setSize(value)}
  52. clearable={false}
  53. />
  54. {icon.additionalProps?.includes('direction') && (
  55. <SelectField
  56. name="direction"
  57. label="Direction"
  58. defaultValue={direction}
  59. options={iconProps.direction.options ?? []}
  60. onChange={(value: string) => setDirection(value)}
  61. clearable={false}
  62. />
  63. )}
  64. {icon.additionalProps?.includes('type') && (
  65. <SelectField
  66. name="type"
  67. defaultValue={type}
  68. options={iconProps.type.options ?? []}
  69. onChange={(value: string) => setType(value)}
  70. clearable={false}
  71. />
  72. )}
  73. {icon.additionalProps?.includes('isCircled') && (
  74. <BooleanField
  75. name="isCircled"
  76. label="Circled"
  77. value={isCircled}
  78. onChange={value => setIsCircled(value)}
  79. />
  80. )}
  81. {icon.additionalProps?.includes('isSolid') && (
  82. <BooleanField
  83. name="isSolid"
  84. label="Solid"
  85. value={isSolid}
  86. onChange={value => setIsSolid(value)}
  87. />
  88. )}
  89. </FieldContainer>
  90. <Code className="language-jsx">{codeSample}</Code>
  91. </Wrap>
  92. );
  93. };
  94. export default Details;
  95. const Wrap = styled('div')`
  96. max-width: 20rem;
  97. `;
  98. const SampleWrap = styled('div')`
  99. width: 100%;
  100. height: 4rem;
  101. display: flex;
  102. justify-content: center;
  103. align-items: center;
  104. margin: 0 auto ${space(3)};
  105. `;
  106. const FieldContainer = styled('div')`
  107. margin: -${space(2)};
  108. border-top: 1px solid ${p => p.theme.innerBorder};
  109. `;