My Component Library
General purpose react components for use in web based projects This does not support React Native Compiled with type definitions, can be used with TypeScript or JavaScript
Getting Started
Quick Start
npm i @noahvarghese/react-components
Components
AppRouter
Description
Wrapper for your base app. To be used in your index.[tsx,jsx] or App.[tsx,jsx].
This keeps track of your scroll location so if the user goes back a page it will remember where on the page the user was previously and scroll to that position.
For usage if using react-router and react-router-dom. Wraps provided routes in Router and Switch components.
Accepts an array of routes, NavProps and FooterProps.
For a deeper dive into props that can be passed check out ProtectedRoute, Nav, and Footer.
Props
name | type | default | description |
---|---|---|---|
navProps | NavProps | See Nav component | |
routes | {path: string?; component?: React.ComponenType<RouteComponentProps> | <React.ComponentType>}[] | Same props as react-router-dom's Route component, or see ProtectedRoute | |
footerProps | FooterProps | See Footer Component |
Sample Usage
<AppRouter
navProps={{
items: loggedIn
? [{ name: "Login", path: "/" }]
: [
{ name: "Home", path: "/" },
{ name: "Logout", path: "/logout" },
],
type: "card",
}}
routes={
loggedIn
? [{ path: "/", component: Login, exact: true }]
: [
{
path: "/",
component: Home,
protectedProps: {
condition: () => loggedIn,
redirectPath: "/404",
},
},
{
path: "/logout",
component: Logout,
protectedProps: {
condition: () => loggedIn,
redirectPath: "/404",
},
},
]
}
footerProps={{ copyright: "Noah Varghese" }}
/>
Button
Description
Styled Button. Will also render as an anchor tag if link is provided
Props
name | type | default | description |
---|---|---|---|
primary | [boolean] | false | determines whether to use the primary or secondary color |
text | string | button text | |
disabled | [boolean] | undefined | sets button disabled |
link | [string] | undefined | if set, renders as an anchor tag but with same stylings as button |
onClick | [(e: MouseEvent<unknown, unknown>) => void;] | undefined | action to perform when clicked, can be applied to anchor tag as well |
size | ["small" | "medium" | "large"] | small | determines the size of the button |
type | ["button" | "reset" | "submit" ] | button | determines button type, does not apply to anchor |
Sample Usage
<Button primary text="Submit" onClick={(_) => console.log("Clicked")} />
Checkbox
Description
Styled HTML Checkbox
Props
name | type | default | description |
---|---|---|---|
name | string | specifies name of input attribute, used as id as well | |
label | [string] | undefined | the label text, if empty uses the name |
state | {state: boolean; setState: (val: boolean) => void | React.Dispatch<SetStateAction>} | provides value and way to set value |
readonly | [boolean] | undefined | sets readOnly attribute of input |
Sample Usage
const [state, setState] = useState(false);
return <Checkbox name="human" label="Are you human?" state={{ state, setState}}>
DropdownArrow
Description
Used to trigger showing/hiding a dropdown. Also used to visually display whether the dropdown should be showing. To be used in combination with other components.
Props
name | type | default | description |
---|---|---|---|
show | [boolean] | undefined | sets whether the arrow should be 'open' or not |
onClick | (e: MouseEvent<unknown, unknown>) => void | function to fire when the arrow gets clicked, used to trigger display |
Sample Usage
const [state, setState] = useState(false);
<DropdownArrow show={state} onClick={(_) => setState(!state) }>
FileInput
Description
Wrapper for file input. Allows drag and drop. Files should be retrieved for sending to a server by accessing the form input elements.
Props
name | type | default | description |
---|---|---|---|
multipleFiles | [boolean] | undefined | whether to allow multiple files to be sent |
name | string | specifies name of input attribute, used as id as well | |
label | [string] | undefined | the label text, if empty uses the name |
accept | [string] | undefined | types of files to accept, if not set allows all |
Sample Usage
<FileInput multipleFiles name="Resume" label="Resume" accept="*.pdf,*.docx" />
Footer
Description
The footer for the webpage.
May display social media links, a quote or blurb, and the copyright information
Props
name | type | default | description |
---|---|---|---|
copyright | string | copyright information | |
socialMedia | [{url: string; image: string; name: string;}[]] | undefined | generates a display of images as links, name is used as the alt text, image is either the source as a string, or the path |
quote | [string] | undefined | a piece of text, slogan or otherwise |
Sample Usage
<Footer
copyright="Noah Varghese 2021"
socialMedia={[
{
url: "facebook.com/noah-varghese",
image: FacebookLogo,
name: "facebook",
},
{
url: "instagram.com/noah-varghese",
image: InstagramLogo,
name: "instagram",
},
]}
/>
Form
Description
A form wrapper to theme and simplify form options Inputs and children must be wrapped by form element
Props
name | type | default | description |
---|---|---|---|
title | string | the form name, will be displayed as a header | |
method | "POST" | "PUT" | "DELETE" | the HTTP verb to be used by the form | |
type | "card" | "bordered" | applies a className to the form to change styling | |
url | string | the form action | |
submitFunction | (e: SyntheticEvent) => Promise | additional actions to be performed on submit, can cancel default form behaviour by applying e.preventDefault() within the function | |
buttons | React.Node[] | form action buttons |
Sample Usage
<Form
title="Sample"
method="POST"
type="card"
url="/"
submitFunction={(e) => e.preventDefault();}
buttons={[<button type="submit">Submit</button>, <button type="reset">Reset</button>]}
>
<input type="text" id="name" placeholder="name" value="" />
</Form>
HamburgerToggle
Description
Toggle for mobile nav
Props
name | type | default | description |
---|---|---|---|
showMenu | boolean | dictates whether the state is 'open' | |
toggleMenu | () => void | function responsible for changing whether it is 'open' or 'closed' |
Sample Usage
const [open, setOpen] = useState(false);
<HamburgerToggle showMenu={open} toggleMenu={setOpen} />;
Input
Description
Wrapper for html input element Provides input validation for email, required, postal-code, phone, date. Postal code validation currently only supports Canadian postal codes, custom validator must be applied for other locales. Phone validation currently only supports Canadian postal codes, custom validator must be applied for other locales. Also can display errors.
Props
name | type | default | description |
---|---|---|---|
type | string | the input type (ex. date, email, tel, text, etc.) | |
name | string | form input name | |
placeholder | string | sets the label text | |
required | boolean | sets whether required validation is performed, and affects styling, the actual html attribute required is always set to true so the animations fire correctly | |
state | {state: string; setState: (val: string) => React.Dispatch<React.SetStateAction>} | allows central store of form values | |
validationOptions | [{runOnInput: boolean; runOnComplete: boolean; [validatorFn: (input: any, field: string) => {success: true} | {success: false, errorMessage: string;}]}] | {runOnInput: true, runOnComplete: true} | can provide custom validator and dictate when to run the validator function, the error message gets sent to the error function provided |
errorState | {error: string | undefined;, setError: (val?: string | undefined) => void | React.Dispatch<SetStateAction>} | allows setting and keeping errors in central state | |
formatter | [(input: any) => any] | undefined | can provide custom formatter for use prior to validation and state change |
autoComplete | [string] | sets autocomplete value for browser use |
Sample Usage
const [emailState, setEmail] = useState("");
const [error, setError] = useState("");
return (
<Input
type="email"
required={true}
name="email"
state={{ setState: setEmail, state: emailState }}
errorState={{ setError: setError, error }}
placeholder="email"
/>
);
Nav
Description
Provides mobile and desktop navigation that is done dynamically using the rendered length of the navigation lengths.
Props
name | type | default | description |
---|---|---|---|
items | {name: string; path: string;}[] | array of links to display in nav | |
type | "card" | className to be assigned, affects styling | |
callToAction | [{text: string; path: string;}] | undefined | if provided provides a 'call to action' in the nav to call user attention to |
displayCallToAction | [() => boolean;] | undefined | provides conditions to display call to action, for example if the user is on the page the call to action would direct them to |
bannerMessage | [ReactNode | string] | undefined | provides a banner message just above the nav |
displayBanner | [() => boolean;] | undefined | conditions to display banner message under |
logo | string | either the imported image source as a string or the path |
Sample Usage
import Logo from "../../assets/img/logo.png";
<Nav
items={[
{ name: "Home", path: "/" },
{ name: "About", path: "/about" },
{ name: "Testimonials", path: "/testimonials" },
{ name: "Gallery", path: "/gallery" },
{ name: "Contact", path: "/contact" },
{ name: "Blog", path: "/blog" },
]}
type="card"
callToAction={{ text: "Request a quote", path: "/contact" }}
displayCallToAction={() => {
return true;
}}
bannerMessage="More than 30 years of experience"
displayBanner={() => true}
logo={Logo}
/>;
Notification
Description
Displays at base of containing component. Container must have set position to reltaive.
position: relative;
Props
name | type | default | description |
---|---|---|---|
message | string | text to display | |
display | boolean | determines whether to display the notification | |
hide | () => void | function to call when the notification is hidden, ex if you disable components on form submission then you can reenable them after the notification is finished | |
error | [boolean] | undefined | if true displays using error color |
timeout | [number] | 2000 | timeout for notification to disappear in ms] |
Sample Usage
const [state, setState] = useState(false);
return (
<div
style={{
width: "500px",
height: "500px",
backgroundColor: "#f3f3f3",
position: "relative",
}}
>
<State store={store}>
<Notification
message="Hello"
display={state}
hide={() => setState(false)}
/>
</State>
</div>
);
ProtectedRoute
Description
Provides a wrapper around Route to check if the route may be used. If not applies a redirect. instead of component can also pass children.
Props
name | type | default | description |
---|---|---|---|
component | [React.ComponentType<RouteComponentProps> | React.ComponentType] | undefined | component to display |
exact | [boolean] | undefined | whether to match the path exactly |
path | [string] | undefined | path to match |
redirectPath | string | if condition is unmet this is the location the user will be redirected to | |
condition | () => boolean; | function to check if condition is valid |
Sample Usage
<ProtectedRoute
component={Dashboard}
exact={true}
path="/dashboard"
redirectPath="/"
condition={() => isLoggedIn}
key="/dashboard"
/>
Radio
Description
Single Radio Button custom styles applied.
Props
name | type | default | description |
---|---|---|---|
name | string | form input name, used s label text if label is not provided | |
id | string | id of specific radio button | |
label | [string] | undefined | label text |
state | {state: boolean; setState: React.Dispatch<React.SetStateAction>; } | provides way of storing and setting a central state | |
readonly | [boolean] | undefined | sets whether the element can be interacted with |
Sample Usage
const [state, setState] = useState(false);
<Radio
label="Test 1"
name="Radio"
id="Test1"
state={{
state,
setState,
}}
/>;
RadioFieldset
Description
Provides wrapper for multiple Radio inputs
Props
name | type | default | description |
---|---|---|---|
title | string | the label for the fieldset | |
radioProps | RadioProps[] | See Radio component above |
Sample Usage
const [state, setState] = useState([false, false, true]);
<RadioFieldset
title="How old are you?"
radioProps={[
{
label: "Too young",
name: "age",
id: "tooYoung",
state: {
state[0],
setState: (val: boolean) => {
setState([val, state[1], state[2]]);
}
}
},
{
label: "just the right age",
name: "age",
id: "right age",
state: {
state[1],
setState: (val: boolean) => {
setState([state[0], val, state[2]]);
}
}
}
{
label: "Too old",
name: "age",
id: "old",
state: {
state[2],
setState: (val: boolean) => {
setState([state[0], state[1], val]);
}
}
}
]}
/>
Select
Description
Styled select dropdown
Props
name | type | default | description |
---|---|---|---|
name | string | name of form input | |
placeholder | string | used as the label | |
items | {id: number; value: any; }[] | items to display in dropdown | |
required | boolean | whether the field is required, this is superficial as the html required attribute is always set to true so the animations fire correctly | |
errorState | {error: string; setError: (val: string) => void | React.Dispatch<React.SetStateAction>} | allows central error store | |
state | {state: {id: number; value: string;}, setState: ({id: number, value: string}) => React.Dispatch<React.SetStateAction<{id: number; value: string;}>>} | allows central store |
Sample Usage
const [selected, setSelected] = useState({ id: -1, value: "" });
const [error, setError] = useState("");
return (
<Select
items={[
{ id: 1, value: "Kitchen" },
{ id: 2, value: "Bar" },
{ id: 3, value: "YOLO" },
]}
name="department"
placeholder="department"
required={true}
state={{ state: selected, setState: setSelected }}
errorState={{ setError, error: error }}
/>
);
Theming
Theme config file is located in your project root after installation at './components.config.scss' There are a few themes provided, the default values in the file are the same as the 'default' theme.
If you wish to override the theme comment out the line '$default-theme: default;' Then any changes to the file will take effect. Any changes made will require a restart of the development server as the scss needs to be compiled.
// components.config.scss
/* If you wish to use your own values
comment out the line below */
$default-theme: owd;
$primary-color: #000000;
$secondary-color: #61dafb;
$highlight-color: #ffffff;
$accent-color: #61dafb;
$error-color: #f55549;
$bg-color: #ffffff;
$secondary-bg-color: #f3f3f3;
$root-font-size: 16px;
$header-font-family: Monsterrat;
$header-font-style: "Regular";
$header-letter-spacing: 16px;
$header-line-height: 1.2rem;
$content-font-family: Roboto;
$content-font-style: "Regular";
$content-letter-spacing: 16px;
$content-line-height: 1.2rem;
$content-font-size: 1.2rem;
$accent-font-style: italic;
Colors
Colors can be hex, rgb, rgba, or strings, same as regular css color values
Fonts
Custom fonts must be imported into your project in your index.css, then they can be referenced in '$*-font-family` variables in the components.config.scss file. The font-style is the rest of the file name if you obtained fonts from Google Fonts.
For example if you downloaded the entire Montserrat font family you would have Montserrat-Regular.ttf, Montserrat-Light.ttf etc. This expects you created @font-face rules for custom fonts using the same name as the downloaded ttf file.
Testing
Tested using react-testing-library Requires SKIP_PREFLIGHT_CHECK to be set to true to run tests
To Run Tests
git clone https://github.com/noahvarghese/react-components
cd ./react-components
echo "SKIP_PREFLIGHT_CHECK=true" > .env
yarn
# To run tests
yarn test
To View Storybook
git clone https://github.com/noahvarghese/react-components
cd ./react-components
yarn
# To launch storybook
yarn storybook