Skip to content

Add playground examples for LayoutGrid for each theme #4509

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

Merged
merged 5 commits into from
Mar 13, 2025

Conversation

heath-freenome
Copy link
Member

Reasons for making this change

Updated the playground so that each theme has an example of the LayoutGridField usage

  • In @rjsf/utils added a browser section to the package.json to support getTestIds() working properly in a browser
    • Updated the getTestIds() to refactor out getTestIdsBrowser() and export it from the new indexBrowser.ts
    • Updated package.json to build indexBrowser.js for each export type
  • In @rjsf/core made a few changes to support the playground examples:
    • In LayoutMultiSchemaField added support for the hiding of labels as well as extracting the placeholder from the UiSchema
    • In GridTemplate removed the explicit adding of the row class, leaving that up to the users of the UiSchema
  • In @rjsf/fluentui-rc made a few changes to support the playground examples:
    • In GridTemplate switched to using the GridShim displaying it only when columns or rows are provided, otherwise simply exporting a div due to the CSS Grid
    • In RadioWidget implemented support for inline styling of the radio elements
  • In playground implemented the Layout Grid example with the following changes:
    • Updated the vite.config.ts to pull the utils classes from the indexBrowser
    • Added the new UiSchemaForTheme type, overriding the uiSchema for Sample to be UiSchema or UiSchemaForTheme
    • Renamed Selector to SampleSelector, adding the selectedSample as a prop, removing the use of the current state in favor of selectedSample
      • Also changed the onSelected() callback to take a sampleName: string rather than data: any
    • Updated Header to replace load with onSampleSelected adding sampleName: string, serializing sampleName on share
      • Also, passed sampleName as selectedSample and onSampleSelected to the SampleSelector
    • Updated EditorProps to take data: any for onChange
    • Updated EditorsProps to take a new hasUiSchemaGenerator: boolean, using it to provide a different title for the UiSchema section when true
    • Updated Playground add two new state variables, uiSchemaGenerator and sampleName
      • Updated onThemeSelected() to update the uiSchema to the one generated from the uiSchemaGenerator(theme) if that function is defined in state
      • Updated load() to take an additional sampleName prop, using it to set the currently selected sample and to set the uiSchemaGenerator if samples[sampleName] has one
        • Also, set the uiSchema to a generated one if the incoming uiSchema is a function and adding a undefined check for the validator
      • Added a new onSampleSelected() which calls load() with the selected sample and sampleName
    • Updated DemoFrame and app.ts to rename material-ui-5 to mui
    • Added a new layoutGrid.ts and exported it from the samples/index.ts

Checklist

  • I'm updating documentation
  • I'm adding or updating code
    • I've added and/or updated tests. I've run npx nx run-many --target=build --exclude=@rjsf/docs && npm run test:update to update snapshots, if needed.
    • I've updated docs if needed
    • I've updated the changelog with a description of the PR
  • I'm adding a new feature
    • I've updated the playground with an example use of the feature

Updated the `playground` so that each theme has an example of the `LayoutGridField` usage
- In `@rjsf/utils` added a `browser` section to the `package.json` to support `getTestIds()` working properly in a browser
  - Updated the `getTestIds()` to refactor out `getTestIdsBrowser()` and export it from the new `indexBrowser.ts`
  - Updated `package.json` to build `indexBrowser.js` for each export type
- In `@rjsf/core` made a few changes to support the playground examples:
  - In `LayoutMultiSchemaField` added support for the hiding of labels as well as extracting the `placeholder` from the UiSchema
  - In `GridTemplate` removed the explicit adding of the `row` class, leaving that up to the users of the `UiSchema`
- In `@rjsf/fluentui-rc` made a few changes to support the playground examples:
  - In `GridTemplate` switched to using the `GridShim` displaying it only when `columns` or `rows` are provided, otherwise simply exporting a `div` due to the CSS Grid
  - In `RadioWidget` implemented support for `inline` styling of the radio elements
