I have a total of 10 items and I am mapping through them to render each one. I want least opacity for last element and highest for first element. I am aware of :first and :last in tailwind-css, but I was wondering if there is way so that I can target lets say my 8th or 9th in tailwind-css
here is my return statement from a component:
{[0,1,2,3,4,5,6,7,8,9].map((item) => (
<section
key={item}
className='last:opacity-20 flex justify-between items-center text-slate-600 bg-white shadow-sm p-5 rounded-xl my-4 cursor-pointer dark:bg-black dark:text-slate-400'
>
<div className='flex gap-3 items-center'>
<div className='rounded-full w-8 h-8 bg-slate-200'></div>
<p className='w-44 h-4 bg-slate-100'></p>
</div>
<p className='w-16 h-4 bg-slate-100'></p>
</section>
))}
I want to decrease opacity going downwards i.e, from first item to last item.
Targeting nth-child can be easy using Tailwind v3.2 matchVariant
// tailwind.config.js
let plugin = require("tailwindcss/plugin");
module.exports = {
plugins: [
plugin(function ({ matchVariant, theme }) {
matchVariant(
'nth',
(value) => {
return `&:nth-child(${value})`;
},
{
values: {
DEFAULT: 'n', // Default value for `nth:`
'2n': '2n', // `nth-2n:utility` will generate `:nth-child(2n)` CSS selector
'3n': '3n',
'4n': '4n',
'5n': '5n',
//... so on if you need
},
}
);
}),
],
}
Usage - every 2n element will be red, 1st, 6th, 11th, 5n+1 - green, every fifth - blue (it will overlap but it is just an example how to use it from config or arbitrary variants)
<ul class="">
<li class="nth-2n:bg-red-400 nth-5n:bg-blue-500 nth-[5n+1]:bg-green-500 p-2">1</li>
<li class="nth-2n:bg-red-400 nth-5n:bg-blue-500 nth-[5n+1]:bg-green-500 p-2">2</li>
<li class="nth-2n:bg-red-400 nth-5n:bg-blue-500 nth-[5n+1]:bg-green-500 p-2">3</li>
<li class="nth-2n:bg-red-400 nth-5n:bg-blue-500 nth-[5n+1]:bg-green-500 p-2">4</li>
<li class="nth-2n:bg-red-400 nth-5n:bg-blue-500 nth-[5n+1]:bg-green-500 p-2">5</li>
<li class="nth-2n:bg-red-400 nth-5n:bg-blue-500 nth-[5n+1]:bg-green-500 p-2">6</li>
</ul>
DEMO
For versions bellow 3.2 you'll need to add variant addVariant for every nth-child selector
This following solution may not use nth-child but does give the needed result: list items will have reduced opacity one by another.
{[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((item) => {
// Generate class name
// Need to config Tailwind as shown later for this to work
const opacity = `opacity-${(10 - item) * 10}`;
// Changed to bg-black here so result is more visible
return (
<section
key={item}
className={`${opacity} flex justify-between items-center text-slate-600 bg-black shadow-sm p-5 rounded-xl my-4 cursor-pointer dark:bg-black dark:text-slate-400`}
>
<div className="flex gap-3 items-center">
<div className="rounded-full w-8 h-8 bg-slate-200"></div>
<p className="w-44 h-4 bg-slate-100"></p>
</div>
<p className="w-16 h-4 bg-slate-100"></p>
</section>
);
})}
But before this can be rendered, in order for Tailwind to generate the class names needed, the following config need to be added to tailwind.config.cjs:
const opacitySafeList = [];
for (i = 1; i < 11; i++) {
opacitySafeList.push(`opacity-${i * 10}`);
}
module.exports = {
content: ["...content of the project"],
// Tell Tailwind to generate these class names which does not exist in content files
safelist: opacitySafeList,
theme: {
extend: {},
},
plugins: [],
};
This feature (safe list) is considered last resort by Tailwind, but this question seem to be a good use case for it.
Related
I made a custom switch in tailwind problem is that when it witch transiton doesnt work I think its becouse of this line
${isSwitched ? ' right-1 ' : 'left-1'}
import type { StateUpdater } from "preact/hooks"
type SwitchButtonProps = {
textLeft: String,
textRight: String,
isSwitched: boolean,
setIsSwitched: StateUpdater<boolean>
}
export const SwitchButton = ({ textLeft, textRight, isSwitched, setIsSwitched }: SwitchButtonProps) => {
return (
<div class="mx-8 shadow rounded border h-10 mt-4 flex p-1 relative items-center bg-gray-200">
<div class="w-full flex justify-center"
onClick={() => setIsSwitched(false)}
>
<button>{textLeft}</button>
</div>
<div class="w-full flex justify-center"
onClick={() => setIsSwitched(true)}>
<button>{textRight}</button>
</div>
<span
class={` bg-white shadow text-gray-800 flex items-center justify-center w-1/2 rounded h-8 transition-all top-[4px] absolute
${isSwitched ? ' right-1 ' : 'left-1'}
`}>
{isSwitched ? textRight : textLeft}
</span>
</div>
)
}
Cannot figure out how to get popover to close when next Link is clicked inside. Used popover from tailwindui and added next Link, tried the headlessUI closing popover using as={Link}, no luck.
<div className='max-w-7xl mx-auto grid gap-y-6 px-4 py-6 sm:grid-cols-2 sm:gap-8 sm:px-6 sm:py-8 lg:grid-cols-4 lg:px-8 lg:py-12 xl:py-16'>
{about.map((item) => (
<Popover.Button key={item.name}>
<Link href={item.href}>
<a
href={item.href}
className='-m-3 p-3 flex flex-col justify-between rounded-lg hover:bg-gray-50'>
<div className='flex md:h-full lg:flex-col'>
<div className='flex-shrink-0'>
<span className='inline-flex items-center justify-center h-10 w-10 rounded-md bg-cyan-500 text-white sm:h-12 sm:w-12'>
<item.icon
className='h-6 w-6'
aria-hidden='true'
/>
</span>
</div>
<div className='ml-4 md:flex-1 md:flex md:flex-col md:justify-between lg:ml-0 lg:mt-4'>
<div>
<p className='text-base font-medium text-gray-900'>
{item.name}
</p>
<p className='mt-1 text-sm text-gray-500'>
{item.description}
</p>
</div>
<p className='mt-2 text-sm font-medium text-cyan-600 lg:mt-4'>
Learn more
<span aria-hidden='true'>
→
</span>
</p>
</div>
</div>
</a>
</Link>
</Popover.Button>```
Help please, what am i missing?
I just ran into this exact issue.
I got it working by doing two things referenced separately in the Headless UI docs. This involved creating a custom wrapper component for Next's Link and exposing the close() render prop on the Popover Panel.
A minimal example using the solution is listed first followed by an explanation with references to the docs.
Solution/Example
import { forwardRef } from 'react'
import Link from 'next/link'
import { Popover } from '#headlessui/react'
const MyLink = forwardRef((props, ref) => {
let { href, children, ...rest } = props
return (
<Link href={href}>
<a ref={ref} {...rest}>
{children}
</a>
</Link>
)
})
function Example() {
return (
<Popover>
{({ open }) => (
<>
<Popover.Button>Open Popover</Popover.Button>
<Popover.Panel>
{({ close }) => (
<MyLink href='/profile' onClick={() => close()}>
Profile
</MyLink>
)}
</Popover.Panel>
</>
)}
</Popover>
)
}
Explanation
Step 1
Expose the close() render prop inside your Popover Panel, per the alternative solution suggested in the docs.
<Popover.Panel>
{({ close }) => (
We will call this in our link to manually close the popup when the link is clicked.
Step 2
Create your own custom MyLink component (or whatever name you want) that wraps Link and forwards props to the child a element. As explained in the Headless UI docs, Next's Link component doesn't forward unknown props by default and Headless needs to do this in order to work by adding the necessary event listeners.
const MyLink = forwardRef((props, ref) => {
let { href, children, ...rest } = props
return (
<Link href={href}>
<a ref={ref} {...rest}>
{children}
</a>
</Link>
)
})
It's my first time asking question on stack overflow and from what I'm feeling I'm missing something very small or don't understand the logic correctly. I show images by {#each} block and slice by adding and subtracting from variables: selected, prevSelected. From what I understood in svelte tutorial on transitions it should work (https://svelte.dev/tutorial/local-transitions), for some reason images just show up in a blink without transitions. I tried remaking the logic in the function, timeouts and restarting and none seemed working.
Please explain to me what I'am missing.
Sorry for little knowledge, picked up svelte as my first frontend framework to learn yesterday.
I'm using the latest sveltekit version.
Edit: I'm also using latest tailwind css.
<script>
import { slide,fade } from 'svelte/transition';
let images = [
{
Index: 0,
src: 'src/images/img2.jpeg',
alt: 'znaki ewakuacyjne',
class: 'show'
},
{
Index: 1,
src: 'src/images/img3.jpeg',
alt: 'buty',
class: ''
},
{
Index: 2,
src: 'src/images/img4.jpeg',
alt: 'znaki informacyjne',
class: ''
}
];
let selected = 1;
let prevSelected = 0;
let shown=true;
function handleClick() {
if (selected == 3) {
return;
}
prevSelected = selected;
selected += 1;
}
function handleBack() {
if (selected == 1) {
return;
}
prevSelected -= 1;
selected -= 1;
}
</script>
<h3 class="text-center font-semibold text-xl m-3">Galeria</h3>
<div class="image-gallery flex flex-col justify-center items-center">
{#if shown}
{#each images.slice(prevSelected, selected) as img}
<img
transition:fade
src={img.src}
alt={img.alt}
class="h-80 w-50 rounded-lg"
/>
{/each}
{/if}
<div class="flex flex-row gap-12">
<button
on:click={handleBack}
type="button"
class="text-white bg-red-700 hover:bg-red-800 focus:outline-none focus:ring-4 focus:ring-red-300 font-medium rounded-full text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900 m-3"
>⬅️</button
>
<button
on:click={handleClick}
type="button"
class="text-white bg-blue-700 hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 font-medium rounded-full text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 m-3"
>➡️</button
>
</div>
</div>
<style lang="scss">
</style>
You need to key the {#each} (see docs), e.g.
{#each images.slice(prevSelected, selected) as img (img)}
Otherwise the same component is reused and only its properties get changed.
Note that you may have to adjust the layout to make both images take the same place, otherwise the image that fades out will push away the one that fades in.
By the way, if you only ever show one image, you do not need an each at all, only {#key} and the index.
{#key selected}
<img
transition:fade
src={images[selected - 1].src}
alt={images[selected - 1].alt}
class="h-80 w-50 rounded-lg"
/>
{/key}
Could be simplified even further via a reactive statement that always resolves to images[selected - 1]. prevSelected is redundant and I would change the logic of selected to be 0-based instead of 1-based.
Hello so I have been working on this for hours and tried brute forcing it, with as many different solutions I could think of, but I don't seem to be getting it to work.
Goal: make the cards take up more width, when the screen is bigger
This is my root component:
function App() {
const event = new Date(Date.UTC(2000, 11, 20, 3, 0, 0));
return (
<div className="bg-gray-200 p-8 min-h-screen flex items-center justify-center antialiased text-gray-900 flex-col">
<Expenses date={event}></Expenses>
<Expenses date={event}></Expenses>
<Expenses date={event}></Expenses>
</div>
);
}
export default App;
This is the Expenses Component
export default function Expenses(props) {
return (
<div className="">
<ExpenseItem time={props.date}></ExpenseItem>
</div>
);
}
This is the Expense Item Component
export default function ExpenseItem(props) {
return (
<div className="bg-white rounded-lg overflow-hidden border flex h-auto mt-4 shadow">
<CalendarItem date={props.time}></CalendarItem>
<div className="p-4">
<h4 className="font-semibold text-lg">All my money for software engineering</h4>
<div>10000€</div>
<div className="mt-4 inline-block bg-indigo-300 text-white px-4 py-1 rounded-lg shadow-lg uppercase tracking-wide font-semibold text-sm ">
Delete
</div>
</div>
</div>
);
}
I am grateful for every input! Thank you!
Add "width: 100%" to the card and its parent component. When Browser resize(expand or shrink), they will resize too. You can handle the detail of their size by giving some width to the parent and the parent's width will be limit width of the card component.
I am trying to make tooltips for icons in my header, and right now I have made a component to make the icon and tooltip into one div, with tailwind styles in that
JSX Component:
const HeaderIcon = ({ icon, redirect = window.location.pathname.replace('/', ""), text = ""}:IconProps) => (
<div className="group relative flex items-center justify-center h-12 w-12 mt-2 mb-2 mx-5 cursor-pointer">
<button onClick={() => goto(redirect)} className="items-center inline-flex">{icon}</button>
<span className="group-hover:visible absolute rounded-md shadow-md text-white bg-gray-900 text-xs font-bold transition-all duration-100 p-2 text-center min-w-max invisible">
{text}
</span>
</div>
)
Here goto is a redirect function, icon is a JSX element from react-feather (icon library), redirect is a string telling the button where to redirect to, and text is the tooltip text. What tailwind classes should I use to position the tooltips under the icons, centered.
If there is any other things you may want then just ask and I will edit the code in.
you need to create a new variant group-hover for the plugin visibility in the Tailwind configuration:
// tailwind.config.js
module.exports = {
// ...
variants: {
extend: {
visibility: ['group-hover'],
}
},
}