1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2024-11-14 17:35:35 +01:00

Merge branch 'add-threedotsmenu-component' into 'dev'

Add ThreeDotsMenu component

See merge request turris/reforis/foris-js!246
This commit is contained in:
Aleksandr Gumroian 2024-09-27 15:17:55 +02:00
commit 1fb83e08ea
8 changed files with 139 additions and 45 deletions

View File

@ -33,5 +33,4 @@ To install a specific version:
npm install foris@version npm install foris@version
``` ```
<a target="_blank" href="https://www.npmjs.com/package/foris">Check [![npm version](https://badge.fury.io/js/foris.svg)](https://badge.fury.io/js/foris)
on<img width="100px" src="./docs/forisjs-npm.svg"></a>

View File

@ -6,6 +6,7 @@ All additional `props` are passed to the `<input type="email">` HTML component.
```js ```js
import { useState } from "react"; import { useState } from "react";
import Button from "./Button";
const [email, setEmail] = useState("Wrong email"); const [email, setEmail] = useState("Wrong email");
<form onSubmit={(e) => e.preventDefault()}> <form onSubmit={(e) => e.preventDefault()}>
<EmailInput <EmailInput
@ -14,6 +15,6 @@ const [email, setEmail] = useState("Wrong email");
helpText="Read the small text!" helpText="Read the small text!"
onChange={(event) => setEmail(event.target.value)} onChange={(event) => setEmail(event.target.value)}
/> />
<button type="submit">Try to submit</button> <Button type="submit">Try to submit</Button>
</form>; </form>;
``` ```

48
src/bootstrap/Radio.js Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import React from "react";
import PropTypes from "prop-types";
Radio.propTypes = {
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
PropTypes.node,
PropTypes.arrayOf(PropTypes.node),
]).isRequired,
id: PropTypes.string.isRequired,
inline: PropTypes.bool,
helpText: PropTypes.string,
className: PropTypes.string,
};
function Radio({ label, id, helpText, inline, className, ...props }) {
return (
<div
className={`${className || "mb-3"} ${inline ? "form-check form-check-inline" : ""}`.trim()}
>
<input
id={id}
className="form-check-input me-2"
type="radio"
{...props}
/>
<label className="form-check-label" htmlFor={id}>
{label}
{helpText && (
<div className="form-text">
<small>{helpText}</small>
</div>
)}
</label>
</div>
);
}
export default Radio;

View File

@ -10,6 +10,8 @@ import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useUID } from "react-uid"; import { useUID } from "react-uid";
import Radio from "./Radio";
RadioSet.propTypes = { RadioSet.propTypes = {
/** Name attribute of the input HTML tag. */ /** Name attribute of the input HTML tag. */
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
@ -73,40 +75,4 @@ function RadioSet({ name, label, choices, value, helpText, inline, ...props }) {
); );
} }
Radio.propTypes = {
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
PropTypes.node,
PropTypes.arrayOf(PropTypes.node),
]).isRequired,
id: PropTypes.string.isRequired,
inline: PropTypes.bool,
helpText: PropTypes.string,
className: PropTypes.string,
};
export function Radio({ label, id, helpText, inline, className, ...props }) {
return (
<div
className={`${className || "mb-3"} ${inline ? "form-check form-check-inline" : ""}`.trim()}
>
<input
id={id}
className="form-check-input me-2"
type="radio"
{...props}
/>
<label className="form-check-label" htmlFor={id}>
{label}
{helpText && (
<div className="form-text">
<small>{helpText}</small>
</div>
)}
</label>
</div>
);
}
export default RadioSet; export default RadioSet;

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import React from "react";
import { faEllipsisVertical } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import PropTypes from "prop-types";
import Button from "./Button";
ThreeDotsMenu.propTypes = {
/** Menu items. */
children: PropTypes.arrayOf(PropTypes.node).isRequired,
};
function ThreeDotsMenu({ children }) {
return (
<div className="dropdown">
<Button
className="btn-sm btn-link text-body"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<FontAwesomeIcon icon={faEllipsisVertical} />
</Button>
<ul className="dropdown-menu">
{children.map((child) => (
<li key={child.key || child.props.id || Math.random()}>
{child}
</li>
))}
</ul>
</div>
);
}
export default ThreeDotsMenu;

View File

@ -0,0 +1,40 @@
ThreeDotsMenu Bootstrap component is a dropdown menu that appears when the user
clicks on three dots. It is used to display a list of actions that can be
performed on a particular item.
```js
import { useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEdit, faTrash } from "@fortawesome/free-solid-svg-icons";
const threeDotsMenuItems = [
{
text: "Edit",
icon: faEdit,
onClick: () => {
alert("Edit clicked");
},
},
{
text: "Delete",
icon: faTrash,
onClick: () => {
alert("Delete clicked");
},
},
];
<ThreeDotsMenu>
{threeDotsMenuItems.map((item, index) => (
<button key={index} onClick={item.onClick} className="dropdown-item">
<FontAwesomeIcon
icon={item.icon}
className="me-1"
width="1rem"
size="sm"
/>
{item.text}
</button>
))}
</ThreeDotsMenu>;
```

View File

@ -28,7 +28,8 @@ export { default as FileInput } from "./bootstrap/FileInput";
export { default as Input } from "./bootstrap/Input"; export { default as Input } from "./bootstrap/Input";
export { default as NumberInput } from "./bootstrap/NumberInput"; export { default as NumberInput } from "./bootstrap/NumberInput";
export { default as PasswordInput } from "./bootstrap/PasswordInput"; export { default as PasswordInput } from "./bootstrap/PasswordInput";
export { default as RadioSet, Radio } from "./bootstrap/RadioSet"; export { default as Radio } from "./bootstrap/Radio";
export { default as RadioSet } from "./bootstrap/RadioSet";
export { default as Select } from "./bootstrap/Select"; export { default as Select } from "./bootstrap/Select";
export { default as TextInput } from "./bootstrap/TextInput"; export { default as TextInput } from "./bootstrap/TextInput";
export { formFieldsSize, buttonFormFieldsSize } from "./bootstrap/constants"; export { formFieldsSize, buttonFormFieldsSize } from "./bootstrap/constants";

View File

@ -65,7 +65,7 @@ module.exports = {
components: "src/bootstrap/*.js", components: "src/bootstrap/*.js",
exampleMode: "expand", exampleMode: "expand",
usageMode: "expand", usageMode: "expand",
ignore: ["src/bootstrap/constants.js"], ignore: ["src/bootstrap/constants.js", "src/bootstrap/Radio.js"],
sectionDepth: 0, sectionDepth: 0,
}, },
], ],
@ -79,10 +79,7 @@ module.exports = {
__dirname, __dirname,
"node_modules/bootstrap/dist/css/bootstrap.min.css" "node_modules/bootstrap/dist/css/bootstrap.min.css"
), ),
path.join( path.join(__dirname, "node_modules/bootstrap/dist/js/bootstrap.min.js"),
__dirname,
"node_modules/@fortawesome/fontawesome-free/css/all.min.css"
),
], ],
styleguideComponents: { styleguideComponents: {
LogoRenderer: path.join(__dirname, "docs/components/Logo"), LogoRenderer: path.join(__dirname, "docs/components/Logo"),