- In `playground` implemented the `Layout Grid` example with the following changes:
  - Updated the `vite.config.ts` to pull the `utils` classes from the `indexBrowser`
  - Added the new `UiSchemaForTheme` type, overriding the `uiSchema` for `Sample` to be `UiSchema` or `UiSchemaForTheme`
  - Renamed `Selector` to `SampleSelector`, adding the `selectedSample` as a prop, removing the use of the `current` state in favor of `selectedSample`
    - Also changed the `onSelected()` callback to take a `sampleName: string` rather than `data: any`
  - Updated `Header` to replace `load` with `onSampleSelected` adding `sampleName: string`, serializing `sampleName` on share
    - Also, passed `sampleName` as `selectedSample` and `onSampleSelected` to the `SampleSelector`
  - Updated `EditorProps` to take `data: any` for `onChange`
  - Updated `EditorsProps` to take a new `hasUiSchemaGenerator: boolean`, using it to provide a different title for the `UiSchema` section when true
  - Updated `Playground` add two new state variables, `uiSchemaGenerator` and `sampleName`
    - Updated `onThemeSelected()` to update the `uiSchema` to the one generated from the `uiSchemaGenerator(theme)` if that function is defined in state
    - Updated `load()` to take an additional `sampleName` prop, using it to set the currently selected sample and to set the `uiSchemaGenerator` if `samples[sampleName]` has one
      - Also, set the `uiSchema` to a generated one if the incoming `uiSchema` is a function and adding a undefined check for the `validator`
    - Added a new `onSampleSelected()` which calls `load()` with the selected sample and `sampleName`
  - Updated `DemoFrame` and `app.ts` to rename `material-ui-5` to `mui`
  - Added a new `layoutGrid.ts` and exported it from the `samples/index.ts`
@jasny
Copy link
Contributor

jasny commented Mar 8, 2025

I dislike this implementation for the grid. For v5 the UI schema works for all themes. Custom ui options are ignored for other themes. That's not the case for this grid implementation. Additionally, it doesn't provide proper options for different screen sizes for all themes, which is a must for a grid layout.

I would suggest assuming a 1/12th grid, and only allow setting the span to 1 to 12. But allow setting it for small, medium and large screens. The fields can just fill up to 12 columns.

Limiting the options makes more sense. The grid should look decent, instead of focussing on finetuned customized styling. For that people can overwrite the template.

{
  "firstName": {
    "ui:autofocus": true,
    "ui:emptyValue": "",
    "ui:placeholder": "ui:emptyValue causes this field to always be valid despite being required",
    "ui:autocomplete": "family-name",
    "ui:enableMarkdownInDescription": true,
    "ui:description": "Make text **bold** or *italic*. Take a look at other options [here](https://markdown-to-jsx.quantizor.dev/).",
    "ui:grid": {
      "medium": 6,
      "large": 4
    }
  },
  "lastName": {
    "ui:autocomplete": "given-name",
    "ui:enableMarkdownInDescription": true,
    "ui:description": "Make things **bold** or *italic*. Embed snippets of `code`. <small>And this is a small texts.</small> ",
    "ui:grid": {
      "medium": 6,
      "large": 4
    }
  },
  "age": {
    "ui:widget": "updown",
    "ui:title": "Age of person",
    "ui:description": "(earth year)"
    "ui:grid": {
      "large": 4
    }
  },
  "bio": {
    "ui:widget": "textarea"
  },
  "password": {
    "ui:widget": "password",
    "ui:help": "Hint: Make it strong!",
    "ui:grid": {
      "medium": 6,
      "large": 6
    }
  },
  "telephone": {
    "ui:options": {
      "inputType": "tel"
    },
    "ui:grid": {
      "medium": 6,
      "large": 6
    }
  }
}

@heath-freenome
Copy link
Member Author

heath-freenome commented Mar 9, 2025

I dislike this implementation for the grid. For v5 the UI schema works for all themes. Custom ui options are ignored for other themes. That's not the case for this grid implementation. Additionally, it doesn't provide proper options for different screen sizes for all themes, which is a must for a grid layout.

I would suggest assuming a 1/12th grid, and only allow setting the span to 1 to 12. But allow setting it for small, medium and large screens. The fields can just fill up to 12 columns.

@jasny Here's the issue I see with your approach; the Fluent and Chakra-UI are both using native CSS grids which do NOT have a 1-12 approach. And antd uses a 24 column grid. Granted we could use math in that theme's GridTemplate if we did go with the 1-12 approach.

At the end of the day, the UiSchema is about modifying the standard UI approach for RJSF to fit the specifics of the UI the developer wants. I imagine that 99% of people using RJSF do so with a single theme making the need for a theme-agnostic grid approach mute. Therefore, providing a way for users to fine tune the gridding to exactly what they want, I believe, is the best approach. Making it a least-common-denominator (LCD) solution like you are suggesting won't help people make exactly the UIs they want. It likely will even hinder it. With this grid approach I've developed one can put any field into any position. Using my example... If you wanted to move the address information after the name and before the birth_date and race, you could. You don't care to show the optional middle name or want it after the last name, no problem. You want to move the employment section first, easy-peasy.

In terms of providing "proper options for different screen sizes for all themes", again, that is up to the developer to build. All of the themes that use the 1-12 grid system support the screen breakpoints, which the developer can easily add to their UI schema. Yes, it likely will take some playing around with the fine grain details of the ui:row/ui:columns/ui:col in the UiSchema for a while, but once the developer has it nailed they likely won't change it much. Moreover, the ui:condition provides a way for the user to alter the gridding of the UI based on the value(s) of a field within the formData

All that said, I definitely want to chat more about your ideas around how imagine see it work and how you might use it. Perhaps we do add support for the simplest LCD approach with a ui:grid option which basically sets up the layout in terms of gridding the properties in the schema in the order they appear. You want everything in a 2 column grid in small and 4 column in large then just set the outer grid to be:

{
    'ui:field': 'LayoutGridField',
    'ui:layoutGrid': {
        large: 4,
        small: 2
    }
}

}

