-
-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(material): add
FilledInput
component
- Loading branch information
Showing
8 changed files
with
345 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@suid/material": patch | ||
--- | ||
|
||
Add `FilledInput` component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
import InputBase from "../InputBase"; | ||
import { | ||
rootOverridesResolver as inputBaseRootOverridesResolver, | ||
inputOverridesResolver as inputBaseInputOverridesResolver, | ||
InputBaseRoot, | ||
InputBaseComponent as InputBaseInput, | ||
} from "../InputBase/InputBase"; | ||
import { PaletteColorName } from "../styles/createPalette"; | ||
import styled from "../styles/styled"; | ||
import { FilledInputTypeMap } from "./FilledInputProps"; | ||
import filledInputClasses, { | ||
getFilledInputUtilityClass, | ||
} from "./filledInputClasses"; | ||
import createComponentFactory from "@suid/base/createComponentFactory"; | ||
import { ComponentProps } from "@suid/types"; | ||
import deepmerge from "@suid/utils/deepmerge"; | ||
import { createMemo, mergeProps } from "solid-js"; | ||
|
||
const $ = createComponentFactory<FilledInputTypeMap>()({ | ||
name: "MuiFilledInput", | ||
propDefaults: ({ set }) => | ||
set({ | ||
components: {}, | ||
fullWidth: false, | ||
inputComponent: "input", | ||
multiline: false, | ||
type: "text", | ||
hiddenLabel: false, | ||
}), | ||
selfPropNames: ["classes", "disableUnderline", "hiddenLabel"], | ||
utilityClass: getFilledInputUtilityClass, | ||
slotClasses: (ownerState) => ({ | ||
root: ["root", !ownerState.disableUnderline && "underline"], | ||
input: ["input"], | ||
}), | ||
}); | ||
|
||
const FilledInputRoot = styled(InputBaseRoot, { | ||
/*shouldForwardProp: (prop) => | ||
rootShouldForwardProp(prop) || prop === "classes",*/ | ||
name: "MuiFilledInput", | ||
slot: "Root", | ||
overridesResolver: (props, styles) => { | ||
const { ownerState } = props; | ||
return [ | ||
...inputBaseRootOverridesResolver(props as any, styles), | ||
!ownerState.disableUnderline && styles.underline, | ||
]; | ||
}, | ||
})<ComponentProps<FilledInputTypeMap>>(({ theme, ownerState }) => { | ||
const light = theme.palette.mode === "light"; | ||
const bottomLineColor = light | ||
? "rgba(0, 0, 0, 0.42)" | ||
: "rgba(255, 255, 255, 0.7)"; | ||
const backgroundColor = light | ||
? "rgba(0, 0, 0, 0.06)" | ||
: "rgba(255, 255, 255, 0.09)"; | ||
return { | ||
position: "relative", | ||
backgroundColor, | ||
// [review] unitless | ||
borderTopLeftRadius: `${theme.shape.borderRadius}px`, | ||
borderTopRightRadius: `${theme.shape.borderRadius}px`, | ||
transition: theme.transitions.create("background-color", { | ||
duration: theme.transitions.duration.shorter, | ||
easing: theme.transitions.easing.easeOut, | ||
}), | ||
"&:hover": { | ||
backgroundColor: light | ||
? "rgba(0, 0, 0, 0.09)" | ||
: "rgba(255, 255, 255, 0.13)", | ||
// Reset on touch devices, it doesn't add specificity | ||
"@media (hover: none)": { | ||
backgroundColor, | ||
}, | ||
}, | ||
[`&.${filledInputClasses.focused}`]: { | ||
backgroundColor, | ||
}, | ||
[`&.${filledInputClasses.disabled}`]: { | ||
backgroundColor: light | ||
? "rgba(0, 0, 0, 0.12)" | ||
: "rgba(255, 255, 255, 0.12)", | ||
}, | ||
...(!ownerState.disableUnderline && { | ||
"&:after": { | ||
borderBottom: `2px solid ${ | ||
theme.palette[ownerState.color as PaletteColorName].main | ||
}`, | ||
left: 0, | ||
bottom: 0, | ||
// Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242 | ||
content: '""', | ||
position: "absolute", | ||
right: 0, | ||
transform: "scaleX(0)", | ||
transition: theme.transitions.create("transform", { | ||
duration: theme.transitions.duration.shorter, | ||
easing: theme.transitions.easing.easeOut, | ||
}), | ||
pointerEvents: "none", // Transparent to the hover style. | ||
}, | ||
[`&.${filledInputClasses.focused}:after`]: { | ||
transform: "scaleX(1)", | ||
}, | ||
[`&.${filledInputClasses.error}:after`]: { | ||
borderBottomColor: theme.palette.error.main, | ||
transform: "scaleX(1)", // error is always underlined in red | ||
}, | ||
"&:before": { | ||
borderBottom: `1px solid ${bottomLineColor}`, | ||
left: 0, | ||
bottom: 0, | ||
// Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242 | ||
content: '"\\00a0"', | ||
position: "absolute", | ||
right: 0, | ||
transition: theme.transitions.create("border-bottom-color", { | ||
duration: theme.transitions.duration.shorter, | ||
}), | ||
pointerEvents: "none", // Transparent to the hover style. | ||
}, | ||
[`&:hover:not(.${filledInputClasses.disabled}):before`]: { | ||
borderBottom: `1px solid ${theme.palette.text.primary}`, | ||
}, | ||
[`&.${filledInputClasses.disabled}:before`]: { | ||
borderBottomStyle: "dotted", | ||
}, | ||
}), | ||
...(ownerState.startAdornment && { | ||
paddingLeft: 12, | ||
}), | ||
...(ownerState.endAdornment && { | ||
paddingRight: 12, | ||
}), | ||
...(ownerState.multiline && { | ||
padding: "25px 12px 8px", | ||
...(ownerState.size === "small" && { | ||
paddingTop: 21, | ||
paddingBottom: 4, | ||
}), | ||
...(ownerState.hiddenLabel && { | ||
paddingTop: 16, | ||
paddingBottom: 17, | ||
}), | ||
}), | ||
}; | ||
}); | ||
|
||
const FilledInputInput = styled(InputBaseInput, { | ||
name: "MuiFilledInput", | ||
slot: "Input", | ||
overridesResolver: inputBaseInputOverridesResolver as any, | ||
})<ComponentProps<FilledInputTypeMap>>(({ theme, ownerState }) => ({ | ||
paddingTop: 25, | ||
paddingRight: 12, | ||
paddingBottom: 8, | ||
paddingLeft: 12, | ||
"&:-webkit-autofill": { | ||
WebkitBoxShadow: | ||
theme.palette.mode === "light" ? null : "0 0 0 100px #266798 inset", | ||
WebkitTextFillColor: theme.palette.mode === "light" ? null : "#fff", | ||
caretColor: theme.palette.mode === "light" ? null : "#fff", | ||
borderTopLeftRadius: "inherit", | ||
borderTopRightRadius: "inherit", | ||
}, | ||
...(ownerState.size === "small" && { | ||
paddingTop: 21, | ||
paddingBottom: 4, | ||
}), | ||
...(ownerState.hiddenLabel && { | ||
paddingTop: 16, | ||
paddingBottom: 17, | ||
}), | ||
...(ownerState.multiline && { | ||
paddingTop: 0, | ||
paddingBottom: 0, | ||
paddingLeft: 0, | ||
paddingRight: 0, | ||
}), | ||
...(ownerState.startAdornment && { | ||
paddingLeft: 0, | ||
}), | ||
...(ownerState.endAdornment && { | ||
paddingRight: 0, | ||
}), | ||
...(ownerState.hiddenLabel && | ||
ownerState.size === "small" && { | ||
paddingTop: 8, | ||
paddingBottom: 9, | ||
}), | ||
})); | ||
|
||
const FilledInput = $.component(function FilledInput({ | ||
allProps, | ||
classes, | ||
otherProps, | ||
props, | ||
}) { | ||
const componentProps = createMemo(() => { | ||
const filledInputComponentsProps = { | ||
root: { ownerState: allProps }, | ||
input: { ownerState: allProps }, | ||
}; | ||
return otherProps.componentsProps | ||
? deepmerge(otherProps.componentsProps, filledInputComponentsProps) | ||
: filledInputComponentsProps; | ||
}); | ||
|
||
const allClasses = mergeProps(() => props.classes || {}, classes); | ||
|
||
return ( | ||
<InputBase | ||
{...otherProps} | ||
components={{ | ||
Root: FilledInputRoot, | ||
Input: FilledInputInput, | ||
...(otherProps.components || {}), | ||
}} | ||
componentsProps={componentProps()} | ||
classes={allClasses} | ||
/> | ||
); | ||
}); | ||
|
||
export default FilledInput; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { InputBaseProps } from "../InputBase"; | ||
import { FilledInputClasses } from "./filledInputClasses"; | ||
import SxProps from "@suid/system/sxProps"; | ||
import { ElementType } from "@suid/types"; | ||
|
||
export interface FilledInputTypeMap<P = {}, D extends ElementType = "input"> { | ||
name: "MuiFilledInput"; | ||
defaultPropNames: "hiddenLabel"; | ||
selfProps: { | ||
/** | ||
* Override or extend the styles applied to the component. | ||
*/ | ||
classes?: Partial<FilledInputClasses>; | ||
/** | ||
* If `true`, the label is hidden. | ||
* This is used to increase density for a `FilledInput`. | ||
* Be sure to add `aria-label` to the `input` element. | ||
* @default false | ||
*/ | ||
hiddenLabel?: boolean; | ||
/** | ||
* If `true`, the input will not have an underline. | ||
*/ | ||
disableUnderline?: boolean; | ||
/** | ||
* The system prop that allows defining system overrides as well as additional CSS styles. | ||
*/ | ||
sx?: SxProps; | ||
}; | ||
props: P & InputBaseProps & FilledInputTypeMap["selfProps"]; | ||
defaultComponent: D; | ||
} | ||
|
||
export type FilledInputProps = FilledInputTypeMap["props"]; | ||
|
||
export default FilledInputProps; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { generateUtilityClasses, generateUtilityClass } from "@suid/base"; | ||
|
||
export interface FilledInputClasses { | ||
/** Styles applied to the root element. */ | ||
root: string; | ||
/** Styles applied to the root element if color secondary. */ | ||
colorSecondary: string; | ||
/** Styles applied to the root element unless `disableUnderline={true}`. */ | ||
underline: string; | ||
/** State class applied to the root element if the component is focused. */ | ||
focused: string; | ||
/** State class applied to the root element if `disabled={true}`. */ | ||
disabled: string; | ||
/** Styles applied to the root element if `startAdornment` is provided. */ | ||
adornedStart: string; | ||
/** Styles applied to the root element if `endAdornment` is provided. */ | ||
adornedEnd: string; | ||
/** State class applied to the root element if `error={true}`. */ | ||
error: string; | ||
/** Styles applied to the input element if `size="small"`. */ | ||
sizeSmall: string; | ||
/** Styles applied to the root element if `multiline={true}`. */ | ||
multiline: string; | ||
/** Styles applied to the root element if `hiddenLabel={true}`. */ | ||
hiddenLabel: string; | ||
/** Styles applied to the input element. */ | ||
input: string; | ||
/** Styles applied to the input element if `size="small"`. */ | ||
inputSizeSmall: string; | ||
/** Styles applied to the `input` if in `<FormControl hiddenLabel />`. */ | ||
inputHiddenLabel: string; | ||
/** Styles applied to the input element if `multiline={true}`. */ | ||
inputMultiline: string; | ||
/** Styles applied to the input element if `startAdornment` is provided. */ | ||
inputAdornedStart: string; | ||
/** Styles applied to the input element if `endAdornment` is provided. */ | ||
inputAdornedEnd: string; | ||
} | ||
|
||
export type FilledInputClassKey = keyof FilledInputClasses; | ||
|
||
export function getFilledInputUtilityClass(slot: string): string { | ||
return generateUtilityClass("MuiFilledInput", slot); | ||
} | ||
|
||
const filledInputClasses: FilledInputClasses = generateUtilityClasses( | ||
"MuiFilledInput", | ||
[ | ||
"root", | ||
"colorSecondary", | ||
"underline", | ||
"focused", | ||
"disabled", | ||
"adornedStart", | ||
"adornedEnd", | ||
"error", | ||
"sizeSmall", | ||
"multiline", | ||
"hiddenLabel", | ||
"input", | ||
"inputSizeSmall", | ||
"inputHiddenLabel", | ||
"inputMultiline", | ||
"inputAdornedStart", | ||
"inputAdornedEnd", | ||
] | ||
); | ||
|
||
export default filledInputClasses; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export { default } from "./FilledInput"; | ||
export * from "./FilledInput"; | ||
export * from "./FilledInputProps"; | ||
|
||
export { default as FilledInputClasses } from "./filledInputClasses"; | ||
export * from "./filledInputClasses"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters