xref: /aosp_15_r20/external/perfetto/ui/src/widgets/form.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2023 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import m from 'mithril';
16import {Button} from './button';
17import {HTMLAttrs, HTMLLabelAttrs} from './common';
18import {Popup} from './popup';
19import {Intent} from '../widgets/common';
20
21export interface FormAttrs extends HTMLAttrs {
22  // Text to show on the "submit" button.
23  // Defaults to "Submit".
24  submitLabel?: string;
25
26  // Icon to show on the "submit" button.
27  submitIcon?: string;
28
29  // Text to show on the "cancel" button.
30  // No button is rendered if this value is omitted.
31  cancelLabel?: string;
32
33  // Text to show on the "reset" button.
34  // No button is rendered if this value is omitted.
35  resetLabel?: string;
36
37  // Action to take when the form is submitted either by the enter key or
38  // the submit button.
39  onSubmit?: () => void;
40
41  // Action to take when the form is cancelled.
42  onCancel?: () => void;
43
44  // Prevent default form action on submit. Defaults to true.
45  preventDefault?: boolean;
46}
47
48// A simple wrapper around a <form> element providing some opinionated default
49// buttons and form behavior. Designed to be used with FormLabel elements.
50// Can be used in popups and popup menus and pressing either of the cancel or
51// submit buttons dismisses the popup.
52// See Widgets page for examples.
53export class Form implements m.ClassComponent<FormAttrs> {
54  view({attrs, children}: m.CVnode<FormAttrs>) {
55    const {
56      submitIcon = undefined,
57      submitLabel = 'Submit',
58      cancelLabel,
59      resetLabel,
60      onSubmit = () => {},
61      preventDefault = true,
62      ...htmlAttrs
63    } = attrs;
64
65    return m(
66      'form.pf-form',
67      htmlAttrs,
68      children,
69      m(
70        '.pf-form-button-bar',
71        m(Button, {
72          type: 'submit',
73          label: submitLabel,
74          rightIcon: submitIcon,
75          className: Popup.DISMISS_POPUP_GROUP_CLASS,
76          intent: Intent.Primary,
77          onclick: (e: Event) => {
78            preventDefault && e.preventDefault();
79            onSubmit();
80          },
81        }),
82        // This cancel button just closes the popup if we are inside one.
83        cancelLabel &&
84          m(Button, {
85            type: 'button',
86            label: cancelLabel,
87            className: Popup.DISMISS_POPUP_GROUP_CLASS,
88          }),
89        // This reset button just clears the form.
90        resetLabel &&
91          m(Button, {
92            label: resetLabel,
93            type: 'reset',
94          }),
95      ),
96    );
97  }
98}
99
100// A simple wrapper around a <label> element. Designed to be used within Form
101// widgets in combination with input controls to provide consistent label
102// styling.
103//
104// Like normal labels, FormLabels provide a name for an input while also
105// improving their hit area which improves a11y.
106//
107// Labels are bound to inputs by placing the input inside the FormLabel widget,
108// or by referencing the input's "id" tag with a "for" tag.
109export class FormLabel implements m.ClassComponent<HTMLLabelAttrs> {
110  view({attrs, children}: m.CVnode<HTMLLabelAttrs>) {
111    return m('label.pf-form-label', attrs, children);
112  }
113}
114