diff --git a/UNRELEASED.md b/UNRELEASED.md
index c9f71570bef..6c119ba4677 100644
--- a/UNRELEASED.md
+++ b/UNRELEASED.md
@@ -21,6 +21,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f
### Documentation
- Updated the `withContext` section in the [v3 to v4 migration guide](https://github.com/Shopify/polaris-react/blob/master/documentation/guides/migrating-from-v3-to-v4.md) ([#2124](https://github.com/Shopify/polaris-react/pull/2124))
+- Converted `TextField`, `Toast`, and `TopBar` examples to functional components ([#2135](https://github.com/Shopify/polaris-react/pull/2135))
### Development workflow
diff --git a/src/components/TextField/README.md b/src/components/TextField/README.md
index af27b2f227e..6bc80a0fa81 100644
--- a/src/components/TextField/README.md
+++ b/src/components/TextField/README.md
@@ -175,6 +175,7 @@ Use to allow merchants to provide text input when the expected input is short. F
```jsx
function TextFieldExample() {
const [value, setValue] = useState('Jaded Pixel');
+
const handleChange = useCallback((newValue) => setValue(newValue), []);
return ;
@@ -200,6 +201,7 @@ Use when input text should be a number.
```jsx
function NumberFieldExample() {
const [value, setValue] = useState('1');
+
const handleChange = useCallback((newValue) => setValue(newValue), []);
return (
@@ -236,6 +238,7 @@ Use when the text input should be an email address.
```jsx
function EmailFieldExample() {
const [value, setValue] = useState('bernadette.lapresse@jadedpixel.com');
+
const handleChange = useCallback((newValue) => setValue(newValue), []);
return (
@@ -272,6 +275,7 @@ Use when the expected input could be more than one line. The field will automati
```jsx
function MultilineFieldExample() {
const [value, setValue] = useState('1776 Barnes Street\nOrlando, FL 32801');
+
const handleChange = useCallback((newValue) => setValue(newValue), []);
return (
@@ -307,7 +311,9 @@ Use to visually hide the label when the text field’s purpose is clear from con
function HiddenLabelExample() {
const [value, setValue] = useState('12');
const [selected, setSelected] = useState('yes');
+
const handleTextChange = useCallback((newValue) => setValue(newValue), []);
+
const handleChoiceChange = useCallback(
(selections) => setSelected(selections[0]),
[],
@@ -351,25 +357,22 @@ function HiddenLabelExample() {
Use when an optional, secondary action is closely associated with a text field. For example, on a field for entering a customs tariff code, a label action might be to look up the appropriate code from a table.
```jsx
-class LabelActionExample extends React.Component {
- state = {
- value: '6201.11.0000',
- };
+function LabelActionExample() {
+ const [textFieldValue, setTextFieldValue] = useState('6201.11.0000');
- handleChange = (value) => {
- this.setState({value});
- };
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
- render() {
- return (
-
- );
- }
+ return (
+
+ );
}
```
@@ -380,29 +383,26 @@ class LabelActionExample extends React.Component {
Use when input text should be aligned right.
```jsx
-class RightAlignExample extends React.Component {
- state = {
- value: '1',
- };
-
- handleChange = (value) => {
- this.setState({value});
- };
-
- render() {
- return (
-
- Price
-
-
- );
- }
+function RightAlignExample() {
+ const [textFieldValue, setTextFieldValue] = useState('1');
+
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
+
+ return (
+
+ Price
+
+
+ );
}
```
@@ -411,25 +411,22 @@ class RightAlignExample extends React.Component {
Use to provide a short, non-essential hint about the expected input. Placeholder text is low-contrast, so don’t rely on it for important information.
```jsx
-class PlaceholderExample extends React.Component {
- state = {
- value: '',
- };
+function PlaceholderExample() {
+ const [textFieldValue, setTextFieldValue] = useState('');
- handleChange = (value) => {
- this.setState({value});
- };
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
- render() {
- return (
-
- );
- }
+ return (
+
+ );
}
```
@@ -450,26 +447,25 @@ class PlaceholderExample extends React.Component {
Use to show short instructional content below the text field. Help text works to help merchants understand how to fix errors that result from incorrect formatting (such as dates or passwords with specific character requirements). If more explanation is needed, link to the Shopify Help Center.
```jsx
-class HelpTextExample extends React.Component {
- state = {
- value: 'bernadette.lapresse@jadedpixel.com',
- };
+function HelpTextExample() {
+ const [textFieldValue, setTextFieldValue] = useState(
+ 'bernadette.lapresse@jadedpixel.com',
+ );
- handleChange = (value) => {
- this.setState({value});
- };
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
- render() {
- return (
-
- );
- }
+ return (
+
+ );
}
```
@@ -493,26 +489,23 @@ Use as a special form of help text that works best inline.
- Use suffix for things like units of measure (“in”, “cm”).
```jsx
-class PrefixExample extends React.Component {
- state = {
- value: '2.00',
- };
+function PrefixExample() {
+ const [textFieldValue, setTextFieldValue] = useState('2.00');
- handleChange = (value) => {
- this.setState({value});
- };
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
- render() {
- return (
-
- );
- }
+ return (
+
+ );
}
```
@@ -539,39 +532,34 @@ If inputting weight as a number and a separate unit of measurement, use a text f
```jsx
-class ConnectedFieldsExample extends React.Component {
- state = {
- value: '10.6',
- selectValue: 'kg',
- };
-
- handleChange = (value) => {
- this.setState({value});
- };
-
- handleSelectChange = (selectValue) => {
- this.setState({selectValue});
- };
-
- render() {
- return (
-
- }
- />
- );
- }
+function ConnectedFieldsExample() {
+ const [textFieldValue, setTextFieldValue] = useState('10.6');
+ const [selectValue, setSelectValue] = useState('kg');
+
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
+
+ const handleSelectChange = useCallback((value) => setSelectValue(value), []);
+
+ return (
+
+ }
+ />
+ );
}
```
@@ -616,25 +604,22 @@ For example, tap on a barcode icon to launch the camera and scan barcode for the
Use to let merchants know if their input is valid or if there’s an error. Whenever possible, validate input as soon as merchants have finished interacting with a field (but not before). If a field already has an error, validate and remove errors as merchants type so they can immediately see when an error has been fixed.
```jsx
-class ValidationErrorExample extends React.Component {
- state = {
- value: '',
- };
+function ValidationErrorExample() {
+ const [textFieldValue, setTextFieldValue] = useState('');
- handleChange = (value) => {
- this.setState({value});
- };
+ const handleTextFieldChange = useCallback(
+ (value) => setTextFieldValue(value),
+ [],
+ );
- render() {
- return (
-
- );
- }
+ return (
+
+ );
}
```
@@ -665,82 +650,82 @@ To render an invalid text field and its validation error separately:
- Use an [inline error component](https://polaris.shopify.com/components/forms/inline-error) to describe the invalid text field input, and set its `fieldID` prop to be the same unique indentifier as the text field component’s `id`
```jsx
-class SeparateValidationErrorExample extends React.Component {
- state = {
- content: '',
- selectTypeValue: 'Product type',
- selectConditionValue: 'is equal to',
- };
-
- handleSelectCollectionTypeChange = (selectTypeValue) => {
- this.setState({selectTypeValue});
- };
-
- handleSelectCollectionConditionChange = (selectConditionValue) => {
- this.setState({selectConditionValue});
- };
-
- render() {
- const {content} = this.state;
- const textFieldID = 'ruleContent';
- const isInvalid = this.isInvalid(content);
- const errorMessage = isInvalid
- ? 'Enter 3 or more characters for product type is equal to'
- : '';
-
- const formGroupMarkup = (
-
-
-
-
-
-
-
-