Angular horizontal scroll with dynamic arrows - css

I want to use horizontal scroll with left and right arrows with dynamically hide and show functionality.
Horizontal scroll (with arrows) for Angular package This thread here answers it but without dynamic hide/show of arrows. Please reply if someone has idea about it. Thanks.
Here is the code below:
.html
<div class="custom-slider-arrow mt-sm">
<img src="assets/img/chevron-left.svg" alt="" (click)="scrollLeft()">
</div>
<div #widgetsContent class="custom-slider-main">
<ng-container *ngFor="let object of statusList">
<status-card ></status-card>
</ng-container>
</div>
<div class="custom-slider-arrow mt-sm">
<img src="assets/img/chevron-right.svg" alt="" (click)="scrollRight()">
</div>
</div>
And .ts file has this code.
#ViewChild('widgetsContent',{static:false}) widgetsContent: ElementRef;
scrollLeft(){
this.widgetsContent.nativeElement.scrollLeft -= 300;
}
scrollRight(){
this.widgetsContent.nativeElement.scrollLeft += 300;
}
.scss file contains
.custom-slider-main{
display: flex;
overflow: hidden;
scroll-behavior: smooth;
}
.custom-slider-arrow{
display: flex;
align-items: center;
img{
width: 48px;
height: 48px;
}
}

1) .ts file
import { Component, OnInit, ViewChild, ElementRef } from '#angular/core';
export class Scroll implements OnInit {
#ViewChild('scrollMenu') scrollMenu: ElementRef;
rightDisabled: boolean = false;
leftDisabled: boolean = true;
constructor(){}
scrollLeft(){
this.scrollMenu.nativeElement.scrollLeft -= 150;
this.checkScroll()
}
scrollRight(){
this.scrollMenu.nativeElement.scrollLeft += 150;
this.checkScroll();
}
onScroll(e){
this.checkScroll();
}
checkScroll(){
this.scrollMenu.nativeElement.scrollLeft==0? this.leftDisabled = true :this.leftDisabled = false;
let newScrollLeft = this.scrollMenu.nativeElement.scrollLeft;
let width = this.scrollMenu.nativeElement.clientWidth;
let scrollWidth = this.scrollMenu.nativeElement.scrollWidth;
scrollWidth - (newScrollLeft+width)==0? this.rightDisabled = true :this.rightDisabled = false;
}
}
2) .html file
<ion-row>
<div class="pull-left mt-sm" (click)="scrollLeft()" [ngClass]="this.leftDisabled ? 'visibility':''">
<ion-icon name="chevron-back-outline" style="font-size: 24px;" ></ion-icon>
</div>
<div class="scroll" scrollX="true" #scrollMenu (scroll)="onScroll($event)" [ngClass]="this.rightDisabled ? 'width':this.leftDisabled?'width':''">
<div *ngFor="let data of yourDataArray">
{{data.someData}}
</div>
</div>
<div class="pull-right" (click)="scrollRight()" [ngClass]="this.rightDisabled ? 'visibility':''">
<ion-icon name="chevron-forward" style="font-size: 24px;" ></ion-icon>
</div></ion-row>
3) .scss file
.scroll {
overflow: auto;
scroll-behavior: smooth;
width: 80%;
background: var(--ion-primary-bg);
}
.pull-right{
background: grey;
display: flex;
align-items: center;
width: 10%;
justify-content: space-around;
}
.visibility{
display: none !important;
}
.pull-left{
background: grey;
display: flex;
align-items: center;
width: 10%;
justify-content: space-around;
}
.width{
width:90% !important;
}

Related

How to give animation on width change with different classname but for same component

