Styling and Theming

Common styles are located in the frontend/src/css folder such as: _calendar.css, _table.css, _scrollbars.css, _progress.css, _theme.css, etc. which are responsible for customizing styles for tables, scroll bars, and other things.

Customizing Colors

The frontend/src/colors.ts file contains text, borders, buttons, backgrounds, and more style variables. Below are some key variables and how they are defined:

Background Colors

The colorsBgLight object defines various background color styles:

export const colorsBgLight = {
  white: 'bg-white text-black',
  light: 'bg-white text-black dark:bg-dark-900 dark:text-white',
  contrast: 'bg-gray-800 text-white dark:bg-white dark:text-black',
  success: 'bg-emerald-500 border-emerald-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
  danger: 'bg-red-500 border-red-500 text-white',
  warning: 'bg-yellow-500 border-yellow-500 text-white',
  info: 'bg-blue-500 border-blue-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
};

Text Colors

The colorsText object defines various text color styles:

export const colorsText = {
  white: 'text-black dark:text-slate-100',
  light: 'text-gray-700 dark:text-slate-400',
  contrast: 'dark:text-white',
  success: 'text-emerald-500',
  danger: 'text-red-500',
  warning: 'text-yellow-500',
  info: 'text-blue-500',
};

Outline Colors

The colorsOutline object defines various outline styles:

export const colorsOutline = {
  white: [colorsText.white, 'border-gray-100'].join(' '),
  light: [colorsText.light, 'border-gray-100'].join(' '),
  contrast: [colorsText.contrast, 'border-gray-900 dark:border-slate-100'].join(' '),
  success: [colorsText.success, 'border-emerald-500'].join(' '),
  danger: [colorsText.danger, 'border-red-500'].join(' '),
  warning: [colorsText.warning, 'border-yellow-500'].join(' '),
  info: [colorsText.info, 'border-blue-500'].join(' '),
};

Button Styles

The getButtonColor function defines styles for buttons:

export const getButtonColor = (
  color: ColorButtonKey,
  isOutlined: boolean,
  hasHover: boolean,
  isActive = false,
) => {
  // Implementation
};

The main color types are enumerated in frontend/src/interfaces/index.ts:

export type ColorKey =
  | 'white'
  | 'light'
  | 'contrast'
  | 'success'
  | 'danger'
  | 'warning'
  | 'info';

The button color types used by the getButtonColor function are also listed in frontend/src/interfaces/index.ts:

export type ColorButtonKey =
  | 'white'
  | 'whiteDark'
  | 'lightDark'
  | 'contrast'
  | 'success'
  | 'danger'
  | 'warning'
  | 'info'
  | 'void';

Styling Widgets

The frontend/src/styles.ts file contains styles for the main widgets of the application:

interface StyleObject {
  aside: string;
  asideScrollbars: string;
  asideBrand: string;
  asideMenuItem: string;
  asideMenuItemActive: string;
  asideMenuDropdown: string;
  navBarItemLabel: string;
  navBarItemLabelHover: string;
  navBarItemLabelActiveColor: string;
  overlay: string;
}

The dataGridStyles variable customizes the datagrid used in the project.

We use the @mui/x-data-grid library for datagrid functionalities.

Managing Layouts

Currently, two layouts are used on the pages: Guest and Authenticated.

The Guest layout is for public pages, and the Authenticated layout is for private pages.

These layouts are in the frontend/src/layouts directory.

Below is an example of how the Authenticated layout is used on the frontend/src/pages/dashboard.tsx page:

import LayoutAuthenticated from '../layouts/Authenticated';

...
...
...

Dashboard.getLayout = function getLayout(page: ReactElement) {
  return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};

Configuring Dark and Custom Themes

Theme styles are located in the file frontend/src/css/_theme.css

The frontend/src/stores/styleSlice.ts file manages theme switching and theme management. The initialState variable contains styles that participate in theme switching:

import * as styles from '../styles';

const initialState: StyleState = {
  asideStyle: styles.white.aside,
  asideScrollbarsStyle: styles.white.asideScrollbars,
  asideBrandStyle: styles.white.asideBrand,
  asideMenuItemStyle: styles.white.asideMenuItem,
  asideMenuItemActiveStyle: styles.white.asideMenuItemActive,
  asideMenuDropdownStyle: styles.white.asideMenuDropdown,
  navBarItemLabelStyle: styles.white.navBarItemLabel,
  navBarItemLabelHoverStyle: styles.white.navBarItemLabelHover,
  navBarItemLabelActiveColorStyle: styles.white.navBarItemLabelActiveColor,
  overlayStyle: styles.white.overlay,
  darkMode: false,
};

Theme Management with Redux

Theme management is implemented using Redux. The reducer code is also contained in frontend/src/stores/styleSlice.ts:

export const styleSlice = createSlice({
  name: 'style',
  initialState,
  reducers: {
    setDarkMode: (state, action: PayloadAction<boolean | null>) => {
      // Implementation
    },
    setStyle: (state, action: PayloadAction<StyleKey>) => {
      // Implementation
    },
    // Additional reducers
  },
});

Using and Customizing Icons

We have components BaseIcon and IconRounded for working with icons, which can be found in the frontend/src/components directory. We also use the @mdi/js library for ready-made icons.

Below is an example of how BaseIcon is used in the frontend/src/components/Pagination.tsx component:

import {
  mdiChevronDoubleLeft,
  mdiChevronDoubleRight,
  mdiChevronLeft,
  mdiChevronRight,
} from '@mdi/js';

<div className='flex'>
  <BaseIcon
    path={mdiChevronDoubleLeft}
    className='mr-2 text-pavitra-600 border-2 border-pavitra-600 rounded-full'
  />
  <BaseIcon
    path={mdiChevronLeft}
    className='mr-2 text-pavitra-600 border-2 border-pavitra-600 rounded-full'
  />
</div>

This is how the pagination icons look: