Like on medium:
Tooltip from matetial-ui react framework.
some ideas:
wrap selected text with <span> and use that element as reference node
of tooltip (over complicated I guess)
create tooltip w/o child and specify
absolute position based on selected text
any other ideas?
The simplest: https://www.w3schools.com/css/css_tooltip.asp
The more effective: https://chrisbracco.com/a-simple-css-tooltip/
:)
Medium.com uses popper.js. I found this out by searching the tag parameters in Medium's HTML.
<div class="bz fx mc yw"
style=
"position: absolute; inset: auto auto 0px 0px; transform: translate(692px, 1233px);"
data-popper-reference-hidden="false"
data-popper-escaped="false"
data-popper-placement="top">
https://popper.js.org/
It does the thing where it repositons the popup if you scroll, I checked.
I used the popper component instead of tooltip component link: https://mui.com/material-ui/react-popper/#virtual-element
demo: https://codesandbox.io/s/iztu66?file=/demo.js
code
import * as React from 'react';
import Popper from '#mui/material/Popper';
import Typography from '#mui/material/Typography';
import Fade from '#mui/material/Fade';
import Paper from '#mui/material/Paper';
export default function VirtualElementPopper() {
const [open, setOpen] = React.useState(false);
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClose = () => {
setOpen(false);
};
const handleMouseUp = () => {
const selection = window.getSelection();
// Resets when the selection has a length of 0
if (!selection || selection.anchorOffset === selection.focusOffset) {
handleClose();
return;
}
const getBoundingClientRect = () =>
selection.getRangeAt(0).getBoundingClientRect();
setOpen(true);
setAnchorEl({
getBoundingClientRect,
});
};
const id = open ? 'virtual-element-popper' : undefined;
return (
<div onMouseLeave={handleClose}>
<Typography aria-describedby={id} onMouseUp={handleMouseUp}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ipsum purus,
bibendum sit amet vulputate eget, porta semper ligula. Donec bibendum
vulputate erat, ac fringilla mi finibus nec. Donec ac dolor sed dolor
porttitor blandit vel vel purus. Fusce vel malesuada ligula. Nam quis
vehicula ante, eu finibus est. Proin ullamcorper fermentum orci, quis finibus
massa. Nunc lobortis, massa ut rutrum ultrices, metus metus finibus ex, sit
amet facilisis neque enim sed neque. Quisque accumsan metus vel maximus
consequat. Suspendisse lacinia tellus a libero volutpat maximus.
</Typography>
<Popper
id={id}
open={open}
anchorEl={anchorEl}
transition
placement="bottom-start"
>
{({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={350}>
<Paper>
<Typography sx={{ p: 2 }}>The content of the Popper.</Typography>
</Paper>
</Fade>
)}
</Popper>
</div>
);
}
You can add your own buttons after fade component or inside in paper component.
Related
I am attempting to reproduce the sliding image effect seen on this website https://chiwawa.es/en/.
I can see how it works on this website (see changeImages function in 63c2acc.js; however, getting this to work in React is proving difficult for me.
To illustrate what I have managed to do, I've published https://dskdirhhwk.vercel.app/.
Solved - (this link now correctly shows animations thanks to answer below)
The difficulty I'm running into is animating the images. The Sections are getting re-rendered by React upon state update, affecting how I apply the classes to the markup. I used Reacts Profiler to verify these are updates, not remounts.
I initially had the Intersection Observer outside the Section component, but this didn't appear to work. I also had a simple setState mechanism and have since built it into a reducer, so that I could add the active class after the other classes.
I am pulling my hair out here. I want a few hints and a push in the right direction!
This is on Next.js. Here is my code.
import React, {
Fragment,
useState,
forwardRef,
useEffect,
useLayoutEffect,
useCallback,
useContext,
useRef,
useMemo,
} from 'react';
import cx from 'classnames';
// yarn add classnames
const useIntersect = ({root = null, rootMargin, threshold = 0}) => {
const [entry, updateEntry] = useState({});
const [node, setNode] = useState(null);
const observer = useRef(null);
useEffect(() => {
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver(([entry]) => updateEntry(entry), {
root,
rootMargin,
threshold,
});
const {current: currentObserver} = observer;
if (node) currentObserver.observe(node);
return () => currentObserver.disconnect();
}, [node]);
return [setNode, entry];
};
const Home = () => {
const initialState = {active: 'teal', current: 'teal'};
const [state, dispatch] = React.useReducer(reducer, initialState);
function reducer(state, {section, type}) {
switch (type) {
case 'reset':
return initialState;
case 'changeSection':
return {
...state,
previous: state?.current,
current: section,
};
case 'makeActive':
return {
...state,
active: section,
};
default:
return state;
}
}
const activeSection = (section) => {
dispatch({section: section, type: 'changeSection'});
setTimeout(() => {
dispatch({type: 'makeActive', section: section});
}, 1000);
};
const Section = ({sectionID, className, children}) => {
const [ref, entry] = useIntersect({
threshold: '0.7',
});
useEffect(() => {
if (state?.current == sectionID) return;
if (entry.isIntersecting) {
activeSection(sectionID);
}
}, [entry]);
const childrenWithProps = React.Children.map(children, (child, index) => {
if (React.isValidElement(child)) {
if (index == 0)
return React.cloneElement(child, {
className: cx(
'fixed top-0 w-1/2 h-screen transition-all duration-[1000ms] place-items-center place-content-center transform-gpu',
{
'translate-y-[-100vh]': sectionID != state?.active,
'z-40 translate-y-0': sectionID == state?.current && sectionID == state?.active,
}
),
data: 'observable',
id: sectionID,
});
}
return child;
});
return (
<section className={className} ref={ref}>
{childrenWithProps}
</section>
);
};
return (
<>
<div className="fixed bottom-0 z-50 w-1/2 opacity-50">
<pre>{JSON.stringify(state, null, 2)}</pre>
</div>
<Section sectionID="teal" className="bg-teal-200">
<div>
<img className="block object-cover w-full h-full" src="http://placekitten.com/800/1600?image=1" />
</div>
<div className="flex flex-col justify-center w-1/2 min-h-screen px-8 py-64 ml-auto section_content">
<p className="mb-6">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mollis molestie eros eget
ultricies. Mauris tempus odio fermentum, elementum odio a, molestie metus. Nullam id dolor
viverra, scelerisque mi nec, volutpat sapien. Aenean ac nibh gravida, congue velit sit amet,
ultricies mi. Ut posuere ullamcorper elit, eget faucibus turpis fermentum mattis. Nulla
facilisi. Aliquam volutpat maximus vehicula. Nulla commodo dolor vitae euismod condimentum.
Maecenas et justo rutrum, varius velit at, facilisis mauris. Maecenas eget eros in dui mollis
tempor iaculis eu massa. Nulla ullamcorper finibus cursus.
</p>
</div>
</Section>
<Section sectionID="blue" className="bg-blue-200">
<div>
<img className="block object-cover w-full h-full" src="http://placekitten.com/800/1600?image=2" />
</div>
<div className="flex flex-col justify-center w-1/2 min-h-screen px-8 py-64 ml-auto section_content">
<p className="mb-6">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mollis molestie eros eget
ultricies. Mauris tempus odio fermentum, elementum odio a, molestie metus. Nullam id dolor
viverra, scelerisque mi nec, volutpat sapien. Aenean ac nibh gravida, congue velit sit amet,
ultricies mi. Ut posuere ullamcorper elit, eget faucibus turpis fermentum mattis. Nulla
facilisi. Aliquam volutpat maximus vehicula. Nulla commodo dolor vitae euismod condimentum.
Maecenas et justo rutrum, varius velit at, facilisis mauris. Maecenas eget eros in dui mollis
tempor iaculis eu massa. Nulla ullamcorper finibus cursus.
</p>
</div>
</Section>
<Section sectionID="orange" className="bg-orange-200">
<div>
<img className="block object-cover w-full h-full" src="http://placekitten.com/800/1600?image=3" />
</div>
<div className="flex flex-col justify-center w-1/2 min-h-screen px-8 py-64 ml-auto section_content">
<p className="mb-6">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mollis molestie eros eget
ultricies. Mauris tempus odio fermentum, elementum odio a, molestie metus. Nullam id dolor
viverra, scelerisque mi nec, volutpat sapien. Aenean ac nibh gravida, congue velit sit amet,
ultricies mi. Ut posuere ullamcorper elit, eget faucibus turpis fermentum mattis. Nulla
facilisi. Aliquam volutpat maximus vehicula. Nulla commodo dolor vitae euismod condimentum.
Maecenas et justo rutrum, varius velit at, facilisis mauris. Maecenas eget eros in dui mollis
tempor iaculis eu massa. Nulla ullamcorper finibus cursus.
</p>
</div>
</Section>
<Section sectionID="pink" className="bg-pink-200">
<div>
<img className="block object-cover w-full h-full" src="http://placekitten.com/800/1600?image=4" />
</div>
<div className="flex flex-col justify-center w-1/2 min-h-screen px-8 py-64 ml-auto section_content">
<p className="mb-6">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mollis molestie eros eget
ultricies. Mauris tempus odio fermentum, elementum odio a, molestie metus. Nullam id dolor
viverra, scelerisque mi nec, volutpat sapien. Aenean ac nibh gravida, congue velit sit amet,
ultricies mi. Ut posuere ullamcorper elit, eget faucibus turpis fermentum mattis. Nulla
facilisi. Aliquam volutpat maximus vehicula. Nulla commodo dolor vitae euismod condimentum.
Maecenas et justo rutrum, varius velit at, facilisis mauris. Maecenas eget eros in dui mollis
tempor iaculis eu massa. Nulla ullamcorper finibus cursus.
</p>
</div>
</Section>
</>
);
};
export default Home;
You should (almost) never ever ever declare a component inside of another functional component. Doing so essentially creates an entirely new React component class every render, which means it is impossible for React to reconcile which component is which between renders. Try moving your <Section> functional component definition out of the scope of <Home>.
I need to show a number, that starts at 0 and increases to X. This "counting" needs to happen when user's reach the number in view, like this example.
For this, I'm trying to use useEffect, useState and useInView, from react-intersection-observer.
But, in my code, my number is a bit crazy, changing from 1 to 2 only.
I've created a component that I can use many times, this way:
function NumericIndicator(props) {
const [counting, setCounting] = useState(false);
const [number, setNumber] = useState(0);
const [ref, inView] = useInView();
useEffect(() => {
setInterval(() => {
if (number < props.value) {
setNumber(number + 1);
} else {
setNumber(props.value);
}
}, 500);
}, [counting]);
useEffect(() => {
if (inView && !counting) {
setCounting(true);
}
}, [inView]);
return (
<div ref={ref}>
<h1>{number}</h1>
<p>
<small>This needs to increase from 0 to {props.value}</small>
</p>
</div>
);
}
Here's a full StackBlitz with my code
Thank you!
Try
import React from 'react';
import { useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';
import './style.css';
export default function App() {
return (
<div>
<div style={{ minHeight: '100vh' }}>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin
convallis sagittis finibus. Maecenas mauris odio, feugiat vel orci
non, consectetur placerat turpis. Proin tincidunt ut tellus posuere
euismod. Donec id venenatis dui. Quisque ultrices dignissim ipsum ut
tempus. Praesent mollis elit ac magna laoreet tempus at a dui.
Suspendisse sed venenatis arcu, quis commodo sapien. Ut at malesuada
dui. Curabitur feugiat elementum ligula, a pellentesque tortor. Fusce
id nisl ornare, congue dui vitae, ornare ex. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos
himenaeos.
</p>
<p>
Vivamus blandit leo ac magna efficitur vulputate. Praesent vitae magna
elit. Nullam non metus nec mauris maximus tincidunt a ac velit. Aenean
elit metus, aliquet at gravida ornare, commodo gravida nisl. Cras
vestibulum lacinia erat sit amet cursus. Donec pretium enim porttitor
magna tincidunt, a venenatis sem bibendum. Aenean ornare enim et odio
pharetra iaculis. Class aptent taciti sociosqu ad litora torquent.
</p>
</div>
<div style={{ height: '50vh', backgroundColor: '#27ae60' }}>
<NumericIndicator value={10} />
</div>
<div style={{ height: '50vh', backgroundColor: '#e67e22' }}>
<NumericIndicator value={70} />
</div>
<div style={{ height: '50vh', backgroundColor: '#9b59b6' }}>
<NumericIndicator value={90} />
</div>
<div style={{ height: '50vh', backgroundColor: '#2c3e50' }}>
<NumericIndicator value={110} />
</div>
</div>
);
}
function NumericIndicator(props) {
const [number, setNumber] = useState(0);
const [ref, inView] = useInView();
useEffect(() => {
if (!inView) return () => {};
const interval = setInterval(() => {
setNumber((prev) => Math.min(prev + 1, props.value));
}, 500);
return () => clearInterval(interval);
}, [inView, props.value, number]);
return (
<div ref={ref}>
<h1>{number}</h1>
<p>
<small>This needs to increase from 0 to {props.value}</small>
</p>
</div>
);
}
I am new to React and I am learning the basics, but right now I need to rewrite a Class component in order to use React Hooks. So I guess I need to rewrite it to a functional component.
I already tried changing some of the things but in the end everything breaks and I will get a 'props not defined' error.
This is the code:
class Main extends React.Component {
render() {
let close = (
<div
className="close"
onClick={() => {
this.props.onCloseArticle()
}}
></div>
)
return (
<div
ref={this.props.setWrapperRef}
id="main"
style={this.props.timeout ? { display: 'flex' } : { display: 'none' }}
>
<article
id="vision"
className={`${this.props.article === 'vision' ? 'active' : ''} ${
this.props.articleTimeout ? 'timeout' : ''
}`}
style={{ display: 'none' }}
>
<h2 className="major">Vision</h2>
<span className="image main">
<img src={pic01} alt="" />
</span>
<p>
Adipiscing magna sed dolor elit. Praesent eleifend dignissim arcu,
at eleifend sapien imperdiet ac. Aliquam erat volutpat. Praesent
urna nisi, fringila lorem et vehicula lacinia quam. Integer
sollicitudin mauris nec lorem luctus ultrices.
</p>
<p>
Nullam et orci eu lorem consequat tincidunt vivamus et sagittis
libero. Mauris aliquet magna magna sed nunc rhoncus pharetra.
Pellentesque condimentum sem. In efficitur ligula tate urna.
Maecenas laoreet massa vel lacinia pellentesque lorem ipsum dolor.
Nullam et orci eu lorem consequat tincidunt. Vivamus et sagittis
libero. Mauris aliquet magna magna sed nunc rhoncus amet feugiat
tempus.
</p>
{close}
</article>
</div>
)
}
}
Main.propTypes = {
route: PropTypes.object,
article: PropTypes.string,
articleTimeout: PropTypes.bool,
onCloseArticle: PropTypes.func,
timeout: PropTypes.bool,
setWrapperRef: PropTypes.func.isRequired,
}
export default Main
What I did is changing class main to const Main = () => {, remove the render() but after that I am confused..
This should do the work
Replace class by const
Remove the render lifecycle method used in class components
Add the props in the parameter of the function
Remove all the this
const Main = (props) => {
let close = (
<div
className="close"
onClick={() => {
props.onCloseArticle()
}}
></div>
)
return (
<div
ref={props.setWrapperRef}
id="main"
style={props.timeout ? { display: 'flex' } : { display: 'none' }}
>
<article
id="vision"
className={`${props.article === 'vision' ? 'active' : ''} ${
props.articleTimeout ? 'timeout' : ''
}`}
style={{ display: 'none' }}
>
<h2 className="major">Vision</h2>
<span className="image main">
<img src={pic01} alt="" />
</span>
<p>
Adipiscing magna sed dolor elit. Praesent eleifend dignissim arcu,
at eleifend sapien imperdiet ac. Aliquam erat volutpat. Praesent
urna nisi, fringila lorem et vehicula lacinia quam. Integer
sollicitudin mauris nec lorem luctus ultrices.
</p>
<p>
Nullam et orci eu lorem consequat tincidunt vivamus et sagittis
libero. Mauris aliquet magna magna sed nunc rhoncus pharetra.
Pellentesque condimentum sem. In efficitur ligula tate urna.
Maecenas laoreet massa vel lacinia pellentesque lorem ipsum dolor.
Nullam et orci eu lorem consequat tincidunt. Vivamus et sagittis
libero. Mauris aliquet magna magna sed nunc rhoncus amet feugiat
tempus.
</p>
{close}
</article>
</div>
)
}
I have a Navbar which is already fixed to Top and looks something like this:
Now I want to add one more Navigation on top of this and it should look something like this:
The NavBars should be fixed to the top and first one should be slightly smaller in height than the second one.
The code that I am currently using right now is:
<Navbar variant="light" fixed="top" expand="lg" className="pt-4 pb-4">
<Container>
<Navbar.Brand href="/"><Image src={logo}></Image></Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link as={Link} to="/" className="ml-xl-4">Home</Nav.Link>
<Nav.Link className="ml-xl-4">Shop</Nav.Link>
<Nav.Link className="ml-xl-4">Sale</Nav.Link>
</Nav>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-5" />
</Form>
<Nav.Link as={Link} to="/"><Image src={accountIcon}></Image></Nav.Link>
<Nav.Link as={Link} to="/cart" className="pr-0"><Image src={cartIcon}></Image></Nav.Link>
</Navbar.Collapse>
</Container>
</Navbar>
I am using FontAwesome, StyledIcons, StyledComponents and ReactBootstrap. Now I am unable to add another NavBar to top of this existing one. I tried to create another Nav inside the Container, but it is failing. Please guide me in aligning the two Navbars.
One the reasons I moved away from UI libraries is that they can be rather limiting in what you can do in terms of appearance customization. I often find that the more customized the look, the more CSS/Style overrides I have write. Some components will have completely different layouts and different classes for the same component, which means more CSS overrides! As such, this back and forth struggle is one the main reasons why I'd highly recommend utilizing the power of CSS-in-JS (like #emotion or styled-components to name a few).
Nevertheless, here's a working demo:
or
Preview: https://7m0hn.csb.app/
I've used Typescript instead of plain Javascript because VSCode allows you to hover over the component to view a JSDoc description (you may need to scroll down to view the description within dialog). Holding ctrl, while mouse left-clicking on the component, opens a preview within the same tab!
The alternative approach is just to manually add classNames to the ReactBootstrap components and apply CSS overrides. In this case, the bottom bar would be:
position: fixed; // locks it to screen
top: 30px; // at this position (factoring in the height of the top bar)
But again, this won't be as flexible as writing your own reusable components. You may find yourself creating many classes to style the same component for different pages/screen layouts/themes (like this DOM versus this DOM; or heck, even compared to this DOM which just uses a UI library sparingly).
Fixed/index.ts
import styled from "#emotion/styled";
/**
* The Fixed component is a custom styled component to mainly adjust related 'fixed: position" CSS properties.
*
* #param background - sets 'background' CSS property (default: "transparent").
* #param bottom - sets 'bottom' CSS property (default: undefined).
* #param height - sets 'height' CSS property (default: "auto").
* #param left - sets 'left' CSS property (default: undefined).
* #param padding - sets 'padding' CSS property (default: "0px").
* #param right - sets 'right' CSS property (default: undefined).
* #param top - sets 'top' CSS property (default: undefined).
* #param width - sets 'width' CSS property (default: "100%").
*/
const Fixed = styled.div<{
background?: string;
bottom?: string;
height?: string;
left?: string;
padding?: string;
right?: string;
top?: string;
width?: string;
}>`
position: fixed;
display: flex;
align-items: center;
width: 100%;
background: ${({ background }) => background || "transparent"};
border-bottom: 2px solid #ccc;
height: ${({ height }) => height || "auto"};
padding: ${({ padding }) => padding || "0px"};
top: ${({ top }) => top};
right: ${({ right }) => right};
bottom: ${({ bottom }) => bottom};
left: ${({ left }) => left};
width: ${({ width }) => width || "100%"};
`;
export default Fixed;
Flex/index.ts
import styled from "#emotion/styled";
/**
* The Flex component is a custom styled component to mainly set 'flex' CSS properties.
*
* #param align - sets 'align-items' CSS property (default: "stretch").
* #param justify - sets 'justify-content' CSS property (default: "flex-start").
* #param padding - sets 'padding' CSS property (default: "0px").
* #param width - sets 'width' CSS property (default: "100%").
*/
const Flex = styled.div<{
align?:
| "stretch"
| "center"
| "flex-start"
| "flex-end"
| "baseline"
| "initial"
| "inherit";
justify?:
| "flex-start"
| "flex-end"
| "center"
| "space-between"
| "space-around"
| "space-evenly";
padding?: string;
width?: string;
}>`
display: flex;
justify-content: ${({ justify }) => justify || "flex-start"};
align-items: ${({ align }) => align || "stretch"};
padding: ${({ padding }) => padding || "0px"};
width: ${({ width }) => width || "100%"};
`;
export default Flex;
Navbar/index.tsx
import * as React from "react";
import Nav from "react-bootstrap/Nav";
import NavDropdown from "react-bootstrap/NavDropdown";
import Navbar from "react-bootstrap/Navbar";
import Form from "react-bootstrap/Form";
import FormControl from "react-bootstrap/FormControl";
import { IoPersonOutline } from "react-icons/io5";
import { GiShoppingCart } from "react-icons/gi";
import Fixed from "../Fixed";
import Flex from "../Flex";
export type eventKey = string | null;
const TopNavBar = () => {
const [language, setLanguage] = React.useState<eventKey>("DE");
const [currency, SetCurrency] = React.useState<eventKey>("€ EUR");
const handleLanguageChange = React.useCallback((eventKey: eventKey) => {
setLanguage(eventKey);
}, []);
const handleCurrencyChange = React.useCallback((eventKey: eventKey) => {
SetCurrency(eventKey);
}, []);
return (
<>
<Navbar className="navbar-top" fixed="top">
<Flex justify="flex-end" padding="0 20px 0 0">
<NavDropdown
onSelect={handleLanguageChange}
alignRight
title={language}
id="basic-nav-dropdown"
>
<NavDropdown.Item eventKey="EN">EN</NavDropdown.Item>
<NavDropdown.Item eventKey="ES">ES</NavDropdown.Item>
<NavDropdown.Item eventKey="DE">DE</NavDropdown.Item>
<NavDropdown.Item eventKey="JP">JP</NavDropdown.Item>
</NavDropdown>
<NavDropdown
onSelect={handleCurrencyChange}
alignRight
title={currency}
id="basic-nav-dropdown"
>
<NavDropdown.Item eventKey="€ EUR">€ EUR</NavDropdown.Item>
<NavDropdown.Item eventKey="£ GBP">£ GBP</NavDropdown.Item>
<NavDropdown.Item eventKey="¥ JPY">¥ JPY</NavDropdown.Item>
<NavDropdown.Item eventKey="$ USD">$ USD</NavDropdown.Item>
</NavDropdown>
</Flex>
</Navbar>
<Fixed background="#fff" padding="5px 60px 0 20px" top="30px">
<Flex justify="flex-start">
<Navbar.Brand href="/">Brand</Navbar.Brand>
</Flex>
<Flex justify="center">
<Form inline>
<FormControl
type="text"
placeholder="Search"
className="search-box"
/>
</Form>
</Flex>
<Flex justify="flex-end">
<Nav.Link>
<IoPersonOutline />
</Nav.Link>
<Nav.Link className="pr-0">
<GiShoppingCart />
</Nav.Link>
</Flex>
</Fixed>
</>
);
};
export default TopNavBar;
App.tsx
import Navbar from "./Navbar";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
const App = () => (
<div className="app">
<Navbar />
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<p>
Curabitur aliquet quam id dui posuere blandit. Nulla porttitor accumsan
tincidunt. Nulla porttitor accumsan tincidunt. Curabitur arcu erat,
accumsan id imperdiet et, porttitor at sem. Vestibulum ante ipsum primis
in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit
neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere
cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper
sit amet ligula. Vestibulum ac diam sit amet quam vehicula elementum sed
sit amet dui. Vestibulum ante ipsum primis in faucibus orci luctus et
ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam
vel, ullamcorper sit amet ligula. Cras ultricies ligula sed magna dictum
porta. Pellentesque in ipsum id orci porta dapibus.
</p>
<p>
Proin eget tortor risus. Donec sollicitudin molestie malesuada. Lorem
ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ante ipsum
primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec
velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula.
Curabitur aliquet quam id dui posuere blandit. Curabitur aliquet quam id
dui posuere blandit. Curabitur aliquet quam id dui posuere blandit.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere
cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper
sit amet ligula. Praesent sapien massa, convallis a pellentesque nec,
egestas non nisi. Vestibulum ac diam sit amet quam vehicula elementum sed
sit amet dui.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eget tortor
risus. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus.
Vivamus suscipit tortor eget felis porttitor volutpat. Pellentesque in
ipsum id orci porta dapibus. Cras ultricies ligula sed magna dictum porta.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque in
ipsum id orci porta dapibus. Vestibulum ante ipsum primis in faucibus orci
luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit
amet aliquam vel, ullamcorper sit amet ligula. Praesent sapien massa,
convallis a pellentesque nec, egestas non nisi.
</p>
</div>
);
export default App;
index.tsx
import { render } from "react-dom";
import App from "./App";
render(<App />, document.getElementById("root"));
styles.css
.app {
margin-top: 120px;
font-family: sans-serif;
text-align: center;
min-height: 120vh;
}
.navbar-top {
padding: 0;
background: #dadada;
border-bottom: 2px solid #ccc;
}
.nav-link {
padding: 2px 20px;
}
.search-box {
height: 35px;
}
::-moz-focus-inner {
border: 0;
}
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
background: #f9f9f9;
}
*,
:after,
:before {
-ms-overflow-style: none;
scrollbar-width: none;
box-sizing: border-box;
}
actually, I am trying to create a responsive app bar using the material UI/app drawer. when I clicked the but it starts from the top of the page and makes the background dark but I want to make it start from the bottom of the app bar without making the background dark. please help me and give example using codesandbox https://codesandbox.io/s/64ulq
I trying to do this
but it shows like that
you can make a mix of multiple exemple of material ui drawer (Persistent and clipped one) and it give you something like this :
import React from 'react';
import { createStyles, Theme, makeStyles } from '#material-ui/core/styles';
import Drawer from '#material-ui/core/Drawer';
import AppBar from '#material-ui/core/AppBar';
import CssBaseline from '#material-ui/core/CssBaseline';
import Toolbar from '#material-ui/core/Toolbar';
import List from '#material-ui/core/List';
import Typography from '#material-ui/core/Typography';
import Divider from '#material-ui/core/Divider';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import InboxIcon from '#material-ui/icons/MoveToInbox';
import MailIcon from '#material-ui/icons/Mail';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
const drawerWidth = "100vw";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
drawer: {
width:"100vw",
},
drawerPaper: {
width: drawerWidth,
},
drawerContainer: {
overflow: 'auto',
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
},
}),
);
export default function ClippedDrawer() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(!open);
};
return (
<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Clipped drawer
</Typography>
</Toolbar>
</AppBar>
<Drawer
anchor="top"
className={classes.drawer}
variant="persistent"
open={open}
classes={{
paper: classes.drawerPaper,
}}
>
<Toolbar />
<div className={classes.drawerContainer}>
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{['All mail', 'Trash', 'Spam'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
</Drawer>
<main className={classes.content}>
<Toolbar />
<Typography paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Rhoncus dolor purus non enim praesent elementum
facilisis leo vel. Risus at ultrices mi tempus imperdiet. Semper risus in hendrerit
gravida rutrum quisque non tellus. Convallis convallis tellus id interdum velit laoreet id
donec ultrices. Odio morbi quis commodo odio aenean sed adipiscing. Amet nisl suscipit
adipiscing bibendum est ultricies integer quis. Cursus euismod quis viverra nibh cras.
Metus vulputate eu scelerisque felis imperdiet proin fermentum leo. Mauris commodo quis
imperdiet massa tincidunt. Cras tincidunt lobortis feugiat vivamus at augue. At augue eget
arcu dictum varius duis at consectetur lorem. Velit sed ullamcorper morbi tincidunt. Lorem
donec massa sapien faucibus et molestie ac.
</Typography>
<Typography paragraph>
Consequat mauris nunc congue nisi vitae suscipit. Fringilla est ullamcorper eget nulla
facilisi etiam dignissim diam. Pulvinar elementum integer enim neque volutpat ac
tincidunt. Ornare suspendisse sed nisi lacus sed viverra tellus. Purus sit amet volutpat
consequat mauris. Elementum eu facilisis sed odio morbi. Euismod lacinia at quis risus sed
vulputate odio. Morbi tincidunt ornare massa eget egestas purus viverra accumsan in. In
hendrerit gravida rutrum quisque non tellus orci ac. Pellentesque nec nam aliquam sem et
tortor. Habitant morbi tristique senectus et. Adipiscing elit duis tristique sollicitudin
nibh sit. Ornare aenean euismod elementum nisi quis eleifend. Commodo viverra maecenas
accumsan lacus vel facilisis. Nulla posuere sollicitudin aliquam ultrices sagittis orci a.
</Typography>
</main>
</div>
);
}
code sandbox