export default function Selector({ onSelected }: SelectorProps) {
const [current, setCurrent] = useState<string>('Simple');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for making this controlled

import getSchemaType from './getSchemaType';
import getSubmitButtonOptions from './getSubmitButtonOptions';
import getTemplate from './getTemplate';
import { getTestIdsBrowser as getTestIds } from './getTestIds';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't getTestIds work in the browser?

Copy link
Member Author

@heath-freenome heath-freenome Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Browsers don't have process defined and using it there cause a TypeError and the playground wouldn't start

Copy link
Contributor

@nickgros nickgros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I agree with @jasny though that it's a good idea to explore augmenting this with a more simple/conventional API.

@heath-freenome heath-freenome merged commit 8eb9bc3 into rjsf-v6 Mar 13, 2025
4 checks passed
@heath-freenome heath-freenome deleted the layoutGrid-playground branch March 13, 2025 18:08
zfarhad pushed a commit to zfarhad/react-jsonschema-form that referenced this pull request May 9, 2025
* Add playground examples for LayoutGrid for each theme
Updated the `playground` so that each theme has an example of the `LayoutGridField` usage
- In `@rjsf/utils` added a `browser` section to the `package.json` to support `getTestIds()` working properly in a browser
  - Updated the `getTestIds()` to refactor out `getTestIdsBrowser()` and export it from the new `indexBrowser.ts`
  - Updated `package.json` to build `indexBrowser.js` for each export type
- In `@rjsf/core` made a few changes to support the playground examples:
  - In `LayoutMultiSchemaField` added support for the hiding of labels as well as extracting the `placeholder` from the UiSchema
  - In `GridTemplate` removed the explicit adding of the `row` class, leaving that up to the users of the `UiSchema`
- In `@rjsf/fluentui-rc` made a few changes to support the playground examples:
  - In `GridTemplate` switched to using the `GridShim` displaying it only when `columns` or `rows` are provided, otherwise simply exporting a `div` due to the CSS Grid
  - In `RadioWidget` implemented support for `inline` styling of the radio elements
- In `playground` implemented the `Layout Grid` example with the following changes:
  - Updated the `vite.config.ts` to pull the `utils` classes from the `indexBrowser`
  - Added the new `UiSchemaForTheme` type, overriding the `uiSchema` for `Sample` to be `UiSchema` or `UiSchemaForTheme`
  - Renamed `Selector` to `SampleSelector`, adding the `selectedSample` as a prop, removing the use of the `current` state in favor of `selectedSample`
    - Also changed the `onSelected()` callback to take a `sampleName: string` rather than `data: any`
  - Updated `Header` to replace `load` with `onSampleSelected` adding `sampleName: string`, serializing `sampleName` on share
    - Also, passed `sampleName` as `selectedSample` and `onSampleSelected` to the `SampleSelector`
  - Updated `EditorProps` to take `data: any` for `onChange`
  - Updated `EditorsProps` to take a new `hasUiSchemaGenerator: boolean`, using it to provide a different title for the `UiSchema` section when true
  - Updated `Playground` add two new state variables, `uiSchemaGenerator` and `sampleName`
    - Updated `onThemeSelected()` to update the `uiSchema` to the one generated from the `uiSchemaGenerator(theme)` if that function is defined in state
    - Updated `load()` to take an additional `sampleName` prop, using it to set the currently selected sample and to set the `uiSchemaGenerator` if `samples[sampleName]` has one
      - Also, set the `uiSchema` to a generated one if the incoming `uiSchema` is a function and adding a undefined check for the `validator`
    - Added a new `onSampleSelected()` which calls `load()` with the selected sample and `sampleName`
  - Updated `DemoFrame` and `app.ts` to rename `material-ui-5` to `mui`
  - Added a new `layoutGrid.ts` and exported it from the `samples/index.ts`

* - Fixed test

* Update CHANGELOG_v6.md

* - Fix `MultiSchemaField` to pass `id` in `onChange`

* - Renamed `MuiV5Theme` to `MuiTheme`
zfarhad pushed a commit to zfarhad/react-jsonschema-form that referenced this pull request May 9, 2025
* Add playground examples for LayoutGrid for each theme
Updated the `playground` so that each theme has an example of the `LayoutGridField` usage
- In `@rjsf/utils` added a `browser` section to the `package.json` to support `getTestIds()` working properly in a browser
  - Updated the `getTestIds()` to refactor out `getTestIdsBrowser()` and export it from the new `indexBrowser.ts`
  - Updated `package.json` to build `indexBrowser.js` for each export type
- In `@rjsf/core` made a few changes to support the playground examples:
  - In `LayoutMultiSchemaField` added support for the hiding of labels as well as extracting the `placeholder` from the UiSchema
  - In `GridTemplate` removed the explicit adding of the `row` class, leaving that up to the users of the `UiSchema`
- In `@rjsf/fluentui-rc` made a few changes to support the playground examples:
  - In `GridTemplate` switched to using the `GridShim` displaying it only when `columns` or `rows` are provided, otherwise simply exporting a `div` due to the CSS Grid
  - In `RadioWidget` implemented support for `inline` styling of the radio elements
- In `playground` implemented the `Layout Grid` example with the following changes:
  - Updated the `vite.config.ts` to pull the `utils` classes from the `indexBrowser`
  - Added the new `UiSchemaForTheme` type, overriding the `uiSchema` for `Sample` to be `UiSchema` or `UiSchemaForTheme`
  - Renamed `Selector` to `SampleSelector`, adding the `selectedSample` as a prop, removing the use of the `current` state in favor of `selectedSample`
    - Also changed the `onSelected()` callback to take a `sampleName: string` rather than `data: any`
  - Updated `Header` to replace `load` with `onSampleSelected` adding `sampleName: string`, serializing `sampleName` on share
    - Also, passed `sampleName` as `selectedSample` and `onSampleSelected` to the `SampleSelector`
  - Updated `EditorProps` to take `data: any` for `onChange`
  - Updated `EditorsProps` to take a new `hasUiSchemaGenerator: boolean`, using it to provide a different title for the `UiSchema` section when true
  - Updated `Playground` add two new state variables, `uiSchemaGenerator` and `sampleName`
    - Updated `onThemeSelected()` to update the `uiSchema` to the one generated from the `uiSchemaGenerator(theme)` if that function is defined in state
    - Updated `load()` to take an additional `sampleName` prop, using it to set the currently selected sample and to set the `uiSchemaGenerator` if `samples[sampleName]` has one
      - Also, set the `uiSchema` to a generated one if the incoming `uiSchema` is a function and adding a undefined check for the `validator`
    - Added a new `onSampleSelected()` which calls `load()` with the selected sample and `sampleName`
  - Updated `DemoFrame` and `app.ts` to rename `material-ui-5` to `mui`
  - Added a new `layoutGrid.ts` and exported it from the `samples/index.ts`

* - Fixed test

* Update CHANGELOG_v6.md

* - Fix `MultiSchemaField` to pass `id` in `onChange`

* - Renamed `MuiV5Theme` to `MuiTheme`
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

Successfully merging this pull request may close these issues.

3 participants