How to use styled-system responsive props - reactjs

Can I use the styled-system to achieve something like this?
<MyComponent
backgroundImage={{
default: "https://placekitten.com/380/80",
sm: "https://placekitten.com/340/80"
}}
/>
or this (because I know it can be done this way too with other "style props" such as width, but I prefer to use an object with keys):
<MyComponent
backgroundImage={[
"https://placekitten.com/300/80",
"https://placekitten.com/500/80"
]}
/>
I think the code examples above are self-descriptive and they follow the library's pattern but just to be clear, I'm mapping the values (image sources) to the breakpoints (default and next one up).
For example, this works out of the box:
<Box
width={[
default: 1,
sm: 1/3,
]}
/>
The output is something like this:
.QWojd {
width: 100%;
}
#media screen and (min-width: 24em) {
.QWojd {
width: 33.33333333333333%;
}
}
I've been looking into the source code and this part here makes me think it should work with backgroundImage too:
Sadly, it doesn't work, and the result is a stringified object (or concatenated array values) in the CSS output.
I can't think of how the variant function would be useful here as people have suggested. I've tried to use the system function but I just can't understand the documentation. The ResponsiveValue type gives me a hint but I feel like crawling in the dark when I try to understand the internals.
Ultimately, I'd like to use the "breakpoints object" (or array) with whatever custom prop I feel like, like this:
<Box
myProp={[
default: 'foo',
sm: 'bar',
]}
/>
Note: I've learned (from experience) that you can just use the "breakpoints array" version (without setting breakpoints in a theme and passing it to a provider) and that will map the value to the first 2 default breakpoints (not sure where they come from) but if you want to use an object with keys you need to use a ThemeProvider with a theme object with your own breakpoints.
Note 2: I can understand the styled-system documentation up to this point: https://styled-system.com/custom-props. When I arrive here I feel like this is what I'm looking for but I can't understand the example, the explanation confuses me even more and I can't find any examples on the web.
Note 3: Spectrum Chat has a styled-system channel and the library author is in there but sadly I haven't been able to send any messages there (constant network error)
Examples

