Fix stories
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { PropDef, GetPropDefTypes } from '../../props/prop-def';
|
||||
|
||||
/** @public */
|
||||
export const textFieldPropDefs = {
|
||||
size: {
|
||||
type: 'enum',
|
||||
values: ['small', 'medium'],
|
||||
className: 'canon-Button--size',
|
||||
default: 'medium',
|
||||
responsive: true,
|
||||
},
|
||||
} satisfies {
|
||||
size: PropDef<'small' | 'medium'>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type TextFieldOwnProps = GetPropDefTypes<typeof textFieldPropDefs>;
|
||||
@@ -89,26 +89,6 @@ export const Responsive: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
async function submitForm(value: string) {
|
||||
// Mimic a server response
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, 200);
|
||||
});
|
||||
|
||||
try {
|
||||
const url = new URL(value);
|
||||
|
||||
const allowedHosts = ['example.com', 'beta.example.com', 'www.example.com'];
|
||||
if (!allowedHosts.includes(url.hostname)) {
|
||||
return { error: 'The example domain is not allowed' };
|
||||
}
|
||||
} catch {
|
||||
return { error: 'This is not a valid URL' };
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
export const ShowErrorOnSubmit: Story = {
|
||||
args: {
|
||||
...WithLabel.args,
|
||||
@@ -116,30 +96,54 @@ export const ShowErrorOnSubmit: Story = {
|
||||
type: 'url',
|
||||
required: true,
|
||||
label: 'Homepage',
|
||||
name: 'url',
|
||||
},
|
||||
decorators: [
|
||||
Story => {
|
||||
const [errors, setErrors] = useState({});
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(event.currentTarget);
|
||||
|
||||
setLoading(true);
|
||||
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, 200);
|
||||
});
|
||||
|
||||
try {
|
||||
const url = new URL(formData.get('url') as string);
|
||||
|
||||
const allowedHosts = [
|
||||
'backstage.io',
|
||||
'beta.backstage.io',
|
||||
'www.backstage.io',
|
||||
];
|
||||
|
||||
if (!allowedHosts.includes(url.hostname)) {
|
||||
setErrors({ url: 'The example domain is not allowed' });
|
||||
setLoading(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setErrors({});
|
||||
setLoading(false);
|
||||
|
||||
return;
|
||||
} catch {
|
||||
setErrors({ url: 'This is not a valid URL' });
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
errors={errors}
|
||||
onClearErrors={setErrors}
|
||||
onSubmit={async event => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(event.currentTarget);
|
||||
const value = formData.get('url') as string;
|
||||
|
||||
setLoading(true);
|
||||
const response = await submitForm(value);
|
||||
const serverErrors = {
|
||||
url: response.error,
|
||||
};
|
||||
|
||||
setErrors(serverErrors);
|
||||
setLoading(false);
|
||||
}}
|
||||
onClearErrors={() => setErrors({})}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Story />
|
||||
<Button
|
||||
@@ -161,7 +165,7 @@ export const ShowErrorOnSubmit: Story = {
|
||||
selector: 'input',
|
||||
});
|
||||
|
||||
await userEvent.type(input, 'https://example.com', {
|
||||
await userEvent.type(input, 'https://backstage-fake-site.com', {
|
||||
delay: 20,
|
||||
});
|
||||
|
||||
|
||||
@@ -16,5 +16,3 @@
|
||||
|
||||
export * from './TextField';
|
||||
export type { TextFieldProps } from './types';
|
||||
export { textFieldPropDefs } from './TextField.props';
|
||||
export type { TextFieldOwnProps } from './TextField.props';
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import type { TextFieldOwnProps } from './TextField.props';
|
||||
|
||||
import type { Breakpoint } from '../../types';
|
||||
|
||||
/** @public */
|
||||
export interface TextFieldProps
|
||||
@@ -27,7 +28,7 @@ export interface TextFieldProps
|
||||
* The size of the text field
|
||||
* @defaultValue 'medium'
|
||||
*/
|
||||
size?: TextFieldOwnProps['size'];
|
||||
size?: 'small' | 'medium' | Partial<Record<Breakpoint, 'small' | 'medium'>>;
|
||||
|
||||
/**
|
||||
* The label of the text field
|
||||
|
||||
Reference in New Issue
Block a user