Skip to content

Commit 2b8b561

Browse files
committed
feat: add Navigation component
1 parent 7634d58 commit 2b8b561

File tree

8 files changed

+169
-1
lines changed

8 files changed

+169
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Below is a list of the components available in this library. Each component has
3636
- [BBBCheckbox](./src/components/Checkbox/README.md)
3737
- [BBBDivider](./src/components/Divider/README.md)
3838
- [BBBHint](./src/components/Hint/README.md)
39+
- [BBBNavigation](./src/components/Navigation/README.md)
3940
- [BBBSelect](./src/components/Select/README.md)
4041
- [BBBTextAreaInput](./src/components/TextAreaInput/README.md)
4142
- [BBBTextInput](./src/components/TextInput/README.md)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# BBBNavigation
2+
3+
The `BBBNavigation` component provides a customizable button with an icon and a label, suitable for navigation actions within an application.
4+
5+
![Demo](assets/example.png)
6+
7+
## Usage Example
8+
9+
### Basic BBBNavigation Button
10+
```jsx
11+
import { BBBNavigation } from 'bbb-ui-components-react';
12+
13+
<BBBNavigation label="Home" onClick={() => console.log('Navigate to Home')} />
14+
```
15+
16+
### BBBNavigation Button with Custom Icon
17+
```jsx
18+
import { BBBNavigation } from 'bbb-ui-components-react';
19+
import { FaHome, MdFavorite } from 'react-icons/fa';
20+
21+
<BBBNavigation label="Home" icon={<FaHome />} onClick={() => console.log('Navigate to Home')} />
22+
```
23+
24+
### BBBNavigation Button with Children
25+
```jsx
26+
import { BBBNavigation } from 'bbb-ui-components-react';
27+
import { MdFavorite } from 'react-icons/fa';
28+
29+
<BBBNavigation label="Settings" onClick={() => console.log('Toggle Settings')}>
30+
<MdFavorite />
31+
</BBBNavigation>
32+
```
33+
34+
## Props
35+
36+
| Property | Type | Default | Description |
37+
| ----------------- | ---------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------- |
38+
| `label` | `string` | | The text to be displayed as the label for the navigation button. |
39+
| `onClick` | `React.MouseEventHandler<HTMLButtonElement>` | | The function to be called when the navigation button is clicked. |
40+
| `onKeyDown` | `React.KeyboardEventHandler<HTMLButtonElement>` | | The function to be called when a key is pressed down on the navigation button. |
41+
| `icon` | `React.ReactNode` | | A custom icon to be displayed. If not provided, a default icon is used. |
42+
| `children` | `React.ReactNode` | | The children to be rendered inside the navigation button, typically used for sub-menus or other content. |
43+
| `ariaLabel` | `string` | | The accessible name for the navigation button. |
44+
| `ariaLabelledBy` | `string` | | The ID of the element that labels the navigation button. |
45+
| `ariaDescribedBy` | `string` | | The ID of the element that describes the navigation button. |
46+
| `dataTest` | `string` | | The test ID for the navigation button, used for testing purposes. |
7.94 KB
Loading
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { JSX } from 'react';
2+
import { NavigationProps } from './types';
3+
import * as Styled from './styles';
4+
import { MdExpandCircleDown } from 'react-icons/md';
5+
import { BBBTypography } from '../Typography';
6+
7+
/**
8+
* A customizable Navigation component that acts as a button with an icon and a label.
9+
* It can be used for navigation actions within an application.
10+
*
11+
* @param {NavigationProps} props - The props for the Navigation component. See {@link NavigationProps} for more details.
12+
* @param {string} props.label - The text to be displayed as the label for the navigation button.
13+
* @param {React.MouseEventHandler<HTMLButtonElement>} props.onClick - The function to be called when the navigation button is clicked.
14+
* @param {React.KeyboardEventHandler<HTMLButtonElement>} [props.onKeyDown] - The function to be called when a key is pressed down on the navigation button.
15+
* @param {React.ReactNode} [props.icon] - A custom icon to be displayed. If not provided, a default icon is used.
16+
* @param {React.ReactNode} [props.children] - The children to be rendered inside the navigation button, typically used for sub-menus or other content.
17+
* @param {string} [props.ariaLabel] - The accessible name for the navigation button.
18+
* @param {string} [props.ariaLabelledBy] - The ID of the element that labels the navigation button.
19+
* @param {string} [props.ariaDescribedBy] - The ID of the element that describes the navigation button.
20+
* @param {string} [props.dataTest] - The test ID for the navigation button, used for testing purposes.
21+
* @returns {JSX.Element} The rendered Navigation component.
22+
*/
23+
function Navigation ({
24+
label,
25+
onClick,
26+
onKeyDown,
27+
icon,
28+
children,
29+
ariaLabel,
30+
ariaLabelledBy,
31+
ariaDescribedBy,
32+
dataTest,
33+
}: NavigationProps): JSX.Element {
34+
const isCustomIcon = !!icon;
35+
const iconToRender = icon || <MdExpandCircleDown size="1.5rem" />;
36+
37+
return (
38+
<Styled.NavigationButton
39+
onClick={onClick}
40+
onKeyDown={onKeyDown}
41+
aria-label={ariaLabel}
42+
aria-labelledby={ariaLabelledBy}
43+
aria-describedby={ariaDescribedBy}
44+
data-test={dataTest}
45+
>
46+
<Styled.IconTextWrapper>
47+
<Styled.IconWrapper isCustomIcon={isCustomIcon}>
48+
{iconToRender}
49+
</Styled.IconWrapper>
50+
<BBBTypography variant="default">
51+
{label}
52+
</BBBTypography>
53+
</Styled.IconTextWrapper>
54+
{children}
55+
</Styled.NavigationButton>
56+
);
57+
}
58+
59+
export default Navigation;

