UNPKG

@postnord/web-components

Version:

PostNord Web Components

346 lines (345 loc) 12 kB
/*! * Built with Stencil * By PostNord. */ import { createDocumentation, createComponent } from "../../../globals/documentation/story"; import docs from "./pn-input-docs.json"; import { getFigmaUrl } from "../../../globals/figmaLinks"; const { argTypes, textContent } = createDocumentation(docs); /** * The `pn-input` is a classic input component. * It comes packaged with support for label, helpertext and validation style features. * * Most common attributes are included, such as placeholder, type, etc... */ const meta = { title: 'Components/Input/Input', parameters: { actions: { handles: ['input'], }, design: { type: 'figma', url: getFigmaUrl(import.meta.url), }, }, args: { label: 'Username', helpertext: '', inputid: '', value: '', language: '', icon: '', textPrefix: '', textSuffix: '', type: '', name: '', placeholder: '', autocomplete: '', maxlength: null, inputmode: null, list: '', pattern: '', min: '', max: '', step: '', arialabel: '', ariacontrols: '', disabled: false, required: false, readonly: false, valid: false, invalid: false, error: '', }, argTypes, }; meta.argTypes.icon.if = { arg: 'textPrefix', eq: '' }; meta.argTypes.textPrefix.if = { arg: 'textSuffix', eq: '' }; meta.argTypes.textSuffix.if = { arg: 'textPrefix', eq: '' }; meta.argTypes.maxlength.type = 'number'; meta.argTypes.valid.if = { arg: 'invalid', eq: false }; meta.argTypes.invalid.if = { arg: 'valid', eq: false }; meta.argTypes.error.if = { arg: 'valid', eq: false }; export default meta; export const PnInput = { name: 'pn-input', parameters: { docs: { description: { story: textContent, }, }, }, render: args => createComponent('pn-input', args), }; /** * We recommend that you always use the `label`, `name` and `type` props. * This greatly improves user experience as it helps the browser to suggest values for the input. * * */ export const PnInputAttributes = { name: 'pn-input (HTML attributes)', render: PnInput.render, args: { label: 'First and last name', value: 'John Doe', inputid: 'pn-name', name: 'first-last-name', autocomplete: 'name full-name first-name last-name', maxlength: 40, required: true, }, }; /** Provide a description for the input element. */ export const PnInputHelper = { name: 'pn-input (helpertext)', render: PnInput.render, args: { label: 'Adress', helpertext: 'Remember to include house number.', }, }; /** * Provide a `placeholder` for the input element. * The `placeholder` should hint the user of what the data should look like. * * <pn-toast * heading="The placeholder is not a replacement for the label prop." * text="The placeholder disappears as soon as the user enters any data, so put important information in the helpertext prop instead. Always use a label." * appearance="warning" * > * </pn-toast> **/ export const PnInputPlaceholder = { name: 'pn-input (placeholder)', render: PnInput.render, args: { label: 'Swedish personal number', placeholder: 'YYYYMMDD-XXXX', }, }; /** * Use one of our icons or your own SVG content. * Icons are eye candy and should not include text or any other type of information. * * If you need additional text to describe the input, use the `prefix` or `suffix` prop. * * <pn-toast appearance="warning">Use the icon property sparingly.</pn-toast> **/ export const PnInputIcon = { name: 'pn-input (icon)', render: PnInput.render, args: { label: 'Credit card number', name: 'credit-card', icon: 'credit_card', }, }; /** * Use the `prefix` to add a piece of text infront of the input value. * * Cannot be used together with an `icon`. **/ export const PnInputPrefix = { name: 'pn-input (prefix)', render: PnInput.render, args: { label: 'Total value', value: '24', textPrefix: '€', }, }; /** * Use the `suffix` to add a piece of text after the input value. * * Cannot be used together with type `search` or `password`. **/ export const PnInputSuffix = { name: 'pn-input (suffix)', render: PnInput.render, args: { label: 'Freight weight', value: '120', textSuffix: 'kg', }, }; const types = [ { type: 'text', value: 'Text value', helpertext: 'The default text type input.' }, { type: 'password', value: 'HiddenPassword', autocomplete: 'off', helpertext: 'Turn the pn-input into a password field. The show/hide button is transalted in sv, en, da, fi and no. The language is changed automatically based on the topbar. Use the language prop to change manually.', }, { type: 'url', value: 'https://portal.postnord.com/se/en/', helpertext: 'Turn the field into a URL type' }, { type: 'tel', value: '0760388344', helpertext: 'Use the pattern prop to set a constraint on the input.' }, { type: 'search', value: 'Search string', helpertext: 'Turn the pn-input into a search field. When you have entered any value, the "clear" button will appear.', }, { type: 'number', value: '24', helpertext: 'You can use the pn-input for numbers. You can set step, min and max as well. Need more control? Use the pn-counter component.', }, { type: 'email', value: 'jon@arbuckle.com', autocomplete: 'email', helpertext: 'Accept an email value' }, ]; /** Get a quick overview of all input types. */ export const PnInputTypes = { name: 'pn-input (all types)', render: args => { const form = document.createElement('form'); form.className = 'sb-button-row'; form.style.flexDirection = 'column'; form.style.width = '20em'; form.style.alignItems = 'stretch'; types.forEach(({ type, value, helpertext, autocomplete = null }) => form.appendChild(createComponent('pn-input', { ...args, type, autocomplete, label: type, value, helpertext }))); return form; }, }; /** * Use the `datalist` element and associate the ID with the same ID supplied in the `list` prop. * * The dropdown list itself looks a bit different between browsers, * but has overall support for all modern browsers (except for Firefox on Android). * * For the `list` prop to work, you must provide a `<datalist></datalist>` element somewhere in the DOM. * The `datalist` element must have the same ID as you set in the `list` prop on the `pn-input`. * * Read more about how to use the list feature on <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist" target="_blank">MDN web docs</a>. */ export const PnInputList = { name: 'pn-input (list)', render: (args, context) => { const div = document.createElement('div'); div.appendChild(PnInput.render(args, context)); div.innerHTML += `<datalist id="${args.list}"> <option value="stockholm">Stockholm</option> <option value="gothenburg">Gothenburg</option> <option value="malmo">Malmö</option> <option value="uppsala">Uppsala</option> <option value="halmstad">Halmstad</option> </datalist> `; return div; }, args: { label: 'Select city', value: '', icon: 'search', type: 'search', name: 'city', list: 'pn-list-example-id', }, }; /** Set the `pn-input` as `valid`. Use this only if you have a validation feature in place, as to not confuse the user. */ export const PnInputValid = { name: 'pn-input (valid)', render: PnInput.render, args: { label: 'Postal code', value: '561 39', helpertext: 'With or out without "-"', valid: true, }, }; /** * Setting the `error` prop/slot will automatically activate the `invalid` style. * This message will hide the existing `helpertext`, if there is one. Removing the `error` will show the `helpertext` again. **/ export const PnInputError = { name: 'pn-input (error)', render: PnInput.render, args: { label: 'Postal code', helpertext: 'Enter a valid postal code.', error: 'Invalid input.', }, }; /** * We recommend that you always use the `error` prop to trigger the invalid state and give an error message to the user. * If you already provide the error message in a way that is tied to the input (with a fieldset for example), you may simply want * to trigger the invalid state without an additional error message with the `invalid` prop. */ export const PnInputInvalid = { name: 'pn-input (invalid)', render: (args, context) => { const input = PnInput.render(args, context); const inputCity = createComponent('pn-input', { label: 'Postal area', value: 'Stockholm', name: 'address.postal-city', }); const inputStreet = createComponent('pn-input', { label: 'Adress', value: 'Terminalvägen 24', name: 'adress.street', }); const field = createComponent('pn-fieldset', { legend: 'User info', error: 'No postal code provided.' }); field.appendChild(inputStreet); field.appendChild(input); field.appendChild(inputCity); const form = document.createElement('form'); form.appendChild(field); return form; }, args: { label: 'Postal code', invalid: true, name: 'address.postal-code', }, }; /** * The **props** `helpertext` and `error` allows you to set the content with a string. * This way does not allow you to include a link for example. * * With the **slots** `helpertext` and `error` you can include additional HTML. This way you keep the accessible markup * as long as you stay with HTML text and links. Do not include buttons or other input elements in this slot. **/ export const PnInputHelperSlot = { name: 'pn-input (helper slot)', render: (args, context) => { const input = PnInput.render(args, context); input.innerHTML += `<span slot="helpertext">Read more about <pn-text-link href="${location.href}">the format of personal IDs.</pn-text-link></span>`; return input; }, args: { label: 'Personal ID', }, }; /** * The slots `helpertext` and `error` works the same as the props. If you set an `error` slot or prop, it will hide the `helpertext`. * * You can use both the slots and props along side each other. **/ export const PnInputErrorSlot = { name: 'pn-input (error slot)', render: (args, context) => { const input = PnInput.render(args, context); const errorMessage = `Wrong format, <pn-text-link href="${location.href}">view personal ID format.</pn-text-link>`; input.innerHTML += `<span slot="helpertext">Read more about <pn-text-link href="${location.href}">the format of personal ID.</pn-text-link></span>`; input.innerHTML += `<span slot="error">${errorMessage}</span>`; input.style.width = '18em'; const button = createComponent('pn-button', { label: 'Toggle Error' }); button.addEventListener('click', () => { const errorElement = input.querySelector('[slot="error"]'); if (errorElement.innerText) errorElement.innerHTML = ''; else errorElement.innerHTML = errorMessage; }); const div = document.createElement('div'); div.className = 'sb-button-row'; div.style.flexDirection = 'column'; div.appendChild(input); div.appendChild(button); return div; }, args: { label: 'Personal ID', }, }; //# sourceMappingURL=pn-input.stories.js.map