Don't fallback to name on label to help clarify the different uses for each and allow label-less filters.
Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-search': minor
|
||||
---
|
||||
|
||||
The way labels are controlled on both the `<SearchFilter.Checkbox />` and
|
||||
`<SearchFilter.Select />` components has changed. Previously, the string passed
|
||||
on the `name` prop (which controls the field being filtered on) was also
|
||||
rendered as the field label. Now, if you want a label rendered, it must be
|
||||
passed on the new `label` prop. If no `label` is provided, no label will be
|
||||
rendered.
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
A `label` prop was added to `<SearchFilter.* />` components in order to allow
|
||||
user-friendly label strings (as well as the option to omit a label). In order
|
||||
to maintain labels on your existing filters, add a `label` prop to them in your
|
||||
`SearchPage.tsx`.
|
||||
|
||||
```diff
|
||||
--- a/packages/app/src/components/search/SearchPage.tsx
|
||||
+++ b/packages/app/src/components/search/SearchPage.tsx
|
||||
@@ -96,11 +96,13 @@ const SearchPage = () => {
|
||||
)}
|
||||
<SearchFilter.Select
|
||||
className={classes.filter}
|
||||
+ label="Kind"
|
||||
name="kind"
|
||||
values={['Component', 'Template']}
|
||||
/>
|
||||
<SearchFilter.Checkbox
|
||||
className={classes.filter}
|
||||
+ label="Lifecycle"
|
||||
name="lifecycle"
|
||||
values={['experimental', 'production']}
|
||||
/>
|
||||
```
|
||||
@@ -115,11 +115,13 @@ const SearchPage = () => {
|
||||
)}
|
||||
<SearchFilter.Select
|
||||
className={classes.filter}
|
||||
label="Kind"
|
||||
name="kind"
|
||||
values={['Component', 'Template']}
|
||||
/>
|
||||
<SearchFilter.Checkbox
|
||||
className={classes.filter}
|
||||
label="Lifecycle"
|
||||
name="lifecycle"
|
||||
values={['experimental', 'production']}
|
||||
/>
|
||||
|
||||
+2
@@ -96,11 +96,13 @@ const SearchPage = () => {
|
||||
)}
|
||||
<SearchFilter.Select
|
||||
className={classes.filter}
|
||||
label="Kind"
|
||||
name="kind"
|
||||
values={['Component', 'Template']}
|
||||
/>
|
||||
<SearchFilter.Checkbox
|
||||
className={classes.filter}
|
||||
label="Lifecycle"
|
||||
name="lifecycle"
|
||||
values={['experimental', 'production']}
|
||||
/>
|
||||
|
||||
@@ -78,7 +78,7 @@ export const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => {
|
||||
{...params}
|
||||
name="search"
|
||||
variant="outlined"
|
||||
label={label || name}
|
||||
label={label}
|
||||
fullWidth
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -34,6 +34,7 @@ describe('SearchFilter', () => {
|
||||
types: [],
|
||||
};
|
||||
|
||||
const label = 'Field';
|
||||
const name = 'field';
|
||||
const values = ['value1', 'value2'];
|
||||
const filters = { unrelated: 'unrelated' };
|
||||
@@ -57,12 +58,12 @@ describe('SearchFilter', () => {
|
||||
it('Renders field name and values when provided as props', async () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Checkbox name={name} values={values} />
|
||||
<SearchFilter.Checkbox label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
@@ -83,12 +84,12 @@ describe('SearchFilter', () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SearchFilter.Checkbox name={name} values={values} />
|
||||
<SearchFilter.Checkbox label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
@@ -101,6 +102,7 @@ describe('SearchFilter', () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Checkbox
|
||||
label={label}
|
||||
name={name}
|
||||
values={values}
|
||||
defaultValue={[values[0]]}
|
||||
@@ -109,7 +111,7 @@ describe('SearchFilter', () => {
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(screen.getByRole('checkbox', { name: values[0] })).toBeChecked();
|
||||
@@ -121,12 +123,12 @@ describe('SearchFilter', () => {
|
||||
it('Checking / unchecking a value sets filter state', async () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Checkbox name={name} values={values} />
|
||||
<SearchFilter.Checkbox label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const checkBox = screen.getByRole('checkbox', { name: values[0] });
|
||||
@@ -151,12 +153,12 @@ describe('SearchFilter', () => {
|
||||
it('Checking / unchecking a value maintains unrelated filter state', async () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={{ ...initialState, filters }}>
|
||||
<SearchFilter.Checkbox name={name} values={values} />
|
||||
<SearchFilter.Checkbox label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const checkBox = screen.getByRole('checkbox', { name: values[0] });
|
||||
@@ -185,12 +187,12 @@ describe('SearchFilter', () => {
|
||||
it('Renders field name and values when provided as props', async () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Select name={name} values={values} />
|
||||
<SearchFilter.Select label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
userEvent.click(screen.getByRole('button'));
|
||||
@@ -210,7 +212,11 @@ describe('SearchFilter', () => {
|
||||
it('Renders values when provided asynchronously', async () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Select name={name} asyncValues={async () => values} />
|
||||
<SearchFilter.Select
|
||||
label={label}
|
||||
name={name}
|
||||
asyncValues={async () => values}
|
||||
/>
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
@@ -245,12 +251,12 @@ describe('SearchFilter', () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SearchFilter.Select name={name} values={values} />
|
||||
<SearchFilter.Select label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
userEvent.click(screen.getByRole('button'));
|
||||
@@ -276,6 +282,7 @@ describe('SearchFilter', () => {
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Select
|
||||
name={name}
|
||||
label={label}
|
||||
values={values}
|
||||
defaultValue={values[0]}
|
||||
/>
|
||||
@@ -283,7 +290,7 @@ describe('SearchFilter', () => {
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
userEvent.click(screen.getByRole('button'));
|
||||
@@ -307,12 +314,12 @@ describe('SearchFilter', () => {
|
||||
it('Selecting a value sets filter state', async () => {
|
||||
render(
|
||||
<SearchContextProvider initialState={initialState}>
|
||||
<SearchFilter.Select name={name} values={values} />
|
||||
<SearchFilter.Select label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
@@ -358,12 +365,12 @@ describe('SearchFilter', () => {
|
||||
filters,
|
||||
}}
|
||||
>
|
||||
<SearchFilter.Select name={name} values={values} />
|
||||
<SearchFilter.Select label={label} name={name} values={values} />
|
||||
</SearchContextProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
expect(screen.getByText(label)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
|
||||
@@ -93,7 +93,7 @@ const CheckboxFilter = (props: SearchFilterComponentProps) => {
|
||||
fullWidth
|
||||
data-testid="search-checkboxfilter-next"
|
||||
>
|
||||
<FormLabel className={classes.label}>{label || name}</FormLabel>
|
||||
{label ? <FormLabel className={classes.label}>{label}</FormLabel> : null}
|
||||
{values.map((value: string) => (
|
||||
<FormControlLabel
|
||||
key={value}
|
||||
@@ -154,9 +154,11 @@ const SelectFilter = (props: SearchFilterComponentProps) => {
|
||||
fullWidth
|
||||
data-testid="search-selectfilter-next"
|
||||
>
|
||||
<InputLabel className={classes.label} margin="dense">
|
||||
{label || name}
|
||||
</InputLabel>
|
||||
{label ? (
|
||||
<InputLabel className={classes.label} margin="dense">
|
||||
{label}
|
||||
</InputLabel>
|
||||
) : null}
|
||||
<Select
|
||||
variant="outlined"
|
||||
value={filters[name] || ''}
|
||||
|
||||
Reference in New Issue
Block a user