Center content and make their position adjustable - css

I'm new to react and css.
My goal here is to center my 3 switches and the name of them in the center of my page. Then I would like the 3 switches button to adjust their position automatically no matter the length of the text on its left.
Here is what I have for the moment.
This is the switch button + text. I made a style to align the text with the middle of the switch icon. I tried the verticalAlign: "middle" but it the text went at the bottom position.
import React, { useState } from "react";
import Switch from "react-switch";
const SwitchMode = ({text}) => {
const [checked, setChecked] = useState(false)
const handleChange = StateCheck => {
setChecked(StateCheck)
}
return(
<div className="switch-position">
<label>
<span style={{display: "inline-flex", verticalAlign: '50%', marginRight: '4%'}}>{text}</span>
<Switch
onChange={handleChange}
checked={checked}
className="react-switch"
/>
</label>
</div>
)
}
export default SwitchMode
And this is the css I've made for the moment
body {
margin: 0;
}
.image-position {
display: flex;
justify-content: center;
width: 100%;
margin-top: 5%;
height: auto;
}
.service-position {
display: flex;
flex-direction: column;
margin-top: 5%;
}
.switch-position {
display: inline;
justify-content: center;
width: 100%;
margin-top: 1%;
}
in this file I create my switch button, apply the css and give them a name.
import React from 'react';
import './index.css';
import ReactRoundedImage from "react-rounded-image";
import Img from './images/Diamond.png'
import SwitchMode from './Switch';
const Profile = () => {
return(
<div>
<div className='image-position'>
<ReactRoundedImage image={Img} roundedSize="0" imageWidth="150" imageHeight="150" />
</div>
<div className='service-position'>
<SwitchMode text="Discord"/>
<SwitchMode text="Google"/>
<SwitchMode text="FEJZIOFZEJ"/>
</div>
</div>
)
}
export default Profile
this is the actual result

You can do something like this:
body {
margin: 0;
}
.image-position {
display: flex;
justify-content: center;
width: 100%;
margin-top: 5%;
height: auto;
}
.service-position {
display: flex;
justify-content: center;
flex-direction: row;
margin-top: 5%;
}
.switch-position {
text-align: center;
width: 100px;
}
and change your SwitchMode component to this:
const SwitchMode = ({ text }) => {
const [checked, setChecked] = useState(false);
const handleChange = (StateCheck) => {
setChecked(StateCheck);
};
return (
<div className="switch-position">
<label>
<span>{text}</span>
<Switch
onChange={handleChange}
checked={checked}
className="react-switch"
/>
</label>
</div>
);
};
The main things I did was set justify-content: center and flex-direction: row on .service-position. To make sure the .switch-position items displayed in a row and were centered.
For centering the text next to the switch button I used text-align: center and to make sure the text is displayed above the switch button I set a fixed with on .switch-position.
Sandbox Example

Related

Change navbar background color on other routes in ReactJS

