Skip to content

Invalid CSS when using Button wrapped with Popover and layer enabled #195

Open
@ethos-vitalii

Description

I use Next.js with antd and @ant-design/nextjs-registry:

<AntdRegistry layer>
  ...
    <Popover title="smth" content="smth" trigger="click">
      <Button>Smth</Button>
    </Popover>
  ...
</AntdRegistry>

AntdRegistry internally wraps everything in StyleProvider and uses extractStyle. I've noticed that whenever Popover is wrapping a button on any page, extractStyle returns an invalid CSS. Here's an example:

...

.css-var-R2cq.ant-popover {
  --ant-popover-title-min-width: 177px;
  --ant-popover-z-index-popup: 1030;
  --ant-popover-arrow-shadow-width: 8.970562748477143px;
  --ant-popover-arrow-path: path('M 0 8 A 4 4 0 0 0 2.82842712474619 6.82842712474619 L 6.585786437626905 3.0710678118654755 A 2 2 0 0 1 9.414213562373096 3.0710678118654755 L 13.17157287525381 6.82842712474619 A 4 4 0 0 0 16 8 Z');
  --ant-popover-arrow-polygon: polygon(1.6568542494923806px 100%, 50% 1.6568542494923806px, 14.34314575050762px 100%, 1.6568542494923806px 100%);
  --ant-popover-arrow-offset-horizontal: 12px;
  --ant-popover-arrow-offset-vertical: 8px;
  --ant-popover-inner-padding: 12px;
  --ant-popover-title-margin-bottom: 8px;
  --ant-popover-title-padding: 0px;
  --ant-popover-title-border-bottom: none;
  --ant-popover-inner-content-padding: 0px;
}

@layer antd@layer antd { /* Here's the problem it includes "@layer antd" twice */
  .ant-progress { /* I have Progress component in a different place on that page */
    font-family: var(--ant-font-family);
    font-size: var(--ant-font-size);
    box-sizing: border-box;
  }

...

@Kiyumi-v reproduced the problem here ant-design/ant-design#49853 (comment) (you might find more details about the issue there).

Workaround

So far, the workaround is to copy the AntdRegistry component and modify the extracted styles not to include duplication of @layer antd@layer antd and replace with one @layer antd.

const AntdRegistry: FC<AntdRegistryProps> = (props) => {
  const [cache] = useState(() => createCache());
  const inserted = useRef(false);

  useServerInsertedHTML(() => {
    let styleText = extractStyle(cache, { plain: true });

    if (inserted.current) {
      return null;
    }
    inserted.current = true;

+   styleText = styleText.replaceAll(/@layer antd@layer antd/g, '@layer antd');

    return (
      <style
        id="antd-cssinjs"
        // to make sure this style is inserted before Ant Design's style generated by client
        data-rc-order="prepend"
        data-rc-priority="-1000"
        dangerouslySetInnerHTML={{ __html: styleText }}
      />
    );
  });

  return <StyleProvider {...props} cache={cache} />;
};

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions