Skip to content

Commit

Permalink
[web] Add a simple Fieldset component
Browse files Browse the repository at this point in the history
Since PF4/FormFieldGroup[1] looks a bit complex for our use cases right now, we
have wrapped the native HTML fieldset/legend elements in a simple Fieldset
component which also tweaks a little bit their default look&feel.

[1] https://www.patternfly.org/v4/components/form/#formfieldgroup)
  • Loading branch information
dgdavid committed Nov 25, 2022
1 parent 49e6a2a commit a33485d
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
76 changes: 76 additions & 0 deletions web/src/components/core/Fieldset.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) [2022] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { classNames } from "@/utils";

import "./fieldset.scss";

/**
*
* Convenient component for grouping form fields in "sections"
* by using the native formfield element
* @component
*
* @example <caption>Simple usage</caption>
* <Fieldset legend="Encryption options">
* <EncryptionType />
* <EncryptionPassword />
* </Fieldset>
*
* @example <caption>Using a complex legend and isDisabled prop</caption>
* <Fieldset
* legend={
* <Switch label="Use Encryption" isChecked={isChecked} onChange={handleChange} isReversed />
* }
* isDisabled={!encryptionAllowed}
* >
* <EncryptionType />
* <EncryptionPassword />
* </Fieldset>
*
* @param {object} props
* @param {React.ReactNode} props.legend - The lengend
* @param {boolean} [props.isDisabled=false] - whether the descendant form controls, except any inside legend, are disable
* @param {string} [props.className] - additionally CSS class names
* @param {JSX.Element} [props.children] - the section content
* @param {object} [props.otherProps] fieldset element attributes, see {@link https://html.spec.whatwg.org/#the-fieldset-element}
*/
export default function Fieldset({
legend,
isDisabled,
className,
children,
...otherProps
}) {
return (
<fieldset
className={classNames("d-installer-fieldset", className)}
disabled={isDisabled}
{...otherProps}
>
{legend && <legend>{legend}</legend>}
{children}
</fieldset>
);
}
75 changes: 75 additions & 0 deletions web/src/components/core/Fieldset.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) [2022] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

import React from "react";
import { screen, within } from "@testing-library/react";
import { installerRender } from "@/test-utils";
import { Fieldset } from "@components/core";

const ComplexLegend = () => {
return (
<>
<label htmlFor="active-fieldset">Using a checkbox in the legend</label>
<input type="checkbox" id="active-fieldset" />
</>
);
};

describe("Fieldset", () => {
it("renders a group element", () => {
installerRender(<Fieldset />);
const fieldset = screen.getByRole("group");
expect(fieldset).toBeInTheDocument();
});

it("renders the given legend", () => {
installerRender(<Fieldset legend="Simple legend" />);
screen.getByRole("group", { name: /Simple legend/i });
});

it("allows using a complex legend", () => {
installerRender(<Fieldset legend={<ComplexLegend />} />);
const fieldset = screen.getByRole("group", { name: /Using a checkbox.*/i });
const checkbox = within(fieldset).getByRole("checkbox");
expect(checkbox).toBeInTheDocument();
});

it("sets children (except legend) as disabled when isDisabled prop is given", () => {
installerRender(
<Fieldset legend={<ComplexLegend />} isDisabled>
<label htmlFor="username">Username</label>
<input type="text" id="username" />
<label htmlFor="superuser">Superuser</label>
<input type="checkbox" id="superuser" />
</Fieldset>
);

const fieldset = screen.getByRole("group", { name: /Using a checkbox/i });
const legendCheckbox = within(fieldset).getByRole("checkbox", { name: "Using a checkbox in the legend" });
const inputText = within(fieldset).getByRole("textbox", { name: "Username" });
const checkbox = within(fieldset).getByRole("checkbox", { name: "Superuser" });

expect(fieldset).toHaveAttribute("disabled");
expect(legendCheckbox).not.toBeDisabled();
expect(inputText).toBeDisabled();
expect(checkbox).toBeDisabled();
});
});
14 changes: 14 additions & 0 deletions web/src/components/core/fieldset.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@use "@assets/fonts.scss";
@use "eos-ds/dist/scss/eos-base/variables/branding.scss";

fieldset.d-installer-fieldset {
padding: fonts.$size-base;
border: 0;
border-top: 1px solid branding.$eos-bc-gray-50;
border-image: linear-gradient(45deg, branding.$eos-bc-gray-50, transparent) 1;

legend {
padding-inline-end: fonts.$size-base;
margin-inline-start: -(fonts.$size-base);
}
}
1 change: 1 addition & 0 deletions web/src/components/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
export { default as About } from "./About";
export { default as Category } from "./Category";
export { default as FormLabel } from "./FormLabel";
export { default as Fieldset } from "./Fieldset";
export { default as InstallationFinished } from "./InstallationFinished";
export { default as InstallationProgress } from "./InstallationProgress";
export { default as InstallButton } from "./InstallButton";
Expand Down

0 comments on commit a33485d

Please sign in to comment.