Ok, so according to the docs (https://styled-system.com/custom-props/), in order to create a custom prop (or in this case, replace the existing one) you should use the system utility. Since I'm not a user of this library (styled-system), I'm not 100% sure that this is correct approach, but I tested on top of your example code and it seems to work as you wanted.
The component declaration (it also works with objects like you wanted) with an array:
<ResponsiveImageBox
color="white"
backgroundImage={[
"https://placekitten.com/300/80",
"https://placekitten.com/500/80"
]}
>
Box 8
</ResponsiveImageBox>
with objects:
<ResponsiveImageBox
color="white"
backgroundImage={{
default: "https://placekitten.com/300/80",
sm: "https://placekitten.com/500/80"
}}
>
Box 8
</ResponsiveImageBox>
And this is the component code:
export const ResponsiveImageBox = styled(Box)(
({ myCustomProp }) => {
return css`
${system({
backgroundImage: {
property: "backgroundImage",
transform: value => `url(${value})`
}
})}
`
});
As you can see on examples 4, 5 and 8 (https://stackblitz.com/edit/styled-system-mccqje?file=Examples.tsx), I also did it for the border-radius attribute with a simple prop renaming and just specifying what css attribute I wanted to change (property), so no need to add transform as the value will remain the same.
export const ExtendedBox2 = styled(Box)<ExtendedBoxProps>`
background-position: center;
${system({
myCustomProp: {
property: "border-radius"
}
})}
`;
Have a look and see if this is what you were looking for! :)

I know you already marked it as solved, and Eduardo's approach definitely works. However another way you can do it "out of the box" is to use aliases so that you can use objects instead of arrays (source: https://styled-system.com/responsive-styles/):
// theme.js
const breakpoints = ['40em', '52em', '64em', '80em']
// aliases
breakpoints.sm = breakpoints[0]
breakpoints.md = breakpoints[1]
breakpoints.lg = breakpoints[2]
breakpoints.xl = breakpoints[3]
export default {
breakpoints,
}
// ResponsiveImageBox.js
<ResponsiveImageBox
color="white"
backgroundImage={{
md: "https://placekitten.com/300/80",
sm: "https://placekitten.com/500/80"
}}
>
Box 8
</ResponsiveImageBox>

Related

How to get className to work with dynamic input from map()

Trying to render some buttons dynamically, cant get the styling to work.
I have my btnList -
const btnList= [
"FirsBtn",
"SecondBtn",
"ThirdBtn",
"ForthBtn",
"FifthBtn",
"SixthBtn",
];
I have my map function -
const RenderBtns = (btnList) => {
return btnList.map((btn) => {
return (
<button className={`classes.${btn}`} name={btn} onClick={onClickHandler}>{btn}</button>
);
});
};
And, I have my btn.module.css, with
.FirstBtn {background-color: #662626;}
.SecondBtn {background-color: #b0bf76;}
.ThirdBtn {background-color: #6b8327;}
.ForthBtn {background-color: #6a5938;}
.FifthBtn {background-color: #b0bf76;}
.SixthBtn {background-color: #1fa593;}
The styling, doesn't work.
This - className={classes.FirstBtn} works.
This - className={`${classes.SecondBtn}`} works.
This - className={`${classes}.${btn}`} Doesn't.
The buttons themselves, the clicks, everything else - works.
I went through all of the combinations, and I can't seem to get it to work.
Even though I get the main idea behind literal, and object,
at this point I'm just beat-up.
I want to get the className to accept the dynamic "btn"
any way to make it happen?
Help, Please, and thank you.
Almost gave up on google, and than I stumbled upon this
Answer
It was actually the second one that worked for me,
but n one the less - it worked.
className={classes[`${item}Btn`]}

What is BackendFactory in context of react dnd?

I am trying to implement the react-chessboard component. I want a page that contains an empty chessboard and the pieces are kept outside for the user to drag and drop them into the board. By default the board is set to the starting position.
In the react-chessboard documentation, I came across a prop called 'customDndBackend' which takes a value of type BackendFactory. I could not find it anywhere so I asked it here. Any help would be appreciated.
react-chessboard-npm page
<Chessboard
className={classes.board}
boardWidth={
window.screen.width < 600 ? 0.9 * window.screen.width : 560
}
arePiecesDraggable={true}
// position={'start'}
animationDuration={200}
customBoardStyle={{
borderRadius: '4px',
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.5)',
}}
customDarkSquareStyle={{ backgroundColor: '#A1B57D' }}
customLightSquareStyle={{ backgroundColor: '#F7F7EE' }}
customPieces={customPieces()}
ref={chessboardRef}
/>
I'm actually the author of this package so maybe I can help.
The package utilises react-dnd to handle dragging and dropping. This comes with different "Backends" for handling dragging and dropping on Mobile devices or Browsers.
react-chessboard has its own logic to try to load the correct backend for you automatically. But in case you want to override it with your own, or set a specific one, you can use the prop to pass it in yourself. That's all there is to it really, here's some code used in the package for more reference.
const backend = customDndBackend || (isMobile ? TouchBackend : HTML5Backend);

How do I display the value of a theme object on the front end (e.g. #141414) vs the token name (e.g. bgPrimary)?

I've styled my website using a theme.js file utilizing emotion and styled-system and want to show the value (e.g #141414) on the front end vs the token name (e.g bgPrimary).
Obviously when I use the token in practice, my website's background is the correct value but I want to showcase the token name and value on the front end as well (for documentation purposes).
An example of how I regularly use it is like so:
background-color: ${props => props.theme.colors.bgPrimary)
But if I wanted to show the value of bgPrimary on the front-end inside a Text component, like so:
<Text value={___} />
how would I have that return the value #141414 without actually hardcoding the HEX value?
Here's how the color object in theme file currently looks:
const colors = {
accent: '#8548FF',
actionPrimary: '#12A55C',
actionPrimaryInteractive: '#0C6E3D',
actionSecondary: '#292929',
actionSecondaryInteractive: '#1F1F1F',
bgPrimary: '#141414',
bgSecondary: '#0A0A0A',
contentPrimary: '#F5F5F5',
contentSecondary: '#8F8F8F',
modes: {
light: {
accent: '#691FFF',
actionPrimary: '#16CA70',
actionPrimaryInteractive: '#109351',
actionSecondary: '#E0E0E0',
actionSecondaryInteractive: '#CCCCCC',
bgPrimary: '#EBEBEB',
bgSecondary: '#F5F5F5',
contentPrimary: '#0A0A0A',
contentSecondary: '#707070',
},
}
}
As you can see, I have two color modes and bgPrimary is different depending on which mode you have set. This is why it's important for the value to be pulled from the theme vs hardcoded.

React-table: how to use getCellProps, getHeaderProps etc.?

The documentation of React Table is really sparse and I can't make sense of the examples.
For example here: https://react-table.tanstack.com/docs/examples/data-driven-classes-and-styles, we see this code:
{row.cells.map(cell => {
return (
<td
// Return an array of prop objects and react-table will merge them appropriately
{...cell.getCellProps([
{
className: cell.column.className,
style: cell.column.style,
},
getColumnProps(cell.column),
getCellProps(cell),
])}
>
{cell.render('Cell')}
</td>
It's not clear to me what's happening.
GetCellProps is called, and provided an array as argument. This array contains 1. an object with two properties, and 2. a call to getColumnProps (what does this do?), and then 3. another call to getCellProps but now with the cell as an argument.
The result of this call is then operated on with the spread-operator (...).
If anyone can help me understand all of this, much appreciated.
I will try to explain this to you -
cell.getCellProps -> is the method exposed on each cell by react-table, this is pretty useful in getting all props which the given cell will require based on the plugins used.
Few eg. of same are -
https://github.com/TanStack/react-table/blob/76a4a861ee56b782404ef91987c3b5691ecf2ebc/src/hooks/useTable.js#L415
https://github.com/TanStack/react-table/blob/76a4a861ee56b782404ef91987c3b5691ecf2ebc/src/plugin-hooks/useFlexLayout.js#L47
https://github.com/TanStack/react-table/blob/76a4a861ee56b782404ef91987c3b5691ecf2ebc/src/plugin-hooks/useAbsoluteLayout.js#L23
Now this method can expect an object or list of object to be provided as argument, which mainly acts as merge/override on prior values, loosely similar to object.assign with some exceptions based on key name, for more details on merge logic refer - https://github.com/TanStack/react-table/blob/76a4a861ee56b782404ef91987c3b5691ecf2ebc/src/publicUtils.js#L19
Below code is helpful in adding className in cell and merge/override styles with previously returned values.
{
className: cell.column.className,
style: cell.column.style,
}
Below two methods are props provided by component
getColumnProps(cell.column),
getCellProps(cell)
getColumnProps={column => ({
onClick: () => alert('Column!'),
})}
getCellProps={cellInfo => ({
style: {
backgroundColor: `hsl(${120 * ((120 - cellInfo.value) / 120) * -1 +
120}, 100%, 67%)`,
},
}
So whatever is returned by these props that will actually get merged in cell props, and will be applied to td.
P.S. - Refer https://github.com/tannerlinsley/react-table/blob/master/src/publicUtils.js#L48 for what all types of argumants can be expected in cell.getCellProps.

Customization of the Height of a Pivot Item Link Line in Fluent UI

I'm trying to increase the height of the line on the selected Pivot item link in Microsoft's Fluent UI using React.
Here's a screenshot for the purposes of clarification:
The orange arrow is pointing to the blue line of which I would like to increase the height.
I have tried setting the styles attribute of the Pivot component but thus far have been unsuccessful. Here's some code
const pivotStyles: Partial<IStyleSet<IPivotStyles>> = {
link: { ? },
linkContent: { ? }
};
<Pivot styles={pivotStyles} linkSize={PivotLinkSize.large}>
<PivotItem headerText="Zane"></PivotItem>
<PivotItem headerText="Kai"></PivotItem>
<PivotItem headerText="Jay"></PivotItem>
</Pivot>
I have experimented with different attributes of both link and linkContent but haven't found a way yet. I believe what I'm trying to do is manipulate the IStyle interface but I can't find details of the attributes of it. The link there is very vague. For example, what are all the available attributes of link, linkContent, etc.?
Any thoughts on this would be most appreciated!
Thank you.
Turns out I was on the right track and just needed the exact fields. Here's what ended up working:
const pivotStyles = {
linkIsSelected: {
selectors: {
':before': {
height: '6px', // was previously defaulted at 2px
}
}
}
};
I scoured about 4.24 million sites to find this answer but here are some of the most helpful in case they are of interest:
the actual source code of Pivot.styles.ts
the Microsoft Fluent UI Pivot Documentation
A deep examination of the classes using Chrome Dev Tools also helped. ;)
Here's a picture of the end result:

Resources