src/components/Navigation/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as BBBNavigation } from './component';
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import styled, { css } from 'styled-components';
2+
import { borderRadiusSmall, spacingMedium } from '../../stylesheets/sizing';
3+
import { colorBrand1 } from '../../stylesheets/pallete';
4+
import { StyledIconWrapper } from './types';
5+
6+
export const NavigationButton = styled.button`
7+
display: flex;
8+
flex-direction: row;
9+
align-items: center;
10+
justify-content: space-between;
11+
background: transparent;
12+
border: none;
13+
cursor: pointer;
14+
margin: 1px; /* Adds margin to prevent outline from being cropped */
15+
border-radius: ${borderRadiusSmall};
16+
17+
&:focus {
18+
outline: 1px solid ${colorBrand1};
19+
}
20+
`;
21+
22+
export const IconTextWrapper = styled.div`
23+
display: flex;
24+
flex-direction: row;
25+
align-items: flex-start;
26+
justify-content: center;
27+
gap: ${spacingMedium};
28+
`;
29+
30+
export const IconWrapper = styled.div<StyledIconWrapper>`
31+
display: flex;
32+
align-items: center;
33+
justify-content: center;
34+
color: ${colorBrand1};
35+
36+
${({ isCustomIcon }) => !isCustomIcon && css`
37+
transform: rotate(90deg);
38+
[dir="rtl"] & {
39+
transform: rotate(-90deg);
40+
}
41+
`}
42+
`;

src/components/Navigation/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react';
2+
3+
export interface StyledIconWrapper {
4+
isCustomIcon: boolean;
5+
}
6+
7+
export interface NavigationProps {
8+
label: string;
9+
onClick: React.MouseEventHandler<HTMLButtonElement>;
10+
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;
11+
icon?: React.ReactNode;
12+
children?: React.ReactNode;
13+
ariaLabel?: string;
14+
ariaLabelledBy?: string;
15+
ariaDescribedBy?: string;
16+
dataTest?: string;
17+
}
18+

src/components/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ export * from './Button';
33
export * from './Checkbox';
44
export * from './Divider';
55
export * from './Hint';
6+
export * from './Navigation';
67
export * from './Select';
78
export * from './TextAreaInput';
89
export * from './TextInput';
910
export * from './Toggle';
10-
export * from './Typography'
11+
export * from './Typography';

0 commit comments

Comments
 (0)