what is the best practice to show/hide the side menu with animation? The way I implement works fine but I can't implement the animation. I also shared images so everyone can have some idea.
The answer might be easy but I couldn't fully understand the toggle class efficiently. If I would I should be able to implement transition just by changing the width from the same classname.
Also I am getting this error on console: Received false for a non-boolean attribute className.
React code ;
const handleSize = () => {
setOpen(!open); }; return (
<div
className={"sideBar" + `${open ? " sideBar__show" : " sideBar__hide"}`}
>
<div className="sideBar__header">
<div className="menu_buttons" onClick={handleSize}>
<MenuIcon className="sideBar_icon" />
<p className={!open && "sideBar_hide__content"}>Menu</p>
</div>
</div>
<hr className="sideBar__divider" />
<div className="sideBar__content">
{sideBarContent.map((item) => {
return (
<div className="menu_buttons" key={item.name}>
<item.icon />
<p className={!open && "sideBar_hide__content"}>{item.name}</p>
</div>
);
})}
</div>
<hr className="sideBar__divider" />
<div className="sideBar__footer">
<Avatar>{firstLetter}</Avatar>
<p className={!open && "sideBar_hide__content"}>{adminName}</p>
</div>
</div> ); };
CSS;
.sideBar {
position: fixed;
left: var(--sidebar-left-margin);
height: max-content;
top: calc(var(--header-height) + 10px);
bottom: 10px;
border-radius: 10px;
background-color: var(--second-color);
display: flex;
flex-direction: column;
align-items: center;
padding: 10px 5px;
border: 1px solid var(--main-color);
/* transition: all ease-in 1s; */
}
.sideBar__show {
width: var(--sidebarOpen-width);
}
.sideBar_hide {
width: var(--sidebarClose-width);
}
.sideBar_hide__content {
display: none;
}
Not sure what is best practice, this is my currently approach:
const handleSize = () => setOpen(!open);
const sideBarClasses = open ? "sideBar sideBar_show : "sideBar sideBar_hide;
<div className="sideBar__header">
<div className={sideBarClasses}>

How to restrict the number of items in flexbox according to screen size

I am new to grid designing on website design
In my react project, I have a row showing 3 components. One is Leverage type dot selection, Two of them are input box, Loan amount and Loan Rate.
Right now, every things seems fine in full screen, but when I shrink it, you can see that Loan Rate is placed on the next line while Loan Amount was still on above line
But what I want is, when I shrink it, it is either like this(1), or like (2) when it is super small
In(2), basically its been achieved with my existing css, when the screen is super small
Q: How could I either showing everything in the same line or showing one line with leverage type and one line with Loan Amount and Loan Rate?
Here is my code
.setting {
display: flex;
justify-content: space-between;
margin-top: 50px;
}
There are many ways we can break flex item in flexbox layout the one I have used here is flex-direction:column, this property sets every flexitem to vertically..
#media(max-width:576px) {
.flexBox {
flex-direction: column;
/*set all flexItem to vertically*/
align-items: stretch;
/* stretch will foce to take full width*/
}
}
Meaning of media(max-width:979px) means, CSS inside of that code block will only apply to screen size lessthan or equal to 979px. Means the CSS will not affect for screensize bigger than 979px.
Speaking about below code,
.flexBox .flexItem {
flex: 1 0 calc(100%/var(--number-of-items-for-midium-screen) - var(--gap-val)*2)
}
calc(100%/var(--number-of-items-for-midium-screen) - var(--gap-val)*2) here we divide 100% width with the number of items we want per row and we minus var(--gap-val) twice because we have applied gap:10px, which applied both side of .flexItem so we minus it 2 times.
And just to make CSS more friendly I have created CSS variables for
--number-of-items-for-midium-screen <= Number of items in a row
--gap-val <= gap between flex items in a row
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--number-of-items-for-midium-screen: 2;
/*Number of items you want in medium screen(below 979px)*/
--gap-val: 10px;
/*Gap you want between flex items*/
}
.flexBox {
display: flex;
align-items: center;
gap: var(--gap-val);
margin: 10px;
}
.flexBox .flexItem {
flex: 1;
border: 2px solid #d6d6d6;
padding: 10px;
}
#media(max-width:979px) {
.flexBox {
flex-wrap: wrap;
}
.flexBox .flexItem {
flex: 1 0 calc(100%/var(--number-of-items-for-midium-screen) - var(--gap-val)*2)
}
}
#media(max-width:576px) {
.flexBox {
flex-direction: column;
/*set all flexItem to vertically*/
align-items: stretch;
/* stretch will foce to take full width*/
}
}
<div class="flexBox">
<div class="flexItem">
<p>Leverage type</p>
<label for="static">static</label>
<input type="radio" value="static" id="static" name="gp1" />
<label for="dynamic">dynamic</label>
<input type="radio" value="static" id="dynamic" name="gp1" />
</div>
<div class="flexItem">
<label for="loanRate">Loan Rate</label>
<input id="loanRate" type="text" />
</div>
<div class="flexItem">
<label for="loanAmount">Loan Amount</label>
<input id="loanAmount" type="text" />
</div>
</div>
Understanding how to break layouts in flexbox
const btn1 = document.querySelector("#btn1"),
btn3 = document.querySelector("#btn3"),
btn4 = document.querySelector("#btn4");
const flexBox = document.querySelectorAll(".flexBox")[0];
const flexItems = document.querySelectorAll(".flexBox .flexItem");
const preview = document.querySelectorAll(".preview")[0];
btn1.onclick = () => {
flexBox.style.flexDirection = "column";
preview.style.display = "block";
preview.innerHTML = `.flexBox{flex-direction:column;}`;
}
btn3.onclick = () => {
flexItems.forEach(flexItem => {
flexItem.style.flex = "1";
})
preview.style.display = "block";
preview.innerHTML = `.flexItems{flex:1;}`;
}
btn4.onclick = () => {
const numberofItems = +document.querySelector("#numberofItems").value;
if (numberofItems && numberofItems >= 1 && numberofItems <= 6) {
flexBox.style.flexFlow = "initial";
flexBox.style.flexWrap = "wrap";
flexItems.forEach(flexItem => {
flexItem.style.flex = `1 0 calc(100%/${numberofItems})`;
})
preview.style.display = "block";
preview.innerHTML = `.flex{flex-wrap:wrap;}</br>.flexItems{flex:1 0 calc(100%/${numberofItems});}`;
} else {
alert("Please enter number of items you need from 1 to 6");
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.flexBox {
display: flex;
}
.flexItem {
display: inline-block;
height: 100px;
}
.bg-red {
background-color: red;
}
.bg-blue {
background-color: blue;
}
.bg-green {
background-color: green;
}
/*Just for styling*/
.buttons {
margin-top: 10px;
}
.buttons button {
padding: 10px;
border: 2px solid #000;
background: #fff;
text-transform: capitalize;
margin: 10px;
}
.textInput {
display: flex;
gap: 5px;
margin: 10px;
}
.textInput input {
flex: 1 0 75%;
}
.textInput button {
padding: 5px;
margin: 0;
}
.preview {
width: 100%;
border: 2px solid #000;
display: none;
padding: 30px;
}
<div class="flexBox">
<div class="flexItem bg-red">
<h5>This is flex box item</h5>
</div>
<div class="flexItem bg-blue">
<h5>This is flex box item</h5>
</div>
<div class="flexItem bg-green">
<h5>This is flex box item</h5>
</div>
<div class="flexItem bg-red">
<h5>This is flex box item</h5>
</div>
<div class="flexItem bg-blue">
<h5>This is flex box item</h5>
</div>
<div class="flexItem bg-green">
<h5>This is flex box item</h5>
</div>
</div>
<div class="buttons">
<button id="btn1">Apply flex-direction to column</button>
<button id="btn3">set all box equal size</button>
<div class="textInput">
<input type="number" id="numberofItems" placeholder="Enter the number of items you want in a row" min="1" max="6">
<button id="btn4">set items in a row</button>
</div>
</div>
<div class="preview">
<h2>Applied css</h2>
</div>

Display flex has no influence - ReactJS

I want to show items as flex but still it is showing like a column. What am I doing wrong here?
This is my component :
import React from "react";
import { Link } from "react-router-dom";
import { useSelector } from "react-redux";
import "./Listing.css";
const ProductComponent = () => {
const products = useSelector((state) => state.allProducts.products);
const renderList = products.map((product) => {
const { id, title, image, price, category } = product;
return (
<div className="container">
<div key={id} className="item-box" >
<Link to={`/product/${id}`}>
<div className="image-box">
<img src={image} alt={title} />
</div>
<div className="detail">
<div >{title}</div>
<div >$ {price}</div>
<div >{category}</div>
</div>
</Link>
</div>
</div>
);
});
return <>{renderList}</>;
};
export default ProductComponent;
This is the css file of this component:
.container{
width: 100%;
height: 90vh;
flex-wrap: wrap;
display: flex;
}
.item-box{
border: 2px solid #000;
display: flex;
height: auto;
width: 380px;
padding: 10px;
justify-content: center;
margin: 20px;
}
img{
height: auto;
width: 300px;
}
And finally this is my App.css:
* {
font-family: "Roboto", sans-serif;
padding: 0;
margin: 0;
box-sizing: border-box;
}
Thanks in advance.
I wanna show the items as flex (from left to right) but it is like a column though I defined "display:flex"
You are looping through the array and outputing multiple containers. Each container is display-flex but the problem is that they all have only one child. Move the map inside the container:
return (
<div className="container">
{ products.map((product) => {
const { id, title, image, price, category } = product;
return (
<div key={id} className="item-box" >
<Link to={`/product/${id}`}>
<div className="image-box">
<img src={image} alt={title} />
</div>
<div className="detail">
<div >{title}</div>
<div >$ {price}</div>
<div >{category}</div>
</div>
</Link>
</div>
)
})}
</div>
)
In the style of .container just add flex-direction:coloum
.container{
width: 100%;
height: 90vh;
display: flex;
flex-direction: column;
}
If you want the column in center, then you can append justify-content:center & align-items:center as well.

CSS Style not loading for the second container in NextJS

I have a two basic div containers and I am trying to apply some styles to it. I do import my CSS styles from a separate .module.css file and the first style gets picked up in the className property, when assigned. However, the same thing is not working for the second div. The css property for class 'sales' is not being picked up
dashboard.js
import HomeSalesmanStyles from '../../../styles/SalesmanHome.module.css';
const HomeSalesman = ({name}) => {
return(
<>
<div className={HomeSalesmanStyles.container}>
<h4>
Hello, {name} 👋
</h4>
</div>
<div className={HomeSalesmanStyles.sales}>
Hello
</div>
</>
)
};
export default HomeSalesman;
SalesmanHome.module.css
.container {
display: flex;
justify-content: center;
margin-top: 5%;
};
.sales {
display: flex;
justify-content: center;
width: 100px;
background-color: red;
}
Any ideas where the issue is?
----------- Edit ------------
The issue was wrong css module name import! After correcting to the right file, everything works.
This looks like a syntax error in the CSS: adding a semicolon after a rule is invalid.
.container {
display: flex;
justify-content: center;
margin-top: 5%;
} /* <- no semicolon */
.sales {
display: flex;
justify-content: center;
width: 100px;
background-color: red;
}
<div class="container">
<h4>
Hello, {name} 👋
</h4>
</div>
<div class="sales">
Hello
</div>

Why 'flex-direction:row' does not arrange all elements in a single row (+ a placement issue)?

Here is my html markup:
<div class="expander-container" data-css="expander-container">
<div class="top-comment-container" data-css="top-comment-container">
<a class="expand-anchor" data-css="expand-anchor" >
<div><span class="alternate-color icon-next arrow"
data-css="alternate-color icon-next _2Cx2VFM04V1vDEfkDEJ3Cw" ></span></div>
<div class="activity-item activity-container"
data-css="activity-item" >
<div class="activity-text" data-css="activity-text" ><span >Content</span></div>
<div class="activity-vote-count" data-css="activity-vote-count" ><span >0</span><span> vote</span></div>
<div class="activity-reply-count"
data-css="activity-reply-count" ><span>1</span><span> reply</span></div>
<time datetime="Wed May 25 2016 15:57:21">
<span >May 25, 2016, 3:57 PM</span></time></div>
</a>
</div>
</div>
Here is my css (in less)
.expander-container {
display: flex;
flex-direction: column;
}
.expand-anchor {
background: none;
border: none;
padding: 0;
cursor: pointer;
align-self: center;
&:hover {
text-decoration: none;
}
}
.icon-next:before {
content: ">";
}
.arrow:before {
display: inline-block;
transform: rotate(0deg);
transition: transform .25s ease-out;
.expand& {
transform: rotate(90deg);
}
}
.top-comment-container {
display: flex;
flex-direction: row;
align-items: flex-start;
border: 1px solid green;
flex-wrap: nowrap;
}
.reply-container {
display: flex;
}
// activity-item
.activity-item {
margin-left: 5px;
}
.reply-item {
margin-left: 10px;
border: 1px solid blue;
}
.activity-container {
display: flex;
}
.activity-text {
align-self: center;
flex-grow: 1;
flex: 5;
// flex-basis: 100;
}
.activity-vote-count {
align-self: center;
// width: 10%;
flex: 1;
}
.activity-reply-count {
align-self: flex-end;
// flex-basis: 1;
// width: 10%;
flex: 1;
}
.activity-container {
align-self: center;
}
What I want to achieve is to have all these elements aligned on a single axis.
e.g.
> Content 0 vote 1 reply May 25, 2016, 3:57 PM
However as you can see in my codepen coode (http://codepen.io/kongakong/pen/YWKvgG?editors=1100), the arrow somehow occupies one line by itself. The rest of content is squeezed to the next line.
I have tried a few thing e.g. add flex-basis, flex-wrap: nowrap etc but they do not have any effect.
A second question is how can I have finer control on the placement? I want the text 'Content' to occupy most of the space in a row. Information such as vote and time should be moved to the right hand side. I have applied the 'flex-grow:1' to the text but it does not grow and fill the space.
Flex row works by aligning its immediate children in a row. You have your elements nested too deeply. Everything you want on the same row needs to be siblings. You can see some work I've done with flex for reference http://codepen.io/steezeburger/pen/LNEaKv
<div class="flex-row">
<div class="wrapper">
<div class="flex-column skinny">
<span class="flex-vertical-center af af-icon" data-bind="css: action_color">
<i class="fa fa-check"></i>
</span>
</div>
<div class="flex-column">
<span class="af af-action">New Order</span>
<span class="af af-name">John Carmack</span>
</div>
</div>
<div class="flex-column">
<span class="af af-time-lapsed">13m ago</span>
<span class="af af-value">$65</span>
</div>
</div>
This is a bit more advanced as I have nested columns in my rows, but you can see above that .wrapper and the last .flex-column div will be on the same row. Check out the codepen for a clearer example.
try this code
<style>
.top-comment-container {
width: 40em;
}
.alternate-color {
display: inline-block;
}
.activity-item {
display: flex;
justify-content: space-between;
}
.abcd {
display: flex;
}
</style>
</head>
<body>
<div class="expander-container" data-css="expander-container">
<div class="top-comment-container" data-css="top-comment-container">
<a class="expand-anchor" data-css="expand-anchor">
<div><span class="alternate-color icon-next arrow" data-css="alternate-color icon-next _2Cx2VFM04V1vDEfkDEJ3Cw"></span></div>
<div class="activity-item activity-container" data-css="activity-item">
<div class="activity-text" data-css="activity-text"><span>Content</span></div>
<div class="abcd">
<div class="activity-vote-count" data-css="activity-vote-count"><span>0</span><span> vote</span></div>
<div class="activity-reply-count" data-css="activity-reply-count"><span>1</span><span> reply</span></div>
<time datetime="Wed May 25 2016 15:57:21">
<span>May 25, 2016, 3:57 PM</span>
</time>
</div>
</div>
</a>
</div>
</div>
</body>
apply margins as you like..

Resources