List items and modal
@@ -0,0 +1,15 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
const Button = ({ children, className, ...props }) => (
|
||||
<button
|
||||
{...props}
|
||||
class={classNames(
|
||||
'inline-block text-xs font-medium leading-6 text-center uppercase transition rounded-lg ripple focus:outline-none',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
|
||||
export default Button;
|
||||
@@ -1,10 +1,13 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
const Content = ({ className, visible, children }) => (
|
||||
<div className={classNames(`h-full overflow-auto py-2 absolute top-0`, className, {
|
||||
visible,
|
||||
invisible: !visible
|
||||
})}>
|
||||
const Content = ({ className, visible, children, ...props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className={classNames(`h-full w-full overflow-auto py-2 absolute top-0`, className, {
|
||||
visible,
|
||||
invisible: !visible,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
const EdgeDrag = () => null;
|
||||
|
||||
export default EdgeDrag;
|
||||
@@ -0,0 +1,3 @@
|
||||
const List = ({ children, ...props }) => <div {...props}>{children}</div>;
|
||||
|
||||
export default List;
|
||||
@@ -0,0 +1,9 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
const ListItem = ({ children, className, ...props }) => (
|
||||
<div className={classNames('p-4', className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ListItem;
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useDrag } from 'react-use-gesture';
|
||||
|
||||
const Menu = ({ open, onClose, children }) => {
|
||||
const Menu = ({ open, onClose, children, className, ...props }) => {
|
||||
const ref = useRef();
|
||||
const [x, setX] = useState(-100000);
|
||||
const [rect, setRect] = useState(null);
|
||||
@@ -68,6 +68,7 @@ const Menu = ({ open, onClose, children }) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
{...bind()}
|
||||
ref={ref}
|
||||
style={{
|
||||
@@ -78,15 +79,10 @@ const Menu = ({ open, onClose, children }) => {
|
||||
}}
|
||||
className={classNames(
|
||||
'fixed z-40 transform transform-gpu translate w-48 h-full bg-gray-100',
|
||||
className,
|
||||
{
|
||||
'transition-transform': !dragging,
|
||||
}
|
||||
/*
|
||||
{
|
||||
'-translate-x-full': !open,
|
||||
'-translate-x-0': open,
|
||||
}
|
||||
*/
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import classNames from 'classnames';
|
||||
import { useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useDrag } from 'react-use-gesture';
|
||||
|
||||
const Modal = ({ open, onClose, children }) => {
|
||||
@@ -7,24 +7,46 @@ const Modal = ({ open, onClose, children }) => {
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const [rect, setRect] = useState(null);
|
||||
const [y, setY] = useState(100000);
|
||||
const [safeAreaTop, setSafeAreaTop] = useState(0);
|
||||
|
||||
const _open = useCallback(() => {
|
||||
setY(safeAreaTop);
|
||||
}, [safeAreaTop]);
|
||||
|
||||
const _close = useCallback(() => {
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
setY(rect.height + safeAreaTop);
|
||||
}, [safeAreaTop, rect]);
|
||||
|
||||
// Get pixel value of safe area insets
|
||||
useEffect(() => {
|
||||
const safeAreaTop = parseInt(
|
||||
getComputedStyle(document.documentElement).getPropertyValue('--safe-area-top')
|
||||
);
|
||||
setSafeAreaTop(safeAreaTop);
|
||||
}, []);
|
||||
|
||||
// Get the layout rectangle for the modal
|
||||
useLayoutEffect(() => {
|
||||
const rect = ref.current?.getBoundingClientRect();
|
||||
setRect(rect);
|
||||
setY(-rect.width);
|
||||
_close();
|
||||
}, []);
|
||||
|
||||
// If open changes, open/close the modal
|
||||
useLayoutEffect(() => {
|
||||
if (open) {
|
||||
setY(0);
|
||||
} else if (rect) {
|
||||
setY(rect.height);
|
||||
_open();
|
||||
} else {
|
||||
_close();
|
||||
}
|
||||
}, [rect, open]);
|
||||
}, [rect, open, _open, _close]);
|
||||
|
||||
const bind = useDrag(
|
||||
({ down, movement: [mx, my] }) => {
|
||||
setY(my < 0 ? 0 : my);
|
||||
setY(my < 0 ? safeAreaTop : my + safeAreaTop);
|
||||
|
||||
if (down) {
|
||||
setDragging(true);
|
||||
@@ -32,16 +54,16 @@ const Modal = ({ open, onClose, children }) => {
|
||||
setDragging(false);
|
||||
}
|
||||
|
||||
// If the drag ended, snap the menu back
|
||||
// If the drag ended, snap the menu back open or close it
|
||||
if (!down) {
|
||||
const mid = rect.height;
|
||||
if (y > mid / 2) {
|
||||
// Close
|
||||
setY(rect.height);
|
||||
_close();
|
||||
onClose();
|
||||
} else {
|
||||
// Re-open
|
||||
setY(0);
|
||||
_open();
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -55,13 +77,13 @@ const Modal = ({ open, onClose, children }) => {
|
||||
ref={ref}
|
||||
{...bind()}
|
||||
className={classNames(
|
||||
'fixed z-40 top-5 transform transform-gpu ranslate w-full h-full bg-white rounded-t-lg',
|
||||
'fixed z-40 top-5 transform transform-gpu ranslate w-full h-full bg-white rounded-t-xl',
|
||||
{
|
||||
'ease-in-out duration-300 transition-transformation': !dragging,
|
||||
}
|
||||
)}
|
||||
style={{
|
||||
height: `calc(100% - 1.25rem)`,
|
||||
height: `calc(100% - env(safe-area-inset-top, 0px) - 1.25rem)`,
|
||||
touchAction: 'pan-y',
|
||||
transform: `translateY(${y}px)`,
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import Content from '../Content';
|
||||
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import List from '../List';
|
||||
import ListItem from '../ListItem';
|
||||
|
||||
const Feed = ({ selected }) => {
|
||||
return (
|
||||
<Content visible={selected} className="p-4">
|
||||
<List className="h-full w-full">
|
||||
{selected && (
|
||||
<Virtuoso
|
||||
totalCount={1000}
|
||||
overscan={200}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
itemContent={index => <ListItem>Item {index}</ListItem>}
|
||||
/>
|
||||
)}
|
||||
</List>
|
||||
</Content>
|
||||
);
|
||||
};
|
||||
|
||||
export default Feed;
|
||||
@@ -1,12 +0,0 @@
|
||||
import { homeItems } from "../../data";
|
||||
import Content from "../Content";
|
||||
|
||||
const Profile = ({ selected }) => {
|
||||
return (
|
||||
<Content visible={selected} className="p-4">
|
||||
<h2>Profile</h2>
|
||||
</Content>
|
||||
)
|
||||
}
|
||||
|
||||
export default Profile;
|
||||
@@ -312,6 +312,19 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
||||
"integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw=="
|
||||
},
|
||||
"@virtuoso.dev/react-urx": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@virtuoso.dev/react-urx/-/react-urx-0.2.2.tgz",
|
||||
"integrity": "sha512-PH2suwXIqFSbAfdkM6COQTRVqKVIC4DWUPPmZVTSWrdPJx6m45rxifAS91a5X3kl9RPaCWD0fBN0ztzWG6BdGQ==",
|
||||
"requires": {
|
||||
"@virtuoso.dev/urx": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"@virtuoso.dev/urx": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@virtuoso.dev/urx/-/urx-0.2.2.tgz",
|
||||
"integrity": "sha512-CbzbWVCtyG2XFSZ+X0K9jNjTpKI+p4dn61ZUM+cpKwCp2HK9jCRWchnOFovqvWqELoGP65TmGNNF06OjCDlk0A=="
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
|
||||
@@ -665,6 +678,11 @@
|
||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
|
||||
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
|
||||
},
|
||||
"asap": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||
},
|
||||
"asn1.js": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
|
||||
@@ -1372,6 +1390,11 @@
|
||||
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
|
||||
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
|
||||
"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
@@ -3869,6 +3892,11 @@
|
||||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||
@@ -4156,6 +4184,14 @@
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"promise": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz",
|
||||
"integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==",
|
||||
"requires": {
|
||||
"asap": "~2.0.6"
|
||||
}
|
||||
},
|
||||
"promise-inflight": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
|
||||
@@ -4269,6 +4305,14 @@
|
||||
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
|
||||
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
|
||||
},
|
||||
"raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"requires": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -4318,6 +4362,19 @@
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"react-app-polyfill": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz",
|
||||
"integrity": "sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==",
|
||||
"requires": {
|
||||
"core-js": "^3.5.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"promise": "^8.0.3",
|
||||
"raf": "^3.4.1",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz",
|
||||
@@ -4354,6 +4411,17 @@
|
||||
"integrity": "sha512-lpn39vmrDu/zB2bNx7rjaL0+Gjm17a9mzn53bX9IP4TIjMUxXlsB0IkiFj/B23F0vq1A9ozDLGHl2OaXkKJcBg==",
|
||||
"dev": true
|
||||
},
|
||||
"react-virtuoso": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-1.1.1.tgz",
|
||||
"integrity": "sha512-ljUxZQUdJtMpobTKL1hLHsJJSznAH5bupEuLFKxlA6gVSfayxnldNZyhRVdoZmHqfVvsaNwQETw246uernMdpw==",
|
||||
"requires": {
|
||||
"@virtuoso.dev/react-urx": "^0.2.0",
|
||||
"@virtuoso.dev/urx": "^0.2.0",
|
||||
"react-app-polyfill": "^1.0.6",
|
||||
"resize-observer-polyfill": "^1.5.1"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
@@ -4423,6 +4491,11 @@
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
|
||||
},
|
||||
"resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
|
||||
@@ -5996,6 +6069,11 @@
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"whatwg-fetch": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz",
|
||||
"integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"postcss": "^8.2.1",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-virtuoso": "^1.1.1",
|
||||
"tailwindcss": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
|
||||
import { faces } from '../data';
|
||||
|
||||
import Store from '../store';
|
||||
|
||||
import App from '../components/App';
|
||||
import Backdrop from '../components/Backdrop';
|
||||
@@ -6,20 +10,23 @@ import Menu from '../components/Menu';
|
||||
import Modal from '../components/Modal';
|
||||
import Nav from '../components/Nav';
|
||||
import Home from '../components/pages/Home';
|
||||
import Profile from '../components/pages/Profile';
|
||||
import Feed from '../components/pages/Feed';
|
||||
import Settings from '../components/pages/Settings';
|
||||
import Tab from '../components/Tab';
|
||||
import TabBar from '../components/TabBar';
|
||||
import Store from '../store';
|
||||
import List from '../components/List';
|
||||
import ListItem from '../components/ListItem';
|
||||
import { useState } from 'react';
|
||||
import Button from '../components/Button';
|
||||
|
||||
const pages = [
|
||||
{ id: 'home', title: 'Home', icon: 'home-outline', selectedIcon: 'home', component: Home },
|
||||
{
|
||||
id: 'profile',
|
||||
title: 'Profile',
|
||||
icon: 'person-outline',
|
||||
id: 'feed',
|
||||
title: 'Feed',
|
||||
icon: 'flash-outline',
|
||||
selectedIcon: 'person',
|
||||
component: Profile,
|
||||
component: Feed,
|
||||
},
|
||||
{
|
||||
id: 'settings',
|
||||
@@ -64,9 +71,40 @@ const MenuContent = () => (
|
||||
</>
|
||||
);
|
||||
|
||||
const FakeNotification = ({ i }) => (
|
||||
<ListItem className="flex align-center">
|
||||
<img
|
||||
src={`/img/faces/image-${(i % 66) + 1}.png`}
|
||||
alt="Notification"
|
||||
className="block rounded-full w-8 h-8 mr-4"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<span className="p-0 m-0 align-middle">You have a new friend request</span>
|
||||
</div>
|
||||
<div>
|
||||
<Button className="background-transparent px-1 py-1 text-green-400 text-lg">
|
||||
<ion-icon name="checkmark-outline" />
|
||||
</Button>
|
||||
<Button className="background-transparent px-1 py-1 text-red-400 text-lg">
|
||||
<ion-icon name="close-outline" />
|
||||
</Button>
|
||||
</div>
|
||||
</ListItem>
|
||||
);
|
||||
|
||||
const NotificationsContent = () => (
|
||||
<div className="p-4">
|
||||
<h2 className="text-xl">Notifications</h2>
|
||||
<div className="w-full h-full flex flex-col">
|
||||
<div className="p-4">
|
||||
<h2 className="text-xl">Notifications</h2>
|
||||
</div>
|
||||
<List className="flex-1">
|
||||
<Virtuoso
|
||||
totalCount={1000}
|
||||
overscan={200}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
itemContent={index => <FakeNotification i={index} />}
|
||||
/>
|
||||
</List>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
@@ -1,3 +1,7 @@
|
||||
:root {
|
||||
--safe-area-top: env(safe-area-inset-top, 0);
|
||||
--safe-area-bottom: env(safe-area-inset-bottom, 0);
|
||||
}
|
||||
body {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
|
||||