Skip to content
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

Suggestion for the conditionals handling in the props #376

Open
kaspar-naaber opened this issue Mar 6, 2025 · 1 comment
Open

Suggestion for the conditionals handling in the props #376

kaspar-naaber opened this issue Mar 6, 2025 · 1 comment

Comments

@kaspar-naaber
Copy link

kaspar-naaber commented Mar 6, 2025

Hi! Thank you for the great library. The only thing that seems to be missing is passing the breakpoint state as a prop so that prop value could change based on the viewport. I ended up adding a helper component that passes it. It is not ideal but maybe gives some ideas how to bake the functionality into the library core.

// Breakpointprovider.tsx
import { Children, cloneElement, isValidElement, ReactElement, ReactNode } from 'react';

import { type Breakpoint, Media } from '@eres-monorepo/shared/util/media-context';

interface BreakpointProviderProps {
  breakpoint: Breakpoint;
  children: ReactNode;
}

export interface BreakpointMatch {
  greaterThanOrEqual?: boolean;
  lessThan?: boolean;
}

export interface BreakpointMatchProp {
  mediaMatchProps?: BreakpointMatch;
}

const getMediaMatchProps = (props: BreakpointMatch) => ({
  greaterThanOrEqual: false,
  lessThan: false,
  ...props,
});

const enhanceChildrenWithBreakpointProp = (
  children: BreakpointProviderProps['children'],
  mediaMatchProps: BreakpointMatch,
) => {
  console.log('mediaMatchProps:', mediaMatchProps);
  return Children.map(children, (child) =>
    isValidElement(child) ? cloneElement(child as ReactElement, { mediaMatchProps }) : child,
  );
};

export const BreakpointProvider = ({ breakpoint, children }: BreakpointProviderProps): ReactElement => (
  <>
    <Media greaterThanOrEqual={breakpoint}>
      {enhanceChildrenWithBreakpointProp(children, getMediaMatchProps({ greaterThanOrEqual: true }))}
    </Media>

    <Media lessThan={breakpoint}>
      {enhanceChildrenWithBreakpointProp(children, getMediaMatchProps({ lessThan: true }))}
    </Media>
  </>
);

And for the usage the child component props must extend the BreakpointMatchProp

export interface SomeReactComponentProps extends BreakpointMatchProp {
  foo: string;
  bar: string;
}
<BreakpointProvider breakpoint="sm">
  <SomeReactComponent /> 
</BreakpointProvider>

Now the SomeReactComponent has its onw props and in addigion the breakpoints too.

export const SomeReactComponent = ({
  foo,
  bar,
  mediaMatchProps,
}: SomeReactComponentProps): ReactElement => (
  <div className={mediaMatchProps.greaterThanOrEqual ? 'greater' : 'less'}>
  {mediaMatchProps.less ? foo : bar}
</div>
)
@damassi
Copy link
Member

damassi commented Mar 6, 2025

Thanks for the suggestion! I'm somewhat hesitant to add additional features given the overall existing complexity (and it seems like a simple functional wrapper like you've written above does the trick).

Can you perhaps show how this would look baked into the lib, used in JSX and utilizing the hypothetical new api?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants