Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SkeletonPlaceholder.Item not rendered if wrapped in another component #124

Open
canpoyrazoglu opened this issue Sep 14, 2023 · 1 comment

Comments

@canpoyrazoglu
Copy link

In my SkeletonPlaceholder if I use SkeletonPlaceholder.Item anywhere its fine. Here is how it works:

<SkeletonPlaceholder.Item width={40} height={16} />

I want to wrap it in a commonly used way so I created this to skip rewriting props each time (and to be able to manage):


type TextPlaceholderProps = {
  width?: number;
};
function TextPlaceholder(props: TextPlaceholderProps) {
  const width = props.width ?? 40;

  return <SkeletonPlaceholder.Item height={16} width={width} />;
}

However, that doesn't render even though it's the exact same component.

@matthewtory
Copy link

Also running into this problem. I came up with a sort of workaround. Not super happy with this, but it seems to work.

Instead of creating reusable components, create reusable markup functions.

Example:

// SkeletonMarkup.tsx

export type SkeletonMarkupFunction<T extends object = {}> = (
  options: {
    theme: Theme;
    props?: React.ComponentProps<typeof SkeletonPlaceholder.Item>;
  } & T,
) => JSX.Element;

export const SkeletonMarkup: Record<string, SkeletonMarkupFunction<any>> = {
  text(options) {
    return (
      <SkeletonPlaceholder.Item
        height={options.theme.textVariants.body.lineHeight}
        width={100}
        {...options.props}
      />
    );
  },
  // Other "globally" reusable skeleton components go here
};

// Avatar.tsx

export const Avatar = () => { <>...</> }

const skeletonMarkup: SkeletonMarkupFunction<{size: AvatarSize}> = ({
  props,
  size
}) => {
  const resolvedSize = AVATAR_SIZES[size];

  return <SkeletonPlaceholder.Item
    {...props}
    width={resolvedSize}
    height={resolvedSize}
    borderRadius={resolvedSize / 2}
  />
}
Avatar.skeletonMarkup = skeletonMarkup;

// Header.tsx – a component I want a complex skeleton for

export const Header = () => { <>...</> }

const skeletonMarkup: SkeletonMarkupFunction = ({theme, props}) => {
  return <SkeletonPlaceholder.Item 
    {...props}>
    {SkeletonMarkup.text({theme, props: {marginButton: 12}})}
    {SkeletonMarkup.text({theme, props: {marginButton: 12}})}
    {Avatar.skeletonMarkup({theme, size: 'sm'})}
  </SkeletonPlaceholder.Item>
}
Header.skeletonMarkup = skeletonMarkup;

// Screen.tsx

const Screen = () => {
  const theme = useTheme();
  
  if(loading) {
    return <SkeletonPlaceholder>
      {Header.skeletonMarkup({theme, marginButton: 12})}
      <SkeletonPlaceholder.Item height={300} width={300} />
    </SkeletonPlaceholder/>
  }

  ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants