@pplancq/react-template 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.babelrc.js +1 -0
  2. package/.commitlintrc.js +1 -0
  3. package/.editorconfig +4 -0
  4. package/.env +36 -0
  5. package/.eslintrc.js +1 -0
  6. package/.gitattributes +1 -0
  7. package/.husky/commit-msg +1 -0
  8. package/.husky/pre-commit +1 -0
  9. package/.lintstagedrc.js +5 -0
  10. package/.postcssrc.js +1 -0
  11. package/.prettierrc.js +1 -0
  12. package/.stylelintrc.js +1 -0
  13. package/CHANGELOG.md +26 -0
  14. package/LICENSE +21 -0
  15. package/README.md +221 -0
  16. package/_gitignore +26 -0
  17. package/package.json +84 -0
  18. package/public/favicon.ico +0 -0
  19. package/public/index.html +17 -0
  20. package/src/api/README.md +64 -0
  21. package/src/api/demoApi.ts +44 -0
  22. package/src/assets/README.md +51 -0
  23. package/src/assets/css/index.ts +2 -0
  24. package/src/assets/css/mainBody.css +4 -0
  25. package/src/assets/css/reset.css +131 -0
  26. package/src/assets/images/logo.png +0 -0
  27. package/src/assets/images/templatePlugins.png +0 -0
  28. package/src/bootstrap.tsx +26 -0
  29. package/src/components/App/App.tsx +18 -0
  30. package/src/components/App/index.ts +1 -0
  31. package/src/components/Footer/Footer.module.css +4 -0
  32. package/src/components/Footer/Footer.tsx +16 -0
  33. package/src/components/Footer/__tests__/Footer.test.tsx +15 -0
  34. package/src/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +21 -0
  35. package/src/components/Footer/index.ts +1 -0
  36. package/src/components/Header/Header.module.css +7 -0
  37. package/src/components/Header/Header.tsx +17 -0
  38. package/src/components/Header/__tests__/Header.test.tsx +15 -0
  39. package/src/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +35 -0
  40. package/src/components/Header/index.ts +1 -0
  41. package/src/components/README.md +34 -0
  42. package/src/components/TextInput/TextInput.tsx +24 -0
  43. package/src/components/TextInput/index.ts +1 -0
  44. package/src/config/README.md +61 -0
  45. package/src/config/index.ts +1 -0
  46. package/src/config/queryClientConfig.ts +3 -0
  47. package/src/forms/ProfileForm/ProfileForm.module.scss +10 -0
  48. package/src/forms/ProfileForm/ProfileForm.tsx +51 -0
  49. package/src/forms/ProfileForm/index.ts +1 -0
  50. package/src/forms/README.md +131 -0
  51. package/src/hooks/README.md +87 -0
  52. package/src/hooks/api/queryKey.ts +1 -0
  53. package/src/hooks/api/useDemoApi.ts +16 -0
  54. package/src/main.ts +3 -0
  55. package/src/pages/Demo/Demo.module.scss +184 -0
  56. package/src/pages/Demo/Demo.tsx +237 -0
  57. package/src/pages/Demo/ReactHookFormDemo/ReactHookFormDemo.module.css +32 -0
  58. package/src/pages/Demo/ReactHookFormDemo/ReactHookFormDemo.tsx +48 -0
  59. package/src/pages/Demo/ReactHookFormDemo/index.ts +1 -0
  60. package/src/pages/Demo/ReactHookFormDemo/routes.tsx +7 -0
  61. package/src/pages/Demo/ReactQueryDemo/ReactQueryDemo.module.scss +38 -0
  62. package/src/pages/Demo/ReactQueryDemo/ReactQueryDemo.tsx +55 -0
  63. package/src/pages/Demo/ReactQueryDemo/index.ts +1 -0
  64. package/src/pages/Demo/ReactQueryDemo/routes.tsx +7 -0
  65. package/src/pages/Demo/__tests__/Demo.test.tsx +15 -0
  66. package/src/pages/Demo/__tests__/__snapshots__/Demo.test.tsx.snap +555 -0
  67. package/src/pages/Demo/index.ts +1 -0
  68. package/src/pages/Demo/routes.tsx +8 -0
  69. package/src/pages/Error/Error.module.css +8 -0
  70. package/src/pages/Error/Error.tsx +22 -0
  71. package/src/pages/Error/index.ts +1 -0
  72. package/src/pages/Layout/Layout.tsx +12 -0
  73. package/src/pages/Layout/index.ts +1 -0
  74. package/src/pages/README.md +88 -0
  75. package/src/providers/QueryClientProvider/QueryClientProvider.tsx +16 -0
  76. package/src/providers/QueryClientProvider/index.ts +1 -0
  77. package/src/providers/README.md +115 -0
  78. package/src/providers/index.ts +1 -0
  79. package/src/providers/withProviders/index.ts +1 -0
  80. package/src/providers/withProviders/withProviders.tsx +18 -0
  81. package/src/react-app-env.d.ts +3 -0
  82. package/src/routing/README.md +80 -0
  83. package/src/routing/appRoutes.ts +5 -0
  84. package/src/routing/routerFactory.ts +10 -0
  85. package/src/routing/routes.tsx +13 -0
  86. package/src/types/README.md +61 -0
  87. package/src/types/demoApi.ts +9 -0
  88. package/src/types/profileTypes.ts +5 -0
  89. package/src/ui/README.md +141 -0
  90. package/src/ui/atoms/Input/Input.module.scss +32 -0
  91. package/src/ui/atoms/Input/Input.tsx +27 -0
  92. package/src/ui/atoms/Input/index.ts +1 -0
  93. package/src/ui/atoms/Logo/Logo.module.css +3 -0
  94. package/src/ui/atoms/Logo/Logo.tsx +11 -0
  95. package/src/ui/atoms/Logo/index.ts +1 -0
  96. package/src/ui/atoms/NavLink/NavLink.tsx +8 -0
  97. package/src/ui/atoms/NavLink/index.ts +1 -0
  98. package/src/ui/molecules/Navigation/Navigation.module.css +22 -0
  99. package/src/ui/molecules/Navigation/Navigation.tsx +25 -0
  100. package/src/ui/molecules/Navigation/index.ts +1 -0
  101. package/src/ui/organisms/Footer/Footer.module.css +10 -0
  102. package/src/ui/organisms/Footer/Footer.tsx +10 -0
  103. package/src/ui/organisms/Footer/index.ts +1 -0
  104. package/src/ui/organisms/Header/Header.module.css +17 -0
  105. package/src/ui/organisms/Header/Header.tsx +16 -0
  106. package/src/ui/organisms/Header/index.ts +1 -0
  107. package/src/ui/organisms/MainContent/MainContent.module.css +3 -0
  108. package/src/ui/organisms/MainContent/MainContent.tsx +6 -0
  109. package/src/ui/organisms/MainContent/index.ts +1 -0
  110. package/src/ui/templates/MainTemplate/MainTemplate.module.css +5 -0
  111. package/src/ui/templates/MainTemplate/MainTemplate.tsx +26 -0
  112. package/src/ui/templates/MainTemplate/index.ts +1 -0
  113. package/src/utils/README.md +68 -0
  114. package/tsconfig.json +32 -0
  115. package/vitest.config.mts +49 -0
  116. package/vitest.setup.ts +1 -0
  117. package/webpack.config.js +22 -0
