diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.tsx b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.tsx index 7c32be103eb319ba55321ec1a10c9432d01f3c63..3f935dacc1abe4d49b8e59174279b172d8ed393d 100644 --- a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.tsx +++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.tsx @@ -95,7 +95,6 @@ const FontFileRow = ({ <TableBodyCell> <Input defaultValue={url} - size="small" placeholder="https://some.trusted.location/font-file.woff2" fullWidth onBlur={handleBlur} diff --git a/frontend/src/metabase/admin/datamodel/components/FieldRemapping.jsx b/frontend/src/metabase/admin/datamodel/components/FieldRemapping.jsx index 9b1ecddee5bd3f13a020292502689e2e835f2fbd..363a60260001ea1e0635674f3e567a4c33294ddf 100644 --- a/frontend/src/metabase/admin/datamodel/components/FieldRemapping.jsx +++ b/frontend/src/metabase/admin/datamodel/components/FieldRemapping.jsx @@ -6,7 +6,6 @@ import _ from "underscore"; import Select from "metabase/core/components/Select"; import PopoverWithTrigger from "metabase/components/PopoverWithTrigger"; -import InputBlurChange from "metabase/components/InputBlurChange"; import ButtonWithStatus from "metabase/components/ButtonWithStatus"; import * as MetabaseAnalytics from "metabase/lib/analytics"; @@ -22,6 +21,7 @@ import { FieldMappingRoot, FieldSelectButton, ForeignKeyList, + FieldValueMappingInput, } from "./FieldRemapping.styled"; const MAP_OPTIONS = { @@ -442,8 +442,8 @@ export class FieldValueMapping extends React.Component { return ( <div className="flex align-center"> <h3>{original}</h3> - <InputBlurChange - className="AdminInput input ml-auto" + <FieldValueMappingInput + className="ml-auto" value={mapped} onChange={this.onInputChange} placeholder={t`Enter value`} diff --git a/frontend/src/metabase/admin/datamodel/components/FieldRemapping.styled.tsx b/frontend/src/metabase/admin/datamodel/components/FieldRemapping.styled.tsx index 71853163aeb00dceff7d13de0071b4e0e109d937..2b4f5dacbe86797083558c725fbc2fbfee0490b7 100644 --- a/frontend/src/metabase/admin/datamodel/components/FieldRemapping.styled.tsx +++ b/frontend/src/metabase/admin/datamodel/components/FieldRemapping.styled.tsx @@ -2,6 +2,7 @@ import styled from "@emotion/styled"; import { alpha, color } from "metabase/lib/colors"; import SelectButton from "metabase/core/components/SelectButton"; import FieldList from "metabase/query_builder/components/FieldList"; +import InputBlurChange from "metabase/components/InputBlurChange"; export const FieldMappingRoot = styled.div` padding: 1rem 4rem; @@ -26,3 +27,7 @@ export const FieldSelectButton = styled(SelectButton)<FieldSelectButtonProps>` export const ForeignKeyList = styled(FieldList)` color: ${color("filter")}; `; + +export const FieldValueMappingInput = styled(InputBlurChange)` + width: auto; +`; diff --git a/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.jsx b/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.jsx index 579f30f38b8b13338a5751cf5a7068b89a1af74f..0c0dedb3f048865cb47b62828a01eb0f58a61fba 100644 --- a/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.jsx +++ b/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.jsx @@ -59,7 +59,7 @@ class Column extends Component { <ColumnItemInput variant="primary" style={{ minWidth: 420 }} - className="AdminInput TableEditor-field-name float-left inline-block rounded text-bold" + className="float-left inline-block" type="text" value={this.props.field.display_name || ""} onBlurChange={this.handleChangeName} @@ -93,11 +93,12 @@ class Column extends Component { <div className="MetadataTable-title flex flex-column flex-full mt1 mr1"> <ColumnItemInput variant="secondary" - className="AdminInput TableEditor-field-description rounded" + className="TableEditor-field-description rounded" type="text" value={this.props.field.description || ""} onBlurChange={this.handleChangeDescription} placeholder={t`No column description yet`} + fullWidth /> </div> </div> diff --git a/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.styled.tsx b/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.styled.tsx index b7a3d1af2010804439cef2976f5ca0160a1bfc81..1583d8650d91959bc311226b320d2d2a73ffa744 100644 --- a/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.styled.tsx +++ b/frontend/src/metabase/admin/datamodel/components/database/ColumnItem/ColumnItem.styled.tsx @@ -1,14 +1,10 @@ import styled from "@emotion/styled"; import InputBlurChange from "metabase/components/InputBlurChange"; -import { color } from "metabase/lib/colors"; interface ColumnItemInputProps { variant: "primary" | "secondary"; } export const ColumnItemInput = styled(InputBlurChange)<ColumnItemInputProps>` - border-color: ${color("border")}; - - background-color: ${props => - color(props.variant === "primary" ? "white" : "bg-light")}; + width: auto; `; diff --git a/frontend/src/metabase/admin/datamodel/components/database/MetadataTable/MetadataTable.styled.tsx b/frontend/src/metabase/admin/datamodel/components/database/MetadataTable/MetadataTable.styled.tsx index c1c7e565245d1d92dfa0e20d94392987e285e9f8..633e28a304233d5e72767bbf09ad0a992d78f483 100644 --- a/frontend/src/metabase/admin/datamodel/components/database/MetadataTable/MetadataTable.styled.tsx +++ b/frontend/src/metabase/admin/datamodel/components/database/MetadataTable/MetadataTable.styled.tsx @@ -3,6 +3,7 @@ import { css } from "@emotion/react"; import { color } from "metabase/lib/colors"; import InputBlurChange from "metabase/components/InputBlurChange"; import { focusOutlineStyle } from "metabase/core/style/input"; +import Input from "metabase/core/components/Input"; interface VisibilityTypeProps { isSelected: boolean; @@ -20,36 +21,26 @@ export const VisibilityType = styled.span<VisibilityTypeProps>` } `; -const headerInputsStyles = css` - background-color: ${color("bg-light")}; - padding: 0.75rem 1.5rem; - z-index: 1; - outline: none; - border-color: ${color("border")}; - - &:hover, - &:focus { - z-index: 2; - } - - ${focusOutlineStyle("brand")}; -`; - export const TableNameInput = styled(InputBlurChange)` - ${headerInputsStyles} - font-weight: 700; - font-size: 20px; - color: ${color("text-dark")}; - border-radius: 8px 8px 0 0; + ${Input.Field} { + font-size: 20px; + color: ${color("text-dark")}; + border-radius: 8px 8px 0 0; + background-color: ${color("bg-light")}; + padding: 0.75rem 1.5rem; + } `; export const TableDescriptionInput = styled(InputBlurChange)` - ${headerInputsStyles} - color: ${color("text-dark")}; - margin-top: -1px; - border-radius: 0 0 8px 8px; - font-weight: 400; - font-size: 14px; + ${Input.Field} { + color: ${color("text-dark")}; + margin-top: -1px; + border-radius: 0 0 8px 8px; + font-weight: 400; + font-size: 14px; + background-color: ${color("bg-light")}; + padding: 0.75rem 1.5rem; + } `; export const TableName = styled.div` diff --git a/frontend/src/metabase/admin/datamodel/containers/FieldApp.jsx b/frontend/src/metabase/admin/datamodel/containers/FieldApp.jsx index 5fed7083fe5db780bca5a2f7a37f64d284577e2f..f10f40bbd832cbe0610f8b2faa91f647f7025b70 100644 --- a/frontend/src/metabase/admin/datamodel/containers/FieldApp.jsx +++ b/frontend/src/metabase/admin/datamodel/containers/FieldApp.jsx @@ -433,17 +433,18 @@ export class FieldHeader extends React.Component { <div> <FieldNameInput name="display_name" - className="h2 AdminInput" + className="h2 " value={this.props.field.display_name} onBlurChange={this.onNameChange} placeholder={this.props.field.name} /> <InputBlurChange name="description" - className="text AdminInput bordered input text-measure block full" + className="text-measure" value={this.props.field.description} onBlurChange={this.onDescriptionChange} placeholder={t`No description for this field yet`} + fullWidth /> </div> ); diff --git a/frontend/src/metabase/admin/datamodel/containers/FieldApp.styled.tsx b/frontend/src/metabase/admin/datamodel/containers/FieldApp.styled.tsx index 0302b28fce52111c4f9aa98a6afade3496fa8f1a..4fab7fef7d9204740037b6a9563d87fda8ee7829 100644 --- a/frontend/src/metabase/admin/datamodel/containers/FieldApp.styled.tsx +++ b/frontend/src/metabase/admin/datamodel/containers/FieldApp.styled.tsx @@ -1,13 +1,11 @@ import styled from "@emotion/styled"; import { Link } from "react-router"; import InputBlurChange from "metabase/components/InputBlurChange"; -import { alpha, color } from "metabase/lib/colors"; +import { color } from "metabase/lib/colors"; export const FieldNameInput = styled(InputBlurChange)` - display: block; + width: auto; margin-bottom: 0.5rem; - border: 1px solid ${alpha("accent2", 0.2)}; - border-radius: 0.5rem; `; export const BackButtonLink = styled(Link)` diff --git a/frontend/src/metabase/admin/people/components/GroupsListing.jsx b/frontend/src/metabase/admin/people/components/GroupsListing.jsx index 78d37214ba21c3554f1898175413e68d5782367b..1a100cbd51587c5992cb5d457326b3e7d9d81ff7 100644 --- a/frontend/src/metabase/admin/people/components/GroupsListing.jsx +++ b/frontend/src/metabase/admin/people/components/GroupsListing.jsx @@ -16,7 +16,7 @@ import { import { KEYCODE_ENTER } from "metabase/lib/keyboard"; import Icon from "metabase/components/Icon"; -import InputBlurChange from "metabase/components/InputBlurChange"; +import Input from "metabase/core/components/Input"; import ModalContent from "metabase/components/ModalContent"; import Alert from "metabase/components/Alert"; import ModalWithTrigger from "metabase/components/ModalWithTrigger"; @@ -113,8 +113,8 @@ function EditingGroupRow({ return ( <tr className="bordered border-brand rounded"> <td> - <InputBlurChange - className="AdminInput h3" + <Input + className="h3" type="text" autoFocus={true} value={group.name} diff --git a/frontend/src/metabase/admin/permissions/components/FilterableTree/FilterableTree.tsx b/frontend/src/metabase/admin/permissions/components/FilterableTree/FilterableTree.tsx index 5cbc0b37ec149122505ca4ad19b80e54c91256ff..5289567e1478bcc7261d1233aa22faeba77e70d3 100644 --- a/frontend/src/metabase/admin/permissions/components/FilterableTree/FilterableTree.tsx +++ b/frontend/src/metabase/admin/permissions/components/FilterableTree/FilterableTree.tsx @@ -57,7 +57,6 @@ export const FilterableTree = ({ fullWidth placeholder={placeholder} value={filter} - size="small" leftIcon="search" colorScheme="filter" onChange={handleFilterChange} diff --git a/frontend/src/metabase/admin/permissions/components/PermissionsEditor/PermissionsEditorContent.jsx b/frontend/src/metabase/admin/permissions/components/PermissionsEditor/PermissionsEditorContent.jsx index 0405491df66a4022414774f5dd7f726f8879764a..21817dc89ef7e5d326be68ea14dc5e085380e0fa 100644 --- a/frontend/src/metabase/admin/permissions/components/PermissionsEditor/PermissionsEditorContent.jsx +++ b/frontend/src/metabase/admin/permissions/components/PermissionsEditor/PermissionsEditorContent.jsx @@ -81,7 +81,6 @@ export function PermissionsEditorContent({ onChange={handleFilterChange} onResetClick={() => setFilter("")} value={filter} - size="small" leftIcon="search" /> </EditorFilterContainer> diff --git a/frontend/src/metabase/admin/settings/components/widgets/SettingCommaDelimitedInput.jsx b/frontend/src/metabase/admin/settings/components/widgets/SettingCommaDelimitedInput.jsx index 39ccf4defd8ef5db9913b600090ebb78b62cf79d..f43829d579b64fc11efe73f6c3ce6d622057cd07 100644 --- a/frontend/src/metabase/admin/settings/components/widgets/SettingCommaDelimitedInput.jsx +++ b/frontend/src/metabase/admin/settings/components/widgets/SettingCommaDelimitedInput.jsx @@ -1,7 +1,6 @@ /* eslint-disable react/prop-types */ import React from "react"; -import cx from "classnames"; -import InputBlurChange from "metabase/components/InputBlurChange"; +import { SettingInputBlurChange } from "./SettingInput.styled"; const maybeSingletonList = value => (value ? [value] : null); @@ -16,11 +15,8 @@ const SettingCommaDelimitedInput = ({ type = "text", }) => { return ( - <InputBlurChange - className={cx("Form-input", { - SettingsInput: true, - "border-error bg-error-input": errorMessage, - })} + <SettingInputBlurChange + error={!!errorMessage} id={id} type={type} // TOOD: change this to support multiple email addresses diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingInput.styled.tsx b/frontend/src/metabase/admin/settings/components/widgets/SettingInput.styled.tsx similarity index 51% rename from frontend/src/metabase/visualizations/components/settings/ChartSettingInput.styled.tsx rename to frontend/src/metabase/admin/settings/components/widgets/SettingInput.styled.tsx index 4f700b5a45ee80c6905ce74e2b7b00b85ea11ba5..e77cdcdd0272aec14ae07b465966d4894db44d55 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingInput.styled.tsx +++ b/frontend/src/metabase/admin/settings/components/widgets/SettingInput.styled.tsx @@ -1,7 +1,6 @@ import styled from "@emotion/styled"; import InputBlurChange from "metabase/components/InputBlurChange"; -export const ChartSettingInputBlurChange = styled(InputBlurChange)` - display: block; - width: 100%; +export const SettingInputBlurChange = styled(InputBlurChange)` + width: 400px; `; diff --git a/frontend/src/metabase/admin/settings/components/widgets/SettingInput.tsx b/frontend/src/metabase/admin/settings/components/widgets/SettingInput.tsx index 43d34769a495dece264f695d4c518e7114918b1e..8f632b33c0a87488ba53f3cec19589fa097b4657 100644 --- a/frontend/src/metabase/admin/settings/components/widgets/SettingInput.tsx +++ b/frontend/src/metabase/admin/settings/components/widgets/SettingInput.tsx @@ -1,7 +1,6 @@ import React from "react"; - import cx from "classnames"; -import InputBlurChange from "metabase/components/InputBlurChange"; +import { SettingInputBlurChange } from "./SettingInput.styled"; const getValue = (value: string, type: string) => { if (type === "number") { @@ -42,12 +41,13 @@ const SettingInput = ({ }; return ( - <InputBlurChange - className={cx("Form-input", { + <SettingInputBlurChange + className={cx({ SettingsInput: type !== "password", SettingsPassword: type === "password", - "border-error bg-error-input": errorMessage, })} + size="large" + error={!!errorMessage} id={id} type={type} value={setting.value || ""} diff --git a/frontend/src/metabase/components/InputBlurChange.jsx b/frontend/src/metabase/components/InputBlurChange.jsx deleted file mode 100644 index e97dc1ee5aabea4d5356246319f94cace8648f53..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/components/InputBlurChange.jsx +++ /dev/null @@ -1,74 +0,0 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; -import _ from "underscore"; -import { Input } from "./InputBlurChange.styled"; - -/** - * A small wrapper around <input>, primarily should be used for the - * `onBlurChange` feature, otherwise you should use <input> directly - */ -export default class InputBlurChange extends Component { - constructor(props, context) { - super(props, context); - this.onBlur = this.onBlur.bind(this); - this.onChange = this.onChange.bind(this); - this.state = { value: props.value }; - } - - static propTypes = { - type: PropTypes.string, - value: PropTypes.string, - defaultValue: PropTypes.string, - className: PropTypes.string, - name: PropTypes.string, - placeholder: PropTypes.string, - autoFocus: PropTypes.bool, - onFocus: PropTypes.func, - onChange: PropTypes.func, - onBlurChange: PropTypes.func, - }; - - static defaultProps = { - type: "text", - }; - - UNSAFE_componentWillReceiveProps(newProps) { - if (newProps.value !== this.state.value) { - this.setState({ value: newProps.value }); - } - } - - onChange(event) { - this.setState({ value: event.target.value }); - if (this.props.onChange) { - this.props.onChange(event); - } - } - - onBlur(event) { - if ( - this.props.onBlurChange && - (this.props.value || "") !== event.target.value - ) { - this.props.onBlurChange(event); - } - } - - render() { - const props = _.omit( - this.props, - "onBlurChange", - "value", - "onBlur", - "onChange", - ); - return ( - <Input - {...props} - value={this.state.value} - onBlur={this.onBlur} - onChange={this.onChange} - /> - ); - } -} diff --git a/frontend/src/metabase/components/InputBlurChange.styled.tsx b/frontend/src/metabase/components/InputBlurChange.styled.tsx deleted file mode 100644 index 94f498a8b3416d312149e8f50e1246407407d88e..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/components/InputBlurChange.styled.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import styled from "@emotion/styled"; -import { - focusOutlineStyle, - inputPadding, - inputTypography, - numericInputReset, -} from "metabase/core/style/input"; -import { color } from "metabase/lib/colors"; - -export const Input = styled.input` - ${inputPadding}; - ${inputTypography}; - ${focusOutlineStyle("brand")}; - ${numericInputReset}; - - border: 1px solid ${() => color("border")}; - border-radius: 0.5rem; - color: ${() => color("text-dark")}; - transition: border 0.3s; -`; diff --git a/frontend/src/metabase/components/InputBlurChange.tsx b/frontend/src/metabase/components/InputBlurChange.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f2ef03a65d83d7fe5c6325a068a01b1cae718026 --- /dev/null +++ b/frontend/src/metabase/components/InputBlurChange.tsx @@ -0,0 +1,58 @@ +import React, { useState, useLayoutEffect, useCallback } from "react"; +import _ from "underscore"; +import Input, { InputProps } from "metabase/core/components/Input"; + +/** + * A small wrapper around <input>, primarily should be used for the + * `onBlurChange` feature, otherwise you should use <input> directly + */ + +interface InputBlurChangeProps extends Omit<InputProps, "onBlur"> { + onBlurChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; +} + +const InputBlurChange = ({ + value, + onChange, + onBlurChange, + ...props +}: InputBlurChangeProps) => { + const [internalValue, setInternalValue] = useState(value); + + useLayoutEffect(() => { + setInternalValue(value); + }, [value]); + + const handleChange = useCallback( + (event: React.ChangeEvent<HTMLInputElement>) => { + setInternalValue(event.target.value); + if (onChange) { + onChange(event); + } + }, + [onChange], + ); + + const handleBlur = useCallback( + (event: React.ChangeEvent<HTMLInputElement>) => { + if (onBlurChange && (value || "") !== event.target.value) { + onBlurChange(event); + } + }, + [value, onBlurChange], + ); + + const inputProps = _.omit(props, "onBlur", "onBlurChange", "onChange"); + + return ( + <Input + {...inputProps} + value={internalValue} + onBlur={handleBlur} + onChange={handleChange} + fullWidth + /> + ); +}; + +export default InputBlurChange; diff --git a/frontend/src/metabase/components/InputWithSelectPrefix.jsx b/frontend/src/metabase/components/InputWithSelectPrefix.jsx index 9dea10f8ab3029e9bb802ec65d15a931467f6938..d236e0c10b22c397952e5890d5a54eb145f35617 100644 --- a/frontend/src/metabase/components/InputWithSelectPrefix.jsx +++ b/frontend/src/metabase/components/InputWithSelectPrefix.jsx @@ -2,7 +2,7 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; import Select, { Option } from "metabase/core/components/Select"; -import InputBlurChange from "./InputBlurChange"; +import { SelectPrefixInput } from "./InputWithSelectPrefix.styled"; function splitValue({ value, @@ -77,12 +77,13 @@ export default class InputWithSelectPrefix extends Component { </Option> ))} </Select> - <InputBlurChange + <SelectPrefixInput type="text" - className="Form-input flex-full borderless" + className="flex-full" value={rest} placeholder={this.props.placeholder} onBlurChange={e => this.setState({ rest: e.target.value })} + size="large" /> </div> ); diff --git a/frontend/src/metabase/components/InputWithSelectPrefix.styled.tsx b/frontend/src/metabase/components/InputWithSelectPrefix.styled.tsx new file mode 100644 index 0000000000000000000000000000000000000000..368b0b21e7a35ec82610e0c6b1669a80bbd62d2d --- /dev/null +++ b/frontend/src/metabase/components/InputWithSelectPrefix.styled.tsx @@ -0,0 +1,12 @@ +import styled from "@emotion/styled"; +import Input from "metabase/core/components/Input"; +import InputBlurChange from "./InputBlurChange"; + +export const SelectPrefixInput = styled(InputBlurChange)` + width: auto; + + ${Input.Field} { + border: none; + outline: none; + } +`; diff --git a/frontend/src/metabase/components/ListField/ListField.tsx b/frontend/src/metabase/components/ListField/ListField.tsx index f9863d9d07a0179cf46bf8a7e70699436b9905eb..884c2f887b6d9a14923be9b2771d310f287e7ca4 100644 --- a/frontend/src/metabase/components/ListField/ListField.tsx +++ b/frontend/src/metabase/components/ListField/ListField.tsx @@ -114,7 +114,6 @@ const ListField = ({ <Input fullWidth autoFocus - size="small" placeholder={placeholder} value={filter} onChange={handleFilterChange} diff --git a/frontend/src/metabase/components/ListSearchField.jsx b/frontend/src/metabase/components/ListSearchField.jsx index e0e905693d523788309904ff3e78f0c4fc2db08d..8457177bd45c93d3ea42f3c05ebf1e8121388ca9 100644 --- a/frontend/src/metabase/components/ListSearchField.jsx +++ b/frontend/src/metabase/components/ListSearchField.jsx @@ -18,9 +18,7 @@ export default function ListSearchField({ autoFocus, ...props }) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - return ( - <Input autoFocus ref={inputRef} {...props} size="small" leftIcon="search" /> - ); + return <Input autoFocus ref={inputRef} {...props} leftIcon="search" />; } ListSearchField.propTypes = Input.propTypes; diff --git a/frontend/src/metabase/components/NumericInput.jsx b/frontend/src/metabase/components/NumericInput.jsx index 68cb2d9074eae463106241ed3a5be3231140caa4..5106c65051ac7def845fc9717050547ec2ef1bf3 100644 --- a/frontend/src/metabase/components/NumericInput.jsx +++ b/frontend/src/metabase/components/NumericInput.jsx @@ -1,10 +1,9 @@ /* eslint-disable react/prop-types */ import React from "react"; - -import InputBlurChange from "metabase/components/InputBlurChange"; +import { NumericInputBlurChange } from "./NumericInput.styled"; const NumericInput = ({ value, onChange, ...props }) => ( - <InputBlurChange + <NumericInputBlurChange value={value == null ? "" : String(value)} onBlurChange={({ target: { value } }) => { value = value ? parseFloat(value) : null; diff --git a/frontend/src/metabase/components/NumericInput.styled.tsx b/frontend/src/metabase/components/NumericInput.styled.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2a9b2124cb6b113a99a40a586400d17217586f89 --- /dev/null +++ b/frontend/src/metabase/components/NumericInput.styled.tsx @@ -0,0 +1,7 @@ +import styled from "@emotion/styled"; + +import InputBlurChange from "./InputBlurChange"; + +export const NumericInputBlurChange = styled(InputBlurChange)` + width: auto; +`; diff --git a/frontend/src/metabase/components/SingleSelectListField/SingleSelectListField.tsx b/frontend/src/metabase/components/SingleSelectListField/SingleSelectListField.tsx index 17af102799541e3db1761c5ac28224f49a9d5a52..44a849244fab0492bdbc2c8096b126a428341f02 100644 --- a/frontend/src/metabase/components/SingleSelectListField/SingleSelectListField.tsx +++ b/frontend/src/metabase/components/SingleSelectListField/SingleSelectListField.tsx @@ -112,7 +112,6 @@ const SingleSelectListField = ({ <Input fullWidth autoFocus - size="small" placeholder={placeholder} value={filter} onChange={handleFilterChange} diff --git a/frontend/src/metabase/core/components/ColorInput/ColorInput.tsx b/frontend/src/metabase/core/components/ColorInput/ColorInput.tsx index ec4b5c7bd0889287596e19b504c6e8c4bf6238ad..f5a8814b051a5ae16d7b4316396bd5f5df23db22 100644 --- a/frontend/src/metabase/core/components/ColorInput/ColorInput.tsx +++ b/frontend/src/metabase/core/components/ColorInput/ColorInput.tsx @@ -8,6 +8,7 @@ import React, { useMemo, useState, } from "react"; +import _ from "underscore"; import Color from "color"; import Input from "metabase/core/components/Input"; @@ -58,10 +59,9 @@ const ColorInput = forwardRef(function ColorInput( return ( <Input - {...props} + {..._.omit(props, "size")} ref={ref} value={isFocused ? inputText : colorText} - size="small" onFocus={handleFocus} onBlur={handleBlur} onChange={handleChange} diff --git a/frontend/src/metabase/core/components/FormInput/FormInput.tsx b/frontend/src/metabase/core/components/FormInput/FormInput.tsx index 9a4d57e6ee01572786b6c867b9c324167b1cd958..649a067775e18399bb791577b486c24250f56af5 100644 --- a/frontend/src/metabase/core/components/FormInput/FormInput.tsx +++ b/frontend/src/metabase/core/components/FormInput/FormInput.tsx @@ -54,6 +54,7 @@ const FormInput = forwardRef(function FormInput( error={touched ? error : undefined} > <Input + size="large" {...props} id={id} name={name} diff --git a/frontend/src/metabase/core/components/Input/Input.styled.tsx b/frontend/src/metabase/core/components/Input/Input.styled.tsx index 4647b5d6552f31aea4efab1f3e8eb8032846ee06..df9ce419027d36961016c851c8bb8242facb9d35 100644 --- a/frontend/src/metabase/core/components/Input/Input.styled.tsx +++ b/frontend/src/metabase/core/components/Input/Input.styled.tsx @@ -3,8 +3,12 @@ import { css } from "@emotion/react"; import { color } from "metabase/lib/colors"; import { monospaceFontFamily, space } from "metabase/styled-components/theme"; import IconButtonWrapper from "metabase/components/IconButtonWrapper"; -import { focusOutlineStyle } from "metabase/core/style/input"; -import { InputSize } from "./types"; +import { + focusOutlineStyle, + inputPadding, + inputTypography, +} from "metabase/core/style/input"; +import { InputSize } from "../../style/types"; export interface InputProps { fieldSize?: InputSize; @@ -47,11 +51,10 @@ export const InputRoot = styled.div<InputRootProps>` `; export const InputField = styled.input<InputProps>` + ${props => inputPadding(props.fieldSize)} + ${props => inputTypography(props.fieldSize)} font-family: inherit; - font-weight: 700; - font-size: 1rem; color: ${color("text-dark")}; - padding: 0.75rem; border: 1px solid ${color("border")}; border-radius: ${space(1)}; background-color: ${props => color(props.readOnly ? "bg-light" : "bg-white")}; @@ -104,12 +107,13 @@ export const InputField = styled.input<InputProps>` type InputButtonProps = { size: InputSize; }; + export const InputButton = styled(IconButtonWrapper)<InputButtonProps>` position: absolute; color: ${color("text-light")}; - padding: 0.75rem; + padding: ${props => (props.size === "small" ? "0.5rem" : "0.75rem")}; border-radius: 50%; - bottom: ${props => (props.size === "medium" ? "0.125rem" : 0)}; + bottom: ${props => (props.size === "large" ? "0.125rem" : 0)}; &:disabled { cursor: default; @@ -129,7 +133,7 @@ type InputResetButtonProps = { }; export const InputResetButton = styled(InputButton)<InputResetButtonProps>` - right: ${props => (props.hasRightIcon ? "0.75rem" : 0)}; + right: ${props => (props.hasRightIcon ? "1.25rem" : 0)}; `; export const InputSubtitle = styled.div` diff --git a/frontend/src/metabase/core/components/Input/Input.tsx b/frontend/src/metabase/core/components/Input/Input.tsx index d3f119f4e64465a2ee924f26fc3d11916660b5c1..e7022a01371d899fcb650c46b67d8daabff2a494 100644 --- a/frontend/src/metabase/core/components/Input/Input.tsx +++ b/frontend/src/metabase/core/components/Input/Input.tsx @@ -8,6 +8,7 @@ import React, { import { t } from "ttag"; import Icon from "metabase/components/Icon"; import Tooltip from "metabase/components/Tooltip"; +import { InputSize } from "../../style/types"; import { InputField, InputLeftButton, @@ -16,7 +17,6 @@ import { InputSubtitle, InputResetButton, } from "./Input.styled"; -import { InputSize } from "./types"; export type InputColorScheme = "brand" | "filter"; diff --git a/frontend/src/metabase/core/components/Input/types.ts b/frontend/src/metabase/core/components/Input/types.ts deleted file mode 100644 index cb47f8b08c37c316b2018e342f127e6255509ece..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/core/components/Input/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type InputSize = "small" | "medium"; diff --git a/frontend/src/metabase/core/components/SelectButton/SelectButton.styled.tsx b/frontend/src/metabase/core/components/SelectButton/SelectButton.styled.tsx index 03c23d8ab608797284959671b2618be39d1e7aae..bdd528e099e413dbc896dbddf4b02e348277abc5 100644 --- a/frontend/src/metabase/core/components/SelectButton/SelectButton.styled.tsx +++ b/frontend/src/metabase/core/components/SelectButton/SelectButton.styled.tsx @@ -18,7 +18,7 @@ const getColor = ({ hasValue, highlighted }: SelectButtonRootProps) => { }; export const SelectButtonRoot = styled.button<SelectButtonRootProps>` - ${inputPadding} + ${inputPadding()} cursor: pointer; display: flex; width: ${props => (props.fullWidth ? "100%" : "unset")}; diff --git a/frontend/src/metabase/core/style/input.ts b/frontend/src/metabase/core/style/input.ts index 6eb610ca9f74cf364d548ad3f95c4f9761ea76e8..13e2a17656e78b8d1e87232b5e58989e2c4940c2 100644 --- a/frontend/src/metabase/core/style/input.ts +++ b/frontend/src/metabase/core/style/input.ts @@ -1,14 +1,39 @@ import { css } from "@emotion/react"; import { getFocusColor } from "metabase/lib/colors"; +import { InputSize } from "./types"; -export const inputPadding = css` - padding: 0.625rem 0.75rem; -`; +const inputPaddingBySize = { + small: css` + padding: 0.5rem 0.625rem; + `, + medium: css` + padding: 0.625rem 0.75rem; + `, + large: css` + padding: 0.75rem; + `, +} as const; -export const inputTypography = css` - font-size: 0.875rem; - font-weight: 700; -`; +export const inputPadding = (size: InputSize = "medium") => + inputPaddingBySize[size]; + +const inputTypographyBySize = { + small: css` + font-size: 0.875rem; + font-weight: 700; + `, + medium: css` + font-size: 0.875rem; + font-weight: 700; + `, + large: css` + font-size: 1rem; + font-weight: 700; + `, +} as const; + +export const inputTypography = (size: InputSize = "medium") => + inputTypographyBySize[size]; export const numericInputReset = () => css` &::-webkit-outer-spin-button, diff --git a/frontend/src/metabase/core/style/types.ts b/frontend/src/metabase/core/style/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..195fb40750c1c38343e5e358688c6d46bcd6dc3c --- /dev/null +++ b/frontend/src/metabase/core/style/types.ts @@ -0,0 +1 @@ +export type InputSize = "small" | "medium" | "large"; diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomLinkText.tsx b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomLinkText.tsx index 5e64226bf7775826fb92c79c2a2de9edba960840..74470eb95669b66ccffdd44abe2fff9e151723ec 100644 --- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomLinkText.tsx +++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomLinkText.tsx @@ -30,7 +30,7 @@ const CustomLinkText = ({ clickBehavior, updateSettings }: Props) => { <div className="mt2 mb1"> <Heading>{t`Customize link text (optional)`}</Heading> <InputBlurChange - className="input block full" + className="block full" placeholder={t`E.x. Details for {{Column Name}}`} value={clickBehavior.linkTextTemplate} onBlurChange={handleChange} diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomURLPicker.tsx b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomURLPicker.tsx index 116c8e090d9b6ba3ae69cd90bbe6268c3018fd2f..7fc0fa307903f6ae5156d2e9f057749d992e4005 100644 --- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomURLPicker.tsx +++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions/CustomURLPicker.tsx @@ -89,7 +89,7 @@ function CustomURLPicker({ value={clickBehavior.linkTemplate} placeholder={t`e.g. http://acme.com/id/\{\{user_id\}\}`} onChange={handleLinkTemplateChange} - className="input block full" + className="block full" /> {isTableDisplay(dashcard) && ( <CustomLinkText diff --git a/frontend/src/metabase/parameters/components/ParameterSidebar.jsx b/frontend/src/metabase/parameters/components/ParameterSidebar.jsx index 357e52319f0b9de40993ae1ca436021a71e06de8..ee0e05d68b5f3a535d68c2d7dfcf939b1b834365 100644 --- a/frontend/src/metabase/parameters/components/ParameterSidebar.jsx +++ b/frontend/src/metabase/parameters/components/ParameterSidebar.jsx @@ -80,7 +80,7 @@ class ParameterSidebar extends React.Component { <div className="py2"> <label className="mt2 mb1 block text-bold">{t`Label`}</label> <InputBlurChange - className="input block full" + className="block full" value={parameter.name} onBlurChange={e => setName(e.target.value)} /> diff --git a/frontend/src/metabase/query_builder/components/filters/modals/BulkFilterSelect/BulkFilterSelect.tsx b/frontend/src/metabase/query_builder/components/filters/modals/BulkFilterSelect/BulkFilterSelect.tsx index 8a0f78681d4f5babac143ed2bef6a2cb2471345c..d5e0834d7bccb848dc82ba588b0cb77d5ce592af 100644 --- a/frontend/src/metabase/query_builder/components/filters/modals/BulkFilterSelect/BulkFilterSelect.tsx +++ b/frontend/src/metabase/query_builder/components/filters/modals/BulkFilterSelect/BulkFilterSelect.tsx @@ -80,6 +80,7 @@ export const BulkFilterSelect = ({ </SelectFilterButton> ) } + maxWidth={370} popoverContent={({ closePopover }) => ( <SelectFilterPopover query={query} diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.styled.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.styled.tsx index 9418e6a3ea86474b3a99b3e0c238ac5e41707f23..41f25a986a75e845abaad81fa19f1ff0718d7b29 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.styled.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.styled.tsx @@ -6,12 +6,8 @@ export interface AmPmLabelProps { } export const AmPmLabel = styled.span<AmPmLabelProps>` - color: ${props => props.isSelected && color("filter")}; - font-weight: ${props => props.isSelected && 900}; + color: ${color("brand")}; + font-weight: 900; margin-right: 0.5rem; - cursor: ${props => !props.isSelected && "pointer"}; - - &:hover { - color: ${color("filter")}; - } + cursor: pointer; `; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.tsx index eb11050dc33379fc829b5a8c9db5fbd573ebd826..2cf9d6f6e02b70870656fb195384aa252f019260 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/HoursMinutesInput.tsx @@ -28,7 +28,6 @@ const HoursMinutesInput = ({ }: Props) => ( <div className="flex align-center"> <NumericInput - className="input" style={{ height: 36 }} size={2} maxLength={2} @@ -47,7 +46,6 @@ const HoursMinutesInput = ({ /> <span className="px1">:</span> <NumericInput - className="input" style={{ height: 36 }} size={2} maxLength={2} @@ -56,18 +54,21 @@ const HoursMinutesInput = ({ /> {!is24HourMode && ( <div className="flex align-center pl1"> - <AmPmLabel - isSelected={hours < 12} - onClick={hours >= 12 ? () => onChangeHours(hours - 12) : undefined} - > - {moment.localeData().meridiem(0, 0, false)} - </AmPmLabel> - <AmPmLabel - isSelected={hours >= 12} - onClick={hours < 12 ? () => onChangeHours(hours + 12) : undefined} - > - {moment.localeData().meridiem(12, 0, false)} - </AmPmLabel> + {hours < 12 ? ( + <AmPmLabel + isSelected={hours < 12} + onClick={() => onChangeHours(hours + 12)} + > + {moment.localeData().meridiem(0, 0, false)} + </AmPmLabel> + ) : ( + <AmPmLabel + isSelected={hours >= 12} + onClick={() => onChangeHours(hours - 12)} + > + {moment.localeData().meridiem(12, 0, false)} + </AmPmLabel> + )} </div> )} {onClear && ( diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx index 5516569d629ec301aee99bc58fa4f8af43740f88..c180dca972b55ab33790878adcfb2aec0308c9ce 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx @@ -65,7 +65,6 @@ const SELECT_STYLE = { width: 65, fontSize: 14, fontWeight: 700, - padding: 8, }; const isSmallerUnit = (unit: string, unitToCompare: string) => { @@ -197,7 +196,7 @@ const RelativeDatePicker = (props: RelativeDatePickerProps) => { <GridText>{intervals < 0 ? t`Past` : t`Next`}</GridText> ) : null} <NumericInput - className="input text-right" + className="text-right" primaryColor={primaryColor} style={SELECT_STYLE} data-ui-tag="relative-date-input" @@ -237,7 +236,7 @@ const RelativeDatePicker = (props: RelativeDatePickerProps) => { <> <GridText>{t`Starting from`}</GridText> <NumericInput - className="input text-right" + className="text-right" primaryColor={primaryColor} style={SELECT_STYLE} data-ui-tag="relative-date-input" diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.styled.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.styled.tsx index 4a8322d25e1bab8ef939a15627b2f203fdf85484..ae78a15bd9e4ed3a78cc4a900b54dbf7ec4ecf73 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.styled.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.styled.tsx @@ -1,10 +1,10 @@ import styled from "@emotion/styled"; import { color } from "metabase/lib/colors"; import Icon from "metabase/components/Icon"; -import InputBlurChange from "metabase/components/InputBlurChange"; export const CalendarIcon = styled(Icon)` margin-right: 0.5rem; + margin-left: 0.5rem; cursor: pointer; &:hover { @@ -12,16 +12,6 @@ export const CalendarIcon = styled(Icon)` } `; -export const DateInput = styled(InputBlurChange)` - font-size: 1rem; - font-weight: 700; - width: 100%; - padding: 0.5rem; - border: none; - outline: none; - background: none; -`; - interface DateInputContainerProps { isActive?: boolean; } @@ -31,9 +21,6 @@ export const DateInputContainer = styled.div<DateInputContainerProps>` align-items: center; width: 100%; margin-bottom: 1rem; - border: 1px solid - ${({ isActive }) => (isActive ? color("brand") : color("border"))}; - border-radius: 0.5rem; &:focus-within { border-color: ${color("brand")}; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.tsx index 90d9d5571c9db4e72ab3a351a1ca4f93dd16aa8f..036a285173f890aa66f03bbed7bc83e06d0af000 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/SpecificDatePicker.tsx @@ -4,6 +4,7 @@ import { t } from "ttag"; import moment, { Moment } from "moment-timezone"; import { getDateStyleFromSettings } from "metabase/lib/time"; import Calendar, { SelectAll } from "metabase/components/Calendar"; +import InputBlurChange from "metabase/components/InputBlurChange"; import ExpandingContent from "metabase/components/ExpandingContent"; import { getTimeComponent, @@ -11,11 +12,7 @@ import { } from "metabase-lib/queries/utils/query-time"; import HoursMinutesInput from "./HoursMinutesInput"; -import { - CalendarIcon, - DateInput, - DateInputContainer, -} from "./SpecificDatePicker.styled"; +import { CalendarIcon, DateInputContainer } from "./SpecificDatePicker.styled"; interface SpecificDatePickerProps { className?: string; @@ -64,7 +61,7 @@ const SpecificDatePicker = ({ return ( <div className={className} data-testid="specific-date-picker"> <DateInputContainer isActive={isActive}> - <DateInput + <InputBlurChange placeholder={moment().format(dateFormat)} value={date ? date.format(dateFormat) : ""} autoFocus={autoFocus} diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/HoursMinutesInput.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/HoursMinutesInput.jsx index 284450ff2527d61f31f9e691ebb9dd265fcf4e18..7b7083c31d8d51fae1cbe19c71974a1a33c7ba12 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/HoursMinutesInput.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/HoursMinutesInput.jsx @@ -19,7 +19,6 @@ const HoursMinutesInput = ({ <div className="flex align-center"> <NumericInput data-testid="hours-input" - className="input" style={{ height: 36 }} size={2} maxLength={2} diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/RelativeDatePicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/RelativeDatePicker.jsx index 33f5f71e9175a2a456b515ff0b2b33547a037d77..75588cfb0150f8d16b397b07ff31f0fbc006ddf8 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/RelativeDatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/LegacyDatePicker/RelativeDatePicker.jsx @@ -30,7 +30,7 @@ export default class RelativeDatePicker extends Component { return ( <div className={cx(className, "flex align-center")}> <IntervalInput - className="mr2 input text-right" + className="mr2 text-right" style={{ width: 65, // needed to match Select's AdminSelect classes :-/ diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx b/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx index ed389538b9426668f914576b0f762cc4e1d1ecdd..46d6d4c2f025502826f3b2021155c5dddf02a437 100644 --- a/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx +++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.jsx @@ -8,6 +8,7 @@ import { Link } from "react-router"; import Schemas from "metabase/entities/schemas"; import Toggle from "metabase/core/components/Toggle"; +import InputBlurChange from "metabase/components/InputBlurChange"; import Select, { Option } from "metabase/core/components/Select"; import { getParameterOptionsForField } from "metabase/parameters/utils/template-tag-options"; @@ -23,7 +24,6 @@ import { TagContainer, ContainerLabel, InputContainer, - WidgetLabelInput, DefaultParameterValueWidget, } from "./TagEditorParam.styled"; @@ -255,7 +255,7 @@ export class TagEditorParam extends Component { {t`Filter widget label`} {hasNoWidgetLabel && <ErrorSpan>{t`(required)`}</ErrorSpan>} </ContainerLabel> - <WidgetLabelInput + <InputBlurChange type="text" value={tag["display-name"]} onBlurChange={e => diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.styled.tsx b/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.styled.tsx index 5fb33db7c5e9e30bc5888c27a333f453dabd2daa..754155b7990e426d405fc78c3927d8a6c20db02c 100644 --- a/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.styled.tsx +++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorParam.styled.tsx @@ -1,5 +1,4 @@ import styled from "@emotion/styled"; -import InputBlurChange from "metabase/components/InputBlurChange"; import { color } from "metabase/lib/colors"; import ParameterValueWidget from "metabase/parameters/components/ParameterValueWidget"; @@ -36,16 +35,6 @@ export const InputContainer = styled.div<InputContainerProps>` padding-bottom: ${props => (props.lessBottomPadding ? "1.5rem" : "2rem")}; `; -export const WidgetLabelInput = styled(InputBlurChange)` - font-weight: 700; - padding: 0.5rem; - border: 1px solid ${color("border-dark")}; - border-radius: 0.5rem; - width: 100%; - color: ${color("text-dark")}; - font-size: 0.875rem; -`; - export const DefaultParameterValueWidget = styled(ParameterValueWidget)` padding: 0.5rem; font-weight: 700; diff --git a/frontend/src/metabase/query_builder/components/view/sidebars/SummarizeSidebar/DimensionList/DimensionList.jsx b/frontend/src/metabase/query_builder/components/view/sidebars/SummarizeSidebar/DimensionList/DimensionList.jsx index 4e21cd7a8deeba59e4b337c581cc62f58329431f..d966e4693590b33fc0c8d329f08c7737f508b1e1 100644 --- a/frontend/src/metabase/query_builder/components/view/sidebars/SummarizeSidebar/DimensionList/DimensionList.jsx +++ b/frontend/src/metabase/query_builder/components/view/sidebars/SummarizeSidebar/DimensionList/DimensionList.jsx @@ -93,7 +93,6 @@ export const DimensionList = ({ fullWidth placeholder={t`Find...`} value={filter} - size="small" leftIcon="search" onResetClick={() => setFilter("")} onChange={handleFilterChange} diff --git a/frontend/src/metabase/reference/components/ReferenceHeader.css b/frontend/src/metabase/reference/components/ReferenceHeader.css index 609c4a78cb6d95bbb213647012d79ffb2b916ddd..3f8e18b66ce4456bc13fe582d16b2a5003bdcba3 100644 --- a/frontend/src/metabase/reference/components/ReferenceHeader.css +++ b/frontend/src/metabase/reference/components/ReferenceHeader.css @@ -10,10 +10,9 @@ } :local(.headerTextInput) { - composes: input p1 pl2 pr2 from "style"; + composes: p1 from "style"; font-size: 18px; color: var(--title-color); - width: 100%; max-width: 550px; } diff --git a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.styled.tsx b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.styled.tsx index 232a160d3d7babb74ac8cbc4e0d62429387df5e2..2c6f036e9f65ded2803ee7bfe9032b94a0eee437 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.styled.tsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeries.styled.tsx @@ -1,6 +1,7 @@ import styled from "@emotion/styled"; import { color } from "metabase/lib/colors"; import Icon from "metabase/components/Icon"; +import InputBlurChange from "metabase/components/InputBlurChange"; export const OptionsIcon = styled(Icon)` color: ${color("text-medium")}; @@ -10,3 +11,7 @@ export const OptionsIcon = styled(Icon)` color: ${color("brand")}; } `; + +export const SeriesNameInput = styled(InputBlurChange)` + width: auto; +`; diff --git a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesMultiple.jsx b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesMultiple.jsx index 5aa754b700e9e2a25f8dcb26789611c6915c9c1a..20afb4cba968afd02eeb0e4ad06c6e50644928e7 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesMultiple.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesMultiple.jsx @@ -4,8 +4,10 @@ import React from "react"; import { getAccentColors } from "metabase/lib/colors/groups"; import ColorSelector from "metabase/core/components/ColorSelector"; import IconWrapper from "metabase/components/IconWrapper"; -import InputBlurChange from "metabase/components/InputBlurChange"; -import { OptionsIcon } from "./ChartNestedSettingSeries.styled"; +import { + OptionsIcon, + SeriesNameInput, +} from "./ChartNestedSettingSeries.styled"; // various props injected by chartSettingNestedSettings HOC export default class ChartNestedSettingSeriesMultiple extends React.Component { @@ -46,11 +48,10 @@ export default class ChartNestedSettingSeriesMultiple extends React.Component { onChangeObjectSettings(single, { color: value }) } /> - <InputBlurChange - className="input flex-full ml1 align-self-stretch" + <SeriesNameInput + className="flex-full ml1 align-self-stretch" // set vertical padding to 0 and use align-self-stretch to match siblings style={{ paddingTop: 0, paddingBottom: 0 }} - size={1} value={settings.title} onBlurChange={e => onChangeObjectSettings(single, { title: e.target.value }) diff --git a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesSingle.tsx b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesSingle.tsx index 6b941dc024bc5a2520680e6ba95c538c6f5b1634..a4d65971510beea89b08dd69568a1df95042ff82 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesSingle.tsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartNestedSettingSeriesSingle.tsx @@ -3,10 +3,11 @@ import React from "react"; import { getAccentColors } from "metabase/lib/colors/groups"; import ColorSelector from "metabase/core/components/ColorSelector"; -import InputBlurChange from "metabase/components/InputBlurChange"; import { Series } from "metabase-types/types/Visualization"; import { VisualizationSettings } from "metabase-types/api/card"; +import { SeriesNameInput } from "./ChartNestedSettingSeries.styled"; + export interface ChartNestedSettingsSeriesSingleProps { object: Series; getObjectKey: (object: Series) => string; @@ -34,10 +35,10 @@ const ChartNestedSettingsSeriesSingle = ({ colors={getAccentColors()} onChange={value => onChangeObjectSettings(object, { color: value })} /> - <InputBlurChange - className="input flex-full ml1 align-self-stretch" - size={1} + <SeriesNameInput + className="flex-full ml1 align-self-stretch" value={computedSettings.title} + data-testid="series-name-input" onBlurChange={(e: React.ChangeEvent<HTMLInputElement>) => onChangeObjectSettings(object, { title: e.target.value }) } diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingGaugeSegments.jsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingGaugeSegments.jsx index 24ff29d12a12a9ce3f2603c0ee5c4b15f52e3fed..9f17c11ff927a5a09486aba85a593db3a64cb3a0 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingGaugeSegments.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingGaugeSegments.jsx @@ -44,7 +44,7 @@ const ChartSettingGaugeSegments = ({ value: segments, onChange }) => { <td> <NumericInput type="number" - className="input full" + className="full" value={segment.min} onChange={value => onChangeProperty(index, "min", value)} placeholder={t`Min`} @@ -53,7 +53,7 @@ const ChartSettingGaugeSegments = ({ value: segments, onChange }) => { <td> <NumericInput type="number" - className="input full" + className="full" value={segment.max} onChange={value => onChangeProperty(index, "max", value)} placeholder={t`Max`} diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingInput.tsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingInput.tsx index 510ab80c5d184765ff557ed7e0349f86b217bc4b..f2c6cf9c75972d6cad961401b8ac6e1a19ad74b9 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingInput.tsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingInput.tsx @@ -1,6 +1,6 @@ import React from "react"; import _ from "underscore"; -import { ChartSettingInputBlurChange } from "./ChartSettingInput.styled"; +import InputBlurChange from "metabase/components/InputBlurChange"; interface ChartSettingInputProps { value: string; @@ -13,7 +13,7 @@ const ChartSettingInput = ({ onChange, ...props }: ChartSettingInputProps) => ( - <ChartSettingInputBlurChange + <InputBlurChange {..._.omit(props, "onChangeSettings")} data-testid={props.id} value={value} diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingInputGroup.jsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingInputGroup.jsx index b0c2b3d220086d6b34a1279ef452eeeac19188ca..79a39efbd16c8f5ae21fe0010e04abd9e7222deb 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingInputGroup.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingInputGroup.jsx @@ -8,7 +8,7 @@ export default function ChartSettingInputGroup({ value: values, onChange }) { const inputs = values.map((str, i) => ( <InputBlurChange key={i} - className="input block full mb1" + className="block full mb1" value={str} onBlurChange={e => { const newStr = e.target.value.trim(); diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingInputNumeric.styled.tsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingInputNumeric.styled.tsx index ac6526474e60bafd997727952ca34c28c45ae6a2..f4cd90bbbb7b826da621a157d6d744621f55a978 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingInputNumeric.styled.tsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingInputNumeric.styled.tsx @@ -1,18 +1,12 @@ import styled from "@emotion/styled"; import Input from "metabase/core/components/Input"; -import { - inputPadding, - inputTypography, - numericInputReset, -} from "metabase/core/style/input"; +import { numericInputReset } from "metabase/core/style/input"; export const ChartSettingNumericInput = styled(Input)` display: block; ${Input.Field} { width: 100%; - ${inputPadding}; - ${inputTypography}; ${numericInputReset}; } `; diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingsTableFormatting.jsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingsTableFormatting.jsx index 1972b54056c08096aac0c1567ac107a9f9c1df58..6379a3702fa1f340bd950b1b3588b2b3bc172f0c 100644 --- a/frontend/src/metabase/visualizations/components/settings/ChartSettingsTableFormatting.jsx +++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingsTableFormatting.jsx @@ -18,8 +18,10 @@ import Toggle from "metabase/core/components/Toggle"; import ColorRange from "metabase/core/components/ColorRange"; import ColorSelector from "metabase/core/components/ColorSelector"; import ColorRangeSelector from "metabase/core/components/ColorRangeSelector"; +import Input from "metabase/core/components/Input"; import NumericInput from "metabase/components/NumericInput"; + import { SortableContainer, SortableElement, @@ -82,7 +84,7 @@ const DEFAULTS_BY_TYPE = { // predicate for columns that can be formatted export const isFormattable = field => isNumeric(field) || isString(field); -const INPUT_CLASSNAME = "AdminSelect input mt1 full"; +const INPUT_CLASSNAME = "mt1 full"; const getValueForDescription = rule => ["is-null", "not-null"].includes(rule.operator) ? "" : ` ${rule.value}`; @@ -379,7 +381,7 @@ const RuleEditor = ({ placeholder="0" /> ) : hasOperand ? ( - <input + <Input data-testid="conditional-formatting-value-input" className={INPUT_CLASSNAME} value={rule.value} diff --git a/frontend/test/metabase/scenarios/admin/datamodel/metadata.cy.spec.js b/frontend/test/metabase/scenarios/admin/datamodel/metadata.cy.spec.js index 7e54761e78e30011999be6ba1d3ceb99e510aaf0..89b8c59170405c3aaca06f73eade4276aff8e1be 100644 --- a/frontend/test/metabase/scenarios/admin/datamodel/metadata.cy.spec.js +++ b/frontend/test/metabase/scenarios/admin/datamodel/metadata.cy.spec.js @@ -21,7 +21,7 @@ describe("scenarios > admin > datamodel > metadata", () => { cy.visit(`/admin/datamodel/database/${SAMPLE_DB_ID}`); // edit "Product ID" column in "Orders" table cy.findByText("Orders").click(); - cy.findByDisplayValue("Product ID").parent().find(".Icon-gear").click(); + cy.findByTestId("column-PRODUCT_ID").find(".Icon-gear").click(); // remap its original value to use foreign key cy.findByText("Use original value").click(); @@ -52,7 +52,7 @@ describe("scenarios > admin > datamodel > metadata", () => { cy.visit(`/admin/datamodel/database/${SAMPLE_DB_ID}`); // edit "Rating" values in "Reviews" table cy.findByText("Reviews").click(); - cy.findByDisplayValue("Rating").parent().find(".Icon-gear").click(); + cy.findByTestId("column-RATING").find(".Icon-gear").click(); // apply custom remapping for "Rating" values 1-5 cy.findByText("Use original value").click(); diff --git a/frontend/test/metabase/scenarios/admin/datamodel/reproductions/18384-field-settings-breaks-ui.cy.spec.js b/frontend/test/metabase/scenarios/admin/datamodel/reproductions/18384-field-settings-breaks-ui.cy.spec.js index 15a8a3f4d0ec8f32429460726395409a70d80ebe..5573d0509afbd66c693c3e22e00e8be811239f0f 100644 --- a/frontend/test/metabase/scenarios/admin/datamodel/reproductions/18384-field-settings-breaks-ui.cy.spec.js +++ b/frontend/test/metabase/scenarios/admin/datamodel/reproductions/18384-field-settings-breaks-ui.cy.spec.js @@ -19,7 +19,7 @@ describe("issue 18384", () => { it("should be able to open field properties even when one of the tables is hidden (metabase#18384)", () => { cy.visit(`/admin/datamodel/database/${SAMPLE_DB_ID}/table/${PEOPLE_ID}`); - cy.findByDisplayValue("Address").parent().find(".Icon-gear").click(); + cy.findByTestId("column-ADDRESS").find(".Icon-gear").click(); cy.location("pathname").should( "eq", diff --git a/frontend/test/metabase/scenarios/visualizations/line_chart.cy.spec.js b/frontend/test/metabase/scenarios/visualizations/line_chart.cy.spec.js index b5f671933f9f69b4d34925a5978dd7ef412b1d19..92b712404a47e96e2d20bd5cd427f02b660dc973 100644 --- a/frontend/test/metabase/scenarios/visualizations/line_chart.cy.spec.js +++ b/frontend/test/metabase/scenarios/visualizations/line_chart.cy.spec.js @@ -167,7 +167,7 @@ describe("scenarios > visualizations > line chart", () => { // Now do the same for the input with no value openSeriesSettings("Unknown", true); popover().within(() => { - cy.get("input[type=text]").type("cat2").blur(); + cy.findAllByTestId("series-name-input").type("cat2").blur(); cy.findByDisplayValue("cat2"); }); cy.button("Done").click(); diff --git a/frontend/test/metabase/scenarios/visualizations/reproductions/21452-xhr-on-every-char-for-rename.cy.spec.js b/frontend/test/metabase/scenarios/visualizations/reproductions/21452-xhr-on-every-char-for-rename.cy.spec.js index 55ab2844c32ee49f75a979fa1e006b7cf856b86e..2b891c59c73cd89c475001769af296dbf4acd70a 100644 --- a/frontend/test/metabase/scenarios/visualizations/reproductions/21452-xhr-on-every-char-for-rename.cy.spec.js +++ b/frontend/test/metabase/scenarios/visualizations/reproductions/21452-xhr-on-every-char-for-rename.cy.spec.js @@ -33,7 +33,8 @@ describe("issue 21452", () => { it("should not fire POST request after every character during display name change (metabase#21452)", () => { openSeriesSettings("Sum of Quantity"); - cy.findByDisplayValue("Sum of Quantity").clear().type("Foo").blur(); + cy.findByDisplayValue("Sum of Quantity").clear().type("Foo"); + cy.findByText("Display type").click(); // Blur will result in another POST request which is expected cy.wait("@dataset"); // Dismiss the popup and close settings