From 528b673e367bb2c6108edc582ab831bce9460ade Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Fri, 24 Nov 2023 13:01:30 +0100 Subject: [PATCH 01/21] :pencil: [#36] Add story for large form progress indicator on mobile Credits for the story go to @vaszig. Co-authored-by: @vaszig --- src/components/App.stories.js | 159 +++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 4 deletions(-) diff --git a/src/components/App.stories.js b/src/components/App.stories.js index 5c14ab79d..dda71a305 100644 --- a/src/components/App.stories.js +++ b/src/components/App.stories.js @@ -20,7 +20,7 @@ import {SUBMISSION_ALLOWED} from './constants'; export default { title: 'Private API / App', component: App, - decorators: [LayoutDecorator, ConfigDecorator], + decorators: [ConfigDecorator], args: { 'form.translationEnabled': true, submissionAllowed: SUBMISSION_ALLOWED.yes, @@ -113,10 +113,11 @@ const render = args => { export const Default = { render, + decorators: [LayoutDecorator], }; export const TranslationEnabled = { - render, + ...Default, args: { 'form.translationEnabled': true, }, @@ -127,7 +128,7 @@ export const TranslationEnabled = { }; export const TranslationDisabled = { - render, + ...Default, args: { 'form.translationEnabled': false, }, @@ -145,9 +146,10 @@ export const TranslationDisabled = { }; export const ActiveSubmission = { + ...Default, name: 'Active submission', - render, decorators: [ + ...Default.decorators, // remove the window.localStorage entry, UUID value is from `api-mocks/forms.js`. // it gets set because of the play function which starts a submission. Story => { @@ -201,3 +203,152 @@ export const ActiveSubmission = { await userEvent.click(beginButton); }, }; + +export const SeveralStepsInMobileViewport = { + render, + args: { + title: 'Progress', + formTitle: 'Formulier', + steps: [ + { + uuid: '9e6eb3c5-e5a4-4abf-b64a-73d3243f2bf5', + slug: 'step-1', + formDefinition: 'Step 1', + index: 0, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/9e6eb3c5-e5a4-4abf-b64a-73d3243f2bf5`, + isApplicable: true, + }, + { + uuid: '71fa50c1-53db-4179-9fe7-eb3378ef39ee', + slug: 'step-2', + formDefinition: 'Step 2', + index: 1, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/71fa50c1-53db-4179-9fe7-eb3378ef39ee`, + isApplicable: true, + }, + { + uuid: 'f4f82113-ac83-429b-a17b-c1b145831fa9', + slug: 'step-3', + formDefinition: 'Step 3', + index: 2, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/f4f82113-ac83-429b-a17b-c1b145831fa9`, + isApplicable: true, + }, + { + uuid: 'ae5af44e-004f-4d2f-be75-d46a22577244', + slug: 'step-4', + formDefinition: 'Step 4', + index: 3, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/ae5af44e-004f-4d2f-be75-d46a22577244`, + isApplicable: true, + }, + { + uuid: 'cae11cf8-2773-4d70-80f4-71e5828b6fe3', + slug: 'step-5', + formDefinition: 'Step 5', + index: 4, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/cae11cf8-2773-4d70-80f4-71e5828b6fe3`, + isApplicable: true, + }, + { + uuid: '3b14f4f5-2283-4a81-adf1-03848672c83b', + slug: 'step-6', + formDefinition: 'Step 6', + index: 5, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/3b14f4f5-2283-4a81-adf1-03848672c83b`, + isApplicable: true, + }, + { + uuid: '3f0a2763-74de-4957-b970-a5117f15b023', + slug: 'step-7', + formDefinition: 'Step 7', + index: 6, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/3f0a2763-74de-4957-b970-a5117f15b023`, + isApplicable: true, + }, + { + uuid: '03657dc1-6bb1-49cf-8113-4b663981b70f', + slug: 'step-8', + formDefinition: 'Step 8', + index: 7, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/03657dc1-6bb1-49cf-8113-4b663981b70f`, + isApplicable: true, + }, + { + uuid: '03657dc1-6bb1-49cf-8113-4b663981b70f', + slug: 'step-9', + formDefinition: 'Step 9', + index: 8, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/03657dc1-6bb1-49cf-8113-4b663981b70f`, + isApplicable: true, + }, + { + uuid: '03657dc1-6bb1-49cf-8113-4b663981b70f', + slug: 'step-10', + formDefinition: 'Step 10', + index: 9, + literals: { + previousText: {resolved: 'Previous', value: ''}, + saveText: {resolved: 'Save', value: ''}, + nextText: {resolved: 'Next', value: ''}, + }, + url: `${BASE_URL}forms/mock/steps/03657dc1-6bb1-49cf-8113-4b663981b70f`, + isApplicable: true, + }, + ], + ariaMobileIconLabel: 'Progress step indicator toggle icon (mobile)', + accessibleToggleStepsLabel: 'Current step in form Formulier: Stap 2', + }, + parameters: { + chromatic: {disableSnapshot: true}, // TODO: set up viewports in chromatic + layout: 'fullscreen', // removes padding in canvas + viewport: { + defaultViewport: 'mobile1', + }, + }, +}; From a6a83a6344108aa7e61902569ba226a6b6af6636 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Thu, 23 Nov 2023 17:01:15 +0100 Subject: [PATCH 02/21] :recycle: [#36] Refactor container app/form components Refactored the React components and CSS components to do away with the Form layout component, favouring a single grid layout for the App container. This introduces more flexibility with the styling when re-arranging elements. --- design-tokens | 2 +- src/Context.js | 3 + src/components/App.js | 38 ++---------- src/components/App.stories.js | 11 ++-- src/components/AppDisplay.js | 38 ++++++++++-- src/components/Form.js | 30 +++++---- src/components/FormDisplay.js | 57 ++++++++++------- src/components/FormDisplay.stories.js | 28 +++++---- src/components/FormStep/FormStep.stories.js | 7 +-- src/components/FormStep/index.js | 5 +- src/components/LanguageSwitcher.js | 12 ++++ .../CreateAppointment/CreateAppointment.js | 43 ++++++------- src/scss/components/_app.scss | 62 ++++++++++++++++--- src/scss/components/_form.scss | 46 -------------- src/styles.scss | 1 - 15 files changed, 202 insertions(+), 181 deletions(-) create mode 100644 src/components/LanguageSwitcher.js delete mode 100644 src/scss/components/_form.scss diff --git a/design-tokens b/design-tokens index ff79cdda4..499476b9f 160000 --- a/design-tokens +++ b/design-tokens @@ -1 +1 @@ -Subproject commit ff79cdda4f02e2fec08e95e1e399ac25244ef8c4 +Subproject commit 499476b9f1d39833ad2850cade0e693bc4637de4 diff --git a/src/Context.js b/src/Context.js index b9a554ae2..1c59fa651 100644 --- a/src/Context.js +++ b/src/Context.js @@ -1,5 +1,7 @@ import React from 'react'; +import {DEBUG} from 'utils'; + const FormContext = React.createContext({ uuid: '', name: '', @@ -33,6 +35,7 @@ const ConfigContext = React.createContext({ progressIndicator: null, loginOptions: null, }, + debug: DEBUG, }); ConfigContext.displayName = 'ConfigContext'; diff --git a/src/components/App.js b/src/components/App.js index 1e6ab8c80..68ed4fc70 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,13 +1,8 @@ -import PropTypes from 'prop-types'; -import React, {useContext} from 'react'; -import ReactDOM from 'react-dom'; +import React from 'react'; import {Navigate, Outlet, useMatch} from 'react-router-dom'; -import {ConfigContext} from 'Context'; -import AppDebug from 'components/AppDebug'; import {Cosign} from 'components/CoSign'; import Form from 'components/Form'; -import LanguageSelection from 'components/LanguageSelection'; import { CreateAppointment, appointmentRoutes, @@ -16,10 +11,6 @@ import { import useFormContext from 'hooks/useFormContext'; import useQuery from 'hooks/useQuery'; import useZodErrorMap from 'hooks/useZodErrorMap'; -import {I18NContext} from 'i18n'; -import {DEBUG} from 'utils'; - -import AppDisplay from './AppDisplay'; export const routes = [ { @@ -42,30 +33,18 @@ export const routes = [ }, ]; -const LanguageSwitcher = () => { - const {languageSelectorTarget: target} = useContext(I18NContext); - return target ? ReactDOM.createPortal(, target) : ; -}; - /* Top level router - routing between an actual form or supporting screens. */ -const App = ({noDebug = false}) => { +const App = () => { const form = useFormContext(); const query = useQuery(); - const config = useContext(ConfigContext); const appointmentMatch = useMatch('afspraak-maken/*'); const appointmentCancelMatch = useMatch('afspraak-annuleren/*'); // register localized error messages in the default zod error map useZodErrorMap(); - const AppDisplayComponent = config?.displayComponents?.app ?? AppDisplay; - - const {translationEnabled} = form; - const languageSwitcher = translationEnabled ? : null; - const appDebug = DEBUG && !noDebug ? : null; - const isAppointment = form.appointmentOptions?.isAppointment ?? false; if (isAppointment && !appointmentMatch && !appointmentCancelMatch) { return ( @@ -78,18 +57,9 @@ const App = ({noDebug = false}) => { /> ); } - - return ( - } - languageSwitcher={languageSwitcher} - appDebug={appDebug} - /> - ); + return ; }; -App.propTypes = { - noDebug: PropTypes.bool, -}; +App.propTypes = {}; export default App; diff --git a/src/components/App.stories.js b/src/components/App.stories.js index dda71a305..fe74ab447 100644 --- a/src/components/App.stories.js +++ b/src/components/App.stories.js @@ -57,8 +57,6 @@ export default { ], }, argTypes: { - form: {table: {disable: true}}, - noDebug: {table: {disable: true}}, submissionAllowed: { options: Object.values(SUBMISSION_ALLOWED), control: {type: 'radio'}, @@ -69,6 +67,9 @@ export default { }, }, parameters: { + config: { + debug: false, + }, msw: { handlers: [ mockLanguageInfoGet([ @@ -85,7 +86,7 @@ const Wrapper = ({form}) => { const routes = [ { path: '*', - element: , + element: , children: nestedRoutes, }, ]; @@ -121,7 +122,7 @@ export const TranslationEnabled = { args: { 'form.translationEnabled': true, }, - play: async ({args, canvasElement}) => { + play: async ({canvasElement}) => { const langSelector = await within(canvasElement).findByText(/^nl$/i); await expect(langSelector).toBeTruthy(); }, @@ -132,7 +133,7 @@ export const TranslationDisabled = { args: { 'form.translationEnabled': false, }, - play: async ({args, canvasElement}) => { + play: async ({canvasElement}) => { const canvas = within(canvasElement); // wait for spinners to disappear diff --git a/src/components/AppDisplay.js b/src/components/AppDisplay.js index 1392df7b6..1bbabfbca 100644 --- a/src/components/AppDisplay.js +++ b/src/components/AppDisplay.js @@ -1,18 +1,48 @@ +import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -const AppDisplay = ({router, languageSwitcher = null, appDebug = null}) => ( -
+/** + * Main application display component - this is the layout wrapper around content. + * + * The Display component uses 'slots' for certain content blocks. The slot 'children' + * is reserved for the main content. + * + */ +export const AppDisplay = ({ + children = null, + languageSwitcher = null, + progressIndicator = null, + appDebug = null, + router, +}) => ( +
{languageSwitcher &&
{languageSwitcher}
} -
{router}
+
{children || router}
+ {progressIndicator && ( +
{progressIndicator}
+ )} {appDebug &&
{appDebug}
}
); AppDisplay.propTypes = { - router: PropTypes.node.isRequired, + children: PropTypes.node.isRequired, languageSwitcher: PropTypes.node, + progressIndicator: PropTypes.node, appDebug: PropTypes.node, + /** + * Main content. + * + * @deprecated Use children instead. + * + */ + router: PropTypes.node, }; export default AppDisplay; diff --git a/src/components/Form.js b/src/components/Form.js index 73f9221b8..995d18a92 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -7,7 +7,6 @@ import {useImmerReducer} from 'use-immer'; import {ConfigContext} from 'Context'; import {destroy} from 'api'; import ErrorBoundary from 'components/Errors/ErrorBoundary'; -import FormDisplay from 'components/FormDisplay'; import FormStart from 'components/FormStart'; import FormStep from 'components/FormStep'; import Loader from 'components/Loader'; @@ -27,6 +26,7 @@ import useQuery from 'hooks/useQuery'; import useRecycleSubmission from 'hooks/useRecycleSubmission'; import useSessionTimeout from 'hooks/useSessionTimeout'; +import FormDisplay from './FormDisplay'; import {addFixedSteps, getStepsInfo} from './ProgressIndicator/utils'; import {PI_TITLE, STEP_LABELS, SUBMISSION_ALLOWED} from './constants'; @@ -328,15 +328,18 @@ const Form = () => { isCompleted ); - const progressIndicator = form.showProgressIndicator ? ( - - ) : null; + // Show the progress indicator if enabled on the form AND we're not in the payment + // status/overview screen. + const progressIndicator = + form.showProgressIndicator && !paymentOverviewMatch ? ( + + ) : null; // Route the correct page based on URL const router = ( @@ -431,12 +434,7 @@ const Form = () => { // render the form step if there's an active submission (and no summary) const FormDisplayComponent = config?.displayComponents?.form ?? FormDisplay; return ( - + {router} ); }; diff --git a/src/components/FormDisplay.js b/src/components/FormDisplay.js index dfeb5640b..350cfdbff 100644 --- a/src/components/FormDisplay.js +++ b/src/components/FormDisplay.js @@ -1,37 +1,52 @@ -import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, {useContext} from 'react'; + +import {ConfigContext} from 'Context'; +import AppDebug from 'components/AppDebug'; +import AppDisplay from 'components/AppDisplay'; +import LanguageSwitcher from 'components/LanguageSwitcher'; +import useFormContext from 'hooks/useFormContext'; /** * Layout component to render the form container. + * + * Takes in the main body and (optional) progress indicator and forwards them to the + * AppDisplay component, while adding in any global/skeleton nodes. + * * @return {JSX} */ -const FormDisplay = ({ - router, - progressIndicator = null, - showProgressIndicator = true, - isPaymentOverview = false, -}) => { - const renderProgressIndicator = progressIndicator && showProgressIndicator && !isPaymentOverview; +const FormDisplay = ({children = null, progressIndicator = null, router = null}) => { + const {translationEnabled} = useFormContext(); + const config = useContext(ConfigContext); + + const appDebug = config.debug ? : null; + const languageSwitcher = translationEnabled ? : null; + + const AppDisplayComponent = config?.displayComponents?.app ?? AppDisplay; return ( -
-
{router}
- {renderProgressIndicator && ( -
{progressIndicator}
- )} -
+ {children || router} + ); }; FormDisplay.propTypes = { - router: PropTypes.node.isRequired, + /** + * Main content. + */ + children: PropTypes.node, progressIndicator: PropTypes.node, - showProgressIndicator: PropTypes.bool, - isPaymentOverview: PropTypes.bool, + /** + * Main content. + * + * @deprecated Use children instead. + * + */ + router: PropTypes.node, }; export default FormDisplay; diff --git a/src/components/FormDisplay.stories.js b/src/components/FormDisplay.stories.js index 2a5d5d99e..31ca228c3 100644 --- a/src/components/FormDisplay.stories.js +++ b/src/components/FormDisplay.stories.js @@ -1,44 +1,46 @@ import Body from 'components/Body'; import Card from 'components/Card'; -import {LayoutDecorator} from 'story-utils/decorators'; +import {ConfigDecorator, LayoutDecorator} from 'story-utils/decorators'; import FormDisplay from './FormDisplay'; export default { title: 'Composites / Form display', component: FormDisplay, - decorators: [LayoutDecorator], + decorators: [LayoutDecorator, ConfigDecorator], render: args => ( - Body for relevant route(s) - - } progressIndicator={ - - Progress indicator - + args.showProgressIndicator ? ( + + Progress indicator + + ) : null } {...args} - /> + > + + Body for relevant route(s) + + ), argTypes: { router: {table: {disable: true}}, progressIndicator: {table: {disable: true}}, }, + parameters: { + config: {debug: false}, + }, }; export const Default = { args: { showProgressIndicator: true, - isPaymentOverview: false, }, }; export const WithoutProgressIndicator = { args: { showProgressIndicator: false, - isPaymentOverview: false, }, }; diff --git a/src/components/FormStep/FormStep.stories.js b/src/components/FormStep/FormStep.stories.js index d17be2372..4a98f3174 100644 --- a/src/components/FormStep/FormStep.stories.js +++ b/src/components/FormStep/FormStep.stories.js @@ -23,6 +23,9 @@ export default { routerArgs: {table: {disable: true}}, }, parameters: { + config: { + debug: false, + }, reactRouter: { routePath: '/stap/:step', routeParams: {step: 'step-1'}, @@ -40,7 +43,6 @@ const render = ({ onStepSubmitted, onLogout, onSessionDestroyed, - showDebug, // story args formioConfiguration, }) => { @@ -66,7 +68,6 @@ const render = ({ onStepSubmitted={onStepSubmitted} onLogout={onLogout} onSessionDestroyed={onSessionDestroyed} - showDebug={showDebug} /> ); }; @@ -96,7 +97,6 @@ export const Default = { }, form: buildForm(), submission: buildSubmission(), - showDebug: false, }, }; @@ -126,6 +126,5 @@ export const SuspensionDisallowed = { }, form: buildForm({suspensionAllowed: false}), submission: buildSubmission(), - showDebug: false, }, }; diff --git a/src/components/FormStep/index.js b/src/components/FormStep/index.js index 95d84178d..07c0c17cb 100644 --- a/src/components/FormStep/index.js +++ b/src/components/FormStep/index.js @@ -49,7 +49,6 @@ import {ValidationError} from 'errors'; import {PREFIX} from 'formio/constants'; import useTitle from 'hooks/useTitle'; import Types from 'types'; -import {DEBUG} from 'utils'; import hooks from '../../formio/hooks'; @@ -300,7 +299,6 @@ const FormStep = ({ onStepSubmitted, onLogout, onSessionDestroyed, - showDebug = DEBUG, }) => { const intl = useIntl(); const config = useContext(ConfigContext); @@ -867,7 +865,7 @@ const FormStep = ({ }, }} /> - {showDebug ? : null} + {config.debug ? : null} { + const {languageSelectorTarget: target} = useContext(I18NContext); + return target ? ReactDOM.createPortal(, target) : ; +}; + +export default LanguageSwitcher; diff --git a/src/components/appointments/CreateAppointment/CreateAppointment.js b/src/components/appointments/CreateAppointment/CreateAppointment.js index f98b29933..093f63aa3 100644 --- a/src/components/appointments/CreateAppointment/CreateAppointment.js +++ b/src/components/appointments/CreateAppointment/CreateAppointment.js @@ -52,6 +52,10 @@ const CreateAppointment = () => { resetSession(); }; + const progressIndicator = form.showProgressIndicator ? ( + + ) : null; + return ( { submission={submission} resetSession={reset} > - - - {isLoading ? ( - - ) : ( - - - - - - )} - - - } - progressIndicator={} - showProgressIndicator={form.showProgressIndicator} - isPaymentOverview={false} - /> + + + + {isLoading ? ( + + ) : ( + + + + + + )} + + + ); diff --git a/src/scss/components/_app.scss b/src/scss/components/_app.scss index 8b95eb238..863af75db 100644 --- a/src/scss/components/_app.scss +++ b/src/scss/components/_app.scss @@ -10,23 +10,69 @@ * The default values are added for backwards compatibility. */ .openforms-app { - display: flex; - flex-direction: column; - gap: var(--of-form-gap, 0); + display: grid; + grid-column-gap: var(--of-app-grid-column-gap, 20px); + grid-template-columns: 2fr 1fr; + grid-template-areas: + 'lang-switcher lang-switcher' + 'body progress-indicator' + 'debug debug'; position: relative; - @include mobile-only { - padding-block-end: var(--of-form-mobile-padding-block-end, 15px); - padding-block-start: var(--of-form-mobile-padding-block-start, 0); - padding-inline-end: var(--of-form-mobile-padding-inline-end, 15px); - padding-inline-start: var(--of-form-mobile-padding-inline-start, 15px); + // When there's no progress indicator, stretch the main content + // over both containers. + @include bem.modifier('no-progress-indicator') { + @include bem.element('body') { + grid-row-start: body; + grid-row-end: progress-indicator; + grid-column-start: body; + grid-column-end: progress-indicator; + } } @include bem.element('language-switcher') { + grid-area: lang-switcher; display: flex; } + @include bem.element('body') { + grid-area: body; + } + + @include bem.element('progress-indicator') { + grid-area: progress-indicator; + } + @include bem.element('debug') { + grid-area: debug; margin-block-start: 2em; } + + // Responsive styles - switch to a column layout and re-order elements. + @include mobile-only { + grid-template-columns: 1fr; + grid-template-areas: + 'progress-indicator' + 'lang-switcher' + 'body' + 'debug'; + grid-row-gap: var(--of-app-mobile-grid-row-gap, 0); + + padding-block-end: var(--of-app-mobile-padding-block-end, 15px); + padding-block-start: var(--of-app-mobile-padding-block-start, 0); + padding-inline-end: var(--of-app-mobile-padding-inline-end, 15px); + padding-inline-start: var(--of-app-mobile-padding-inline-start, 15px); + + @include bem.element('progress-indicator') { + margin-inline-end: var(--of-app-progress-indicator-mobile-margin-inline-end, -15px); + margin-inline-start: var(--of-app-progress-indicator-mobile-margin-inline-start, -15px); + + // on mobile, the order of elements is swapped and to keep the progress indicator + // in view, we need to apply the positioning to this element rather than + // .openforms-progress-indicator + position: sticky; + inset-block-start: var(--of-app-mobile-progress-indicator-inset-block-start, 0px); + z-index: 1; + } + } } diff --git a/src/scss/components/_form.scss b/src/scss/components/_form.scss deleted file mode 100644 index 4a9eb9e88..000000000 --- a/src/scss/components/_form.scss +++ /dev/null @@ -1,46 +0,0 @@ -@use 'microscope-sass/lib/bem'; - -// @import instead of @use because breakpoints are defined globally -@import 'microscope-sass/lib/responsive'; - -/** - * Custom component to manage our form layout, arranging body and progress indicator. - * - * The default values are added for backwards compatibility. - */ -.openforms-form { - display: grid; - grid-template-columns: 2fr 1fr; - grid-template-areas: 'body progress-indicator'; - grid-column-gap: var(--of-form-grid-column-gap, 20px); - position: relative; - - @include bem.modifier('body-only') { - grid-template-columns: 1fr; - grid-template-areas: 'body'; - } - - @include bem.element('body') { - grid-area: body; - } - - @include bem.element('progress-indicator') { - grid-area: progress-indicator; - } - - @include mobile-only { - grid-row-gap: var(--of-form-grid-mobile-row-gap, 15px); - grid-template-columns: 1fr; - grid-template-rows: auto; - grid-template-areas: - 'progress-indicator' - 'body'; - - @include bem.element('progress-indicator') { - position: sticky; - top: 0; - margin-inline-end: var(--of-form-progress-indicator-mobile-margin-inline-end, -15px); - margin-inline-start: var(--of-form-progress-indicator-mobile-margin-inline-start, -15px); - } - } -} diff --git a/src/styles.scss b/src/styles.scss index 2eb60e937..d8dbcbf2b 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -31,7 +31,6 @@ @import './scss/components/checkbox'; @import './scss/components/content'; @import './scss/components/errors'; -@import './scss/components/form'; @import './scss/components/formio-component'; @import './scss/components/help-text'; @import './scss/components/image'; From c27cd6010eca89273fcf21a9902823155080b9ec Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Fri, 24 Nov 2023 14:32:37 +0100 Subject: [PATCH 03/21] :wheelchair: [#36] Use (hidden) caption as description for nav element Co-authored-by: @vaszig --- src/components/Caption.js | 8 ++++++-- src/components/ProgressIndicator/index.js | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/Caption.js b/src/components/Caption.js index d71fbc406..f7decbf47 100644 --- a/src/components/Caption.js +++ b/src/components/Caption.js @@ -3,9 +3,13 @@ import React from 'react'; import {getBEMClassName} from 'utils'; -const Caption = ({children, component = 'caption'}) => { +const Caption = ({children, component = 'caption', ...props}) => { const Component = `${component}`; - return {children}; + return ( + + {children} + + ); }; Caption.propTypes = { diff --git a/src/components/ProgressIndicator/index.js b/src/components/ProgressIndicator/index.js index 773f2dc6b..4aa3e9207 100644 --- a/src/components/ProgressIndicator/index.js +++ b/src/components/ProgressIndicator/index.js @@ -36,7 +36,7 @@ const ProgressIndicator = ({ return ( -