@adactive/az-scroller

Adsum A-Z scrolling component

Usage no npm install needed!

<script type="module">
  import adactiveAzScroller from 'https://cdn.skypack.dev/@adactive/az-scroller';
</script>

README

react-badge touch-badge

A to Z scrolling list

Made with <3 for easier touch experience.

Screenshot of AzScroller component

[//]: # (Live examples here

Getting started

npm i --save @adactive/az-scroller

OR

yarn add @adactive/az-scroller

How to use

The only non-optional prop is the list you want to display. It has to be properly formatted, with the list divided in Sections, and each Section having a Header object and an Items array.

See the example below:

    import AzScroller from "@adactive/az-scroller";
    
    // ...

    const listExample = [
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'A',
             },
             items: [
                 { text: 'ABEL' },
                 { text: 'ABRAHAM' },
                 { text: 'ACHILLE' },
                 { text: 'ADAM' },
                 { text: 'ADÈLE' },
                 { text: 'ADELINE' },
                 { text: 'ADOLPHE' },
                 { text: 'ANTOINE' },
             ],
         },
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'B',
             },
             items: [
                 { text: 'BAPTISTE' },
                 { text: 'BARBARA' },
                 { text: 'BARNABÉ' },
                 { text: 'BARTHÉLÉMY' },
                 { text: 'BASILE' },
             ],
         },
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'C',
             },
             items: [
                 { text: 'CERISE' },
                 { text: 'CÉSAIRE' },
                 { text: 'CHARLES' },
                 { text: 'CHARLOT' },
                 { text: 'CHRISTIAN' },
             ],
         },
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'E',
             },
             items: [
                 { text: 'ESTELLE' },
                 { text: 'ETHAN' },
                 { text: 'ÉTIENNE' },
                 { text: 'EUGÈNE' },
             ],
         },
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'M',
             },
             items: [
                 { text: 'MICHÈLE' },
                 { text: 'MOROINE' },
                 { text: 'MURIELLE' },
                 { text: 'MYLÈNE' },
             ],
         },
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'S',
             },
             items: [
                 { text: 'SEBASTIAN' },
                 { text: 'SEREN' },
                 { text: 'STANLEY' },
                 { text: 'STÉPHANE' },
                 { text: 'SYBILLE' },
                 { text: 'SYLVAIN' },
             ],
         },
         {
             header: {
                 type: 'SectionHeader',
                 letter: 'W',
             },
             items: [
                 { text: 'WANDY' },
                 { text: 'WAN' },
                 { text: 'WREN' },
                 { text: 'WILGELM' },
                 { text: 'WADE' },
                 { text: 'WILLIAM' },
                 { text: 'WINOC' },
             ],
         },
     ];
    
    <AzScroller list={listExample} />

The Header object must have a type: 'SectionHeader' and a letter: 'anyString' field, those are mandatory. Plus, you must NOT use a letter field in any Items.

Else, in the Header and the Items you can tweak the other fields and name them as you want, add fields, etc. You will be able to retrieve those fields in the renderListItem & renderListSectionHeader render methods.

Optional props

type PropsType = {|
  list: ListType,
  renderSectionItem?: ?(item: SectionItemType, key: string | number) => React.Node,
  renderSectionHeader?: ?(header: SectionHeaderType, key: string | number) => React.Node,
  shouldShowSectionHeaders?: boolean,
  sectionItemHeight?: ?number,
  sectionHeaderHeight?: ?number,
  wrapperClassNames?: Array<string>,
  wrapperStyle?: ?CSSStyleDeclaration,
  listClassNames?: Array<string>,
  listStyle?: ?CSSStyleDeclaration,
  alphabetListClassNames?: Array<string>,
  alphabetListStyle?: ?CSSStyleDeclaration,
  letterClassNames?: Array<string>,
  letterStyle?: ?CSSStyleDeclaration,
  letterHighlightedClassNames?: Array<string>,
  letterHighlightedStyle?: ?CSSStyleDeclaration,
|};

list

The list of items to scroll through.

renderSectionItem

A function, which you should provide and which will be called for each listItem. Should return a JSX component.

renderSectionHeader

Same as renderSectionItem, but the purpose is to render list section headers.

shouldShowSectionHeaders

Shows if you need to display each section height, or you need just a list without any headers.

sectionItemHeight & sectionHeaderHeight

Should be provided to assure a smooth scrolling experience. The easiest way to do that is to set a fixed height in the 2 render methods and pass them as props here as well (see Default Props section for an example). If you pass render methods, don't forget to pass the corresponding height, else default height from default props will be used, which can lead to UI issues. For more indormations on the topic, take a look at react-list package which is used here: https://www.npmjs.com/package/react-list

listClassNames & listStyle

Modify the style of list wrapper element either with CSS classnames or inline style object, or both.

alphabetListClassNames & alphabetListStyle

Modify the style of wrapper of alphabetList either with CSS classnames or inline style object, or both.

letterClassNames & letterStyle

Modify the style of each letter in alphabetList either with CSS classnames or inline style object, or both.

letterHighlightedClassNames & letterHighlightedStyle

Modify the style of the highlighted letter in alphabetList either with CSS classnames or inline style object, or both.

Note that classnames props are an array of strings (one string for each classname you want to pass) and not a single string with spaces. So if you want to pass only one classname 'letter-class-name' to letter for example, you must pass

<AzScroller
    list={listExample}
    letterClassNames={["letter-class-name"]}
/>

Exported Types

export type SectionItemType = Object;
export type SectionHeaderType = {
  type: 'SectionHeader',
  letter: string,
};
export type ListSectionType = {|
    header: SectionHeaderType,
    items: Array<SectionItemType>,
|};
export type ListType = Array<ListSectionType>;

Default props

static defaultProps = {
    renderSectionItem: (item: SectionItemType, key: string | number) => (
        <div
            key={key}
            style={{
                boxSizing: 'border-box',
                height: '30px',
                padding: '10px 20px',
            }}
        >
            {item.text}
        </div>
    ),
    renderSectionHeader: (header: SectionHeaderType, key: string | number) => (
        <div
            key={key}
            style={{
                boxSizing: 'border-box',
                height: '50px',
                padding: '20px 20px',
                fontWeight: 'bold',
                backgroundColor: 'lightgrey',
            }}
        >
            {header.letter}
        </div>
    ),
    shouldShowSectionHeaders: false,
    sectionItemHeight: null,
    sectionHeaderHeight: null,
    wrapperClassNames: [],
    wrapperStyle: null,
    listClassNames: [],
    listStyle: null,
    alphabetListClassNames: [],
    alphabetListStyle: null,
    letterClassNames: [],
    letterStyle: null,
    letterHighlightedClassNames: [],
    letterHighlightedStyle: null,
};

static defaultStyleProps = {
    wrapperStyle: {
        boxSizing: 'border-box',
        width: '500px',
        height: '500px',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'space-between',
    },
    listStyle: {
        overflow: 'auto',
        maxHeight: '80%',
    },
    alphabetListStyle: {
        boxSizing: 'border-box',
        width: '100%',
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        padding: '20px 10px',
    },
    letterStyle: {
        outline: 'none',
    },
    letterHighlightedStyle: {
        color: 'red',
        fontWeight: 'bold',
    },
};

Default style props will apply if:

  • of course the corresponding style prop is not passed
  • AND the corresponding classnames prop is not passed

This means that passing a classname or a inline style object will desactivate the corresponding default style

Copy component inside your project src folder

It will copy the component inside your project, in src/adsum-az-scroller.

npx @adactive/az-scroller copy