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

[Feature Request] Config option for a custom node to attach toast notifications #117

Open
calebbergman opened this issue Nov 10, 2021 · 2 comments

Comments

@calebbergman
Copy link

calebbergman commented Nov 10, 2021

I have a vite project that utilizes postcss-scopify to scope styles to the application. This has the side effect of scoping 3rd party node_module package styles as well, such as notyf, which is generally ok. However, due to the fact that notyf defaults attaching the toast 'view' directly to the body, this leaves the toasts document fragment non-targetable by the postcss-scopify modified stylesheet selectors.

document.body.appendChild(docFrag);

One solution would be to have postcss-scopify ignore certain files, which I would love to be able to do, but alas I'm not that smart to figure out how to accomplish such a feat using the postcss.config.js file. One may be able to by some other means (such as in vite.config.ts) but I have not discovered this quite yet. See vite issue 4653

Another option would be to be allowed to manage where the toasts get attached to in the DOM, as this feature request suggests, either by passing a querySelector string or DOM Node. This would ensure that toasts get attached as a child to where they've been scoped to by postcss-scopify.

@calebbergman
Copy link
Author

calebbergman commented Nov 10, 2021

As a work around you can take advantage of dynamic module imports to re-create the original stylesheet at runtime. Not ideal, but works - while debugging, that is. See next comment for better solution.

import { Notyf } from 'notyf'
// import 'notyf/notyf.min.css'

import('notyf/notyf.min.css').then((module) => {
  // Remove scoped stylesheet from DOM
  const children = Array.from(document.head.childNodes)
  const scopedCss = children.reverse().find(c => c.textContent?.match(/notyf/))
  if (scopedCss)
    document.head.removeChild(scopedCss)
  
  // Remove scope from css
  const pattern = new RegExp('#my-custom-app-scope', 'gi')
  const css = module.default.replace(pattern, '')
  // Append updated stylesheet to DOM
  const style = document.createElement('style')
  style.setAttribute('type', 'text/css')
  style.setAttribute('id', 'notyf-stylesheet')
  style.innerText = css
  document.head.appendChild(style)
})

export default new Notyf({
  dismissible: true,
  duration: 5000,
})

@calebbergman
Copy link
Author

The above worked fine while debugging. Post build, when everything was bundled up, not-so-much. After some more Rollup/Vite learning, I came up with the following plugin to selectively undo postcss-scopify's affects.

// rollup-plugin-postcss-unscopify.js
export default function postCssUnscopify(options = {}) {
  const { patterns, scope } = options
  return {
    name: 'postcss-unscopify',

    transform(src, id) {
      const match = patterns.reduce((result, cur) => result || !!cur.test(id), false)
      if (match) {
        const regex = new RegExp(scope, 'gi')
        return {
          code: src.replace(regex, ''),
          map: null
        }
      }
    }
  }
}
// vite.config.js
import postCssUnscopify from './rollup-plugin-postcss-unscopify'
export default defineConfig({
  plugins: [
    postCssUnscopify({
      scope: '#my-custom-scope',
      patterns: [/.*ignore-me.*css/]
    })
  ]
})

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

1 participant