I have following react code.
the code
What I would like is to just when I click on "about" menu background color should change from red to blue otherwise stay in red.
in another scenario:
(my problem is how to access to links "route" or "path" in react because i want to add condition like ==> if (path =="./about) do somthing...)
is there any way to do this? i would appreciate for your help.
If you are using react-router-dom
Then you can use the useLocation hook to get the current location
First import it
import { useLocation } from 'react-router-dom';
Then get the location
const location = useLocation();
You can use a useEffect hook to change the background color whenever the location changes
useEffect(()=>
{
if(location.pathname == '/about'){
// Change background color
}
}
},[location])
This should work for you
Try to include this code in your App.js
Following code works:
const Nav = styled.nav`
height: 100px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
padding: 0px 10px;
width: 100%;
z-index: 100;
/* background-color: red; */
`;
const Menu = styled.div`
display: flex;
flex-wrap: wrap;
gap: 20px;
align-items: center;
justify-content: center;
`;
const Navbar = ({ toggle }) => {
const [navBg, setNavBg] = React.useState("red");
const location = useLocation();
React.useEffect(() => {
if (window.location.pathname === "/about") {
setNavBg("yellow");
} else {
setNavBg('red')
}
}, [location]);
return (
<Nav style={{ backgroundColor: navBg }}>
<h1 to="/">logo</h1>
<Menu>
<Link to="/">home</Link>
<Link to="/about">about</Link>
<Link to="/services">services</Link>
</Menu>
</Nav>

I want the sidebar to appear on all interfaces

I am creating a site for the sake of monitoring employees, and there are six interfaces on the site, as the first interface is for the Sine-Up, the second for logging, and the third interface is for creating a project, the fourth interface is for displaying projects, the fifth is for creating TASK and the sixth In order to view the tasks.
And I created a sidebar in a separate interface, which is the image shown in the screen, and my problem now is that I want the sidebar to appear in all interfaces except for the signup and the log.
This is the application file from which router-view is used.
App.vue:
<template>
<v-app>
<router-view></router-view>
</v-app>
</template>
<script>
export default {
components:{
}
}
</script>
And in this file, the sidebar was created, which I want to appear in all the interfaces.
navbar.vue:
<template>
<v-app>
<div class="main-sidebar-container">
<div class="main-sidebar-container_content">
<v-navigation-drawer class="deep-purple accent-4" dark permanent>
<div class="main-sidebar-container_content_header">
<img class="logo" src="../../../src/assets/logo_base.png" />
</div>
<v-divider></v-divider>
<div class="sidebar-search">
<div class="cu2-search_simple-layout cu2-search">
<div class="cu2-search__inner ">
<div class="cu2-search__icon icon">
<svg class="ng-star-inserted">
<use
xlink:href="https://app.clickup.com/map.e7a227c29e2316abeae1.svg#svg-sprite-
cu3-search"
></use>
</svg>
</div>
</div>
</div>
</div>
<div class="cu2-search__text"> Search </div>
<v-list>
<v-list-item v-for="item in items" :key="item.title" class="twoSection" link>
<v-list-item-icon>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
<template v-slot:append>
<div class="pa-2">
<v-btn block>
Logout
</v-btn>
</div>
</template>
</v-navigation-drawer>
</div>
</div>
</v-app>
</template>
<script>
export default {
data() {
return {
drawer: true,
items: [
{ title: "Home", icon: "mdi-home-city" },
{ title: "Notifications", icon: "mdi-account" },
{ title: "Pulse", icon: "mdi-account-group-outline" },
{ title: "Goals", icon: "mdi-account" },
{ title: "Show less", icon: "mdi-account-group-outline" }
],
mini: true,
};
},
};
</script>
<style scoped>
.main-sidebar-container {
left: 0;
top: 0;
bottom: 0;
height: 100%;
width: 60%;
position: fixed;
z-index: 1;
top: 0;
overflow-x: hidden;
}
.main-sidebar-container_content {
width: 50%;
height: 100%;
}
.main-sidebar-container_content_header {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
height: 10%;
padding-left: 1rem;
}
.logo {
display: flex;
width: 50%;
z-index: 1;
position: fixed;
}
.sidebar-search {
display: flex;
align-items: center;
height: 32px;
flex-shrink: 0;
margin: 0 8px 10px;
}
.cu2-search_simple-layout {
width: auto;
height: 100%;
flex-grow: 1;
border-radius: 4px;
background: #f6f7f9;
}
.cu2-search {
transition: background-color 0.2s cubic-bezier(0.785, 0.135, 0.15, 0.86) 0s;
display: flex;
align-items: center;
justify-content: center;
position: relative;
width: 30px;
height: 30px;
border-radius: 3px;
overflow: hidden;
flex-shrink: 0;
}
.cu2-search__inner {
display: flex;
align-items: center;
cursor: pointer;
width: 100%;
height: 100%;
}
.cu2-search__icon {
transition: fill 0.2s cubic-bezier(0.785, 0.135, 0.15, 0.86) 0s;
}
.icon {
display: flex;
align-items: center;
justify-content: center;
flex-grow: 0;
flex-shrink: 0;
}
.icon svg {
display: block;
}
.cu2-search__text{
display: block;
font: 400 12px/1 Gotham Pro,Proxima Nova,arial,serif;
color: rgba(124,130,141,.5);
transition: color .2s cubic-bezier(.785,.135,.15,.86) 0s;
cursor: pointer;
display: none;
}
.twoSection{
display: flex;
justify-content: center;
align-items: center;
height: 10%;
}
</style>
main.js:
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import VueRouter from "vue-router";
import { routes } from "./router";
import axios from "axios";
import { store } from './store/index';
import Vuelidate from "vuelidate";
import 'material-design-icons-iconfont/dist/material-design-icons.css'
Vue.config.productionTip = false
Vue.use(VueRouter);
Vue.use(Vuelidate);
axios.defaults.baseURL = "localhost:4000/api/services";
axios.defaults.headers.common["Authorization"] =
"Bearer " + localStorage.getItem("accessToken") || null;
axios.defaults.headers.get["Accepts"] = "application/json";
const router = new VueRouter({
routes,
mode: "history",
});
new Vue({
vuetify,
router,
store,
render: h => h(App)
}).$mount('#app')
you can add your navbar component to App .vue
like
<template>
<v-app>
<div>
<div class="flex w-full overflow-auto h-screen bg-page">
<navbar class="w-full flex-1 max-w-72"/>
<div class="px-4 flex-1 max-h-screen overflow-auto">
<div class="pb-16">
<router-view></router-view>
</div>
</div>
</div>
</v-app>
</template>
<script>
import navbar from './navbar'
export default {
components:{
navbar
}
}
</script>
but you should handle login and signup views to make sidebar disappears.
to do this you have several options.
For it to appear in every page, you need to import the navigation component in every page.
So for instance, let's say your navigation file is called TheNavigation.vue, then on every interface you need to do something as following in the template where you want that component to appear-->
<div style="text-align: center;">
<TheNavigation />
<transition name="fade" mode="out-in">
<router-view :key="$route.path" />
</transition>
</div>
Then, in the script, you need to import the component like below
<script>
import TheNavigation from '../components/TheNavigation.vue';
import axios from "axios";
export default {
components: {
TheNavigation
},
data() {
}
}
</script>
Let me know if this worked! Or if you need me to go deeper into this! Make sure to put your relative path when importing the navigation component in the script!
The way I used to do this in React.js was, I used to make a Menu Component then use that component with every MenuItem component.
Like in your case Home MenuItem or others component you can call Menu component in that MenuItem Component
Something like this
const Menu = () => {
return <div>{...Menu}</div>
}
const HomeMenuItem = () => {
return (
<div>
<Menu />
<div>
{...this menu content in here!}
</div>
</div>
)
}
and the same goes for every other menuItem, it's somewhat of a hack but it works.

How to show less number of pages on mobile view in Pagination?

Problem
Need to show less number of pages in mobile view so that it can be aligned with heading (My Orders) in the same line.
Library
material-ui/pagination
Progress
Able to remove Next and Previous content in the mobile view but neither able to find any out-of-the-box prop(s) nor any CSS to reduce number of pages in mobile view
Web view
Mobile View
Code
CSS
#media (min-width: 501px) {
.MuiPagination-root {
.MuiPagination-ul {
flex-wrap: nowrap;
li {
&:first-child {
flex-basis: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
> button::before {
margin-right: 10px;
content: "Previous ";
}
}
&:last-child {
flex-basis: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
> button::after {
margin-left: 10px;
margin-right: 20px;
content: " Next";
}
}
}
}
}
Custom Component
import React, { useState } from "react";
import PropTypes from "prop-types";
import Pagination from '#material-ui/lab/Pagination';
export const CustomPagination = ({ onChange, totalRecords, currentPage, className, shape }) => {
return (
<Pagination
count={totalRecords}
shape={shape}
className={className}
onChange={onChange}
page={currentPage}
/>
)
};
CustomPagination.propTypes = {
paginationLength: PropTypes.number,
selectPage: PropTypes.func,
activePage: PropTypes.number,
};
One of the solutions I came up with is wrapping the component pagination inside a Box then changing its size depending on the view :
export function Test() {
return;
<>
<Box sx={{ display: { xs: "none", md: "block" } }}>
<Pagination
/>
</Box>
<Box sx={{ display: { xs: "block", md: "none" } }}>
<Pagination
size="small"
/>
</Box>
</>;
}
</Box>

How to make container expand up instead of down when component added?

I have a React component that asks user to upload profile photo. In the same view, the user can see a greyed out 'next' button. When the photo is uploaded and displayed, the user sees a horizontal scrolling bar to adjust photo size that comes between the photo and next button. My goal is to keep the next button in view at all times but also keep all elements of the component in the same order. Right now, a user has to scroll down to see the 'next' once the image is loaded. I've been experimenting with flex and position and even a ternary in the JSX to add paddingBottom when !isLoading. Can someone give a good direction so that the user doesn't have to scroll down to see the next' button?
Here is my component:
import React, { useContext, useState, useEffect } from 'react';
import styled from 'styled-components';
import Typography from 'components/Typography';
// import { useMediaQuery } from 'beautiful-react-hooks';
import { medium } from 'constants/mediaQueries';
import AppButton from 'components/AppButton';
import useFetcher from 'hooks/useFetcher';
import { getMeApi } from 'utils/apiRoutes';
import Loader from 'components/Loader';
import routePaths from 'containers/Router/routePaths';
import { useHistory, useLocation } from 'react-router-dom';
import { UserContext } from 'containers/context/UserContext';
import checkmarkImage from 'assets/images/checkmark.svg';
import { useDispatch } from 'react-redux';
import BackArrowGrid from 'components/Auth/BackArrowGrid';
import UploadImageInput from 'components/UploadImageInput';
import { setPlainLogo, setInitialLogo } from '../../store/header/actions';
// const MOBILE = 250;
// const DESKTOP = 356;
const Container = styled.div`
width: 100%;
position: relative;
align-items: center;
justify-content: flex-end;
display: flex;
flex-direction: column;
border: pink solid 2px;
`;
const ButtonContainer = styled.div`
margin-top: 32px;
display: flex;
align-items: center;
flex-direction: row;
div {
margin-bottom: 16px;
}
img {
margin-left: 8px;
}
`;
const Title = styled(Typography)`
font-size: 40px;
text-transform: uppercase;
margin-bottom: 64px;
#media (min-width: ${medium}) {
margin-bottom: 64px;
}
`;
const ButtonContent = styled.span`
display: flex;
align-items: center;
`;
const Form = styled.div`
width: 100%;
display: flex;
flex-direction: column;
align-self: flex-end;
border: yellow solid 2px;
.empty {
display: none;
}
#media (min-width: ${medium}) {
flex-direction: column;
align-items: center;
min-height: auto;
.empty {
display: block;
width: 118px;
}
}
`;
const UploadPicture = () => {
const { fetcher, error, isLoading } = useFetcher();
const { setUserFromLogin } = useContext(UserContext);
const history = useHistory();
const location = useLocation();
// const isDesktop = useMediaQuery(`(min-width: ${medium})`);
const dispatch = useDispatch();
const [image, setImage] = useState({});
const uploadImage = async () => {
const result = await fetcher({
url: getMeApi,
method: 'POST',
body: {
photo: image.croppedImage.source,
},
});
if (result.errors) {
return;
}
setUserFromLogin(result.user);
if (location.profile) {
history.push(routePaths.Profile);
} else {
history.push(routePaths.Welcome);
}
};
useEffect(() => {
dispatch(setPlainLogo());
return () => dispatch(setInitialLogo());
}, []);
const onPictureChange = newImage => {
setImage(prevImage => ({
...prevImage,
...newImage,
}));
};
return (
<>
<BackArrowGrid>
<Container>
<Title h1>Profile photo</Title>
<Form>
<div className="empty"> </div>
<UploadImageInput
onChange={onPictureChange}
image={image}
placeholder={
"Upload a profile photo. This is how you'll appear to other Color TV users."
}
height={356}
width={356}
horizontalPadding={60}
aspect={1}
round
/>
<ButtonContainer>
{error && (
<Typography error>
Error while uploading the image, please try again.
</Typography>
)}
<AppButton
primary={!!image.croppedImage}
disabled={isLoading || !image.croppedImage}
onClick={uploadImage}
noBorder
>
<ButtonContent>
{isLoading ? (
<Loader className="center" size={30} />
) : (
'Next'
)}
{!isLoading && !!image.croppedImage && (
<img src={checkmarkImage} alt="checkmark_icon" />
)}
</ButtonContent>
</AppButton>
</ButtonContainer>
</Form>
</Container>
</BackArrowGrid>
</>
);
};
export default UploadPicture;
Since this component is part of a larger code base, I'm not sure how to run a snippet of it but here are 2 photos - before and after. Once the photo is uploaded, the next button drops out of view because the slider component is added in. I want to next button to stay in view no matter how the browser size.

React: Using State to change the appearance of a circle component when a button component is pressed

I'm trying to change the appearance of a circle component when it's selected by a button in another component. they both have to change appearance when selected. I'm running into problems with state and I'm kinda confused. Also, I've been trying to use the onClick functionality, but can't seem to get it right. Any help will be appreciated
App.js
import "./App.css";
import CircleSelector from "./CircleSelector";
import Circles from "./Circles";
class App extends Component {
constructor(props) {
super();
this.addActiveClass = this.addActiveClass.bind(this);
this.state = {
active: false
};
}
toggleClass() {
const currentState = this.state.active;
this.setState({ active: !currentState });
}
render() {
return (
<div className="App">
<header className="App-header">test </header>
<main>
<CircleSelector
className={this.state.active ? "selected" : null}
onClick={this.toggleClass}
/>
<Circles />
</main>
</div>
);
}
}
export default App;
CircleSelector.js
import React from "react";
function CircleSelector(props) {
return (
<div className="CircleSelector">
<button className="selected">Select Circle 1</button>
<button>Select Circle 2</button>
<button>Select Circle 3</button>
<button>Select Circle 4</button>
</div>
);
}
// Must export the component's function (or class)
export default CircleSelector;
Circles.js
import React from "react";
function Circles(props) {
return (
<div className="Circles">
<div className="selected">1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
);
}
// Must export the component's function (or class)
export default Circles;
App.css
body,
* {
box-sizing: border-box;
}
.App {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.App-header {
width: 100%;
padding: 20px;
font-size: 24px;
background-color: grey;
color: white;
text-align: center;
letter-spacing: 3px;
}
.App main {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex: 1;
}
.CircleSelector {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
height: 200px;
width: 150px;
border: 4px solid purple;
border-radius: 8px;
margin-right: 20px;
}
It appears as though your problem may be from toggleClass. When the function executes onClick, it is using this from inside the button's scope, not the class scope.
Try binding the function like so:
<CircleSelector
className={this.state.active ? "selected" : null}
onClick={this.toggleClass.bind(this)}
/>
You can read more and find more potential solutions to the scope issue here

Resources