Skip to content

Commit

Permalink
[TextField | IndexFilters] Add support for autoSize TextField, and us…
Browse files Browse the repository at this point in the history
…e in IndexFilters (Shopify#11412)

### WHY are these changes introduced?

Fixes Shopify/shopify#407738

Updates the TextField component with new `loading` and `autoSize` props.
The `loading` prop will show a spinner at the right of the input if
`true`, whereas the `autoSize` prop will make the input grow with the
value of the input itself.

This is a required update to cater for the desired UX we want in the
IndexFilters to persist the view name to the immediate right of the
search query.

This PR also updates the SearchField within the Filters component to
utilise these new props on the TextField, as well as update stories and
examples to show off the new functionality.

### WHAT is this pull request doing?

<!--
  Summary of the changes committed.

Before / after screenshots are appreciated for UI changes. Make sure to
include alt text that describes the screenshot.

  Include a video if your changes include interactive content.

If you include an animated gif showing your change, wrapping it in a
details tag is recommended. Gifs usually autoplay, which can cause
accessibility issues for people reviewing your PR:

  <details>
    <summary>Summary of your gif(s)</summary>
    <img src="..." alt="Description of what the gif shows">
  </details>
-->

### How to 🎩

🖥 [Local development
instructions](https://github.com/Shopify/polaris/blob/main/README.md#install-dependencies-and-build-workspaces)
🗒 [General tophatting
guidelines](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md)
📄 [Changelog
guidelines](https://github.com/Shopify/polaris/blob/main/.github/CONTRIBUTING.md#changelog)

Spin URL:
https://admin.web.persistent-view-name.marc-thomas.eu.spin.dev/store/shop1/products?selectedView=archived&status=ARCHIVED

- Navigate to the URL
- Confirm that a placeholder is visible in the search TextField
- Start typing into the search TextField
- Confirm that the TextField grows as you type
- Confirm that a suffix saying "in: [View name]" is visible only when a
value is present in the TextField
- Confirm that the suffix always stays a consistent spacing apart from
the TextField
- Confirm that other UI, such as the loading indicator, remain placed
where they should be, right-aligned to the edge of the search area

### 🎩 checklist

- [x] Tested a
[snapshot](https://github.com/Shopify/polaris/blob/main/documentation/Releasing.md#-snapshot-releases)
- [x] Tested on
[mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing)
- [x] Tested on [multiple
browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers)
- [x] Tested for
[accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md)
- [x] Updated the component's `README.md` with documentation changes
- [x] [Tophatted
documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md)
changes in the style guide

---------

Co-authored-by: translation-platform[bot] <34770790+translation-platform[bot]@users.noreply.github.com>
  • Loading branch information
mrcthms and translation-platform[bot] authored Jan 16, 2024
1 parent bbdb125 commit 7e6b239
Show file tree
Hide file tree
Showing 34 changed files with 498 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-ears-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/polaris': minor
---

[TextField] Updated the TextField with new `autoSize` and `loading` props
3 changes: 2 additions & 1 deletion polaris-react/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Vymazat {filterName}",
"moreFiltersWithCount": "Další filtry ({count})",
"addFilter": "Přidat filtr",
"clearFilters": "Vymazat vše"
"clearFilters": "Vymazat vše",
"searchInView": "v zobrazení: {viewName}"
},
"Modal": {
"iFrameTitle": "kód hlavní části",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Ryd {filterName}",
"moreFiltersWithCount": "Flere filtre: ({count})",
"addFilter": "Tilføj filter",
"clearFilters": "Ryd alt"
"clearFilters": "Ryd alt",
"searchInView": "i: {viewName}"
},
"Modal": {
"iFrameTitle": "body markup",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "{filterName} löschen",
"moreFiltersWithCount": "Weitere Filter ({count})",
"addFilter": "Filter hinzufügen",
"clearFilters": "Alles löschen"
"clearFilters": "Alles löschen",
"searchInView": "in: {viewName}"
},
"Modal": {
"iFrameTitle": "Text-Markup",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@
"clear": "Clear",
"clearLabel": "Clear {filterName}",
"addFilter": "Add filter",
"clearFilters": "Clear all"
"clearFilters": "Clear all",
"searchInView": "in:{viewName}"
},
"FilterPill": {
"clear": "Clear"
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Borrar {filterName}",
"moreFiltersWithCount": "Más filtros ({count})",
"addFilter": "Agregar filtro",
"clearFilters": "Borrar todo"
"clearFilters": "Borrar todo",
"searchInView": "in:{viewName}"
},
"Modal": {
"iFrameTitle": "marcado body",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Tyhjennä {filterName}",
"moreFiltersWithCount": "Lisää suodattimia ({count})",
"addFilter": "Lisää suodatin",
"clearFilters": "Tyhjennä kaikki"
"clearFilters": "Tyhjennä kaikki",
"searchInView": "kohde:{viewName}"
},
"Modal": {
"iFrameTitle": "tekstin merkintä",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Effacer {filterName}",
"moreFiltersWithCount": "Plus de filtres ({count})",
"addFilter": "Ajouter un filtre",
"clearFilters": "Tout effacer"
"clearFilters": "Tout effacer",
"searchInView": "dans : {viewName}"
},
"Modal": {
"iFrameTitle": "balisage du corps",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Rimuovi {filterName}",
"moreFiltersWithCount": "Altri filtri ({count})",
"addFilter": "Aggiungi filtro",
"clearFilters": "Cancella tutto"
"clearFilters": "Cancella tutto",
"searchInView": "in: {viewName}"
},
"Modal": {
"iFrameTitle": "markup del testo",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "{filterName}をクリアする",
"moreFiltersWithCount": "詳細な絞り込み ({count})",
"addFilter": "絞り込みを追加",
"clearFilters": "すべてクリア"
"clearFilters": "すべてクリア",
"searchInView": "{viewName}内"
},
"Modal": {
"iFrameTitle": "body markup",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "{filterName} 지우기",
"moreFiltersWithCount": "추가 필터({count}개)",
"addFilter": "필터 추가",
"clearFilters": "모두 지우기"
"clearFilters": "모두 지우기",
"searchInView": "{viewName} 보기에서 검색 중"
},
"Modal": {
"iFrameTitle": "본문 표시",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Fjern {filterName}",
"moreFiltersWithCount": "Flere filtre ({count})",
"addFilter": "Legg til filter",
"clearFilters": "Fjern alle"
"clearFilters": "Fjern alle",
"searchInView": "i: {viewName}"
},
"Modal": {
"iFrameTitle": "brødtekstpåslag",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "{filterName} wissen",
"moreFiltersWithCount": "Meer filters ({count})",
"addFilter": "Filter toevoegen",
"clearFilters": "Alles wissen"
"clearFilters": "Alles wissen",
"searchInView": "in: {viewName}"
},
"Modal": {
"iFrameTitle": "opmaak hoofdtekst",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Wyczyść {filterName}",
"moreFiltersWithCount": "Więcej filtrów ({count})",
"addFilter": "Dodaj filtr",
"clearFilters": "Wyczyść wszystko"
"clearFilters": "Wyczyść wszystko",
"searchInView": "w:{viewName}"
},
"Modal": {
"iFrameTitle": "znacznik treści",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Limpar {filterName}",
"moreFiltersWithCount": "Mais filtros ({count})",
"addFilter": "Adicionar filtro",
"clearFilters": "Limpar tudo"
"clearFilters": "Limpar tudo",
"searchInView": "in: {viewName}"
},
"Modal": {
"iFrameTitle": "marcação de corpo",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/pt-PT.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Limpar {filterName}",
"moreFiltersWithCount": "Mais filtros ({count})",
"addFilter": "Adicionar filtro",
"clearFilters": "Limpar tudo"
"clearFilters": "Limpar tudo",
"searchInView": "em:{viewName}"
},
"Modal": {
"iFrameTitle": "marcação de corpo",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/sv.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "Rensa {filterName}",
"moreFiltersWithCount": "Fler filter ({count})",
"addFilter": "Lägg till filter",
"clearFilters": "Rensa alla"
"clearFilters": "Rensa alla",
"searchInView": "i:{viewName}"
},
"Modal": {
"iFrameTitle": "markering av brödtext",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/th.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "ล้าง {filterName}",
"moreFiltersWithCount": "ตัวกรองเพิ่มเติม ({count})",
"addFilter": "เพิ่มตัวกรอง",
"clearFilters": "ล้างทั้งหมด"
"clearFilters": "ล้างทั้งหมด",
"searchInView": "ใน:{viewName}"
},
"Modal": {
"iFrameTitle": "มาร์กอัปเนื้อหา",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "{filterName} filtresini temizle",
"moreFiltersWithCount": "Daha fazla filtre ({count})",
"addFilter": "Filtre ekle",
"clearFilters": "Tümünü temizle"
"clearFilters": "Tümünü temizle",
"searchInView": "Şu görünümde: {viewName}"
},
"Modal": {
"iFrameTitle": "gövde işaretlemesi",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clear": "Xóa",
"clearLabel": "Xóa {filterName}",
"addFilter": "Thêm bộ lọc",
"clearFilters": "Xóa tất cả"
"clearFilters": "Xóa tất cả",
"searchInView": "in:{viewName}"
},
"Modal": {
"iFrameTitle": "điểm đánh dấu nội dung",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "清除 {filterName}",
"moreFiltersWithCount": "更多筛选条件({count} 个)",
"addFilter": "添加筛选条件",
"clearFilters": "全部清除"
"clearFilters": "全部清除",
"searchInView": "在:{viewName}"
},
"Modal": {
"iFrameTitle": "正文标记",
Expand Down
3 changes: 2 additions & 1 deletion polaris-react/locales/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
"clearLabel": "清除 {filterName}",
"moreFiltersWithCount": "更多篩選條件 ({count})",
"addFilter": "新增篩選條件",
"clearFilters": "全部清除"
"clearFilters": "全部清除",
"searchInView": "in: {viewName}"
},
"Modal": {
"iFrameTitle": "本文標記",
Expand Down
4 changes: 4 additions & 0 deletions polaris-react/src/components/Filters/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export interface FiltersProps {
onAddFilterClick?: () => void;
/** Whether the filter should close when clicking inside another Popover. */
closeOnChildOverlayClick?: boolean;
/** The name of the currently selected view */
selectedViewName?: string;
}

export function Filters({
Expand All @@ -121,6 +123,7 @@ export function Filters({
mountedState,
onAddFilterClick,
closeOnChildOverlayClick,
selectedViewName,
}: FiltersProps) {
const hideFilterBar = hideFilters || filters.length === 0;
const queryFieldMarkup = hideQueryField ? null : (
Expand Down Expand Up @@ -156,6 +159,7 @@ export function Filters({
disabled={disabled || disableQueryField}
borderlessQueryField={borderlessQueryField}
loading={loading}
selectedViewName={selectedViewName}
/>
</div>
{children}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, {useId} from 'react';
import {SearchIcon} from '@shopify/polaris-icons';

import {Spinner} from '../../../Spinner';
import {Icon} from '../../../Icon';
import {TextField} from '../../../TextField';
import {Text} from '../../../Text';
import {useBreakpoints} from '../../../../utilities/breakpoints';

import styles from './SearchField.module.scss';
import {useI18n} from '../../../../utilities/i18n';

export interface SearchFieldProps {
onChange: (value: string) => void;
Expand All @@ -20,6 +19,8 @@ export interface SearchFieldProps {
borderlessQueryField?: boolean;
/** Show a loading spinner to the right of the input */
loading?: boolean;
/** If present, will show as a suffix in the text field when entering a search term */
selectedViewName?: string;
}

export function SearchField({
Expand All @@ -33,10 +34,21 @@ export function SearchField({
disabled,
borderlessQueryField,
loading,
selectedViewName,
}: SearchFieldProps) {
const i18n = useI18n();
const id = useId();
const {mdUp} = useBreakpoints();

const suffix =
value && selectedViewName && mdUp ? (
<Text as="span" variant="bodyMd" tone="subdued">
{i18n.translate('Polaris.Filters.searchInView', {
viewName: selectedViewName,
})}
</Text>
) : null;

function handleChange(value: string) {
onChange(value);
}
Expand All @@ -63,17 +75,13 @@ export function SearchField({
variant={borderlessQueryField ? 'borderless' : 'inherit'}
size="slim"
prefix={mdUp ? <Icon source={SearchIcon} /> : undefined}
suffix={
loading ? (
<div className={styles.Spinner}>
<Spinner size="small" />
</div>
) : null
}
suffix={suffix}
focused={focused}
label={placeholder}
labelHidden
clearButton
autoSize={mdUp}
loading={loading}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ import {matchMedia} from '@shopify/jest-dom-mocks';
import {SearchField} from '..';
import {TextField} from '../../../../TextField';

jest.mock('../../../../../utilities/breakpoints', () => ({
...(jest.requireActual('../../../../../utilities/breakpoints') as any),
useBreakpoints: jest.fn(),
}));

function mockUseBreakpoints(mdUp: boolean) {
const useBreakpoints: jest.Mock = jest.requireMock(
'../../../../../utilities/breakpoints',
).useBreakpoints;

useBreakpoints.mockReturnValue({
mdUp,
});
}

describe('SearchField', () => {
const defaultProps: ComponentProps<typeof SearchField> = {
onChange: jest.fn(),
Expand All @@ -16,6 +31,7 @@ describe('SearchField', () => {
beforeEach(() => {
jest.clearAllMocks();
matchMedia.mock();
mockUseBreakpoints(false);
});

afterEach(() => {
Expand Down Expand Up @@ -74,4 +90,31 @@ describe('SearchField', () => {
placeholder: defaultProps.placeholder,
});
});

it('will add a suffix when there is a selectedViewName and value', () => {
mockUseBreakpoints(true);
const wrapper = mountWithApp(
<SearchField {...defaultProps} selectedViewName="All" />,
);

expect(wrapper).toContainReactText('in:All');
});

it('will not add a suffix when there is no selectedViewName', () => {
const wrapper = mountWithApp(<SearchField {...defaultProps} />);

expect(wrapper).not.toContainReactText('in:All');
});

it('will not add a suffix when there is no value', () => {
const wrapper = mountWithApp(
<SearchField
{...defaultProps}
value={undefined}
selectedViewName="All"
/>,
);

expect(wrapper).not.toContainReactText('in:All');
});
});
3 changes: 3 additions & 0 deletions polaris-react/src/components/IndexFilters/IndexFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ export function IndexFilters({

const viewNames = tabs.map(({content}) => content);

const selectedViewName = viewNames[selected];

const handleChangeSortButton = useCallback(
(value: string[]) => {
onSort?.(value);
Expand Down Expand Up @@ -459,6 +461,7 @@ export function IndexFilters({
mountedState={mdDown ? undefined : state}
borderlessQueryField
closeOnChildOverlayClick={closeOnChildOverlayClick}
selectedViewName={selectedViewName}
>
<div className={styles.ButtonWrap}>
<InlineStack gap="200" align="start" blockAlign="center">
Expand Down
Loading

0 comments on commit 7e6b239

Please sign in to comment.