Force TextInput and Select to be `block`. Also, removed props regarding styling.tags/0.3.0
@@ -68,3 +68,4 @@ typings/ | |||||
dist/ | dist/ | ||||
.gitignore | .gitignore | ||||
.docz/ | .docz/ | ||||
/docz.config.js |
@@ -21,5 +21,5 @@ Component for values that have an on/off state. | |||||
## See Also | ## See Also | ||||
- <Link to="../lib-components-select-select">Select</Link> for a similar component suitable for selecting more values. | |||||
- <Link to="../lib-components-radio-button-radio-button">Radio Button</Link> for a similar component on selecting a single value among very few choices. | |||||
- <Link to="../select">Select</Link> for a similar component suitable for selecting more values. | |||||
- <Link to="../radiobutton">RadioButton</Link> for a similar component on selecting a single value among very few choices. |
@@ -119,6 +119,10 @@ const propTypes = { | |||||
* Short textual description indicating the nature of the component's value. | * Short textual description indicating the nature of the component's value. | ||||
*/ | */ | ||||
label: PropTypes.any, | label: PropTypes.any, | ||||
/** | |||||
* Name of the form field associated with this component. | |||||
*/ | |||||
name: PropTypes.string, | |||||
} | } | ||||
type Props = PropTypes.InferProps<typeof propTypes> | type Props = PropTypes.InferProps<typeof propTypes> | ||||
@@ -129,10 +133,10 @@ type Props = PropTypes.InferProps<typeof propTypes> | |||||
* @see {@link RadioButton} for a similar component on selecting a single value among very few choices. | * @see {@link RadioButton} for a similar component on selecting a single value among very few choices. | ||||
* @type {React.ComponentType<{readonly label?: string} & React.ClassAttributes<unknown>>} | * @type {React.ComponentType<{readonly label?: string} & React.ClassAttributes<unknown>>} | ||||
*/ | */ | ||||
const Checkbox = React.forwardRef<HTMLInputElement, Props>(({ label = '', ...etcProps }, ref) => ( | |||||
const Checkbox = React.forwardRef<HTMLInputElement, Props>(({ label = '', name, }, ref) => ( | |||||
<Base> | <Base> | ||||
<CaptureArea> | <CaptureArea> | ||||
<Input {...etcProps} ref={ref} type="checkbox" /> | |||||
<Input ref={ref} type="checkbox" name={name!} /> | |||||
<IndicatorWrapper> | <IndicatorWrapper> | ||||
<Border /> | <Border /> | ||||
<Indicator> | <Indicator> | ||||
@@ -35,18 +35,10 @@ const propTypes = { | |||||
* Size of the icon. This controls both the width and the height. | * Size of the icon. This controls both the width and the height. | ||||
*/ | */ | ||||
size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||||
/** | |||||
* CSS style of the icon. For icon dimensions, use `size` instead. | |||||
*/ | |||||
style: PropTypes.object, | |||||
/** | /** | ||||
* Describe of what the component represents. | * Describe of what the component represents. | ||||
*/ | */ | ||||
label: PropTypes.string, | label: PropTypes.string, | ||||
/** | |||||
* Class name used for styling. | |||||
*/ | |||||
className: PropTypes.string, | |||||
} | } | ||||
type Props = PropTypes.InferProps<typeof propTypes> | type Props = PropTypes.InferProps<typeof propTypes> | ||||
@@ -55,10 +47,7 @@ const Icon: React.FC<Props> = ({ | |||||
name, | name, | ||||
weight = '0.125rem', | weight = '0.125rem', | ||||
size = '1.5rem', | size = '1.5rem', | ||||
style = {}, | |||||
label = name, | label = name, | ||||
className = '', | |||||
...etcProps | |||||
}) => { | }) => { | ||||
const iconName = pascalCase(name, { transform: pascalCaseTransformMerge }) | const iconName = pascalCase(name, { transform: pascalCaseTransformMerge }) | ||||
const { [iconName as keyof typeof FeatherIcon]: TheIcon = null } = FeatherIcon | const { [iconName as keyof typeof FeatherIcon]: TheIcon = null } = FeatherIcon | ||||
@@ -68,9 +57,8 @@ const Icon: React.FC<Props> = ({ | |||||
if (TheIcon !== null) { | if (TheIcon !== null) { | ||||
return ( | return ( | ||||
<span {...etcProps} style={style!}> | |||||
<span> | |||||
<StyledIcon | <StyledIcon | ||||
className={className!} | |||||
as={TheIcon} | as={TheIcon} | ||||
size={undefined} | size={undefined} | ||||
color={undefined} | color={undefined} | ||||
@@ -1,22 +1,24 @@ | |||||
--- | --- | ||||
name: Radio Button | |||||
route: /components/radio-button | |||||
name: RadioButton | |||||
route: /components/radiobutton | |||||
menu: Components | menu: Components | ||||
--- | --- | ||||
import { Playground, Props, Link } from 'docz' | import { Playground, Props, Link } from 'docz' | ||||
import RadioButton from './RadioButton' | import RadioButton from './RadioButton' | ||||
# Radio Button | |||||
# RadioButton | |||||
Component for values which are to be selected from a few list of options. | Component for values which are to be selected from a few list of options. | ||||
<Playground> | <Playground> | ||||
<div style={{ margin: '1rem 0' }}> | |||||
<RadioButton name="flavor" label="Chocolate" /> | |||||
</div> | |||||
<div style={{ margin: '1rem 0' }}> | |||||
<RadioButton name="flavor" label="Vanilla" /> | |||||
<div style={{ display: 'grid', gap: '1rem', }}> | |||||
<div> | |||||
<RadioButton name="flavor" label="Chocolate" /> | |||||
</div> | |||||
<div> | |||||
<RadioButton name="flavor" label="Vanilla" /> | |||||
</div> | |||||
</div> | </div> | ||||
</Playground> | </Playground> | ||||
@@ -26,5 +28,5 @@ Component for values which are to be selected from a few list of options. | |||||
## See Also | ## See Also | ||||
- <Link to="../lib-components-checkbox-checkbox">Checkbox</Link> for a similar component on selecting values among very few choices. | |||||
- <Link to="../lib-components-select-select">Select</Link> for a similar component suitable for selecting more values. | |||||
- <Link to="../checkbox">Checkbox</Link> for a similar component on selecting values among very few choices. | |||||
- <Link to="../select">Select</Link> for a similar component suitable for selecting more values. |
@@ -133,12 +133,12 @@ type Props = PropTypes.InferProps<typeof propTypes> | |||||
*/ | */ | ||||
const RadioButton = React.forwardRef<HTMLInputElement, Props>( | const RadioButton = React.forwardRef<HTMLInputElement, Props>( | ||||
( | ( | ||||
{ label = '', name, ...etcProps }, | |||||
{ label = '', name, }, | |||||
ref | ref | ||||
) => ( | ) => ( | ||||
<Base> | <Base> | ||||
<CaptureArea> | <CaptureArea> | ||||
<Input {...etcProps} ref={ref} name={name} type="radio" /> | |||||
<Input ref={ref} name={name} type="radio" /> | |||||
<IndicatorWrapper> | <IndicatorWrapper> | ||||
<Border /> | <Border /> | ||||
<Indicator /> | <Indicator /> | ||||
@@ -12,14 +12,34 @@ import Select from './Select' | |||||
Component for selecting values from a larger number of options. | Component for selecting values from a larger number of options. | ||||
<Playground> | <Playground> | ||||
<Select /> | |||||
<Select> | |||||
<optgroup | |||||
label="Fruits" | |||||
> | |||||
<option value="mango">Mango</option> | |||||
<option value="strawberry">Strawberry</option> | |||||
<option value="blueberry">Blueberry</option> | |||||
</optgroup> | |||||
<optgroup | |||||
label="Classic" | |||||
> | |||||
<option value="chocolate">Chocolate</option> | |||||
<option value="vanilla">Vanilla</option> | |||||
</optgroup> | |||||
</Select> | |||||
</Playground> | </Playground> | ||||
## Props | ## Props | ||||
<Props of={Select} /> | <Props of={Select} /> | ||||
## Usage Notes | |||||
The component will behave as `block`, i.e. it takes the remaining of the horizontal space. | |||||
To use the component together with layouts, see [TextInput](./textinput) for examples. Both `Select` and | |||||
`TextInput` have similar strategies on usage with layouts. | |||||
## See Also | ## See Also | ||||
- <Link to="../lib-components-checkbox-checkbox">Checkbox</Link> for a similar component on selecting values among very few choices. | |||||
- <Link to="../lib-components-radio-button-radio-button">Radio Button</Link> for a similar component on selecting a single value among very few choices. | |||||
- <Link to="../checkbox">Checkbox</Link> for a similar component on selecting values among very few choices. | |||||
- <Link to="../radiobutton">RadioButton</Link> for a similar component on selecting a single value among very few choices. |
@@ -87,8 +87,9 @@ const Input = styled('select')({ | |||||
margin: 0, | margin: 0, | ||||
font: 'inherit', | font: 'inherit', | ||||
minHeight: '4rem', | minHeight: '4rem', | ||||
minWidth: '8rem', | |||||
minWidth: '3rem', | |||||
maxWidth: '100%', | maxWidth: '100%', | ||||
width: '100%', | |||||
zIndex: 1, | zIndex: 1, | ||||
cursor: 'pointer', | cursor: 'pointer', | ||||
transitionProperty: 'background-color, color', | transitionProperty: 'background-color, color', | ||||
@@ -177,10 +178,6 @@ const propTypes = { | |||||
* Short textual description indicating the nature of the component's value. | * Short textual description indicating the nature of the component's value. | ||||
*/ | */ | ||||
label: PropTypes.any, | label: PropTypes.any, | ||||
/** | |||||
* Class name for the component, used for styling. | |||||
*/ | |||||
className: PropTypes.string, | |||||
/** | /** | ||||
* Short textual description as guidelines for valid input values. | * Short textual description as guidelines for valid input values. | ||||
*/ | */ | ||||
@@ -198,9 +195,9 @@ const propTypes = { | |||||
*/ | */ | ||||
disabled: PropTypes.bool, | disabled: PropTypes.bool, | ||||
/** | /** | ||||
* CSS styles. | |||||
* Name of the form field associated with this component. | |||||
*/ | */ | ||||
style: PropTypes.object, | |||||
name: PropTypes.string, | |||||
} | } | ||||
type Props = PropTypes.InferProps<typeof propTypes> | type Props = PropTypes.InferProps<typeof propTypes> | ||||
@@ -209,13 +206,12 @@ const Select = React.forwardRef<HTMLSelectElement, Props>( | |||||
( | ( | ||||
{ | { | ||||
label = '', | label = '', | ||||
className = '', | |||||
hint = '', | hint = '', | ||||
size = 'medium', | size = 'medium', | ||||
multiple = false, | multiple = false, | ||||
disabled = false, | disabled = false, | ||||
style = {}, | |||||
...etcProps | |||||
name, | |||||
children, | |||||
}, | }, | ||||
ref, | ref, | ||||
) => { | ) => { | ||||
@@ -226,7 +222,7 @@ const Select = React.forwardRef<HTMLSelectElement, Props>( | |||||
}} | }} | ||||
> | > | ||||
<Border /> | <Border /> | ||||
<CaptureArea className={className!}> | |||||
<CaptureArea> | |||||
<LabelWrapper | <LabelWrapper | ||||
style={{ | style={{ | ||||
paddingTop: LABEL_VERTICAL_PADDING_SIZES[size!], | paddingTop: LABEL_VERTICAL_PADDING_SIZES[size!], | ||||
@@ -239,12 +235,11 @@ const Select = React.forwardRef<HTMLSelectElement, Props>( | |||||
</LabelWrapper> | </LabelWrapper> | ||||
{stringify(label).length > 0 && ' '} | {stringify(label).length > 0 && ' '} | ||||
<Input | <Input | ||||
{...etcProps} | |||||
ref={ref} | ref={ref} | ||||
disabled={disabled!} | disabled={disabled!} | ||||
multiple={multiple!} | multiple={multiple!} | ||||
name={name!} | |||||
style={{ | style={{ | ||||
...style, | |||||
verticalAlign: 'top', | verticalAlign: 'top', | ||||
fontSize: INPUT_FONT_SIZES[size!], | fontSize: INPUT_FONT_SIZES[size!], | ||||
height: multiple ? undefined : MIN_HEIGHTS[size!], | height: multiple ? undefined : MIN_HEIGHTS[size!], | ||||
@@ -254,7 +249,9 @@ const Select = React.forwardRef<HTMLSelectElement, Props>( | |||||
paddingBottom: VERTICAL_PADDING_SIZES[size!], | paddingBottom: VERTICAL_PADDING_SIZES[size!], | ||||
paddingRight: !multiple ? MIN_HEIGHTS[size!] : '1rem', | paddingRight: !multiple ? MIN_HEIGHTS[size!] : '1rem', | ||||
}} | }} | ||||
/> | |||||
> | |||||
{children} | |||||
</Input> | |||||
</CaptureArea> | </CaptureArea> | ||||
{stringify(hint).length > 0 && ' '} | {stringify(hint).length > 0 && ' '} | ||||
{stringify(hint).length > 0 && ( | {stringify(hint).length > 0 && ( | ||||
@@ -21,3 +21,7 @@ the component falls back into the original `<input type="range">` element. | |||||
## Props | ## Props | ||||
<Props of={Slider} /> | <Props of={Slider} /> | ||||
## See Also | |||||
- [Reach UI Slider](//reacttraining.com/reach-ui/slider/#sliderinput) for the client-side implementation. |
@@ -200,10 +200,6 @@ const propTypes = { | |||||
* CSS size for the component length. | * CSS size for the component length. | ||||
*/ | */ | ||||
length: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | length: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||||
/** | |||||
* Class name used for styling. | |||||
*/ | |||||
className: PropTypes.string, | |||||
/** | /** | ||||
* Is the component active? | * Is the component active? | ||||
*/ | */ | ||||
@@ -222,18 +218,14 @@ type Props = PropTypes.InferProps<typeof propTypes> | |||||
* @param {'vertical' | 'horizontal'} [orientation] - The component orientation. | * @param {'vertical' | 'horizontal'} [orientation] - The component orientation. | ||||
* @param {*} [label] - Short textual description indicating the nature of the component's value. | * @param {*} [label] - Short textual description indicating the nature of the component's value. | ||||
* @param {string | number} [length] - CSS size for the component length. | * @param {string | number} [length] - CSS size for the component length. | ||||
* @param {string} [className] - Class name used for styling. | |||||
* @param {boolean} [disabled] - Is the component active? | * @param {boolean} [disabled] - Is the component active? | ||||
* @param {object} etcProps - The component props. | |||||
* @returns {React.ReactElement} The component elements. | * @returns {React.ReactElement} The component elements. | ||||
*/ | */ | ||||
const Slider: React.FC<Props> = ({ | const Slider: React.FC<Props> = ({ | ||||
orientation = 'horizontal', | orientation = 'horizontal', | ||||
label = '', | label = '', | ||||
length = '16rem', | length = '16rem', | ||||
className = '', | |||||
disabled = false, | disabled = false, | ||||
...etcProps | |||||
}) => { | }) => { | ||||
const [isClient, setIsClient] = React.useState(false) | const [isClient, setIsClient] = React.useState(false) | ||||
@@ -250,10 +242,17 @@ const Slider: React.FC<Props> = ({ | |||||
const perpendicularTransform = orientation === 'horizontal' ? 'translateY' : 'translateX' | const perpendicularTransform = orientation === 'horizontal' ? 'translateY' : 'translateX' | ||||
const customBaseProps: any = { | |||||
orientation, | |||||
} | |||||
const customFallbackProps: any = { | |||||
orient: orientation, | |||||
} | |||||
if (isClient) { | if (isClient) { | ||||
return ( | return ( | ||||
<Wrapper | <Wrapper | ||||
className={className!} | |||||
style={{ | style={{ | ||||
opacity: disabled ? 0.5 : undefined, | opacity: disabled ? 0.5 : undefined, | ||||
[parallelDimension]: length!, | [parallelDimension]: length!, | ||||
@@ -288,7 +287,7 @@ const Slider: React.FC<Props> = ({ | |||||
</TransformWrapper> | </TransformWrapper> | ||||
</SizingWrapper> | </SizingWrapper> | ||||
<Base | <Base | ||||
{...etcProps} | |||||
{...customBaseProps} | |||||
disabled={disabled!} | disabled={disabled!} | ||||
style={{ | style={{ | ||||
[parallelDimension]: length, | [parallelDimension]: length, | ||||
@@ -319,7 +318,6 @@ const Slider: React.FC<Props> = ({ | |||||
return ( | return ( | ||||
<Wrapper | <Wrapper | ||||
className={className!} | |||||
style={{ | style={{ | ||||
opacity: disabled ? 0.5 : undefined, | opacity: disabled ? 0.5 : undefined, | ||||
[parallelDimension]: length!, | [parallelDimension]: length!, | ||||
@@ -358,7 +356,7 @@ const Slider: React.FC<Props> = ({ | |||||
</LabelWrapper> | </LabelWrapper> | ||||
{stringify(label).length > 0 && ' '} | {stringify(label).length > 0 && ' '} | ||||
<FallbackSlider | <FallbackSlider | ||||
{...etcProps} | |||||
{...customFallbackProps} | |||||
style={{ | style={{ | ||||
width: length!, | width: length!, | ||||
}} | }} | ||||
@@ -1,13 +1,13 @@ | |||||
--- | --- | ||||
name: Text Input | |||||
route: /components/text-input | |||||
name: TextInput | |||||
route: /components/textinput | |||||
menu: Components | menu: Components | ||||
--- | --- | ||||
import { Playground, Props } from 'docz' | |||||
import { Playground, Props, Link } from 'docz' | |||||
import TextInput from './TextInput' | import TextInput from './TextInput' | ||||
# Text Input | |||||
# TextInput | |||||
Component for inputting textual values. | Component for inputting textual values. | ||||
@@ -18,3 +18,54 @@ Component for inputting textual values. | |||||
## Props | ## Props | ||||
<Props of={TextInput} /> | <Props of={TextInput} /> | ||||
## Usage Notes | |||||
The component will behave as `block`, i.e. it takes the remaining of the horizontal space. | |||||
To use the component together with layouts, see the following examples. | |||||
### Inline | |||||
The components are surrounded by `inline-block` elements. These surrounding elements have specified widths, which could | |||||
act as guide to the user on how long the expected input values are. | |||||
<Playground> | |||||
<form> | |||||
I am <span style={{ display: 'inline-block', width: '16rem', }}><TextInput label="Full name" hint="given and family name" /></span> and I live in <span style={{ display: 'inline-block', width: '24rem', }}><TextInput label="Address" hint="city, state and country" /></span>. | |||||
</form> | |||||
</Playground> | |||||
### Grid | |||||
It is advisable to put surrounding elements instead of the `TextInput` components themselves as children of the | |||||
element specified as `grid`. This is to be able to add complementing content to the components, if for example there are | |||||
some content that is best displayed outside the component instead of putting in the `hint` prop. | |||||
<Playground> | |||||
<form | |||||
style={{ display: 'grid', gridTemplateColumns: '4fr 4fr 5fr', gap: '1rem', }} | |||||
> | |||||
<div style={{ gridColumnStart: 1, gridColumnEnd: 4, }}> | |||||
<TextInput label="Address line 1" hint="unit/house number, building" /> | |||||
</div> | |||||
<div style={{ gridColumnStart: 1, gridColumnEnd: 4, }}> | |||||
<TextInput label="Address line 2" hint="street, area" /> | |||||
</div> | |||||
<div> | |||||
<TextInput size="large" label="City/Town" /> | |||||
</div> | |||||
<div> | |||||
<TextInput size="large" label="State/Province" /> | |||||
</div> | |||||
<div> | |||||
<TextInput size="large" label="Country" hint="abbreviations are accepted" /> | |||||
<small> | |||||
Consult the <a href="#">fees table</a> for shipping fee details. | |||||
</small> | |||||
</div> | |||||
</form> | |||||
</Playground> | |||||
## See Also | |||||
- <Link to="../select">Select</Link> for a graphically-similar component suitable for selecting more values. |
@@ -124,6 +124,7 @@ const Input = styled('input')({ | |||||
minHeight: '4rem', | minHeight: '4rem', | ||||
minWidth: '8rem', | minWidth: '8rem', | ||||
maxWidth: '100%', | maxWidth: '100%', | ||||
width: '100%', | |||||
zIndex: 1, | zIndex: 1, | ||||
transitionProperty: 'background-color, color', | transitionProperty: 'background-color, color', | ||||
':focus': { | ':focus': { | ||||
@@ -151,7 +152,7 @@ const TextArea = styled('textarea')({ | |||||
margin: 0, | margin: 0, | ||||
font: 'inherit', | font: 'inherit', | ||||
minHeight: '4rem', | minHeight: '4rem', | ||||
minWidth: '16rem', | |||||
minWidth: '3rem', | |||||
maxWidth: '100%', | maxWidth: '100%', | ||||
zIndex: 1, | zIndex: 1, | ||||
transitionProperty: 'background-color, color', | transitionProperty: 'background-color, color', | ||||
@@ -201,10 +202,6 @@ const propTypes = { | |||||
* Short textual description indicating the nature of the component's value. | * Short textual description indicating the nature of the component's value. | ||||
*/ | */ | ||||
label: PropTypes.any, | label: PropTypes.any, | ||||
/** | |||||
* Class name for the component, used for styling. | |||||
*/ | |||||
className: PropTypes.string, | |||||
/** | /** | ||||
* Short textual description as guidelines for valid input values. | * Short textual description as guidelines for valid input values. | ||||
*/ | */ | ||||
@@ -233,6 +230,10 @@ const propTypes = { | |||||
* Placeholder of the component when there is no value. | * Placeholder of the component when there is no value. | ||||
*/ | */ | ||||
placeholder: PropTypes.string, | placeholder: PropTypes.string, | ||||
/** | |||||
* How many rows should the component display if it accepts multiline input? | |||||
*/ | |||||
rows: PropTypes.number, | |||||
} | } | ||||
type Props = PropTypes.InferProps<typeof propTypes> | type Props = PropTypes.InferProps<typeof propTypes> | ||||
@@ -241,7 +242,6 @@ const TextInput = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, Props | |||||
( | ( | ||||
{ | { | ||||
label = '', | label = '', | ||||
className = '', | |||||
hint = '', | hint = '', | ||||
indicator = null, | indicator = null, | ||||
size = 'medium', | size = 'medium', | ||||
@@ -249,6 +249,7 @@ const TextInput = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, Props | |||||
disabled = false, | disabled = false, | ||||
autoResize = false, | autoResize = false, | ||||
placeholder = '', | placeholder = '', | ||||
rows = 3, | |||||
}, | }, | ||||
ref, | ref, | ||||
) => ( | ) => ( | ||||
@@ -258,7 +259,7 @@ const TextInput = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, Props | |||||
}} | }} | ||||
> | > | ||||
<Border /> | <Border /> | ||||
<CaptureArea className={className!}> | |||||
<CaptureArea> | |||||
<LabelWrapper | <LabelWrapper | ||||
style={{ | style={{ | ||||
paddingTop: LABEL_VERTICAL_PADDING_SIZES[size!], | paddingTop: LABEL_VERTICAL_PADDING_SIZES[size!], | ||||
@@ -275,7 +276,9 @@ const TextInput = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, Props | |||||
placeholder={placeholder!} | placeholder={placeholder!} | ||||
ref={ref as React.Ref<HTMLTextAreaElement>} | ref={ref as React.Ref<HTMLTextAreaElement>} | ||||
disabled={disabled!} | disabled={disabled!} | ||||
rows={rows!} | |||||
style={{ | style={{ | ||||
height: `calc(${MIN_HEIGHTS[size!]} * ${rows})`, | |||||
fontSize: INPUT_FONT_SIZES[size!], | fontSize: INPUT_FONT_SIZES[size!], | ||||
minHeight: MIN_HEIGHTS[size!], | minHeight: MIN_HEIGHTS[size!], | ||||
paddingTop: VERTICAL_PADDING_SIZES[size!], | paddingTop: VERTICAL_PADDING_SIZES[size!], | ||||