I am a newbie for tailwindcss.Today I found the width transition not working in tailwindcss when I want to toggle this
to
In the process I want to the width change is smooth.
This is my approach:
const navigationRef = useRef<HTMLDivElement>(null);
const toggle = () => {
navigationRef.current?.classList.toggle('w-[300px]');
}
<div ref={navigationRef} className='relative w-[80px] h-[420px] bg-white rounded-[10px] overflow-hidden shadow-sidebar transition duration-500'>
...
</div>
...
<div
onClick={toggle}
className='toggle absolute topCenterY right-[-20px] w-[40px] h-[40px] bg-[#f5f5f5] cursor-pointer border-[5px] border-[#6843d1] rounded-full' >
</div>
Notice that I want to toggle w-[80px] to w-[300px].
I also attempt to use scale:
const toggle = () => {
navigationRef.current?.classList.toggle('transform');
}
<div ref={navigationRef} className='... scale-x-[3.75] duration-500'>
</div>
...
Then, I failed.
So, is there a solution for this?
Related
JS 13 and inside my ReadMoreButton client component i push my article data using useRouter hook of NEXT.
Not i can not use useRouter hook inside NEXT.JS server component so here i fetch searchParams and fetch that data.
here problem is before rendering i am checking if searchParams are defined or not not if i check in development everything work fine it render data but in production mode it show page not found error even if data is correctly send.
when i run next build it give me following output Output
and i am running side in production mode using next start and it show page not found when i do /article?serchParamsData.
You can check my whole code here : https://github.com/ssiwach8888/Next.JS-News-App
i also deploy production build on Vercel but it also show same error.
I am using NEXT.JS 13 with typescript
# ReadMoreButton.tsx "First Control goes here."
"use client";
type Props = {
article: NewsData;
};
import { useRouter } from "next/navigation";
//For navigate to SSC
const ReadMoreButton = ({ article }: Props) => {
const router = useRouter();
const handleClick = () => {
const queryString = Object.entries(article)
.map(([key, value]) => `${key}=${value}`)
.join("&");
const url = `/article?${queryString}`;
router.push(url);
};
return (
<button
className="bg-orange-400 h-10 rounded-b-lg dark:text-gray-900 hover:bg-orange-500"
onClick={handleClick}
>
Read More
</button>
);
};
export default ReadMoreButton;
# Article.tsx "Then we navigate to this page."
type Props = {
searchParams?: NewsData;
};
import { notFound } from "next/navigation";
import LiveTimestamp from "../Components/LiveTimestamp";
import Link from "next/link";
const ArticlePage = ({ searchParams }: Props) => {
if (
(searchParams && Object.entries(searchParams).length === 0) ||
!searchParams
) {
return notFound();
}
const article: NewsData = searchParams;
return (
<article className="mt-6">
<section className="flex flex-col lg:flex-row pb-24 px-0 lg:px-10">
<img
src={article.image === "null" ? "/no-image.jpeg" : article.image}
alt={article.title}
className="h-50 max-w-md mx-auto md:max-w-lg lg:max-w-xl object-contain rounded-lg shadow-md"
/>
<div className="px-8">
<Link legacyBehavior href={article.url || ""}>
<a target="_blank">
<h1 className="headerTitle hover:underline cursor-pointer px-0 pb-2">
{article.title}
</h1>
</a>
</Link>
<div className="flex divide-x-2 space-x-4">
<h2 className="font-bold">
By: {article.author !== "null" ? article.author : "Unknown"}
</h2>
<h2 className="font-bold pl-4">Source: {article.source}</h2>
<p className="pl-4">
<LiveTimestamp
time={
article.published_at === "null" ? "" : article.published_at
}
/>
</p>
</div>
<p className="pt-4 text-lg">{article.description}</p>
</div>
</section>
</article>
);
};
export default ArticlePage;
You just need to put the article page in [bracket] to make it dynamic so next js can fetch all pages otherwise it would display blank----
change article folder to [article]
more reference https://nextjs.org/docs/routing/dynamic-routes
I am using a date picker somewhat similar to this example
File: datepicker.vue
<template>
<v-menu
v-model="dateMenu"
:close-on-content-click="false"
:nudge-right="40"
:return-value.sync="dateValue"
transition="scale-transition"
offset-y
>
<template v-slot:activator="{ on }">
<v-text-field
:label="dateLabel"
prepend-icon="fa-calendar"
readonly
v-model="dateValue"
v-on="on"
clearable
></v-text-field>
</template>
<v-date-picker
locale="en-in"
v-model="dateValue"
no-title
#input="dateMenu = false"
>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
#click="dateMenu = false"
>Cancel</v-btn>
<v-btn
text
color="primary"
#click="$refs.dialog.save(dateValue)"
>OK</v-btn>
</v-date-picker>
</v-menu>
</template>
<script>
export default {
props: ['dateLabel','dateModel'],
data() {
return {
dateMenu: false,
dateValue: this.dateModel,
};
},
watch: {
dateValue(){
$nuxt.$emit('update',this.dateValue);
}
},
};
</script>
File: projects-subform.vue
...
<DatePicker
dateLabel="Project Start Date"
:dateModel="project.start_date"
#update="(v) => (project.start_date = v)"/>
...
(I exported DatePicker as a component from the projects form. )
When I select the date from picker UI, the display text on the v-text-field does not reflect the selected date. Also, the model project.start_date does not seem to update after I select the date from my datepicker. It becomes very tricky to debug when event errors like this don't show up on the dev tools console.
First of all, it is not recommended to change the model passed in as a prop directly. We don't want any unwanted breaks in the parent component. Rely on events. Somehow even this style of passing also didn't work quite well for me.
I did some workaround like this. (I know it is a very dirty way). But for some reason $emit with input/update/change just fails to be detected in the parent component. I am very sure there's a better way of doing this. But for now, moving on with life. :-(
File: datepicker.vue
<template>
...
<v-date-picker
locale="en-in"
v-model="dateValue"
no-title
#input="dateMenu = false;"
#change="saveDate" //change here
>
</v-date-picker>
...
</template>
<script>
...
methods(){
saveDate(val){
this.dateValue = val;
//changed here...emitting a custom event.
$nuxt.$emit("datePicked",{
project_number:this.project_number,
selectedDate: selDateVal
});
this.$refs.dateMenu.save(selDateVal);
}
...
</script>
File: project-subform.vue
...
<script>
...
created:{
this.$nuxt.$on('datePicked',this.updateDate);
}
...
methods:{
updateDate(v){
//do my stuff
this.projects[v.project_number].startDate = v.selectedDate
}
}
</script>
Hi so I have these radio buttons where I want to save their data as json in my Postgres db . It is not being sent I get a message.success back that says I did but when i check my db nothing happens.
I don't exactly know where I am wrong so if u can help please do share.
PS: Im using Ant Design vue that's where the a- come from .
I do click on a button and it opens a modal where I have the radio buttons :
<template #modalite="{ record }">
<span>
<a-button
#click="showModalite(record)"
class="btn btn-sm btn-light mr-2"
>
<i class="fe fe-edit mr-2" />
Modalité
</a-button>
</span>
</template>
and here is my buttons code :
<a-modal
v-model:visible="visible"
:width="500"
#ok="ChangeModalite(modelInfo)"
>
<div class="row">
<a-radio-group name="radioGroup" v-model:value="traitement">
<div class="col-md-6">Négociation directe</div>
<div class="col-md-3">
<a-radio value="Négociation directe" v-model:checked="modalite.negociation" />
</div>
<div class="col-md-6">Appel à concurrence</div>
<div class="col-md-3">
<a-radio value="Appel à concurrence" v-model:checked="modalite.concurrence"/>
</div>
</a-radio-group>
</div>
</a-modal>
The script :
setup() {
const visible = ref(false)
const traitement = ref('Négociation directe');
const modalite = ref({
negociation:false,
concurrence:false,
})
const showModalite = (record) => {
modelInfo.value = record
modalite.value = { ...modalite.value, ...record.modalite }
visible.value = true
}
const ChangeModalite = (record) => {
console.log(record.id+": "+traitement.value)
axios.patch('/prop/' + record.id,{
modalite:modalite.value,
})
.then(()=>{
record.modalite=modalite.value
Object.assign(
dataSource.value.filter((item) => record.id === item.id),
record,
)
message.success(`successfully updated !!`)
visible.value = false
})
.catch((e)=>{
message.warning("smthg wrong ")
})
}
return {
dataSource,
modelInfo,
showModalite,
ChangeModalite,
modalite,
traitement,
}
},
}
So what happens now is i get the 'succefully updated ' msg without being really updated.where did i miss something?
I changed the type from json to string in my db everything works fine when I changed this line :axios.patch('/prop/' + record.id,{ modalite:modalite.value, }) to this axios.patch('/prop/' + record.id,{ modalite:traitement.value, })
so yeah data gets updated, still don't know why with the json type it's not working but at least i found a way if u have an explanation or suggestion it will be appriciated .
Problem : Getting double Scrollbars - Removing Paper Scrollbar makes the autocomplete content not scrollable hence showing ONLY the contents in the visible height of the dropdown.
If I hide the other scroll then the Infinite Scroll API does not get invoked. How can I get it working :
Description -
I am trying to create a Infinite Scroll with Material UI Autocomplete for which I am using react-infinite-scroll-component attached link for reference
The way I implemented is :
As we need to attach the Infinite Scroll to the Popper that renders the list items; hence I have written my custom PAPER Component (as per documentation it is responsible for rendering items in the dropdown )
PaperComponent={myCustomComponent}
My InfiniteScrollAutoComplete definition is attached below :
<Autocomplete
options={list.data && list.data !== null ? list.data : []}
getOptionLabel={(option) => option.name}
PaperComponent={(param) => (
<InfiniteScroll
height={200}
dataLength={list.total}
next={this.handleFetchNext.bind(this)}
hasMore={list.data.length < list.total ? true : false}
loader={
<p style={{ textAlign: "center", backgroundColor: "#f9dc01" }}>
<b>Loading...</b>
</p>
}
endMessage={
<p style={{ textAlign: "center", backgroundColor: "#f9dc01" }}>
<b>Yay! You have seen it all</b>
</p>
}
>
<Paper {...param} />
</InfiniteScroll>
)}
renderInput={(params) => (
<TextField {...params} label="" variant="outlined" />
)}
/>
const observer = useRef();
const lastOptionElementRef = useCallback((node) => {
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver(async (entries) => {
if (entries[0].isIntersecting && props.hasMore) {
setPageNumber((pageNumber) => pageNumber + 1);
}
});
if (node) observer.current.observe(node);
}, [props.loader]);
you can add this lastOptionElementRef to the last element of the options using the render option prop. This will trigger an function whenever the last option is visible in the viewport. Also, it avoids the scrolling issue
I'm trying to test an Info HOC on my react app :
const InfoHOC = (HocComponent) => ({ message }) => (
<>
<Tooltip title={message}>
<InfoIcon />
</Tooltip>
{HocComponent}
</>
);
export default InfoHOC;
I've simplified it. But as it's using material ui Tooltip component, I can't test if message is displayed on mouseover...
it('should display info message on <div /> mouseover', () => {
const Component = InfoHoc(<div>jest div</div>)({ message: 'jest infoHoc message' });
const { getByTitle, getByDisplayValue } = render(Component);
const icon = getByTitle('jest infoHoc message');
act(() => {
fireEvent(
icon,
new MouseEvent('mouseover', {
bubbles: true,
}),
);
});
expect(getByDisplayValue('jest infoHoc message')).toBeInTheDocument();
});
My last line is wrong... I think it's because mui tooltip display the message in a div at the end of the body, so not really in my rtl tree... BUT the first element of this tree is body !
I know that I should not test mui component, but here is not the purpose, I just want to be sure that InfoHoc has the right comportment, using mui tooltip or something else.
Here is the RTL tree after mouseover action :
<body>
<div>
<div
class="infoHoc"
>
<div>
jest div
</div>
<svg
aria-hidden="true"
class="MuiSvgIcon-root icon--right"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"
/>
</svg>
</div>
</div>
</body>
The event is good because icon has a title attr with message as value till mouseover is fired. As title attr is not here on my tree, I assume my event is well executed ;p
I am wrong testing that ? If not do you have an idea to solve my problem ?
Thank you all !
I think this is the cleanest way.
it('Renders tooltip when hovering over button', async () => {
render(<Search />);
const button = await screen.findByRole('button');
await userEvent.hover(button);
const tip = await screen.findByRole('tooltip');
expect(tip).toBeInTheDocument();
});
In case this can still help you, you need to findBy instead of getBy as the Tooltip is showing the tooltip after a delay
it('should display info message on <div /> mouseover', async () => {
const Component = InfoHoc(<div>jest div</div>)({ message: 'jest infoHoc message' });
const { getByTitle, findByDisplayValue } = render(Component);
const icon = getByTitle('jest infoHoc message');
act(() => {
fireEvent(
icon,
new MouseEvent('mouseover', {
bubbles: true,
}),
);
});
// Wait for the tooltip to show up
const tooltipText = await findByDisplayValue('jest infoHoc message')
expect(tooltipText).toBeInTheDocument();
});
Side note 1: I am not sure if you really need the act around fireEvent. testing-library should do it for you.
Side note 2: you can use user-event which has a cleaner syntax (and a .hover function)