-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[system] Allow theme.spacing()
to return a number
#29086
Comments
As per your code this is all it takes to implement it:
I am not sure if it is worth adding it to the theme. I would wait to see if it will get some traction :) |
I would also like access to the raw spacing value. Having to convert from a string to a number is a little excessive. |
If I recall correctly, this used to be the default behaviour of |
Yep. After migration all my calculated |
Workaround: |
Nope. It's not workaround. It force browser to calc thing it shouldn't. Workaround is |
@jankanty Could you please explain why you're subtracting Anyway, we're migrating now from v4 to v5 and I'd also like to have the spacing utility to return We're working with tons of charts and use the spacing utility of the theme to make sure everything's aligned and for this, we calculate extra spacing using offsets to position SVG elements correctly. For every single usage, we have to The suggestion of adding a second param for the |
@cristi-shoreline it was only for example for previous person |
I really hope it would be fixed to previous behaviour so parseInt is best workaround since you can after that quickly remove it with search and replace. |
I was working on this. But found out that can't we simply supply a decimal value accordingly to `${Number(theme.spacing(3).slice(0, -2)) + 2}px` == 26px We can do, theme.spacing(3.25) == 26px cc: @mnajdova |
Sorry, I don't understand what you mean we cannot apply decimal value. |
In version 4 it worked correctly if I needed a number, it returned a number, if I needed something in px, it returned a string in px, please return that behavior |
Please read through the initial issue #16205 (comment) and the PR that changed the behavior #22552 if you are interested why the change was made. There is a simple fix to the solution, provided in the comments above. I don't think it's worth spending time on this issue. |
I know the "solution" works, but that's really brittle: who is to say that the units will forever be "px". The other solution by using calc is more robust - however it doesn't work in all places, notably things like breakpoints don't allow such syntax. |
I just wrote this in a MUI v5 project to easily use this version of the function. In a folder called import { Theme } from "@mui/material";
import { SpacingArgument } from "@mui/system/createTheme/createSpacing";
/**
* Version of the `spacing` function that returns a number or an array of numbers
* instead of a string. Suffixed with `V4` because it's the behaviour it had on @mui/v4.
*
* @see https://mui.com/material-ui/customization/spacing/
* @see https://github.com/mui/material-ui/issues/29086
*/
export interface SpacingV4 {
(): number;
(value: number): number;
(topBottom: SpacingArgument, rightLeft: SpacingArgument): [number, number];
(top: SpacingArgument, rightLeft: SpacingArgument, bottom: SpacingArgument): [
number,
number,
number
];
(
top: SpacingArgument,
right: SpacingArgument,
bottom: SpacingArgument,
left: SpacingArgument
): [number, number, number, number];
}
export interface WithSpacingV4 {
spacingV4: SpacingV4;
}
export default function spacingV4(
/* mutable */ theme: Theme
): Theme & WithSpacingV4 {
return Object.assign(theme, { spacingV4: makeSpacingV4(theme) });
}
export const makeSpacingV4 = (theme: Theme): SpacingV4 => {
// @ts-expect-error: wrongly typed from the `SpacingV4` interface
const spacingV4: SpacingV4 = (...args: number[]) => {
const [top, right, bottom, left] = theme
// @ts-expect-error: wrongly typed from `number[]` to tuples
.spacing(...args)
.split(" ")
.map((value) => Number.parseInt(value, 10));
switch (args.length) {
case 0:
case 1:
return top;
case 2:
return [top, right];
case 3:
return [top, right, bottom];
case 4:
return [top, right, bottom, left];
}
};
return spacingV4;
}; Then in the import spacingV4, { SpacingV4 } from "./theme-augmentations/spacingV4";
const theme = createTheme();
export default spacingV4(theme);
declare module "@mui/material/styles" {
interface Theme {
spacingV4: SpacingV4;
}
} And then wherever the theme is available: theme.spacingV4(); // 8
theme.spacingV4(2); // 16
theme.spacingV4(2, 3); // [16, 24]
theme.spacingV4(2, 3, 4); // [16, 24, 32]
theme.spacingV4(2, 3, 4, 5); // [16, 24, 32, 40] |
Any update on this? |
Feel free to create a PR if anyone wants to. |
Hi I'm using the Joy UI library and I do have the same request. I want to use the spacing value during painting on a canvas, to align the custom graphical rendering with the spacing used in the HTML. I'm in the process of updating the Joy UI package to its latest version: In the previous version, I could get the
Although a bit of overhead, but it did the job. And thus I loose the possibility to get the actual spacing-value.
Is there any supported solution for this? Regards |
@HansDP I think it was due to the change done in #40224. Maybe you can use const useSpacingValue = () => {
const [spacingValue, setSpacingValue] = useState(0);
useEffect(() => {
const computedStyle = getComputedStyle(document.documentElement);
const spacing = computedStyle.getPropertyValue('--joy-spacing');
const spacingInPixels = parseInt(spacing, 10);
setSpacingValue(spacingInPixels);
}, []);
return spacingValue;
};
const MyComponent = () => {
const spacing = useSpacingValue();
return <div>{spacing}</div>; // This should output the spacing value in pixels
}; Please create a new issue if this doesn't work. This is unrelated to this issue. |
@ZeeshanTamboli Thanks for the suggestion. I already considered that, but rejected it as a good solution. The getComputedStyle solution requires a JavaScript variable to be transferred into the DOM (using CSS) to be able to extract it back into JavaScript. This seems like an anti-pattern and using the wrong solution. Secondly, this requires an additional render cycle (the first render cycle, the spacing variable will be 0, the second render cycle will contain the correct value). I do think this is related to the issue. As stated by the OP, the request is to get the spacing multiplier from the theme. This is exactly what I need (something that was possible using a work-around in the past, but in the end, I do want to get a hold of the spacing multiplier). But, if creating a new ticket is what is needed here, just let me know. I gladly create a duplicate ticket. |
theme.spacing()
to return a number
Motivation 🔦
I love the spacing utility function because it makes keeping spacing consistent throughout an application very easy, but in some cases, I want to tweak the value returned by it a little. This is currently quite difficult because the function always returns a string with
"px"
appended to it.Currently, if I want to, for example, add 2 to the return value of the spacing function, I would have to do something like this:
`${Number(theme.spacing(3).slice(0, -2)) + 2}px`
I did check to see if the spacing value provided to
createTheme()
was exposed anywhere in theTheme
object, but it didn't look like it was.Summary 💡
There should be some way (possibly a fifth argument?) to make the spacing function return a number. If this isn't possible, then the spacing multiplier value provided to
createTheme()
should be exposed somewhere in theTheme
object so that developers can use it to do the multiplication themselves.The text was updated successfully, but these errors were encountered: