I'm trying to style a component properly. At the moment, the table works beautifully, but the style of it isn't ideal, and usually this would be easy to fix with tailwind but the components layout makes it very confusing to know exactly how to style it.
This is the example I am referencing,
https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/kitchen-sink
Now specifically what I want to change is the group functions. Currently the use emoji's to work, I really want to to be a proper button so users understand very clearly the functionality of the component, as below.
<table className="w-full text-md bg-white shadow-md rounded mb-4" {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th className={td_header} {...column.getHeaderProps()}>
<div>
{column.canGroupBy ? (
// If the column can be grouped, let's add a toggle
<span {...column.getGroupByToggleProps()}>
{column.isGrouped ? 'Click to Un-Group 🛑 Click to Sort!' : ' Click to Group 🔮 Click to Sort!'}
</span>
) : null}
<span {...column.getSortByToggleProps()}>
{column.render('Header')}
{/* Add a sort direction indicator */}
{column.isSorted
? column.isSortedDesc
? ' 🔽'
: ' 🔼'
: ''}
</span>
</div>
{/* Render the columns filter UI */}
<div>{column.canFilter ? column.render('Filter') : null}</div>
</th>
))}
Now ideally I want something like this for the group and filter toggle, taken from tailwind
https://tailwindcss.com/components/buttons
<div class="inline-flex">
<button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-l">
Group
</button>
<button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-r">
Filter
</button>
</div>
How does one go about styling this effectively, given the string it is using is not a component and does not have any styling that I can see involved?
Thanks in advance,
The string present in your question is not a component, but it easily could be. Those elements don't necessarily need to be strings; react-table is a headless library, so you're free to change the visuals the way you want. There are a variety of possible solutions here. One solution would be to replace the entire ternary by defining a custom functional component for that sort icon:
const sortIcon = (sorted, sortedDesc) => {
if (sortedDesc) {
return (<h1> this is arbitrary </h1>);
} else if (sorted) {
return (<h2> more arbitrary </h2>);
} else {
return null;
}
}
and then replacing the ternary:
<span {...column.getSortByToggleProps()}>
{column.render('Header')}
{/* Add a sort direction indicator */}
{sortIcon(column.isSorted, column.isSortedDesc)}
</span>
This is a bad way to do it, probably, and untested beside that, but the point is that the HTML/JSX stuff is arbitrary. Those emoji strings can be replaced with valid JSX in any form. You could do a similar thing with the column.isGrouped ternary, as well! It may be worth looking at some JSX tutorials if you're not already familiar, or re-familiarizing yourself with exactly what a column Object contains if you want to continue to add functionality.
(link caveat: each of the different useX hooks adds more stuff to the column/row/etc Objects, so I just linked the core useTable one)
Related
Such as the Title, I try to create a menu that I use v-for to get array items and keys. Then I need the keys to create the second layer menu.
const localSite = ref('us')
const products = ref({})
const softwares = ref({})
const menuShow = ref({})
const menuTxt = ref({
"us": {
"products": "Products",
"softwares": "Software"
}
})
<div id="menu-wrapper">
<div class="flex">
<div v-for="( item, dataKey ) in menuTxt[localSite]" class="menu-item">
<button class="text-white" :data-category="dataKey" #click="slideDown(dataKey)">
{{ item }}
<font-awesome-icon icon="angle-down" />
</button>
<div class="text-box menu-content">
<p v-for="itemA in dataKey">{{itemA}}</p>
</div>
</div>
</div>
</div>
I think the 'dataKey' is a variable which is the vue data Object.
But I can always get the wrong result.
What shoul I do ?
If I understand your problem correctly, you are trying to access the products and softwares properties by using the dataKey in the template. This is not possible the way you are doing it as it's referring to the key of menuTxt.
I made a StackBlitz to show a different kind of approach. Defining the child menu items along with it's parent in the same object. This also makes it more readable.
I am trying to learn Tailwind CSS and generally working better with CSS. In this case, I am trying to make my search icon appear inside of my search input field.
I found some tutorials online but they mostly use plain CSS.
Is there any simple way to achieve this using Tailwind?
import React from "react";
import { FaSearch } from "react-icons/fa";
const SearchBar = () => {
return (
<div>
<input className="bg-slate-50 hover:bg-red-200 rounded-3xl h-12 w-56" />
<FaSearch />
</div>
I also tried to wrap the input elment in a <div> and <form> tags, but none of those worked.
This should do it:
<div className='flex items-center'>
<input className='bg-slate-50 hover:bg-red-200 rounded-3xl h-12 w-56' />
<SearchIcon className='-ml-9' />
</div>
Docs:
align items | MDN
using negative margins | MDN
I'm new to Tailwind, and I'm not sure if there's a way to solve this edge case. Here is the scenario:
We have different variants listed on the product page(for example different color tags). When you hover we are showing a faded border around the tag, and when you select the variant, the tag becomes active, and its border should get darker.
The problem:
Even when the user clicks on the tag to make it active, the user still sees hover still rather than the 'active' style.
These are the classes I'm using for now
<Tag
clssName={`flex rounded border border-gray-200 bg-white hover:border-gray-400 ${active && 'border-gray-700'}`}
...prop
/>
Now the question is if there's a way to override the hover styles on when the item is active. One way could be to remove the hover class when the item is active, but I was wording if there is a Tailwind way to fix it.
You can add different styles for active and non-active variants.
<Tag
clssName={`flex rounded border bg-white ${active && 'border-gray-700 hover:border-black'}`} ${!active && "border-gray-200 hover:border-gray-400"}
...prop
/>
Well you can use focus utility for this.
Below is the example you can see where button has different behaviour on hover and focus.
<script src="https://cdn.tailwindcss.com"></script>
<div class="p-10">
<button class="p-4 bg-pink-100 hover:bg-pink-300 focus:bg-red-500 focus:border-2 focus:border-red-700">Click </button>
</div>
You can achieve this with a ternary operator on className. By default we have border-gray-200 hover:border-gray-400 when state changes, we replace border-gray-700 instead of border-gray-200 hover:border-gray-400.
const App = () => {
const [active, setActive] = React.useState(false);
return (
<button onClick = {() => setActive(!active)}
className={`flex p-3 rounded border bg-white ${active ? 'border-gray-700' : 'border-gray-200 hover:border-gray-400'}`
}>
{active ? 'Active' : 'Inactive'}
</button>
);
};
const rootElement = document.getElementById('root');
ReactDOM.createRoot(rootElement).render( < App / > );
<script src="https://cdn.tailwindcss.com"></script>
<script crossorigin src="https://unpkg.com/react#18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div id="root" class="p-10"></div>
I'm trying to animate the list of cards when it gets re-rendered with a different values (i.e , Popular movies to Searched movies)
I followed the documentation of framer-motion and gave the parent div and the child div the Layout property yet nothing seems to change or happen.
If there's a different way of animating this I would love to hear
I've added the code here below :
the parent div :
<motion.div Layout className='movie-container'>
{movie.map((moviee) => (
<MoviePreview
moviee={moviee}
setFavorites={setFavorites}
favorites={favorites}
setTrailer={setTrailer}
setTrailerWindow={setTrailerWindow}
/>
))}
</motion.div>
the child div :
<motion.div Layout className='movie-card-container'>
<article className='movie-card'>
<h3>{moviee.title} </h3>
<div className='trailer-favorite'>
<button onClick={(e) => onHandleTrailer(moviee.id)} className='trailer-btn'>
Watch Trailer
</button>
<button onClick={() => addFavorite(moviee)} className='heart'>
💗
</button>
</div>
<img src={`https://image.tmdb.org/t/p/w500/${moviee.poster_path}`}></img>
<div className='movie-overview'>
<p>{!moviee.overview ? 'No description available.' : moviee.overview}</p>
</div>
</article>
</motion.div>
Thanks for any kind of help!
I have a list of items (dynamically created buttons) coming from a reactjs map function. I want them listed horizontally and also allow wrapping remaining items to the next line if needed. Can some one please help with this. Given below is my code snippet.
return( <div>
{ relevantMessages.map(function(thisQuestion){
return
<p key={thisQuestion.id}>
<button key={thisQuestion.id} onClick={() => this.sendThisMessage(thisQuestion.question)}>
{thisQuestion.title}
</button>
</p>
}, this)
}
</div>)
You can use css to align horizontally.
For example:
return( <div>
{ relevantMessages.map(function(thisQuestion){
return
<p key={thisQuestion.id} style="display:inline-block;">
<button key={thisQuestion.id} onClick={() => this.sendThisMessage(thisQuestion.question)}>
{thisQuestion.title}
</button>
</p>
}, this)
}
</div>)
Using span tag instead of p tag in the above code snippet solved my issue.
This isn't really an issue with React, but more so with CSS.
What you are probably looking for is something such as flex-box. Check out css-tricks for a good tutorial on how to use it.
Or try flexbox-froggy for a gamified of learning it :)