-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
[Divider] Responsive orientation #29908
Comments
This would be cool to implement, not seeing many downsides. |
Would love to see this implemented as well. |
This would be very nice to see indeed. Until then, the snippet below works to achieve similar results
|
I have created a wrapper for the Divider using logic similar to the MUI breakpoint utilities(#29864). This enables me to use the prop exactly like the direction prop. As you can see I have used "react-singleton-hook. If you have a custom theme (specifically custom breakpoints), you must ensure you add // src/hooks/useCurrentBreakpoint/index.ts
import { useTheme } from "@mui/material";
import { Breakpoint } from "@mui/system";
import { useEffect, useState } from "react";
import { singletonHook } from "react-singleton-hook";
// https://github.com/Light-Keeper/react-singleton-hook/issues/406#issuecomment-962282765
// eslint-disable-next-line no-underscore-dangle
export function _useCurrentBreakpoint(): Breakpoint {
const globalTheme = useTheme();
const mqs: [Breakpoint, string][] = globalTheme.breakpoints.keys.map(
(key, index, breakpoints) => {
let mq = "";
if (index === breakpoints.length - 1) {
mq = globalTheme.breakpoints.up(key);
} else {
mq = globalTheme.breakpoints.between(key, breakpoints[index + 1]);
}
return [key, mq.replace(/^@media( ?)/m, "")];
}
);
const [currentBreakpoint, setCurrentBreakpoint] = useState<Breakpoint>(() => {
const bp = mqs.find(([, mq]) => window.matchMedia(mq).matches);
return bp ? bp[0] : "xs";
});
useEffect(() => {
function handleCurrentBreakpointChange(
key: Breakpoint,
e: MediaQueryListEvent
) {
if (e.matches) {
setCurrentBreakpoint(key);
}
}
const handlers: [string, (e: MediaQueryListEvent) => void][] = mqs.map(
([key, mq]) => {
const handler = (e: MediaQueryListEvent) =>
handleCurrentBreakpointChange(key, e);
return [mq, handler];
}
);
handlers.forEach(([mq, handler]) => {
window.matchMedia(mq).addEventListener("change", handler);
});
return () => {
handlers.forEach(([mq, handler]) => {
window.matchMedia(mq).removeEventListener("change", handler);
});
};
}, [mqs]);
return currentBreakpoint;
}
const useCurrentBreakpoint = singletonHook("xs", _useCurrentBreakpoint);
export { useCurrentBreakpoint }; // src/components/ResponsiveDivider/index.tsx
import { useTheme } from "@mui/material";
import { Breakpoint, ResponsiveStyleValue } from "@mui/system";
function isBPValueAnObject<T>(
breakpointValues: ResponsiveStyleValue<T>
): breakpointValues is Record<Breakpoint, T | null> {
return (
typeof breakpointValues === "object" && !Array.isArray(breakpointValues)
);
}
export function useResolveAllBreakpoints<T>(
breakpointValues: ResponsiveStyleValue<T>
): Record<Breakpoint, T> {
const bpKeys = useTheme().breakpoints.keys;
const bpsProvided = (() => {
if (typeof breakpointValues !== "object") {
return [];
}
let b: Breakpoint[] = [];
if (Array.isArray(breakpointValues)) {
b = breakpointValues.map((_, i) => bpKeys[i]);
} else {
b = Object.entries(breakpointValues as Record<Breakpoint, T | null>)
.filter(([k, v]) => bpKeys.includes(k as Breakpoint) && v != null)
.map(([k]) => k as Breakpoint);
}
return b;
})();
if (bpsProvided.length === 0) {
return Object.fromEntries(
bpKeys.map((k) => [k, breakpointValues as T])
) as Record<Breakpoint, T>;
}
let previous: Breakpoint | number;
return bpKeys.reduce(
(acc: Partial<Record<Breakpoint, unknown>>, breakpoint, i) => {
if (Array.isArray(breakpointValues)) {
if (breakpointValues[i] != null) {
acc[breakpoint] = breakpointValues[i];
previous = i;
} else {
acc[breakpoint] = breakpointValues[previous as number];
}
} else if (isBPValueAnObject(breakpointValues)) {
if (breakpointValues[breakpoint] != null) {
acc[breakpoint] = breakpointValues[breakpoint];
previous = breakpoint;
} else {
acc[breakpoint] = breakpointValues[previous as Breakpoint];
}
} else {
acc[breakpoint] = breakpointValues;
}
return acc;
},
{}
) as Record<Breakpoint, T>;
} // src/hooks/useResolveAllBreakpoints/index.ts
import { Divider, DividerProps } from "@mui/material";
import { ResponsiveStyleValue } from "@mui/system";
import { useCurrentBreakpoint } from "src/hooks/useCurrentBreakpoint";
import { useResolveAllBreakpoints } from "src/hooks/useResolveAllBreakpoints";
export function ResponsiveDivider({
orientation,
...props
}: {
orientation: ResponsiveStyleValue<"horizontal" | "vertical">;
} & Omit<DividerProps, "orientation">): JSX.Element {
const currentBreakpoint = useCurrentBreakpoint();
const bpValues = useResolveAllBreakpoints(orientation);
const currentOrientation = bpValues[currentBreakpoint];
return <Divider {...props} orientation={currentOrientation} />;
} |
Still looking forward to this! |
Any updates on this issue? Its still not fixed. |
waiting for this, also for the calendar ahahhahaha |
Any updates on this, to have different orientation in different breakpoints |
How is this not a thing yet? |
Would love to see this |
Crap I thought this was the Nextui page haha |
Hey maintainers |
Duplicates
Latest version
Summary 💡
Currently the
Divider
component can only consumehorizontal | vertical
.I would like to see it use the
ResponsiveStyleValue
as a possible option for theorientation
property.It should work something like this...
Examples 🌈
No response
Motivation 🔦
I want to use a responsive
Divider
in conjunction with theStack
component as theStack
component can change directions responsively.Using the components together would look something like this...
I think that this features would be very useful not just to me but others developers as they start using the
Stack
component. I am sure that I won't be the only one to run into these problem in the future.The text was updated successfully, but these errors were encountered: