react-frame-component icon indicating copy to clipboard operation
react-frame-component copied to clipboard

Add documentation on various techniques of handling CSS

Open ryanseddon opened this issue 1 year ago • 8 comments

This project gets a lot of questions on how to make CSS work inside the iframe from various CSS-in-JS libraries to CSS modules, SCSS etc.

Add some good examples covering how this can be done in the read me.

See latest issue with demo and code examples on solving that.

ryanseddon avatar Mar 17 '23 03:03 ryanseddon

For Next.js and tailwindCSS, I cannot guarantee it will work consistently

  const { document: doc } = useFrame();

  useLayoutEffect(() => {
    // this covers development case as well as part of production
    document.head.querySelectorAll("style").forEach((style) => {
      const frameStyles = style.cloneNode(true);
      doc?.head.append(frameStyles);
    });
   // inject the production minified styles into the iframe
    if (process && process.env.NODE_ENV === "production") {
      document.head.querySelectorAll('link[as="style"]').forEach((ele) => {
        doc?.head.append(ele.cloneNode(true));
      });
      document.head
        .querySelectorAll('link[rel="stylesheet"]')
        .forEach((ele) => {
          doc?.head.append(ele.cloneNode(true));
        });
    }
  }, [doc]);

aboveyunhai avatar Apr 07 '23 16:04 aboveyunhai

@aboveyunhai What version of next and what version of this lib are you running?

I'm running 13.1.1 and 5.2.6. All I get is a blank screen. If I regress to 4.1.3 of the lib. It works, but then I don't get the useFrame helper.

Found out here, that it's possibly a state issue: https://github.com/ryanseddon/react-frame-component/issues/192

I have partial success but then

const { document: doc } = useFrame();

Outputs the same as document. Both giving the same parent html and not the parent AND iframe.

Too many issues. If you could supply the full code, would be great! Thanks

paulm17 avatar Apr 12 '23 13:04 paulm17

@paulm17 it's a react issue, you need to call useFrame() inside the <Frame /> instead of at the same level.

const Inner = () => {
 useFrame();
}

const Outer = () => {
// useFrame();    call hook here will fail because it's outside of <Frame />

<Frame>
 <Inner/>
</Frame>
}

aboveyunhai avatar Apr 12 '23 14:04 aboveyunhai

@aboveyunhai Thanks for the quick reply.

That's what I needed, I've written a wrapper function.

My code in case this helps someone else.

interface wrapperProps {
  children: React.ReactNode
}

function Wrapper({children}: wrapperProps) {
  const { document: doc } = useFrame();

  document.head.querySelectorAll("style").forEach((style) => {
    const frameStyles = style.cloneNode(true);
    doc?.head?.append(frameStyles);
  });   

  return <>{children}</>
}

This is how I'm using it in my proof of concept app.

const Home: NextPage = () => {  
  const [isMounted, setMounted] = useState(false)
  
  useEffect(() => {
    setMounted(true)
  }, [])

  return (
    <>
      <Head>
        <title>Create T3 App</title>
        <meta name="description" content="Generated by create-t3-app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      {isMounted && <Frame    
        id="frame"    
        style={{
          border: "none",
          width: "100%",
          height: "100vh",
        }}
      >
        <Wrapper>
          <Sortable/>       
        </Wrapper>
      </Frame>}
    </>
  );
};

I saw the examples from @ryanseddon but perhaps they work for CRA only? 🤷‍♂️

Anyway, I now have the latest 5.2.6 working with the help from the other thread.

paulm17 avatar Apr 12 '23 15:04 paulm17

@paulm17 you are missing my production insert part, so it will only work on dev, if you use build step npm run build, npm run start, the production probably will miss all the stylings.

aboveyunhai avatar Apr 12 '23 17:04 aboveyunhai

proof of concept app.

Thanks, but you missed the part where I said ^. The app won't ever see production.

paulm17 avatar Apr 12 '23 17:04 paulm17