
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@qyu/reactcmp-modal
Advanced tools
React component library for modal. Includes focus-management, animations, accessibility
// import styles with your bundler or copy them by hand and reference in your html
import "@qyu/reactcmp-modal/style/index.global"
// append modal root
const modalroot = document.createElement("div")
// modal-root is default id for modal target, if you choose that id it will be used as default for portal targets
modalroot.setAttribute("id", "modal-root")
document.body.append(modalroot)
function App() {
// register layers context - required, will throw if not done
return <CmpContextLayersFilled>
<Page />
</CmpContextLayersFilled>
}
function Page() {
// register page as a layer - used to add accesibility, styles and control focus
// z = -1 as page is always lower than any modal
// active - shows if page is visible (eg. display: none), exists - shows if page is rendered at all
// istop represents if layer is top layer or not
const istop = useLayerStackTop({ z: -1, active: true, exists: true })
// used to control focus
const ref_root = r.useRef<HTMLDivElement | null>(null)
// focus controller will save focus when istop is changed to false and restore it back when istop is changed back
useFocusCapture({
active: istop,
target_new: r.useCallback(() => ref_root.current, [])
})
// apply layer order based customisations
return <div ref={ref_root} aria-hidden={!istop}>
<Toggle />
</div>
}
function Toggle() {
// modal show controlled declaratively
const [show, show_set] = r.useState(false)
return <>
<button onClick={() => show_set(true)}>
Hello World
</button>
{/* overlay is required wrapper for any modal - it registers layers, manages focus etc */}
<CmpOverlayInstant
show={show}
// optional, this represents existing z index, but does not affect anything in styles or render order
layer_z={1}
// optional, toggle if modal goes to not displayed. It will apply overlay_inactive styles (by default just make display: none)
layer_active={false}
// optional, target for modal portal, in this case optional as we have element with modal-root id that will be used by default
root={document.getElementById("modal-root")}
// optional, custom styles
styles={{
overlay: "myclassname"
// ...
}}
>
<CmpFG
// optional, required for custom modal close events to work
show_set={show_set}
// optional, custom styles
styles={{
foreground: "myclassname",
// ...
}}
// close events conditions, all optional, here represented with their default values
// close on foreground press
close_onpress={true}
// close on escape press
close_onescape={true}
// close on escape press event if event target is not directly foreground
close_onescape_global={true}
>
<div style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%) translateY(-50%);",
background: "white",
width: "200px",
height: "200px"
}}>
Foreground is focused. Press on it or press enter/space/escape to close
</div>
</CmpFG>
</CmpOverlayInstant>
</>
}
function ToggleAnimFade() {
// modal show controlled declaratively
const [show, show_set] = r.useState(false)
return <>
<button onClick={() => show_set(true)}>
Hello World
</button>
{/* Animated Overlay required for any animation */}
{/* Extends instant overlay properties so optional ones will be omited to not repeat */}
<CmpOverlayAnimated
show={show}
// animation moves from 0 to 1 linear. Velocity represents movement per ms
// optional, this animation will last 1/3 seconds. This is also default value
animation_velocity={3e-3}
// events, all optional
on_didhide={() => console.log("didhide")}
on_didshow={() => console.log("didshow")}
on_willshow={() => console.log("willshow")}
on_willhide={() => console.log("willhide")}
>
{/* Also extends all FG properties they also will be omited */}
{/* Opacty based fade animation */}
<CmpFGAnimFade
// lenear by default
// allows to add custom easing with bezier curve or any other function
easing={state => state * state}
>
<div style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%) translateY(-50%);",
background: "white",
width: "200px",
height: "200px"
}}>
Foreground is focused. Press on it or press enter/space/escape to close
</div>
</CmpFGAnimFade>
</CmpOverlayAnimated>
</>
}
List is poor so you might want to make custom one
// animations are signal based so need to use theese libraries
import * as sc from "@qyu/signal-core"
import * as sr from "@qyu/signal-react"
function FGAnimCustom(props: { children?: r.ReactNode }) {
const ref = r.useRef<HTMLDivElement | null>(null)
// get state signal from context, defined in CmpOverlayAnimated
const animstate = useContextAnimationGet()
// update styles
sr.useDOMStyleMap(
r.useCallback(() => ref.current, []),
r.useMemo(() => {
return sc.osignal_new_pipe(animstate, state => {
return {
opacity: `${state}`
}
})
}, [animstate])
)
// normal foreground
return <CmpFG ref={ref}>
{props.children}
</CmpFG>
}
FAQs
Generic Modal components for react
We found that @qyu/reactcmp-modal demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.