mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.26k stars 32.12k forks source link

[TextField] Implement maxlength counter #24681

Open mygithubid1 opened 3 years ago

mygithubid1 commented 3 years ago

Thank you for material-ui.

Could we show counter as endAdornment to ensure that user gets better feedback when typing into TextField?

Summary 💡

As the user types into the TextField, it would be really nice to have a feedback mechanism with an endAdornment. Something like num chars / max chars should be sufficient as provided by other UI frameworks.

Only when the user hasn't provided an endAdornment or has provided maxLength property, this counter behavior needs to show up. The reason for including the endAdornment as another check is that, I don't know if it's ok to stack endAdornments. If that's something that's doable, then, let's have the constraint to just maxLength as a required prop for this counter to show up.

Examples 🌈

Here's a vuejs framework implementation of Counter. https://vuetifyjs.com/en/components/text-fields/#counter

Here's my sample based on material-ui: https://codesandbox.io/s/material-ui-textfield-with-counter-pdkdd

Motivation 🔦

It's non-trivial to get feedback when typing into a TextField. With the maxLength property, it's possible to restrict the maximum input size. The drawback is, user cannot know why input beyond maxLength won't be accepted.

When we show the number of characters the user has typed and then a danger styled indicator that maxLength has been reached, user can understand the restricition on the field.

adiramardiani commented 3 years ago

@oliviertassinari On https://material.io/components/text-fields#anatomy Assistive elements section, this is written in the material design spec image

Is it possible to give character or word counter options too? (not just maxlength counter) especially for developing (ex: cms) in the text field (meta_keyword case need word counter : separator can customized default = space, custom = commas ) textarea (meta_description case need char counter)

I hope this is implement on v5 :)

mygithubid1 commented 6 months ago

@oliviertassinari Please confirm how many upvotes are required for considering this feature.

oliviertassinari commented 6 months ago

@mygithubid1 the number of upvotes isn't a fixed number, it's a moving target, it's about stars/day avergage.

mygithubid1 commented 6 months ago

@oliviertassinari How is the github issue label waiting for 👍️ tied to stars/day average?

oliviertassinari commented 6 months ago

It's just about seeing enough inertia to justify the opportunity cost of maintainers time or to justify the bloat this add to everyone bundle if they don't use the feature.

fvanwijk commented 3 months ago

I solved it with right aligned helper text instead of using an endAdornment.

// Instead of justifyContent ternary you can also put <Box flex={1} /> in between helper text and counter
const CharacterCount = ({ count, helperText, max }: { count: number; helperText?: ReactNode; max: number }) => (
  <Stack direction="row" justifyContent={helperText ? 'space-between' : 'flex-end'} whiteSpace="nowrap">
    <Box overflow="hidden" textOverflow="ellipsis">
      {helperText}
    </Box>
    <Box color={count >= max ? 'error.main' : undefined}>
      {count} / {max}
    </Box>
  </Stack>
);

const TextFieldWithCounter = () => {
  const [value, setValue] = useState('');
  const maxLength = 10;

  // error and invalid are from React Hook Form but obviously you can use any validating logic.

  return <TextField
      error={invalid}
      helperText={<CharacterCount count={value.length} helperText={error?.message} max={maxLength} />}
      label="Title"
      inputProps={{ maxLength }}
      onChange={e => field.onChange(e.target.value)}
      value={value}
  />;
}

IMO it's a pretty small and reusable solution but I would rather see it built in TextField.