materialRenderers - categories - vertical?

Hi,
is it possible to use the materialRenderers and display categories vertical. In the default layout the categories are displayed horizontal:

But in the mui project there is also a feature to display tabs vertical:

image

For the vanilaRenderer I solved this by tweeking the CSS, but for materialRenderer this seems much more complex. So I wonder if there is a trick how I can tell my react form to display categories vertical?

The Material UI Theming support is very powerful. It can also be used to set default props of Material UI components. You could try handing over orientation="vertical" to the Tabs component this way. See here for more information.

Yes, I have found this too. But I was not clear how to use the options? This is not really explained in the documentation or at least I did not found an example about setting options.
In the mean time I switched back to the VanillaRenderer as I don’t want to overload my modeller application without need (you know I am working now on a custom renderer).

The documentation link provides all the information needed:

  • Build your custom theme specifying the props you would like to see set by default
  • Wrap JsonForms with the Material UI ThemeProvider and hand over the theme. Alternatively you could of course also wrap your whole application.

I’m wondering if anyone was able to get this to work. I believe I’m successfully doing the MUI theme part, but I’m having a display problem: the tabs get full-width, and the tab content is displayed beneath them.

Here is my code:

import React, { useState } from 'react';
import {
    materialRenderers,
    materialCells,
} from '@jsonforms/material-renderers';
import { JsonForms } from '@jsonforms/react';
import { createTheme, ThemeProvider } from '@mui/material/styles';

const App = () => {
    const theme = createTheme({
        components: {
            MuiTabs: {
                defaultProps: {
                    orientation: 'vertical',
                },
            },
        },
    });
    const schema = opensdg.configForm.schema;
    const uischema = opensdg.configForm.uiSchema;
    const initialData = opensdg.configForm.existingData;
    const [data, setData] = useState(initialData);
    return (
        <ThemeProvider theme={theme}>
            <div>
                <JsonForms
                    schema={schema}
                    uischema={uischema}
                    data={data}
                    renderers={materialRenderers}
                    cells={materialCells}
                    onChange={({ data, errors }) => setData(data)}
                />
            </div>
        </ThemeProvider>
    )
}

export default App;

And here is what I’m seeing:

Has anyone else run into this issue?

Hi @brockfanning,

There are two problems here:

  • We use AppBar for the tabs which automatically grabs 100% width
  • Our CategoryRenderer does not introduce a wrapper container element, e.g. a div

Assuming you render the Categorization at the root of the form you can apply display: 'flex' on a container div wrapping the JsonForms component and apply width: inherit on the app bar via the default props mechanism, e.g.

const theme = createTheme({
  components: {
    MuiTabs: {
      defaultProps: {
        orientation: 'vertical',
      },
    },
    MuiAppBar: {
      defaultProps: {
        sx: {
          width: 'inherit',
          marginRight: '16px'
        }
      }
    }
  },
});

// in the render code

<div style={{display: 'flex'}}>
  <ThemeProvider theme={theme}>
    <JsonForms {...jsonFormsProps} />
  </ThemeProvider>
</div>

If that is not the case for you you could wrap your Categorization with a VerticalLayout and then target the div of the VerticalLayout to apply the display: flex.

Alternatively you can of course always just use a custom renderer. I would also be fine with a contribution to JsonForms which adds a wrapper Box element in the Categorization renderer and replaces the AppBar component with a more neutral component.

1 Like

@sdirix Thanks very much! This worked for me.