Skip to content

Commit

Permalink
Mobile Textfield exploration minimal changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ssetem committed Apr 12, 2024
1 parent 571e3d7 commit d95df43
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-donkeys-shake.md
@@ -0,0 +1,5 @@
---
'@shopify/polaris': major
---

Experimenting with TextField styles
Expand Up @@ -46,6 +46,12 @@ export const featureFlagOptions = {
defaultValue: false,
control: {type: 'boolean'},
},
mobileInlineFormLabels: {
name: 'mobileInlineFormLabels',
description: 'Toggle Mobile Inline Form Labels',
defaultValue: false,
control: {type: 'boolean'},
},
};

export const gridOptions = {
Expand Down
15 changes: 12 additions & 3 deletions polaris-react/src/components/Label/Label.tsx
@@ -1,7 +1,8 @@
import React from 'react';

import {Text} from '../Text';
import {classNames} from '../../utilities/css';
import type {TextProps} from '../Text';
import {Text} from '../Text';

import styles from './Label.module.css';

Expand All @@ -14,13 +15,21 @@ export interface LabelProps {
hidden?: boolean;
/** Visual required indicator for the label */
requiredIndicator?: boolean;

variant?: TextProps['variant'];
}

export function labelID(id: string) {
return `${id}Label`;
}

export function Label({children, id, hidden, requiredIndicator}: LabelProps) {
export function Label({
children,
id,
hidden,
requiredIndicator,
variant = 'bodyMd',
}: LabelProps) {
const className = classNames(styles.Label, hidden && styles.hidden);

return (
Expand All @@ -33,7 +42,7 @@ export function Label({children, id, hidden, requiredIndicator}: LabelProps) {
requiredIndicator && styles.RequiredIndicator,
)}
>
<Text as="span" variant="bodyMd">
<Text as="span" variant={variant}>
{children}
</Text>
</label>
Expand Down
17 changes: 17 additions & 0 deletions polaris-react/src/components/Labelled/Labelled.module.css
Expand Up @@ -26,6 +26,19 @@
margin-bottom: var(--p-space-100);
}

.labelInline {
position: relative;
}

.labelInline .LabelWrapper {
position: absolute;
top: 5px;
color: var(--p-color-text-secondary);
left: var(--p-space-300);
right: var(--p-space-300);
z-index: var(--p-z-index-2);
}

.HelpText {
margin-top: var(--p-space-100);
}
Expand All @@ -39,3 +52,7 @@
.Action {
flex: 0 0 auto;
}

.labelInline .Action {
margin-top: var(--p-space-200);
}
5 changes: 5 additions & 0 deletions polaris-react/src/components/Labelled/Labelled.tsx
Expand Up @@ -33,6 +33,8 @@ export interface LabelledProps {
disabled?: boolean;
/** Labels signify a readOnly control */
readOnly?: boolean;

labelInline?: boolean;
}

export function Labelled({
Expand All @@ -46,9 +48,11 @@ export function Labelled({
requiredIndicator,
disabled,
readOnly,
labelInline,
...rest
}: LabelledProps) {
const className = classNames(
labelInline && styles.labelInline,
labelHidden && styles.hidden,
disabled && styles.disabled,
readOnly && styles.readOnly,
Expand Down Expand Up @@ -85,6 +89,7 @@ export function Labelled({
requiredIndicator={requiredIndicator}
{...rest}
hidden={false}
variant={labelInline ? 'bodySm' : undefined}
>
{label}
</Label>
Expand Down
23 changes: 22 additions & 1 deletion polaris-react/src/components/Select/Select.module.css
Expand Up @@ -77,6 +77,17 @@
text-overflow: ellipsis;
}

.labelInline .SelectedOption {
padding-block-start: 16px;
}

.labelOneLine.labelInline .SelectedOption,
.labelInline.labelHidden .SelectedOption,
.labelInline.labelAction .SelectedOption {
padding-block-start: 8px;
padding-block-end: 8px;
}

.Prefix {
padding-right: var(--p-space-100);
}
Expand Down Expand Up @@ -159,7 +170,17 @@
outline-offset: var(--p-space-025);
}
}

@media (--p-breakpoints-md-down) {
.Input:focus-visible {
~ .Backdrop {
border-color: var(--p-color-border-focus);
border-width: var(--p-border-width-025);
background-color: var(--p-color-input-bg-surface-active);
outline: var(--p-border-width-025) solid var(--p-color-border-focus);
outline-offset: 0;
}
}
}
.toneMagic {
.Content {
color: var(--p-color-text-magic);
Expand Down
8 changes: 7 additions & 1 deletion polaris-react/src/components/Select/Select.tsx
Expand Up @@ -9,6 +9,7 @@ import {Icon} from '../Icon';
import {Text} from '../Text';
import type {Error} from '../../types';
import {useToggle} from '../../utilities/use-toggle';
import {useIsMobileFormsInline} from '../../utilities/use-is-mobile-forms-inline';

import styles from './Select.module.css';

Expand Down Expand Up @@ -102,13 +103,17 @@ export function Select({
tone,
}: SelectProps) {
const {value: focused, toggle: toggleFocused} = useToggle(false);

const isMobileFormsInline = useIsMobileFormsInline();
const uniqId = useId();
const id = idProp ?? uniqId;
const labelHidden = labelInline ? true : labelHiddenProp;

const className = classNames(
styles.Select,
isMobileFormsInline && styles.labelInline,
labelAction && styles.labelAction,
labelInline && styles.labelOneLine,
labelHidden && styles.labelHidden,
error && styles.error,
tone && styles[variationName('tone', tone)],
disabled && styles.disabled,
Expand Down Expand Up @@ -198,6 +203,7 @@ export function Select({
error={error}
action={labelAction}
labelHidden={labelHidden}
labelInline={isMobileFormsInline && !labelAction}
helpText={helpText}
requiredIndicator={requiredIndicator}
disabled={disabled}
Expand Down
26 changes: 26 additions & 0 deletions polaris-react/src/components/TextField/TextField.module.css
Expand Up @@ -88,6 +88,21 @@
}
}

@media (--p-breakpoints-md-down) {
.focus > .Input,
.focus > .VerticalContent,
.focus > .InputAndSuffixWrapper,
.TextField:focus-within > .Input,
.Input:focus-visible {
/* stylelint-disable-next-line selector-max-class, selector-max-combinators, selector-max-specificity -- outline based on child focus requires complex specificity */
~ .Backdrop {
border-color: var(--p-color-border-focus);
outline-width: var(--p-border-width-025);
outline-offset: 0;
}
}
}

.error {
/* stylelint-disable-next-line -- set Backdrop styles */
.Input:hover ~ .Backdrop,
Expand Down Expand Up @@ -316,6 +331,17 @@
}
}

.labelInline .Input,
.prefixInline {
padding-block-start: 14px;
padding-block-end: 14px;
}
.labelInline.hasValue:not(.labelAction) .Input,
.labelInline.hasValue:not(.labelAction) .prefixInline {
padding-block-start: 22px;
padding-block-end: 6px;
}

.borderless {
.Input,
.Backdrop {
Expand Down
21 changes: 18 additions & 3 deletions polaris-react/src/components/TextField/TextField.tsx
Expand Up @@ -20,6 +20,7 @@ import {Icon} from '../Icon';
import {Text} from '../Text';
import {Spinner as LoadingSpinner} from '../Spinner';
import {useEventListener} from '../../utilities/use-event-listener';
import {useIsMobileFormsInline} from '../../utilities/use-is-mobile-forms-inline';

import {Resizer, Spinner} from './components';
import type {SpinnerProps} from './components';
Expand Down Expand Up @@ -262,6 +263,9 @@ export function TextField({
const [height, setHeight] = useState<number | null>(null);
const [focus, setFocus] = useState(Boolean(focused));
const isAfterInitial = useIsAfterInitialMount();
const isMobileFormsInline = useIsMobileFormsInline();
const labelInline =
isMobileFormsInline && !connectedLeft && !(labelHidden && prefix);
const uniqId = useId();
const id = idProp ?? uniqId;

Expand Down Expand Up @@ -308,6 +312,8 @@ export function TextField({

const className = classNames(
styles.TextField,
labelInline && styles.labelInline,
Boolean(labelAction) && styles.labelAction,
Boolean(normalizedValue) && styles.hasValue,
disabled && styles.disabled,
readOnly && styles.readOnly,
Expand All @@ -325,7 +331,11 @@ export function TextField({

const prefixMarkup = prefix ? (
<div
className={classNames(styles.Prefix, iconPrefix && styles.PrefixIcon)}
className={classNames(
styles.Prefix,
iconPrefix && styles.PrefixIcon,
labelInline && styles.prefixInline,
)}
id={`${id}-Prefix`}
ref={prefixRef}
>
Expand Down Expand Up @@ -574,7 +584,7 @@ export function TextField({
role,
autoFocus,
value: normalizedValue,
placeholder,
placeholder: isMobileFormsInline ? label || placeholder : placeholder,
style,
autoComplete,
className: inputClassName,
Expand Down Expand Up @@ -665,7 +675,12 @@ export function TextField({
id={id}
error={error}
action={labelAction}
labelHidden={labelHidden}
labelHidden={
isMobileFormsInline
? Boolean(connectedLeft) || value.length === 0
: labelHidden
}
labelInline={labelInline && !labelAction}
helpText={helpText}
requiredIndicator={requiredIndicator}
disabled={disabled}
Expand Down
1 change: 1 addition & 0 deletions polaris-react/src/utilities/features/types.ts
@@ -1,5 +1,6 @@
export interface FeaturesConfig {
dynamicTopBarAndReframe?: boolean;
mobileInlineFormLabels?: boolean;
[key: string]: boolean | undefined;
}

Expand Down
9 changes: 9 additions & 0 deletions polaris-react/src/utilities/use-is-mobile-forms-inline.ts
@@ -0,0 +1,9 @@
import {useBreakpoints} from './breakpoints';
import {useFeatures} from './features';

export function useIsMobileFormsInline() {
const {mdDown} = useBreakpoints();
const {mobileInlineFormLabels} = useFeatures();

return mdDown || mobileInlineFormLabels;
}

0 comments on commit d95df43

Please sign in to comment.