Skip to content
This repository was archived by the owner on Jan 9, 2023. It is now read-only.

Commit f80382f

Browse files
committed
feat(navbar): support navbar items horizontal position w array order
fix #225
1 parent 64bbb29 commit f80382f

3 files changed

Lines changed: 124 additions & 103 deletions

File tree

src/components/Navbar/Navbar.tsx

Lines changed: 63 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,78 +5,88 @@ import Form from 'react-bootstrap/Form'
55
import FormControl from 'react-bootstrap/FormControl'
66
import NavDropdown from 'react-bootstrap/NavDropdown'
77
import { Button } from '../Button'
8-
import { NavLink, Brand, NavLinkElement, Search } from './interfaces'
8+
import { NavLink, NavBrand, NavLinkList, NavSearch } from './interfaces'
99

1010
interface Props extends React.Props<any> {
1111
/** Determines the navbar background color */
1212
bg?: string
1313
/** Determines the letters color. It should be combined with the background color (bg) */
1414
variant?: 'light' | 'dark'
1515
/** Determines the links names, theirs onClick methods and paths. It has children array which contain links to be used on a dropdown. */
16-
navLinks: NavLink[]
17-
/** Determines the hospital/clinic name to be shown at the navbar */
18-
brand: Brand
19-
/** Defines the properties of the search element */
20-
search: Search
16+
navItems: (NavBrand | NavLink | NavLinkList | NavSearch)[]
2117
}
2218

2319
/**
2420
* Used to redirect users to the main topics.
2521
*/
2622
const Navbar = (props: Props) => {
27-
const { bg, variant, navLinks, brand, search } = props
23+
const { bg, variant, navItems } = props
2824

29-
const getNavItems = (subLink: NavLinkElement, index: number) => (
30-
<NavDropdown.Item href={subLink.href ? subLink.href : ''} key={index} onClick={subLink.onClick}>
31-
{subLink.label}
25+
const getNavListLinks = (link: NavLink, index: number) => (
26+
<NavDropdown.Item href={link.href ? link.href : ''} key={index} onClick={link.onClick}>
27+
{link.label}
3228
</NavDropdown.Item>
3329
)
34-
35-
const getNavLinks = (link: NavLink, index: number) => {
36-
if (link.children.length === 0) {
37-
return (
38-
<Nav.Link onClick={link.onClick} key={index}>
39-
{link.label}
40-
</Nav.Link>
41-
)
42-
}
43-
44-
return (
45-
<NavDropdown title={link.label} id="collasible-nav-dropdown" key={index}>
46-
{link.children.map((subLink, i) => getNavItems(subLink, i))}
47-
</NavDropdown>
48-
)
49-
}
30+
const getNavSearch = (search: NavSearch) => (
31+
<Nav>
32+
<Form inline>
33+
<FormControl
34+
type="text"
35+
placeholder={search.placeholderText || 'Search'}
36+
className="mr-sm-2"
37+
onChange={search.onChangeInput}
38+
/>
39+
<Button color={search.buttonColor || 'primary'} onClick={search.onClickButton}>
40+
{search.buttonText || 'Search'}
41+
</Button>
42+
</Form>
43+
</Nav>
44+
)
45+
const getNavList = (list: NavLinkList, index: number) => (
46+
<NavDropdown title={list.label} id="collasible-nav-dropdown" key={index}>
47+
{list.children.map((subLink, i) => getNavListLinks(subLink, i))}
48+
</NavDropdown>
49+
)
50+
const getNavBrand = (brand: NavBrand) => (
51+
<NavbarRB.Brand onClick={brand.onClick} style={{ cursor: 'pointer' }}>
52+
{brand.src ? (
53+
<img
54+
alt={brand.label}
55+
src={brand.src}
56+
width="28"
57+
height="28"
58+
className="d-inline-block align-top mr-3"
59+
/>
60+
) : (
61+
''
62+
)}
63+
<span style={{ color: brand.color }}>{`${brand.label}`}</span>
64+
</NavbarRB.Brand>
65+
)
66+
const getNavLink = (link: NavLink, index: number) => (
67+
<Nav.Link onClick={link.onClick} key={index}>
68+
{link.label}
69+
</Nav.Link>
70+
)
5071
return (
5172
<NavbarRB bg={bg} variant={variant}>
52-
<NavbarRB.Brand onClick={brand.onClick} style={{ cursor: 'pointer' }}>
53-
{brand.src ? (
54-
<img
55-
alt={brand.label}
56-
src={brand.src}
57-
width="28"
58-
height="28"
59-
className="d-inline-block align-top mr-3"
60-
/>
61-
) : (
62-
''
63-
)}
64-
<span style={{ color: brand.color }}>{`${brand.label}`}</span>
65-
</NavbarRB.Brand>
6673
<NavbarRB.Collapse id="responsive-navbar-nav">
67-
<Nav className="mr-auto">{navLinks.map((link, index) => getNavLinks(link, index))}</Nav>
68-
<Nav>
69-
<Form inline>
70-
<FormControl
71-
type="text"
72-
placeholder={search.placeholderText || 'Search'}
73-
className="mr-sm-2"
74-
onChange={search.onChangeInput}
75-
/>
76-
<Button color={search.buttonColor || 'primary'} onClick={search.onClickButton}>
77-
{search.buttonText || 'Search'}
78-
</Button>
79-
</Form>
74+
<Nav className="mr-auto">
75+
{navItems.map((item, index) => {
76+
if ((item as NavBrand).type === 'brand') {
77+
return getNavBrand(item as NavBrand)
78+
}
79+
if ((item as NavLink).type === 'link') {
80+
return getNavLink(item as NavLink, index)
81+
}
82+
if ((item as NavSearch).type === 'search') {
83+
return getNavSearch(item as NavSearch)
84+
}
85+
if ((item as NavLinkList).type === 'link-list') {
86+
return getNavList(item as NavLinkList, index)
87+
}
88+
return null
89+
})}
8090
</Nav>
8191
</NavbarRB.Collapse>
8292
</NavbarRB>

src/components/Navbar/interfaces.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export interface Brand {
1+
export interface NavBrand extends NavItem {
22
/** Clinic/Hospital name */
33
label: string
44
/** Label color */
@@ -9,7 +9,11 @@ export interface Brand {
99
onClick?: (event: React.MouseEvent<any>) => void
1010
}
1111

12-
export interface NavLinkElement {
12+
export interface NavItem {
13+
type: string
14+
}
15+
16+
export interface NavLink extends NavItem {
1317
/** The link name */
1418
label: string
1519
/** A click handle which will redirect the user to whenever it is clicked */
@@ -18,12 +22,12 @@ export interface NavLinkElement {
1822
href?: string
1923
}
2024

21-
export interface NavLink extends NavLinkElement {
25+
export interface NavLinkList extends NavLink {
2226
/** An array to hold a dropdown Links */
23-
children: NavLinkElement[]
27+
children: Array<NavLink>
2428
}
2529

26-
export interface Search {
30+
export interface NavSearch extends NavItem {
2731
/** Defines the placeholder text. */
2832
placeholderText?: string
2933
/** Defines the button text. */

stories/navbar.stories.tsx

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,69 +14,37 @@ storiesOf('Navbar', module)
1414
.add('Navbar', () => (
1515
<div>
1616
<Navbar
17-
brand={{
18-
label: 'Hospital',
19-
onClick: () => {
20-
Toast('success', 'Brand button clicked!!', 'Success')
21-
},
22-
}}
23-
search={{
24-
placeholderText: 'Custom',
25-
buttonText: 'Text',
26-
buttonColor: 'secondary',
27-
onClickButton: () => {
28-
Toast('success', 'Button clicked!!', 'Success')
29-
},
30-
onChangeInput: () => {
31-
Toast('success', 'Search box changed!!', 'Success')
17+
navItems={[
18+
{
19+
type: 'brand',
20+
label: 'Hospital',
21+
onClick: () => {
22+
Toast('success', 'Brand button clicked!!', 'Success')
23+
},
3224
},
33-
}}
34-
navLinks={[
3525
{
26+
type: 'link',
3627
label: 'Link',
3728
onClick: () => {
3829
Toast('success', 'NavLink clicked!!', 'Success')
3930
},
40-
children: [],
4131
},
42-
]}
43-
/>
44-
45-
<br />
46-
47-
<Navbar
48-
brand={{
49-
label: 'HospitalRun',
50-
src:
51-
'https://raw.githubusercontent.com/HospitalRun/hospitalrun.github.io/master/favicon.png',
52-
onClick: () => {
53-
Toast('success', 'Brand button clicked!!', 'Success')
54-
},
55-
}}
56-
search={{
57-
onClickButton: () => {
58-
Toast('success', 'Button clicked!!', 'Success')
59-
},
60-
onChangeInput: () => {
61-
Toast('success', 'Search box changed!!', 'Success')
62-
},
63-
}}
64-
bg="light"
65-
variant="light"
66-
navLinks={[
6732
{
68-
label: 'Dropdown',
33+
type: 'link-list',
34+
label: 'Link',
6935
onClick: () => {
7036
Toast('success', 'NavLink clicked!!', 'Success')
7137
},
7238
children: [
7339
{
40+
type: 'link',
7441
label: 'Sublink1',
7542
onClick: () => {
7643
Toast('success', 'Sublink1 clicked!!', 'Success')
7744
},
7845
},
7946
{
47+
type: 'link',
8048
label: 'Sublink2',
8149
onClick: () => {
8250
Toast('success', 'Sublink2 clicked!!', 'Success')
@@ -85,11 +53,50 @@ storiesOf('Navbar', module)
8553
],
8654
},
8755
{
56+
type: 'search',
57+
placeholderText: 'Custom',
58+
buttonText: 'Text',
59+
buttonColor: 'secondary',
60+
onClickButton: () => {
61+
Toast('success', 'Button clicked!!', 'Success')
62+
},
63+
onChangeInput: () => {
64+
Toast('success', 'Search box changed!!', 'Success')
65+
},
66+
},
67+
]}
68+
/>
69+
70+
<br />
71+
72+
<Navbar
73+
bg="light"
74+
variant="light"
75+
navItems={[
76+
{
77+
type: 'brand',
78+
label: 'HospitalRun',
79+
src:
80+
'https://raw.githubusercontent.com/HospitalRun/hospitalrun.github.io/master/favicon.png',
81+
onClick: () => {
82+
Toast('success', 'Brand button clicked!!', 'Success')
83+
},
84+
},
85+
{
86+
type: 'link',
8887
label: 'Link',
8988
onClick: () => {
9089
Toast('success', 'NavLink clicked!!', 'Success')
9190
},
92-
children: [],
91+
},
92+
{
93+
type: 'search',
94+
onClickButton: () => {
95+
Toast('success', 'Button clicked!!', 'Success')
96+
},
97+
onChangeInput: () => {
98+
Toast('success', 'Search box changed!!', 'Success')
99+
},
93100
},
94101
]}
95102
/>

0 commit comments

Comments
 (0)