diff --git a/packages/grafana-toolkit/src/cli/templates/component.tsx.template.ts b/packages/grafana-toolkit/src/cli/templates/component.tsx.template.ts index 9cf159aefc1..7345eb529d5 100644 --- a/packages/grafana-toolkit/src/cli/templates/component.tsx.template.ts +++ b/packages/grafana-toolkit/src/cli/templates/component.tsx.template.ts @@ -1,6 +1,6 @@ export const componentTpl = `import React, { FC } from 'react'; -interface Props {}; +export interface Props {}; export const <%= name %>: FC = (props) => { return ( diff --git a/packages/grafana-ui/src/components/Forms/FieldSet.mdx b/packages/grafana-ui/src/components/Forms/FieldSet.mdx new file mode 100644 index 00000000000..a89f52a86d4 --- /dev/null +++ b/packages/grafana-ui/src/components/Forms/FieldSet.mdx @@ -0,0 +1,42 @@ +import { Story, Preview, Props } from '@storybook/addon-docs/blocks'; +import { FieldSet } from './FieldSet'; + +# FieldSet + +Component used to group form elements inside a form, equivalent to HTML's [fieldset](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset) tag. +Accepts optional label, which, if provided, is used as a text for the set's legend. + + +### Usage + +```jsx +import { FieldSet } from '@grafana/ui'; + +
console.log('Submit')}> + {() => ( + <> +
+ + + + + + +
+ +
+ + + + + + +
+ + + )} +
+``` + +### Props + diff --git a/packages/grafana-ui/src/components/Forms/FieldSet.story.tsx b/packages/grafana-ui/src/components/Forms/FieldSet.story.tsx new file mode 100644 index 00000000000..a269af80169 --- /dev/null +++ b/packages/grafana-ui/src/components/Forms/FieldSet.story.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; +import { FieldSet } from './FieldSet'; +import { Form } from './Form'; +import { Field } from './Field'; +import { Input } from '../Input/Input'; +import mdx from './FieldSet.mdx'; +import { Button } from '../Button'; + +export default { + title: 'Forms/FieldSet', + component: FieldSet, + decorators: [withCenteredStory], + parameters: { + docs: { + page: mdx, + }, + }, +}; + +export const basic = () => { + return ( +
console.log('Submit')}> + {() => ( + <> +
+ + + + + + +
+ +
+ + + + + + +
+ + + )} +
+ ); +}; diff --git a/packages/grafana-ui/src/components/Forms/FieldSet.tsx b/packages/grafana-ui/src/components/Forms/FieldSet.tsx new file mode 100644 index 00000000000..b71b4166055 --- /dev/null +++ b/packages/grafana-ui/src/components/Forms/FieldSet.tsx @@ -0,0 +1,31 @@ +import React, { FC, HTMLProps } from 'react'; +import { css, cx } from 'emotion'; +import { GrafanaTheme } from '@grafana/data'; +import { stylesFactory, useTheme } from '../../themes'; +import { Legend } from './Legend'; + +export interface Props extends HTMLProps { + children: React.ReactNode[] | React.ReactNode; + /** Text for the fieldset's legend */ + label?: string; +} + +export const FieldSet: FC = ({ label, children, className, ...rest }) => { + const theme = useTheme(); + const styles = getStyles(theme); + + return ( +
+ {label && {label}} + {children} +
+ ); +}; + +const getStyles = stylesFactory((theme: GrafanaTheme) => { + return { + wrapper: css` + margin-bottom: ${theme.spacing.formSpacingBase * 4}px; + `, + }; +}); diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index b7faf9bc9b2..da4aa2ea0e5 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -134,6 +134,7 @@ export { getFormStyles } from './Forms/getFormStyles'; export { Label } from './Forms/Label'; export { Field } from './Forms/Field'; export { Legend } from './Forms/Legend'; +export { FieldSet } from './Forms/FieldSet'; export { default as resetSelectStyles } from './Select/resetSelectStyles'; export * from './Select/Select';