TSX
import React from "react"; import Draggable from 'react-draggable'; import classes from "./index.module.scss"; import clsx from "clsx"; interface GlassProps { isDark?: boolean; } const Glass = ({ isDark = true }: GlassProps) => { return ( <Draggable> <div className={classes.Glass}> <div className={classes['Glass-effect']} /> <div className={clsx(classes['Glass-tint'], isDark && classes['Glass-tint_dark'])} /> <div className={clsx(classes['Glass-shine'], isDark && classes['Glass-shine_dark'])} /> <svg style={{ display: 'none' }}> <filter id="glass" filterUnits="objectBoundingBox"> <feTurbulence type="fractalNoise" baseFrequency="0.01 0.01" numOctaves="1" result="turbulence"seed="5" /> <feComponentTransfer in="turbulence" result="mapped"> <feFuncR amplitude="1" exponent="10" offset="0.5" type="gamma" /> <feFuncG amplitude="0" exponent="1" offset="0" type="gamma" /> <feFuncB amplitude="0" exponent="1" offset="0.5" type="gamma" /> </feComponentTransfer> <feGaussianBlur in="turbulence" result="softMap" stdDeviation="2" /> <feSpecularLighting in="softMap" lightingColor="white" result="specLight" surfaceScale="5" specularConstant="1" specularExponent="100" > <fePointLight x="-200" y="-200" z="300" /> </feSpecularLighting> <feComposite in="specLight" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litImage" /> <feDisplacementMap in="SourceGraphic" in2="softMap" scale="50" xChannelSelector="R" yChannelSelector="G" /> </filter> </svg> </div> </Draggable> ); }; export default Glass;
SCSS
.Glass { border-radius: 1em; box-shadow: 0 -1px 0 0 rgba(var(--theme-border-rgb), 0.15), 0 0 0 1px rgba(var(--theme-border-rgb), 0.15); cursor: grab; height: 100px; overflow: hidden; position: relative; width: 100px; z-index: 1000; &-effect, &-tint, &-shine { inset: 0; overflow: hidden; pointer-events: none; position: absolute; } &-effect { backdrop-filter: blur(0.25em); filter: url("#glass"); isolation: isolate; z-index: -2; } &-tint { --Glass-tint: rgba(var(--theme-bg-rgb), 0.7); background: var(--Glass-tint); z-index: -1; &_dark { --Glass-tint: rgba(var(--theme-bg-rgb), 0.1); } } &-shine { --Glass-shine-gradient: linear-gradient( 135deg, var(--purple), var(--blue), var(--green), var(--yellow), var(--red) ); --Glass-shine: inset 2px 2px 1px 0 rgba(white, 0.075), inset -1px -1px 1px 1px rgba(white, 0.075); --Glass-shine-opacity: 0.1; box-shadow: var(--Glass-shine); z-index: 0; &_dark { --Glass-shine: inset 2px 2px 1px 0 rgba(black, 0.075), inset -1px -1px 1px 1px rgba(black, 0.075); --Glass-shine-opacity: 0.1; } &::before { background: var(--Glass-shine-gradient); content: ""; display: block; inset: 0; mask-image: linear-gradient(to top, rgba(black, 1), rgba(black, 0)); opacity: var(--Glass-shine-opacity); position: absolute; z-index: 5; } } }