├── src
├── hooks
│ ├── index.js
│ └── useResizeObserver.js
├── index.js
├── .eslintrc
├── util
│ ├── index.js
│ ├── common.js
│ ├── dom.js
│ └── props.js
├── components
│ ├── index.js
│ ├── background
│ │ ├── Background.module.css
│ │ └── Background.jsx
│ ├── card
│ │ ├── Card.module.css
│ │ └── Card.jsx
│ └── styles.module.css
└── index.test.js
├── .travis.yml
├── .eslintignore
├── example
├── src
│ ├── bg.webp
│ ├── book.png
│ ├── play.png
│ ├── laptop.png
│ ├── dumbell.png
│ ├── index.js
│ ├── App.test.js
│ ├── index.css
│ └── App.js
├── public
│ ├── favicon.ico
│ ├── manifest.json
│ └── index.html
├── README.md
└── package.json
├── .editorconfig
├── .prettierrc
├── .gitignore
├── .eslintrc
├── README.md
└── package.json
/src/hooks/index.js:
--------------------------------------------------------------------------------
1 | export * from './useResizeObserver'
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 12
4 | - 10
5 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export { Card, Background } from './components'
2 |
--------------------------------------------------------------------------------
/src/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | node_modules/
4 | .snapshots/
5 | *.min.js
--------------------------------------------------------------------------------
/example/src/bg.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AKAspanion/ui-glassmorphism/HEAD/example/src/bg.webp
--------------------------------------------------------------------------------
/example/src/book.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AKAspanion/ui-glassmorphism/HEAD/example/src/book.png
--------------------------------------------------------------------------------
/example/src/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AKAspanion/ui-glassmorphism/HEAD/example/src/play.png
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | export * from './dom'
2 | export * from './props'
3 | export * from './common'
4 |
--------------------------------------------------------------------------------
/example/src/laptop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AKAspanion/ui-glassmorphism/HEAD/example/src/laptop.png
--------------------------------------------------------------------------------
/example/src/dumbell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AKAspanion/ui-glassmorphism/HEAD/example/src/dumbell.png
--------------------------------------------------------------------------------
/example/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AKAspanion/ui-glassmorphism/HEAD/example/public/favicon.ico
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | export { Card } from './card/Card.jsx'
2 | export { Background } from './background/Background.jsx'
3 |
--------------------------------------------------------------------------------
/src/index.test.js:
--------------------------------------------------------------------------------
1 | import { Card } from './components'
2 |
3 | describe('Card', () => {
4 | it('is truthy', () => {
5 | expect(Card).toBeTruthy()
6 | })
7 | })
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import './index.css'
2 |
3 | import React from 'react'
4 | import ReactDOM from 'react-dom'
5 | import App from './App'
6 |
7 | ReactDOM.render(, document.getElementById('root'))
8 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "jsxSingleQuote": true,
4 | "semi": false,
5 | "tabWidth": 2,
6 | "bracketSpacing": true,
7 | "jsxBracketSameLine": false,
8 | "arrowParens": "always",
9 | "trailingComma": "none"
10 | }
11 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | This example was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | It is linked to the ui-glassmorphism package in the parent directory for development purposes.
4 |
5 | You can run `npm install` and then `npm start` to test your package.
6 |
--------------------------------------------------------------------------------
/example/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import App from './App'
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div')
7 | ReactDOM.render(, div)
8 | ReactDOM.unmountComponentAtNode(div)
9 | })
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # See https://help.github.com/ignore-files/ for more about ignoring files.
3 |
4 | # dependencies
5 | node_modules
6 |
7 | # builds
8 | build
9 | dist
10 | .rpt2_cache
11 |
12 | # misc
13 | .DS_Store
14 | .env
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 |
--------------------------------------------------------------------------------
/example/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "ui-glassmorphism",
3 | "name": "ui-glassmorphism",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/util/common.js:
--------------------------------------------------------------------------------
1 | import globalModule from '../components/styles.module.css'
2 |
3 | export const getModuleClasses = (localModule, classNames) => {
4 | const styles = {
5 | ...localModule,
6 | ...globalModule
7 | }
8 |
9 | return classNames
10 | .replace(/^\s+|\s+$/g, '')
11 | .split(/\s+/)
12 | .map((cl) => styles[cl.trim()])
13 | .join(' ')
14 | .trim()
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/background/Background.module.css:
--------------------------------------------------------------------------------
1 | .gl-background {
2 | background-size: cover !important;
3 | /* background: var(--gl-background-value); */
4 | }
5 |
6 | .gl-background:before {
7 | content: '';
8 | top: 0;
9 | left: 0;
10 | position: absolute;
11 | width: var(--gl-background-width);
12 | height: var(--gl-background-height);
13 | backdrop-filter: blur(var(--gl-background-blur));
14 | }
15 |
--------------------------------------------------------------------------------
/example/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
5 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
6 | sans-serif;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | }
10 |
11 | code {
12 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
13 | monospace;
14 | }
15 |
16 | .activity__card__container::-webkit-scrollbar {
17 | display: none;
18 | }
19 |
20 | .activity__card:last-of-type {
21 | margin-right: 0px !important;
22 | }
23 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "standard",
5 | "standard-react"
6 | ],
7 | "env": {
8 | "node": true
9 | },
10 | "parserOptions": {
11 | "ecmaVersion": 2020,
12 | "ecmaFeatures": {
13 | "legacyDecorators": true,
14 | "jsx": true
15 | }
16 | },
17 | "settings": {
18 | "react": {
19 | "version": "17"
20 | }
21 | },
22 | "rules": {
23 | "space-before-function-parent": 0,
24 | "react/prop-types": 0,
25 | "react/jsx-handler-names": 0,
26 | "react/jsx-fragments": 0,
27 | "react/no-unused-prop-types": 0,
28 | "import/export": 0
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/util/dom.js:
--------------------------------------------------------------------------------
1 | export const RGBFromCSSColor = (color) => {
2 | var canvas = document.createElement('canvas')
3 |
4 | canvas.id = 'color-canvas'
5 | canvas.width = 2
6 | canvas.height = 2
7 | canvas.style.zIndex = -1
8 | canvas.style.position = 'absolute'
9 | canvas.style.border = '1px solid'
10 |
11 | var fragment = document.createDocumentFragment()
12 | fragment.appendChild(canvas)
13 |
14 | var ctx = canvas.getContext('2d')
15 | ctx.fillStyle = color
16 | ctx.fillRect(0, 0, 2, 2)
17 |
18 | var imgData = ctx.getImageData(0, 0, 2, 2)
19 |
20 | var colorArray = imgData.data.slice(2 * 4, 2 * 4 + 4)
21 |
22 | // document.getElementById('color-canvas').remove()
23 |
24 | return [colorArray[0], colorArray[1], colorArray[2]]
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ui-glassmorphism
2 |
3 | > React component library on "glassmorphism" UI/UX trend.
4 |
5 | [](https://www.npmjs.com/package/ui-glassmorphism) [](https://standardjs.com)
6 |
7 | ## Install
8 |
9 | ```bash
10 | npm install --save ui-glassmorphism
11 | ```
12 |
13 | ## Usage
14 |
15 | ```jsx
16 | import React, { Component } from 'react'
17 |
18 | import Card from 'ui-glassmorphism'
19 | import 'ui-glassmorphism/dist/index.css'
20 |
21 | class Example extends Component {
22 | render() {
23 | return
24 | }
25 | }
26 | ```
27 |
28 | ## License
29 |
30 | MIT © [AKAspanion](https://github.com/AKAspanion)
31 |
--------------------------------------------------------------------------------
/src/components/card/Card.module.css:
--------------------------------------------------------------------------------
1 | .gl-card {
2 | padding: 16px;
3 | overflow: hidden;
4 | border-radius: 12px;
5 | box-sizing: border-box;
6 | color: var(--text-color);
7 | }
8 |
9 | .gl-card-shine {
10 | position: absolute;
11 | pointer-events: none;
12 | background: radial-gradient(
13 | ellipse at center,
14 | rgba(255, 255, 255, 0.24) 0%,
15 | rgba(255, 255, 255, 0) 65%
16 | );
17 | transform: translate3d(-50%, -50%, 0);
18 | }
19 |
20 | .gl-card--outlined {
21 | border: 2px solid rgba(255, 255, 255, 0.18);
22 | }
23 |
24 | .gl-card.gl-card--light {
25 | --text-color: var(--g-text-color-light);
26 | }
27 |
28 | .gl-card.gl-card--dark {
29 | --text-color: var(--g-text-color-dark);
30 | }
31 |
32 | .gl-card.gl-card--elevation-1 {
33 | box-shadow: 0 3px 32px 0 rgba(31, 38, 135, 0.07);
34 | }
35 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui-glassmorphism-example",
3 | "homepage": ".",
4 | "version": "0.0.0",
5 | "private": true,
6 | "scripts": {
7 | "start": "node ../node_modules/react-scripts/bin/react-scripts.js start",
8 | "build": "node ../node_modules/react-scripts/bin/react-scripts.js build",
9 | "test": "node ../node_modules/react-scripts/bin/react-scripts.js test",
10 | "eject": "node ../node_modules/react-scripts/bin/react-scripts.js eject"
11 | },
12 | "dependencies": {
13 | "react": "file:../node_modules/react",
14 | "react-dom": "file:../node_modules/react-dom",
15 | "react-scripts": "file:../node_modules/react-scripts",
16 | "ui-glassmorphism": "file:.."
17 | },
18 | "devDependencies": {
19 | "@babel/plugin-syntax-object-rest-spread": "^7.8.3"
20 | },
21 | "eslintConfig": {
22 | "extends": "react-app"
23 | },
24 | "browserslist": [
25 | ">0.2%",
26 | "not dead",
27 | "not ie <= 11",
28 | "not op_mini all"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/styles.module.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --gradient-left: #bbf4dc;
3 | --gradient-right: #aacce9;
4 |
5 | --white: #ffffff;
6 | --black: #000000;
7 |
8 | --primary: #2979ff;
9 | --primary-dark: #2962ff;
10 | --primary-light: #82b1ff;
11 |
12 | --error: #ff5252;
13 | --info: #2196f3;
14 | --success: #4caf50;
15 | --warning: #dfa700;
16 |
17 | --g-text-color-light: rgba(0, 0, 0, 0.8);
18 | --g-text-color-disabled-light: rgba(0, 0, 0, 0.45);
19 | --g-text-color-secondary-light: rgba(0, 0, 0, 0.67);
20 |
21 | --g-text-color-dark: rgba(255, 255, 255, 0.8);
22 | --g-text-color-disabled-dark: rgba(255, 255, 255, 0.45);
23 | --g-text-color-secondary-dark: rgba(255, 255, 255, 0.67);
24 |
25 | --g-bg-color-disabled-light: #dee5e8;
26 | --g-bg-color-disabled-dark: #727272;
27 | }
28 |
29 | * {
30 | margin: 0;
31 | padding: 0;
32 | box-sizing: inherit;
33 | }
34 |
35 | input,
36 | label,
37 | textarea,
38 | button,
39 | select,
40 | a {
41 | -webkit-tap-highlight-color: transparent !important;
42 | font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Oxygen',
43 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
44 | sans-serif;
45 | }
46 |
--------------------------------------------------------------------------------
/src/util/props.js:
--------------------------------------------------------------------------------
1 | import { Children, cloneElement } from 'react'
2 |
3 | export const isMyReactComponent = (component) => {
4 | let componentName = ''
5 | if (component && component.type && typeof component.type !== 'string') {
6 | componentName = component.type.displayName
7 | }
8 | return componentName && componentName.includes('Gu')
9 | }
10 |
11 | export const passDownProp = (children, props, propName) => {
12 | return Children.map(children, (child) => {
13 | if (isMyReactComponent(child)) {
14 | const newProps = {
15 | ...child.props
16 | }
17 |
18 | if (typeof propName === 'string') {
19 | if (props[propName] !== undefined) {
20 | newProps[propName] =
21 | child.props[propName] === undefined
22 | ? props[propName]
23 | : child.props[propName]
24 | }
25 | } else if (Array.isArray(propName)) {
26 | propName.forEach((prop) => {
27 | if (props[prop] === undefined) return
28 |
29 | newProps[prop] =
30 | child.props[prop] === undefined ? props[prop] : child.props[prop]
31 | })
32 | }
33 | return cloneElement(child, newProps)
34 | } else {
35 | return child
36 | }
37 | })
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/background/Background.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable indent */
2 | import React from 'react'
3 | import styles from './Background.module.css'
4 |
5 | import { passDownProp, getModuleClasses } from '../../util'
6 | import { useResizeObserver } from '../../hooks'
7 |
8 | const Background = (props) => {
9 | const { style, children, className = '', blur = 100, img } = props
10 |
11 | const bgNode = React.useRef(null)
12 |
13 | const { height, width } = useResizeObserver(bgNode)
14 |
15 | const getClasses = (key) => {
16 | switch (key) {
17 | default:
18 | return getModuleClasses(styles, key)
19 | }
20 | }
21 |
22 | const backgroundStyle = () => {
23 | return img
24 | ? { backgroundImage: `url(${img})` }
25 | : {
26 | background: `linear-gradient(
27 | 90deg,
28 | var(--gradient-left) 0%,
29 | var(--gradient-right) 100%)
30 | `
31 | }
32 | }
33 |
34 | const getChildren = () => {
35 | return passDownProp(children, props, 'dark')
36 | }
37 |
38 | return (
39 |
50 | {getChildren()}
51 |
52 | )
53 | }
54 |
55 | Background.displayName = 'GuBackground'
56 |
57 | export { Background }
58 |
--------------------------------------------------------------------------------
/src/hooks/useResizeObserver.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const useResizeObserver = (element) => {
4 | const current = element && element.current
5 |
6 | const observer = React.useRef(null)
7 |
8 | const [width, setWidth] = React.useState(0)
9 | const [height, setHeight] = React.useState(0)
10 |
11 | React.useLayoutEffect(() => {
12 | if (observer && observer.current && current) {
13 | observer.current.unobserve(current)
14 | }
15 |
16 | // eslint-disable-next-line no-undef
17 | observer.current = new ResizeObserver((entries) => {
18 | const currentWidth = width
19 | const currentHeight = height
20 |
21 | entries.forEach((entry) => {
22 | const { clientHeight, clientWidth } = (entry && entry.target) || {}
23 |
24 | const isWidthChanged = currentWidth !== clientWidth
25 | const isHeightChanged = currentHeight !== clientHeight
26 |
27 | if (isWidthChanged) {
28 | setWidth(clientWidth)
29 | }
30 | if (isHeightChanged) {
31 | setHeight(clientHeight)
32 | }
33 | })
34 | })
35 |
36 | observe()
37 |
38 | return () => unobserve()
39 | }, [current])
40 |
41 | const observe = () => {
42 | if (isObserverValid()) {
43 | observer.current.observe(element.current)
44 | }
45 | }
46 |
47 | const unobserve = () => {
48 | if (isObserverValid()) {
49 | observer.current.unobserve(element.current)
50 | }
51 | }
52 |
53 | const isObserverValid = () => {
54 | return element && element.current && observer.current
55 | }
56 |
57 | return { width, height }
58 | }
59 |
--------------------------------------------------------------------------------
/example/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
16 |
17 |
18 |
27 | ui-glassmorphism
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui-glassmorphism",
3 | "version": "0.0.1",
4 | "description": "React component library on 'glassmorphism' UI/UX trend.",
5 | "author": "Ankit Kumar Pandit",
6 | "license": "MIT",
7 | "repository": "https://github.com/AKAspanion/ui-glassmorphism",
8 | "main": "dist/index.js",
9 | "module": "dist/index.modern.js",
10 | "source": "src/index.js",
11 | "engines": {
12 | "node": ">=10"
13 | },
14 | "scripts": {
15 | "build": "microbundle-crl --no-compress --format modern,cjs",
16 | "start": "microbundle-crl watch --no-compress --format modern,cjs",
17 | "prepare": "run-s build",
18 | "test": "run-s test:unit test:lint test:build",
19 | "test:build": "run-s build",
20 | "test:lint": "eslint .",
21 | "test:unit": "cross-env CI=1 react-scripts test --env=jsdom",
22 | "test:watch": "react-scripts test --env=jsdom",
23 | "predeploy": "cd example && npm install && npm run build",
24 | "deploy": "gh-pages -d example/build"
25 | },
26 | "peerDependencies": {
27 | "react": "^17.0.1",
28 | "react-dom": "^17.0.1"
29 | },
30 | "devDependencies": {
31 | "microbundle-crl": "^0.13.10",
32 | "babel-eslint": "^10.0.3",
33 | "cross-env": "^7.0.2",
34 | "eslint": "^6.8.0",
35 | "eslint-config-prettier": "^6.7.0",
36 | "eslint-config-standard": "^14.1.0",
37 | "eslint-config-standard-react": "^9.2.0",
38 | "eslint-plugin-import": "^2.18.2",
39 | "eslint-plugin-node": "^11.0.0",
40 | "eslint-plugin-prettier": "^3.1.1",
41 | "eslint-plugin-promise": "^4.2.1",
42 | "eslint-plugin-react": "^7.17.0",
43 | "eslint-plugin-standard": "^4.0.1",
44 | "gh-pages": "^2.2.0",
45 | "npm-run-all": "^4.1.5",
46 | "prettier": "^2.0.4",
47 | "react": "^17.0.1",
48 | "react-dom": "^17.0.1",
49 | "react-scripts": "^3.4.1"
50 | },
51 | "files": [
52 | "dist"
53 | ]
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/card/Card.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import styles from './Card.module.css'
3 |
4 | import { getModuleClasses, RGBFromCSSColor } from '../../util'
5 | import { useResizeObserver } from '../../hooks'
6 |
7 | const Card = (props) => {
8 | const {
9 | style,
10 | children,
11 | dark = false,
12 | className = '',
13 | color,
14 | blur = 4,
15 | elevation,
16 | outlined = false,
17 | transparency = 0.25,
18 | shineOnHover = false
19 | } = props
20 |
21 | const shine = React.useRef(null)
22 | const cardNode = React.useRef(null)
23 |
24 | const { width } = useResizeObserver(cardNode)
25 |
26 | const background = () => {
27 | if (transparency === 0) return ''
28 |
29 | const colorLight = '255, 255, 255'
30 | const colorDark = '0, 0, 0'
31 |
32 | let rgbColor = colorLight
33 |
34 | if (dark) {
35 | rgbColor = colorDark
36 | }
37 |
38 | if (color) {
39 | const [r, g, b] = RGBFromCSSColor(color)
40 |
41 | if (r === 0 && g === 0 && b === 0) {
42 | if (dark) {
43 | rgbColor = colorDark
44 | } else {
45 | rgbColor = colorLight
46 | }
47 | } else {
48 | rgbColor = `${r}, ${g}, ${b}`
49 | }
50 | }
51 |
52 | return `rgba(${rgbColor}, ${transparency})`
53 | }
54 |
55 | const bgBlur = () => {
56 | if (transparency === 0) return ''
57 |
58 | return `blur(${blur}px)`
59 | }
60 |
61 | const getClasses = (key) => {
62 | switch (key) {
63 | case 'card':
64 | return getModuleClasses(
65 | styles,
66 | `
67 | gl-card
68 | gl-card--${dark ? 'dark' : 'light'}
69 | ${outlined ? 'gl-card--outlined' : ''}
70 | ${elevation ? `gl-card--elevation-${elevation}` : ''}
71 | `
72 | )
73 | default:
74 | return getModuleClasses(styles, key)
75 | }
76 | }
77 |
78 | const mouseMoveHandler = (event) => {
79 | if (!shineOnHover) return
80 |
81 | if (!event || !shine.current) return
82 |
83 | event.preventDefault()
84 | event.stopPropagation()
85 | event.nativeEvent.stopImmediatePropagation()
86 |
87 | const { pageX, pageY } = event
88 | const { x: cardX, y: cardY } = event.target.getBoundingClientRect()
89 |
90 | shine.current.style.top = `${pageY - cardY}px`
91 | shine.current.style.left = `${pageX - cardX}px`
92 | }
93 |
94 | return (
95 |
105 | {shineOnHover && (
106 |
111 | )}
112 | {children}
113 |
114 | )
115 | }
116 |
117 | Card.displayName = 'GuCard'
118 |
119 | export { Card }
120 |
--------------------------------------------------------------------------------
/example/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import { Card, Background } from 'ui-glassmorphism'
4 | import 'ui-glassmorphism/dist/index.css'
5 |
6 | import './index.css'
7 |
8 | import bg from './bg.webp'
9 | import book from './book.png'
10 | import play from './play.png'
11 | import laptop from './laptop.png'
12 | import dumbell from './dumbell.png'
13 |
14 | const cards = [
15 | {
16 | name: 'Fitness',
17 | image: dumbell,
18 | color: '#f400d0',
19 | width: '50%',
20 | time: '1:30h',
21 | transparency: 0.2
22 | },
23 | {
24 | name: 'Work',
25 | color: '#54A1D2',
26 | width: '100%',
27 | time: '6h',
28 | image: laptop,
29 | transparency: 0.8
30 | },
31 | {
32 | name: 'Study',
33 | image: book,
34 | color: 'cyan',
35 | width: '70%',
36 | time: '1h',
37 | transparency: 0.8
38 | },
39 | {
40 | name: 'Play',
41 | image: play,
42 | color: 'red',
43 | width: '70%',
44 | time: '1h',
45 | transparency: 0.8
46 | }
47 | ]
48 |
49 | const activities = [
50 | { name: 'S', percent: '50' },
51 | { name: 'M', percent: '70' },
52 | { name: 'T', percent: '30' },
53 | { name: 'W', percent: '90' },
54 | { name: 'T', percent: '80' },
55 | { name: 'F', percent: '60' },
56 | { name: 'S', percent: '80' }
57 | ]
58 |
59 | const flexItem = {
60 | display: 'flex',
61 | alignItems: 'center',
62 | justifyContent: 'center'
63 | }
64 | const App = () => {
65 | return (
66 |
72 |
79 |
90 |
112 |
113 | Today
114 |
120 |
125 |
138 |
139 | Fitness
140 |
141 | 1:30
142 |
143 |
144 |
145 |
146 |
149 | Last activity
150 |
151 |
159 |
166 | {cards.map(
167 | ({ name, color, image, time, width, transparency }, i) => (
168 |
184 |
195 |
196 | {name}
197 |
198 |
205 | {time}
206 |
207 |
217 |
227 |
228 |
229 | )
230 | )}
231 |
232 |
233 |
234 |
242 |
266 |
267 |
268 | Statistics
269 |
270 |
277 | This week
278 |
279 |
286 | {cards.map(({ name, image, transparency }) => (
287 |
288 |
297 |
305 |
306 |
309 | {name}
310 |
311 |
312 | ))}
313 |
314 |
315 |
322 | Activity
323 |
324 |
325 | {activities.map(({ name, percent }) => (
326 |
327 |
336 |
348 |
351 | {name}
352 |
353 |
354 | ))}
355 |
356 |
357 |
358 |
359 |
365 | Plan your daytime!
366 |
367 |
368 |
369 |
370 |
371 |
372 | )
373 | }
374 |
375 | export default App
376 |
--------------------------------------------------------------------------------