https://github.com/dan1229/nextjs-base-blocks
NextJS + TypeScript component library - meant to be used as a git submodule
https://github.com/dan1229/nextjs-base-blocks
nextjs react typescript
Last synced: 10 days ago
JSON representation
NextJS + TypeScript component library - meant to be used as a git submodule
- Host: GitHub
- URL: https://github.com/dan1229/nextjs-base-blocks
- Owner: dan1229
- Created: 2023-05-23T01:30:11.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-30T03:51:33.000Z (about 1 year ago)
- Last Synced: 2024-10-30T06:26:20.846Z (about 1 year ago)
- Topics: nextjs, react, typescript
- Language: TypeScript
- Homepage:
- Size: 433 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# NextJS Base Blocks
[](https://github.com/dan1229/nextjs-base-blocks/actions/workflows/lint.yml)
[](https://github.com/dan1229/nextjs-base-blocks/actions/workflows/build.yml)
[](https://github.com/dan1229/nextjs-base-blocks/actions/workflows/test.yml)
[](https://codecov.io/gh/dan1229/nextjs-base-blocks)
#### By: [Daniel Nazarian](https://danielnazarian) 🐧👹
##### Contact me at
-------------------------------------------------------
## Description
`Base Block`s is a collection of UI 'blocks' that are used to build the rest of the components used on the sites.
This is intended to be used as a git submodule in a NextJS + Typescript project.
A `block` ideally is the smallest unit of UI code that can be reasonably reused. It is a self-contained piece of code that can be used in any context. It is not a component, but a building block for other, bigger components.
The idea behind this is that you can standardize your components and styling without an overabundance of classes and styles or a third party style library like [bootstrap](https://getbootstrap.com/docs/4.3/getting-started/introduction/) or [tailwind](https://tailwindcss.com/) (you can still switch to one if you want though!) This will make it easier to maintain and update your codebase as requirements grow.
If you ever want to move away or edit the base components, you can easily remove the git submodule and take what you need.
The goal here is to provide consistent and easy to use components that can be used in any project, helping you get a project off the ground quickly or to improve an existing project.
### Why A Submodule?
One of the most common questions about this project - it could easily be an NPM package like [Tailwind](https://www.npmjs.com/package/tailwindcss) or similar.
While true and this package is meant to serve a similar purpose, the reality is this is just maintained by myself ([Daniel Nazarian](https://DanielNazarian.com)). So, sadly, this project is far more likely to have bugs or just generally not fit every edge case its end users may be searching for.
To that end, I chose to make it a submodule so client projects could easily directly implement fixes, improvements and even fork it themselves if they choose to go a completely different direction.
**While I love contributions to the repo directly** I didn't want to force people to do that should they run into a bug or something like that.
## Requirements
You must have the following installed to use this submodule
- [React Hook Forms](https://react-hook-form.com/)
- [React Icons](https://react-icons.github.io/react-icons/)
- [Sass](https://sass-lang.com/)
- [Node Sass](https://www.npmjs.com/package/node-sass)
- [classnames](https://www.npmjs.com/package/classnames)
- [UseHooks TS](https://usehooks-typescript.com/)
See `package.json` for all the requirements.
Since this is a submodule it can't enforce these requirements, but you will get errors if you don't have them installed.
### Components
At the moment, the following components are available:
- `BBAlert`
- `BBButton`
- `BBCard`
- `BBCollapsible`
- `BBLink`
- `BBLoadingSpinner`
- `BBModal`
- `BBNavbar`
- `BBNavbarItem`
- `BBText`
As well as the following 'Form Components':
- `BBFieldBase`
- `BBFieldCheckbox`
- `BBFieldSelect`
- `BBFieldFile`
- `BBFieldNumber`
- `BBFieldSelectCard`
- `BBFieldSelectMultiple`
- `BBFieldText`
Also including a number of form helper functions and components.
**Form Components Sizing**: All form components support `sm`, `md`, and `lg` sizing options that maintain proper proportional dimensions. The checkbox sizing system uses SCSS mixins to ensure consistent visual scaling across all size variants.
### SCSS Variables
You are also able to customize `Base Blocks` via SCSS variables. You typically will want to put these in `globals.scss`.
The list of available options is here:
```scss
// keep these variables separate to allow for dynamic lighten/darken usage
// NOTE: these are not required but it is highly recommended to at least
// set these theme colors
$primary-color: #5a65ff;
$secondary-color: #45b689;
$accent-color: #FF6B6C;
$info-color: #FFC800;
$warning-color: #f1c500;
$success-color: #50c758;
$danger-color: #78CDD7;
html,
:root {
// app theme
--primary-color: #{$primary-color};
--primary-dark-color: #{darken($primary-color, 10%)};
--primary-darkest-color: #{darken($primary-color, 20%)};
--primary-light-color: #{lighten($primary-color, 10%)};
--secondary-color: #{$secondary-color};
--secondary-dark-color: #{darken($secondary-color, 10%)};
--secondary-darkest-color: #{darken($secondary-color, 20%)};
--secondary-light-color: #{lighten($secondary-color, 10%)};
--accent-color: #{$accent-color};
--accent-dark-color: #{darken($accent-color, 10%)};
--accent-light-color: #{lighten($accent-color, 10%)};
--accent-darkest-color: #{darken($accent-color, 20%)};
// general colors
--white: #fff;
--black: rgb(35, 35, 35);
--grey-lightest: #abb3c0;
--grey-light: #b1bfd5;
--grey-dark: #969dac;
--grey-darkest: #6f7e9d;
// theme colors
--info-color: #{$info-color};
--info-dark-color: #{darken($info-color, 10%)};
--info-light-color: #{lighten($info-color, 10%)};
--warning-color: #{$warning-color};
--warning-dark-color: #{darken($warning-color, 10%)};
--warning-light-color: #{lighten($warning-color, 10%)};
--success-color: #{$success-color};
--success-dark-color: #{darken($success-color, 10%)};
--success-light-color: #{lighten($success-color, 10%)};
--danger-color: #{$danger-color};
--danger-dark-color: #{darken($danger-color, 10%)};
--danger-light-color: #{lighten($danger-color, 10%)};
// bg theme colors
--bg-color: rgb(233, 233, 233);
--bg-light-color: rgba(241, 241, 241, 1);
--bg-dark-color: rgb(189, 189, 189);
// bb alert
--alert-border-radius: 1rem;
// bb button
--button-base-padding: 0.6rem;
--button-border-radius: 1rem;
// bb card
--card-background-default-color: rgb(250, 250, 250);
--card-border-default-color: rgb(230, 230, 230);
--card-border-radius: 1rem;
--card-border-thickness: 2px;
--card-elevation-default: rgba(0, 0, 0, 0.12) 0px 1px 1px, rgba(0, 0, 0, 0.24) 0px 1px 1px;
--card-elevation-low: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px;
--card-elevation-med: rgba(0, 0, 0, 0.12) 0px 3px 6px, rgba(0, 0, 0, 0.24) 0px 3px 6px;
--card-elevation-high: rgba(0, 0, 0, 0.12) 0px 10px 20px, rgba(0, 0, 0, 0.24) 0px 6px 6px;
// bb divider
--divider-color-default: rgb(221, 221, 221);
// bb loading
--loading-default-variant: default;
--loading-default-size: md;
--loading-default-color: primary;
--loading-thickness: 2px;
// bb modal
--modal-z-index: 9999;
// bb navbar
--navbar-background-color: var(--primary-color);
--navbar-icon-mobile-color: var(--primary-color);
--navbar-transition: all 0.2s ease-in-out;
// responsive vertical navbar widths for different screen sizes
--navbar-vertical-width-xs: 5rem;
--navbar-vertical-width-sm: 6rem;
--navbar-vertical-width-md: 8rem;
--navbar-vertical-width-lg: 10rem;
--navbar-vertical-width-xl: 11rem;
// bb navbar item
--navbar-item-border-radius: 1rem;
--navbar-item-padding: 0.5rem;
--navbar-item-background-color: transparent;
--navbar-item-text-color: var(--accent-color);
--navbar-item-text-color-hover: #{darken($accent-color, 20%)};
--navbar-item-bg-color-active: #{lighten($primary-color, 45%)};
--navbar-item-bg-color-hover: #{lighten($accent-color, 20%)};
--navbar-item-border-thickness: 2px;
--navbar-item-border-default-color: var(--primary-color);
// bb tooltip
--tooltip-padding: 0.5rem 1rem;
--tooltip-border-radius: 8px;
--tooltip-z-index: 9000;
--tooltip-box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
--tooltip-arrow-size: 4px;
// bb form components
--form-input-bg: var(--bg-color);
--form-input-border-color: var(--bg-dark-color);
--form-input-color: var(--text-color-default);
--form-input-focus-color: var(--secondary-color);
--form-input-focus-bg: var(--bg-color);
--form-input-focus-border-color: var(--secondary-color);
--form-input-placeholder-color: var(--grey-lightest);
--form-input-disabled-color: var(--grey-lightest);
--form-input-disabled-bg: var(--bg-color);
--form-input-disabled-border-color: var(--grey-dark);
--form-file-button-border-color: var(--grey-dark);
--form-file-button-hover-color: var(--white);
--form-file-button-color: var(--text-color-default);
--form-file-button-hover-bg: var(--primary-color);
--form-input-plaintext-color: var(--white);
--form-select-arrow-color: var(--form-input-color);
--form-required-indicator-color: var(--form-input-color);
// bb table
--table-cell-bg: var(--card-background-default-color);
--table-header-bg: var(--bg-light-color);
--table-row-hover-bg: var(--bg-color);
--table-row-selected-bg: var(--accent-color);
// bb text
--text-color-default: rgb(24, 24, 24);
--text-size-xs: 0.5rem;
--text-size-s: 0.75rem;
--text-size-m: 1rem;
--text-size-l: 1.5rem;
--text-size-xl: 2rem;
--text-size-xxl: 2.5rem;
--text-size-xxxl: 3rem;
--mobile-text-size-xs: 0.6rem;
--mobile-text-size-s: 0.8rem;
--mobile-text-size-m: 1rem;
--mobile-text-size-l: 1.2rem;
--mobile-text-size-xl: 1.6rem;
--mobile-text-size-xxl: 2rem;
--mobile-text-size-xxxl: 2.5rem;
// font family - page router font usage
--font-family-main: 'Josefin Sans'; // Used for main text
--font-family-header: 'Montserrat'; // Used for larger fonts/headers
--font-family-navbar-header: 'Montserrat'; // Used for navbar headers
--form-input-font-family: 'Montserrat' // Font family for all form fields
--form-label-font-family: 'Montserrat' // Font family for all form field labels
// font family - app router font usage
--font-family-main: var(--font-lexend);
--font-family-header: var(--font-lexend);
--font-family-navbar-header: var(--font-lexend);
--form-input-font-family: var(--font-family-main); // Font family for all form fields
--form-label-font-family: var(--font-family-main); // Font family for all form field labels
}
```
While none of these variables are required, it definitely will help make your app look and feel more custom.
It is recommended to copy and paste this whole block into your `globals.scss` file and then edit the variables as needed.
#### Responsive Breakpoints & SCSS Mixins
The responsive mixins provide consistent breakpoints and utilities throughout your application.
##### Setup (Required - One-time breaking change in v2.2.0)
Add this to your `next.config.js`:
```ts
const { configureSubmoduleSass } = require('./base_blocks/mixins');
const nextConfig = {
// configure sass for this project and nextjs base blocks
sassOptions: configureSubmoduleSass(__dirname),
// ... rest of your config
};
module.exports = nextConfig;
```
> ⚠️ **Your build will fail without this setup** - the error message should guide you here.
##### Usage
After setup, these mixins are automatically available in all your `.scss` files to use as so:
**Responsive Breakpoints:**
```scss
@include media-lg {
...
}
@include media-sm {
...
}
```
`BB` components will automatically use these breakpoints to be mobile friendly.
See `mixins.scss` for the specific breakpoints and mixins available.
#### Dark Mode / Themes
Add overrides for dark themes like so:
```scss
[data-theme='dark'] {
// override any of the above variables
--bg-color: rgb(25, 25, 25);
--bg-light-color: rgb(60, 60, 60);
--bg-dark-color: rgb(39, 39, 39);
// bb navbar
--navbar-background-color: rgb(54, 54, 54);
// bb card
--card-background-default-color: rgb(77, 77, 77);
--card-border-default-color: rgb(77, 77, 77);
// bb divider
--divider-color-default: rgb(77, 77, 77);
// bb text
--text-color-default: rgb(255, 255, 255);
}
```
## Testing
This project includes comprehensive testing with Cypress component testing and code coverage.
### Running Tests
```bash
# Run all component tests
npm run test
# Run tests with coverage report
npm run test:coverage
# Open Cypress GUI for component testing
npm run test:open
# Generate coverage reports
npm run coverage:report
# Open HTML coverage report in browser
npm run coverage:open
```
### Test Structure
- **Component Tests**: Located in `cypress/component/` directory
- **Test Utilities**: Custom commands and helpers in `cypress/support/`
- **Coverage Reports**: Generated in `coverage/` directory
All base components have comprehensive test coverage including:
- Rendering tests for all prop variations
- Interaction testing (clicks, hovers, form inputs)
- Responsive behavior testing
- Accessibility testing
- Edge case handling
### Writing New Tests
To create a new test file, use the template in `cypress/support/_template.cy.tsx` or follow the existing test patterns. All tests should follow the established naming convention: `component-name.cy.tsx`.
## Demo
This project is also a standalone NextJS project that you can run to see the components in action.
To do so, simply run:
```bash
npm run dev
```
Then navigate to [http://localhost:3000](http://localhost:3000) to see the demo of the components.
Form Components Demo are available at [http://localhost:3000/form-components](http://localhost:3000/form-components).
**Please note this is a work in progress.**
-------------------------------------------------------
##### [https://danielnazarian.com](https://danielnazarian.com)
##### Copyright 2025 © Daniel Nazarian.