Repository: strapi/strapi
File: packages/core/admin/admin/src/components/UnstableGuidedTour/Step.tsx (TypeScript)

Code before:

type Step = {
  Root: React.ForwardRefExoticComponent<React.ComponentProps<typeof Popover.Content>>;
  Title: (props: StepProps) => React.ReactNode;
  Content: (props: StepProps) => React.ReactNode;
  Actions: (props: ActionsProps & { to?: string }) => React.ReactNode;
};

const ActionsContainer = styled(Flex)`
  border-top: ${({ theme }) => `1px solid ${theme.colors.neutral150}`};
`;

const PopoverArrowStandard = styled(Popover.Arrow)`
  fill: ${({ theme }) => `${theme.colors.neutral0}`};
`;

const createStepComponents = (tourName: ValidTourName): Step => ({
  Root: React.forwardRef((props, ref) => {
    const state = unstableUseGuidedTour('GuidedTourPopover', (s) => s.state);
    const currentStep = state.tours[tourName].currentStep + 1;
    return (
      <Popover.Content ref={ref} side="top" align="center" {...props}>
        <Flex width="360px" direction="column" alignItems="start">
          {props.children}
        </Flex>
        {currentStep > 1 && <PopoverArrowStandard width="20px" height="12px" />}
      </Popover.Content>
    );
  }),

  Title: (props) => {
    return (
      <Box paddingTop={5} paddingLeft={5} paddingRight={5} paddingBottom={1} width="100%">
        {'children' in props ? (
          props.children
        ) : (
          <Typography tag="div" variant="omega" fontWeight="bold">
            <FormattedMessage tagName="h1" id={props.id} defaultMessage={props.defaultMessage} />
          </Typography>
        )}
      </Box>
    );
  },

  Content: (props) => (
    <Box paddingBottom={5} paddingLeft={5} paddingRight={5} width="100%">
      {'children' in props ? (
        props.children
      ) : (
        <Typography tag="div" variant="omega">
          <FormattedMessage tagName="p" id={props.id} defaultMessage={props.defaultMessage} />

Review comment (suggestion):
I see what you did there, makes sense for our current setup but I think still would be better to either
- add a prop like `withArrow` that defaults to true since most cases have the arrow, and then set it to false on the ones that don't have it
- rely on composition and add the PopoverArrow directly in the steps that need it


Code after:
type ActionsProps = WithActionsChildren | WithActionsProps;

type Step = {
  Root: React.ForwardRefExoticComponent<
    React.ComponentProps<typeof Popover.Content> & { withArrow?: boolean }
  >;
  Title: (props: StepProps) => React.ReactNode;
  Content: (props: StepProps) => React.ReactNode;
  Actions: (props: ActionsProps & { to?: string }) => React.ReactNode;
};

const ActionsContainer = styled(Flex)`
  border-top: ${({ theme }) => `1px solid ${theme.colors.neutral150}`};
`;

/**
 * TODO:
 * We should probably move all arrow styles + svg to the DS
 */
const PopoverArrow = styled(Popover.Arrow)`
  fill: ${({ theme }) => theme.colors.neutral0};
  transform: translateY(-16px) rotate(-90deg);
`;

const createStepComponents = (tourName: ValidTourName): Step => ({
  Root: React.forwardRef(({ withArrow = true, ...props }, ref) => {
    return (
      <Popover.Content ref={ref} side="top" align="center" style={{ border: 'none' }} {...props}>
        {withArrow && (
          <PopoverArrow asChild>
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="23"
              height="25"
              viewBox="0 0 23 25"
              fill="none"
            >
              <path d="M11 24.5L1.82843 15.3284C0.266332 13.7663 0.26633 11.2337 1.82843 9.67157L11 0.5L23 12.5L11 24.5Z" />
            </svg>
          </PopoverArrow>
        )}
        <Flex width="360px" direction="column" alignItems="start">
          {props.children}
        </Flex>
      </Popover.Content>
    );
  }),

  Title: (props) => {
    return (
      <Box paddingTop={5} paddingLeft={5} paddingRight={5} paddingBottom={1} width="100%">