| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- import { Meta, StoryObj } from '@storybook/react-webpack5'
- import { useState } from 'react'
- import OLAutocomplete from '@/shared/components/ol/ol-autocomplete'
- type Args = React.ComponentProps<typeof OLAutocomplete>
- const sampleItems = [
- { value: 'react', label: 'React' },
- { value: 'vue', label: 'Vue' },
- { value: 'angular', label: 'Angular' },
- { value: 'svelte', label: 'Svelte' },
- { value: 'ember', label: 'Ember' },
- { value: 'backbone', label: 'Backbone' },
- { value: 'preact', label: 'Preact' },
- { value: 'nextjs', label: 'Next.js' },
- { value: 'nuxtjs', label: 'Nuxt.js' },
- { value: 'gatsby', label: 'Gatsby' },
- ]
- const programmingLanguages = [
- { value: 'javascript', label: 'JavaScript' },
- { value: 'typescript', label: 'TypeScript' },
- { value: 'python', label: 'Python' },
- { value: 'java', label: 'Java' },
- { value: 'cpp', label: 'C++' },
- { value: 'csharp', label: 'C#' },
- { value: 'go', label: 'Go' },
- { value: 'rust', label: 'Rust' },
- { value: 'ruby', label: 'Ruby' },
- { value: 'php', label: 'PHP' },
- { value: 'swift', label: 'Swift' },
- { value: 'kotlin', label: 'Kotlin' },
- { value: 'dart', label: 'Dart' },
- ]
- const countries = [
- { value: 'us', label: 'United States' },
- { value: 'uk', label: 'United Kingdom' },
- { value: 'ca', label: 'Canada' },
- { value: 'au', label: 'Australia' },
- { value: 'de', label: 'Germany' },
- { value: 'fr', label: 'France' },
- { value: 'es', label: 'Spain' },
- { value: 'it', label: 'Italy' },
- { value: 'nl', label: 'Netherlands' },
- { value: 'be', label: 'Belgium' },
- ]
- const entryTypeItems = [
- { value: 'article', label: 'Article', group: 'Most common' },
- { value: 'review', label: 'Review', group: 'Most common' },
- { value: 'book', label: 'Book', group: 'Most common' },
- { value: 'conference', label: 'Conference paper', group: 'Most common' },
- { value: 'thesis', label: 'Thesis', group: 'Most common' },
- { value: 'mastersthesis', label: "Master's thesis", group: 'Most common' },
- { value: 'phdthesis', label: 'PhD thesis', group: 'Most common' },
- { value: 'bookchapter', label: 'Book chapter', group: 'Book types' },
- { value: 'booksection', label: 'Book section', group: 'Book types' },
- { value: 'bookpart', label: 'Book part', group: 'Book types' },
- { value: 'editedbook', label: 'Edited book', group: 'Book types' },
- { value: 'referencebook', label: 'Reference book', group: 'Book types' },
- { value: 'proceedings', label: 'Conference proceedings', group: 'Other' },
- { value: 'journalarticle', label: 'Journal article', group: 'Other' },
- { value: 'techreport', label: 'Technical report', group: 'Other' },
- { value: 'preprint', label: 'Preprint', group: 'Other' },
- { value: 'patent', label: 'Patent', group: 'Other' },
- { value: 'manuscript', label: 'Manuscript', group: 'Other' },
- { value: 'unpublished', label: 'Unpublished', group: 'Other' },
- ]
- function InteractiveAutocomplete(args: Args) {
- const [value, setValue] = useState('')
- return (
- <div style={{ maxWidth: '400px' }}>
- <OLAutocomplete {...args} onChange={setValue} />
- <div style={{ marginTop: '1rem' }}>
- <strong>Current value:</strong> {value || '(empty)'}
- </div>
- </div>
- )
- }
- export const Default: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: sampleItems,
- label: 'Select a framework',
- placeholder: 'Type to search...',
- showLabel: true,
- allowCreate: true,
- },
- }
- export const WithoutCreateOption: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: programmingLanguages,
- label: 'Programming language',
- placeholder: 'Choose a language',
- showLabel: true,
- allowCreate: false,
- },
- }
- export const AllowCreatePredicate: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: programmingLanguages,
- label: 'Programming language (custom rule)',
- placeholder: 'Try typing java or script',
- showLabel: true,
- allowCreate: value => {
- const normalized = value.trim().toLowerCase()
- return (
- normalized.length >= 4 &&
- !normalized.includes('script') &&
- normalized !== 'java'
- )
- },
- },
- }
- export const HiddenLabel: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: countries,
- label: 'Country',
- placeholder: 'Select your country',
- showLabel: false,
- allowCreate: true,
- },
- }
- export const CustomCreatePrefix: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: [
- { value: 'alpha', label: 'Project Alpha' },
- { value: 'beta', label: 'Project Beta' },
- { value: 'gamma', label: 'Project Gamma' },
- ],
- label: 'Project name',
- placeholder: 'Select or create a project',
- showLabel: true,
- allowCreate: true,
- createOptionPrefix: '➕ Create new project:',
- },
- }
- export const Disabled: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: sampleItems,
- label: 'Framework (disabled)',
- placeholder: 'Cannot interact',
- showLabel: true,
- disabled: true,
- },
- }
- export const SmallList: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: [
- { value: 'option1', label: 'Option 1' },
- { value: 'option2', label: 'Option 2' },
- { value: 'option3', label: 'Option 3' },
- ],
- label: 'Choose an option',
- placeholder: 'Type or select...',
- showLabel: true,
- allowCreate: true,
- },
- }
- export const GroupedItems: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: entryTypeItems,
- label: 'Entry type',
- placeholder: 'Enter entry type',
- showLabel: true,
- allowCreate: true,
- },
- }
- export const GroupedWithoutCreate: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: [
- { value: 'react', label: 'React', group: 'Frontend' },
- { value: 'vue', label: 'Vue', group: 'Frontend' },
- { value: 'angular', label: 'Angular', group: 'Frontend' },
- { value: 'svelte', label: 'Svelte', group: 'Frontend' },
- { value: 'nodejs', label: 'Node.js', group: 'Backend' },
- { value: 'django', label: 'Django', group: 'Backend' },
- { value: 'rails', label: 'Ruby on Rails', group: 'Backend' },
- { value: 'spring', label: 'Spring Boot', group: 'Backend' },
- { value: 'reactnative', label: 'React Native', group: 'Mobile' },
- { value: 'flutter', label: 'Flutter', group: 'Mobile' },
- { value: 'swift', label: 'Swift', group: 'Mobile' },
- { value: 'kotlin', label: 'Kotlin', group: 'Mobile' },
- ],
- label: 'Technology',
- placeholder: 'Search technologies...',
- showLabel: true,
- allowCreate: false,
- },
- }
- export const FuzzySearch: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: [
- { value: 'javascript', label: 'JavaScript' },
- { value: 'typescript', label: 'TypeScript' },
- { value: 'python', label: 'Python' },
- { value: 'rust', label: 'Rust' },
- { value: 'golang', label: 'Go' },
- ],
- label: 'Language (fuzzy search)',
- placeholder: 'Try typo searches, e.g. javasript or pyton',
- showLabel: true,
- allowCreate: true,
- useFuzzySearch: true,
- },
- }
- export const GroupedFuzzySearch: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: entryTypeItems,
- label: 'Grouped entry type (fuzzy search)',
- placeholder: 'Try typo searches, e.g. confernce or theis',
- showLabel: true,
- allowCreate: true,
- useFuzzySearch: true,
- },
- }
- export const ExpandUp: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: sampleItems,
- label: 'Framework (expand up)',
- placeholder: 'Dropdown expands upward',
- showLabel: true,
- allowCreate: true,
- expandUp: true,
- },
- }
- export const ExpandUpGrouped: StoryObj<Args> = {
- render: args => <InteractiveAutocomplete {...args} />,
- args: {
- items: entryTypeItems,
- label: 'Entry type (expand up)',
- placeholder: 'Grouped items expanding upward',
- showLabel: true,
- allowCreate: true,
- expandUp: true,
- },
- }
- const meta: Meta<typeof OLAutocomplete> = {
- title: 'Shared / Components / Autocomplete',
- component: OLAutocomplete,
- tags: ['autodocs'],
- parameters: {
- controls: {
- include: [
- 'items',
- 'label',
- 'placeholder',
- 'showLabel',
- 'allowCreate',
- 'disabled',
- 'createOptionPrefix',
- 'useFuzzySearch',
- 'expandUp',
- ],
- },
- },
- argTypes: {
- items: {
- control: 'object',
- description:
- 'Array of available options; use the optional group property for grouped sections',
- },
- onChange: {
- description: 'Callback when value changes',
- },
- label: {
- control: 'text',
- description: 'Label for the input',
- },
- placeholder: {
- control: 'text',
- description: 'Placeholder text',
- },
- showLabel: {
- control: 'boolean',
- description: 'Show or hide the label visually',
- },
- allowCreate: {
- control: 'boolean',
- description:
- 'Allow creating custom values, or provide a predicate function `(value) => boolean` to conditionally allow create per input value',
- table: {
- type: {
- summary: 'boolean | ((value: string) => boolean)',
- },
- },
- },
- disabled: {
- control: 'boolean',
- description: 'Disable the input',
- },
- createOptionPrefix: {
- control: 'text',
- description: 'Text prefix for the create option',
- },
- useFuzzySearch: {
- control: 'boolean',
- description: 'Enable fuzzy search matching for suggestions',
- },
- expandUp: {
- control: 'boolean',
- description:
- 'When true, the dropdown expands upward and the search bar appears below the results list',
- },
- },
- }
- export default meta
|