@@ -0,0 +1,88 @@
1
+ # 📁 pages
2
+
3
+ The "pages" folder is designed to contain all the pages of our application. This structure facilitates organization, management, and navigation between the different views of our application. Additionally, if a page contains components related to its structure, we can create sub-folders to maintain order.
4
+
5
+ ## 📑 Table of Contents
6
+ - [Why Use a "pages" Folder](#folder-organization)
7
+ - [Typical Structure of a "pages" Folder](#structure)
8
+ - [Usage Example](#usage)
9
+ - [Best Practice](#best-practice)
10
+
11
+
12
+ ## <span id="folder-organization">Why Use a "pages" Folder?</span>
13
+
14
+ 1. **Clear Organization** : By grouping all our pages in a single folder, we maintain a clear organization of our application, making it easy to find specific pages.
15
+
16
+ 2. **Ease of Navigation** : A well-organized "pages" folder structure makes navigation between the views of our application easier.
17
+
18
+ 3. **Reusability** : Components specific to a page can be reused in other pages, promoting code modularity.
19
+
20
+ ## <span id="structure">Typical Structure of a "pages" Folder</span>
21
+
22
+ The structure of a "pages" folder can vary depending on the size of your application, but here is a typical structure you might adopt:
23
+ ```
24
+ 📁 Pages
25
+ ├── 📁 Home
26
+ ├── 📁 User
27
+ │ ├── 📁 UserProfile
28
+ ├── 📁 Posts
29
+ │ ├── 📁 Article
30
+ ├── 📁 Admin
31
+ ```
32
+
33
+ In this structure, each page, such as "Home" or "User," is typically defined in its own file. If a page is complex and requires related components, you can create a sub-folder to maintain order related to the URL, as with "UserProfile" or "Article" in this example.
34
+
35
+ ## <span id="usage">🧑🏻‍💻 Usage Example</span>
36
+
37
+ Suppose we have a "UserProfile" page with a complex structure:
38
+
39
+ ```
40
+ 📁 UserProfile
41
+ ├── 📄 index.ts
42
+ ├── 📄 UserProfile.tsx
43
+ ├── 📄 routes.tsx
44
+ ```
45
+ ```javascript
46
+ // index.ts
47
+ export { userProfileRoutes } from './routes';
48
+
49
+ // routes.tsx (react-router-dom v6)
50
+ import { RouteObject } from 'react-router-dom';
51
+ import { UserProfile } from './UserProfile';
52
+
53
+ export const userProfileRoutes: RouteObject = {
54
+ path: 'user-profile',
55
+ element: <UserProfile />,
56
+ };
57
+
58
+ // UserProfile.tsx
59
+ export const UserProfile = () => {
60
+ return (
61
+ <div>
62
+ UserProfile
63
+ {/* Content of the UserProfile page */}
64
+ </div>
65
+ );
66
+ }
67
+ ```
68
+
69
+ By using a "pages" folder and the ability to create sub-folders, we effectively organize our pages and their related components for better management of our application.
70
+
71
+
72
+ ## <span id="best-practice">🎖️ Best Practice</span>
73
+ When working with page components, it is advisable to follow these best practices to maintain a clean and organized code structure:
74
+
75
+ #### - Minimize Business Logic
76
+
77
+ Limit the inclusion of business logic within page components.
78
+
79
+ Instead, delegate complex business logic to separate utility functions, services, or hooks. This keeps your page components focused on rendering and layout.
80
+
81
+ #### - Data Presence Control
82
+
83
+ Keep the logic within page components to a minimum, focusing primarily on controlling the presence of data.
84
+
85
+ If data is not available or meets certain conditions, consider redirecting to a dedicated error or not-found page.
86
+
87
+ ---
88
+ ***By adopting these practices, you create page components that are focused on their primary responsibilities, leading to cleaner and more maintainable code.***
@@ -0,0 +1,16 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import { type QueryClient, QueryClientProvider as ReactQueryClientProvider } from 'react-query';
3
+ import { ReactQueryDevtools } from 'react-query/devtools';
4
+
5
+ type ClientProviderProps = {
6
+ client: QueryClient;
7
+ };
8
+
9
+ export const QueryClientProvider = ({ children, client }: PropsWithChildren<ClientProviderProps>) => {
10
+ return (
11
+ <ReactQueryClientProvider client={client}>
12
+ {children}
13
+ <ReactQueryDevtools initialIsOpen={false} />
14
+ </ReactQueryClientProvider>
15
+ );
16
+ };
@@ -0,0 +1 @@
1
+ export { QueryClientProvider } from './QueryClientProvider';
@@ -0,0 +1,115 @@
1
+ # 📁 providers
2
+
3
+ The "providers" folder is designed to expose service handlers and custom contexts that provide shared functionality across our entire application. It serves as a centralized way to manage services such as authentication, authorization, translation management, and many others.
4
+
5
+ ## 📑 Table of Contents
6
+ - [Why Use a "providers" Folder?](#folder-organization)
7
+ - [Structure of a "providers" Folder](#structure)
8
+ - [Usage Example](#usage)
9
+ - [Best Practice](#best-practice)
10
+
11
+ ## <span id="folder-organization">Why Use a "providers" Folder?</span>
12
+
13
+ 1. **Centralization** : By grouping all our service handlers in a "providers" folder, we centralize the management of these services, making configuration and usage simpler.
14
+
15
+ 2. **Reusability** : Service handlers and custom contexts exposed in this folder can be reused across different components of our application, promoting code reuse.
16
+
17
+ 3. **Better Separation of Concerns** : By separating services from the user interface, we improve code readability and adhere to the separation of concerns principle.
18
+
19
+ ## <span id="structure">Structure of a "providers" Folder</span>
20
+
21
+ The structure of a "providers" folder can vary based on your project's needs, but here is a typical structure you might adopt :
22
+
23
+ ```
24
+ 📁 providers
25
+ ├── 📁 AuthProvider
26
+ ├── 📁 AuthorizationProvider
27
+ ├── 📁 TranslationProvider
28
+ ├── 📁 CustomRouterProvider
29
+ ├── 📁 CustomContextProvider
30
+ ├── 📁 ...
31
+ ```
32
+
33
+ Each file, such as "AuthProvider.ts" or "TranslationProvider.ts," contains a service handler or custom context intended to be used throughout your application.
34
+
35
+ ## <span id="usage">🧑🏻‍💻Usage Example </span>
36
+
37
+ Suppose we have an authentication service handler "AuthProvider" in our "providers" folder:
38
+
39
+ ```javascript
40
+ // AuthProvider.js
41
+ import { createContext, useState } from 'react';
42
+
43
+ export const AuthContext = createContext();
44
+
45
+ export const AuthProvider = ({ children }) => {
46
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
47
+
48
+ const login = () => {
49
+ setIsAuthenticated(true);
50
+ };
51
+
52
+ const logout = () => {
53
+ setIsAuthenticated(false);
54
+ };
55
+
56
+ return (
57
+ <AuthContext.Provider value={{ isAuthenticated, login, logout }}>
58
+ {children}
59
+ </AuthContext.Provider>
60
+ );
61
+ }
62
+ ```
63
+ We can then use this authentication service provider in our components by wrapping our components in the provided context:
64
+ ```javascript
65
+ import { AuthProvider } from '@Front/Providers/AuthProvider';
66
+
67
+ export const App = () => {
68
+ return (
69
+ <AuthProvider>
70
+ {/* Vos composants React ici */}
71
+ </AuthProvider>
72
+ );
73
+ }
74
+ ```
75
+ ## <span id="best-practice">🎖️ Best Practice</span>
76
+
77
+ A good practice is to set up a Higher Order Component (HOC) "withProvider" that allows injecting all providers at
78
+ once.
79
+
80
+ Example:
81
+ ```typescript
82
+ import { ComponentType } from 'react';
83
+ import { QueryClient } from '@tanstack/react-query';
84
+ import { AuthProvider } from '@Front/Providers/AuthProvider';
85
+ import { QueryClientProvider } from '@Front/Providers/QueryClientProvider ';
86
+
87
+ export interface WithRootProps {
88
+ queryClient: QueryClient;
89
+ }
90
+
91
+ export const withProvider = <P extends object>(Component: ComponentType<P>) => {
92
+ const WithProvider = ({ queryClient, ...props }: P & WithRootProps) => (
93
+ <QueryClientProvider client={queryClient}>
94
+ <AuthProvider>
95
+ <Component {...props as P} />
96
+ </AuthProvider>
97
+ </QueryClientProvider>
98
+ );
99
+ WithProvider.displayName = `withProvider(${Component.displayName || Component.name})`
100
+
101
+ return WithProvider
102
+
103
+ }
104
+ ```
105
+
106
+ ```javascript
107
+ import { withProvider } from '@Front/Providers/withProvider';
108
+ import { App } from '@Front/components/App';
109
+
110
+ const Root = withProvider(App);
111
+ ```
112
+
113
+ ----------
114
+
115
+ ***By using a "providers" folder, we centralize the management of services and custom contexts, enhancing code reuse and ease of maintenance.***
@@ -0,0 +1 @@
1
+ export { withProvider } from './withProviders';
@@ -0,0 +1 @@
1
+ export { withProvider } from './withProviders';
@@ -0,0 +1,18 @@
1
+ import { QueryClientProvider } from '@Front/providers/QueryClientProvider';
2
+ import type { ComponentProps, ComponentType } from 'react';
3
+
4
+ type WithRootProps = {
5
+ queryClient: ComponentProps<typeof QueryClientProvider>['client'];
6
+ };
7
+
8
+ export const withProvider = <P extends object>(Component: ComponentType<P>) => {
9
+ const WithProvider = ({ queryClient, ...props }: P & WithRootProps) => (
10
+ <QueryClientProvider client={queryClient}>
11
+ <Component {...(props as P)} />
12
+ </QueryClientProvider>
13
+ );
14
+
15
+ WithProvider.displayName = `withProvider(${Component.displayName || Component.name})`;
16
+
17
+ return WithProvider;
18
+ };
@@ -0,0 +1,3 @@
1
+ // interface ImportMetaEnv {
2
+ // readonly FRONT_FOO: string;
3
+ // }
@@ -0,0 +1,80 @@
1
+ # 📁routing
2
+
3
+ The "routing" folder is responsible for managing navigation within the application. We use the `react-router-dom` library to facilitate route creation and navigation between different views of our application.
4
+
5
+ ## 📑 Table of Contents
6
+ - [Folder Organization](#folder-organization)
7
+ - [Using `react-router-dom`](#react-router-dom)
8
+ - [Using `appRoutes.ts`](#using-appRoutes)
9
+ - [Learn More](#learn-more)
10
+
11
+ ## <span id="folder-organization">Folder Organization</span>
12
+
13
+ In the "routing" folder, you can find the following files and components:
14
+
15
+ 1. **`routesObject.tsx`** : This file contains the configuration of our main router. It declares the various routes of the application and defines the components associated with each route.
16
+
17
+ 2. **`routerFactory.ts`** : The `routerFactory.ts` file can contain functions or reusable components related to routing. You can place routing utilities or custom components to facilitate navigation management in our application.
18
+
19
+ 3. **`appRoutes.ts`** It contains a simple structure to define the paths of our application.
20
+
21
+ ## <span id="react-router-dom">🧑🏻‍💻 Using `react-router-dom` </span>
22
+
23
+ `react-router-dom` is a library that makes it easy to create routes in a React application. You can import it into the appropriate files to define routes and manage navigation between views. Here's a simple example of its usage:
24
+
25
+ ```javascript
26
+ import { createRoot } from "react-dom/client";
27
+ import {
28
+ createBrowserRouter,
29
+ RouterProvider,
30
+ } from "react-router-dom";
31
+
32
+ const router = createBrowserRouter([
33
+ {
34
+ path: "/",
35
+ element: (
36
+ <div>
37
+ <h1>Hello World</h1>
38
+ <Link to="about">About Us</Link>
39
+ </div>
40
+ ),
41
+ },
42
+ {
43
+ path: "about",
44
+ element: <div>About</div>,
45
+ },
46
+ ]);
47
+
48
+ createRoot(document.getElementById("root")).render(
49
+ <RouterProvider router={router} />
50
+ );
51
+ ```
52
+
53
+ ## <span id="using-appRoutes">Using `appRoutes.ts`</span>
54
+ How to define a router with parameters ?
55
+
56
+ The simplest way is to write it with the parameters as `react-router` requires, and when using it in a `NavLink` call the `generatPath` function from `react-router`.
57
+
58
+ For example:
59
+
60
+ ```javascript
61
+ // appRoutes.ts
62
+ export const appRoutes = {
63
+ home: '/',
64
+ post: '/post',
65
+ article: '/post/:id',
66
+ }
67
+ // component.tsx
68
+ import { NavLink, generatePath } from 'react-router-dom';
69
+ import { appRoutes } from '@Front/routing/appRoutes';
70
+ export const ComponentName = () => {
71
+ return (
72
+ <NavLink to={generatePath(appRoutes .article, { id: 1 })}>link to article 1</NavLink>
73
+ );
74
+ };
75
+ ```
76
+ With the `generatePath` function, it is possible to generate URIs with dynamic parameters.
77
+
78
+
79
+ ## <span id="learn-more">🙇 Learn More</span>
80
+ - [React Router](https://reactrouter.com/en/main/start/overview)
@@ -0,0 +1,5 @@
1
+ export const approutes = {
2
+ home: '/',
3
+ reactQueryDemo: '/reactQueryDemo',
4
+ reactHookFormDemo: '/reactHookFormDemo',
5
+ };
@@ -0,0 +1,10 @@
1
+ import { createBrowserRouter } from 'react-router-dom';
2
+ import { routeObject } from './routes';
3
+
4
+ interface CreateRouterProps {
5
+ basename?: string;
6
+ }
7
+
8
+ export const createRouter = ({ basename }: CreateRouterProps = {}) => {
9
+ return createBrowserRouter(routeObject, { basename });
10
+ };
@@ -0,0 +1,13 @@
1
+ import { demoRoutes } from '@Front/pages/Demo';
2
+ import { Error } from '@Front/pages/Error';
3
+ import { Layout } from '@Front/pages/Layout';
4
+ import type { RouteObject } from 'react-router-dom';
5
+
6
+ export const routeObject: RouteObject[] = [
7
+ {
8
+ path: '/',
9
+ element: <Layout />,
10
+ children: [demoRoutes],
11
+ errorElement: <Error />,
12
+ },
13
+ ];
@@ -0,0 +1,61 @@
1
+ # 📁 types
2
+
3
+ The "types" folder: since we are using TypeScript, this folder is intended to contain custom type definition files that enhance type checking and auto-completion in your code.
4
+
5
+ ## 📑 Table of Contents
6
+ - [Why use a "types" folder?](#folder-organization)
7
+ - [Structure of a "types" folder](#structure)
8
+ - [Example of usage](#usage)
9
+
10
+ ## <span id="folder-organization">Why use a "types" folder?</span>
11
+
12
+ 1. **Type Checking** : By defining custom types for our application, we improve type checking, making it easier to detect and prevent typing errors.
13
+
14
+ 2. **Better Auto-Completion** : Custom type definition files allow code editors to provide more accurate auto-completion when working with objects, functions, and components.
15
+
16
+ 3. **Integrated Documentation** : By creating explicit types, you effectively document your code, making it easier for other developers to understand your components, functions, and data.
17
+
18
+ ## <span id="structure">Structure of a "types" folder</span>
19
+
20
+ The structure of a "types" folder can vary based on need, but here's a typical structure you might adopt :
21
+
22
+ ```
23
+ 📁 src
24
+ 📁 types
25
+ ├── 📄 customTypes.ts
26
+ ├── 📄 apiTypes.ts
27
+ ```
28
+
29
+ In this structure, each file, such as "customTypes.ts" or "apiTypes.ts," contains type definitions specific to your application. For example, you might define types for API data, business objects, or component props.
30
+
31
+ ## <span id="usage">🧑🏻‍💻 Example of usage</span>
32
+
33
+ Suppose you have defined a custom type in "customTypes.ts":
34
+
35
+ ```typescript
36
+ // customTypes.ts
37
+ export type User = {
38
+ id: number;
39
+ name: string;
40
+ email?: string;
41
+ };
42
+ ```
43
+
44
+ You can then use this type in your React components to define props or states, enhancing type checking:
45
+
46
+ ```typescript
47
+ import { User } from '@Front/types/customTypes';
48
+
49
+ type UserProfileProps = {
50
+ user: User;
51
+ };
52
+
53
+ export const UserProfile = ({ user }: UserProfileProps) => {
54
+ return (
55
+ <div id={user.id}>
56
+ <h1>{user.name}</h1>
57
+ {user.email && <p>Email: {user.email}</p>}
58
+ </div>
59
+ );
60
+ };
61
+ ```
@@ -0,0 +1,9 @@
1
+ export type User = {
2
+ id: number;
3
+ firstName: string;
4
+ lastName: string;
5
+ age: number;
6
+ email: string;
7
+ };
8
+
9
+ export type Users = User[];
@@ -0,0 +1,5 @@
1
+ export type ProfileType = {
2
+ mail: string;
3
+ firstName: string;
4
+ lastName: string;
5
+ };
@@ -0,0 +1,141 @@
1
+ # 📁 ui
2
+ The "ui" folder is a directory designed to group and organize reusable components.
3
+
4
+ We follow the concept of Atomic design to structure our components into "atoms," "molecules," "organisms," and "templates," ensuring consistent design and maximum reusability.
5
+
6
+ ## 📑 Table of Contents
7
+ - [Why use a "ui" folder with Atomic Design](#folder-organization)
8
+ - [Structure of a "ui" folder according to Atomic Design](#structure)
9
+ - [Usage Example](#usage)
10
+ - [Best Practice](#best-practice)
11
+
12
+
13
+ ## <span id="folder-organization">Why use a "ui" folder with Atomic Design?</span>
14
+
15
+ 1. **Modularity** : Atomic Design divides components into levels of increasing complexity, making it easy to create reusable components at different levels.
16
+
17
+ 2. **Visual Consistency** : By following the concept of Atomic Design, we can maintain visual consistency across our entire application by reusing atoms, molecules, and organisms.
18
+
19
+ 3. **Productivity** : Creating prefab components in a "ui" folder speeds up development by reducing code duplication.
20
+
21
+ ## <span id="structure">Structure of a "ui" folder according to Atomic Design</span>
22
+
23
+ The structure of a "ui" folder can follow the hierarchy of Atomic Design:
24
+
25
+ ```
26
+ 📁 ui
27
+ ├── 📁 atoms
28
+ │ ├──📁 Button
29
+ │ ├──📁 Input
30
+ │ ├── ...
31
+ ├── 📁 molecules
32
+ │ ├── 📁 FormField
33
+ │ ├── 📁 SearchBar
34
+ │ ├── ...
35
+ ├── 📁 organisms
36
+ │ ├── 📁 Header
37
+ │ ├── 📁 Footer
38
+ │ ├── ...
39
+ ├── 📁 templates
40
+ │ ├── 📁 PageTemplate
41
+ │ ├── ...
42
+ ```
43
+
44
+ Each level (atoms, molecules, organisms, templates) groups components based on their complexity. You can create subfolders to better organize the components.
45
+
46
+ ## <span id="usage">🧑🏻‍💻Example of usage</span>
47
+
48
+ ## Using components from Atomic Design
49
+
50
+ In our project, we use Atomic Design to organize our reusable components into levels ranging from "atoms" to "templates." Here's a concrete example of using these components in our application.
51
+
52
+ ### Atom - "Button" Component
53
+
54
+ "Atoms" are basic components that don't depend on other components. In our "ui/atoms" folder, we have the "Button" component. It's a simple UI element that we can use as follows:
55
+
56
+ ```javascript
57
+ import { Button } from '@Front/ui/atoms/Button';
58
+
59
+ export const MyComponent = () => {
60
+ return (
61
+ <div>
62
+ <Button label="Cliquez-moi" />
63
+ {/* ... other elements of the application */}
64
+ </div>
65
+ );
66
+ }
67
+ ```
68
+
69
+ ### Molecule - "SearchBar" Component
70
+ "Molecules" are more complex components that group atoms to form a functional set. In our "ui/molecules" folder, we have the "SearchBar" component that uses the atomic "Button":
71
+
72
+
73
+ ```javascript
74
+ import { SearchBar } from '@Front/ui/molecules/SearchBar';
75
+
76
+ export const MyComponent = () => {
77
+ return (
78
+ <div>
79
+ <SearchBar placeholder="Rechercher..." />
80
+ {/* ... other elements of the application */}
81
+ </div>
82
+ );
83
+ }
84
+ ```
85
+ The "SearchBar" component is a molecule because it combines the "Button" atom with other atoms.
86
+
87
+ ### Organism - "Header" Component
88
+ "Organisms" are even more complex components that combine molecules and atoms to create self-contained parts of the UI. In our "ui/organisms" folder, we have the "Header" component that might include the molecular "SearchBar":
89
+
90
+ ```javascript
91
+ import Header from '@Front/ui/organisms/Header';
92
+
93
+ export const MyComponent = () => {
94
+ return (
95
+ <div>
96
+ <Header />
97
+ {/* ... other elements of the application */}
98
+ </div>
99
+ );
100
+ }
101
+ ```
102
+ The "Header" component is an organism because it combines the molecular "SearchBar" with other elements to form a self-contained part of the interface.
103
+
104
+ ### Templates - "PageTemplate" Component
105
+ "Templates" are "skeleton" components that define the placement of elements using React's composition ability.
106
+
107
+ In our "ui/templates" folder, we have the "PageTemplate" component that defines the placement of the "topBar," "body," and "footer" to create a complete page:
108
+
109
+ ```javascript
110
+ import PageTemplate from '@Front/ui/templates/PageTemplate';
111
+
112
+ export const MyComponent = () => {
113
+ return (
114
+ <PageTemplate
115
+ topBar={<div>TopBar</div>}
116
+ body={<div>Boby</div>}
117
+ footer={<div>Footer</div>}
118
+ />
119
+ );
120
+ }
121
+ ```
122
+ The "PageTemplate" component is a template because it incorporates the "Header" organism and other elements to create a complete page.
123
+
124
+ ## <span id="best-practice">🎖️ Best Practice</span>
125
+ When incorporating external component libraries, it is recommended to adhere to the following best practices for the organization of UI components:
126
+
127
+ #### - Export Components via the `ui` Directory
128
+
129
+ Always export UI components from the `ui` directory, even if they are sourced from an external component library.
130
+
131
+ This practice serves as a central point for managing component exports and facilitates handling bugs or breaking changes.
132
+
133
+ #### - Centralized Component Management
134
+ By exporting components through the ui directory, you establish a centralized location for managing changes or addressing issues related to external components.
135
+
136
+ In the event of a bug or breaking change, modifications can be made at a single location, preventing the need to update multiple parts of the codebase.
137
+
138
+ This approach contributes to better maintainability and ensures that updates to external components are efficiently managed.
139
+
140
+ ---
141
+ ***By adopting this practice, you create a clear separation between your custom components and external components, simplifying maintenance and reducing the impact of changes from external dependencies.***
@@ -0,0 +1,32 @@
1
+ .inputContainerStyle {
2
+ display: flex;
3
+ flex-direction: row;
4
+ align-items: center;
5
+ justify-content: space-between;
6
+ }
7
+
8
+ %inputStyle {
9
+ margin: 10px;
10
+ padding: 10px;
11
+ }
12
+
13
+ .inputStyle {
14
+ @extend %inputStyle;
15
+ }
16
+
17
+ .hasInputError {
18
+ @extend %inputStyle;
19
+
20
+ border: 1px solid red;
21
+ border-radius: 2px;
22
+
23
+ &:focus {
24
+ border: 2px solid red;
25
+ outline: none !important;
26
+ }
27
+ }
28
+
29
+ .errorsStyle {
30
+ font-size: x-small;
31
+ color: red;
32
+ }
@@ -0,0 +1,27 @@
1
+ import { forwardRef, InputHTMLAttributes, useId } from 'react';
2
+ import classes from './Input.module.scss';
3
+
4
+ interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
5
+ label: string;
6
+ hasError?: boolean;
7
+ helperText?: string;
8
+ }
9
+
10
+ export const Input = forwardRef<HTMLInputElement, InputProps>(({ label, hasError, helperText, ...rest }, ref) => {
11
+ const id = useId();
12
+ return (
13
+ <>
14
+ <div className={classes.inputContainerStyle}>
15
+ <label htmlFor={id}>{label} </label>
16
+ <input id={id} ref={ref} {...rest} className={hasError ? classes.hasInputError : classes.inputStyle} />
17
+ </div>
18
+ {hasError && (
19
+ <p role="alert" className={classes.errorsStyle}>
20
+ {helperText}
21
+ </p>
22
+ )}
23
+ </>
24
+ );
25
+ });
26
+
27
+ Input.displayName = 'Input';
@@ -0,0 +1 @@
1
+ export { Input } from './Input';
@@ -0,0 +1,3 @@
1
+ .logoStyle {
2
+ height: 100%;
3
+ }
@@ -0,0 +1,11 @@
1
+ import classes from './Logo.module.css';
2
+
3
+ type LogoProps = {
4
+ src: string;
5
+ alt: string;
6
+ size?: string;
7
+ };
8
+
9
+ export const Logo = ({ src, alt, size = '80px' }: LogoProps) => {
10
+ return <img className={classes.logoStyle} style={{ width: size }} src={src} alt={alt} />;
11
+ };
@@ -0,0 +1 @@
1
+ export { Logo } from './Logo';