gwan-design-system 0.1.1
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.
- package/.github/workflows/bump-version.yml +50 -0
- package/.github/workflows/publish.yml +43 -0
- package/CODEOWNERS +1 -0
- package/README.md +54 -0
- package/eslint.config.mjs +16 -0
- package/next.config.ts +7 -0
- package/package.json +27 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/images/empty.png +0 -0
- package/public/images/empty_state.png +0 -0
- package/public/images/hero.png +0 -0
- package/public/images/hero2.png +0 -0
- package/public/images/logo.png +0 -0
- package/public/images/logo_short.png +0 -0
- package/public/images/profile_picture.png +0 -0
- package/public/images/success.png +0 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/src/app/components-library/page.tsx +8 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +108 -0
- package/src/app/layout.tsx +34 -0
- package/src/app/page.tsx +5 -0
- package/src/components/avatar/index.tsx +109 -0
- package/src/components/banner/index.tsx +58 -0
- package/src/components/button/index.tsx +61 -0
- package/src/components/carousel/index.tsx +58 -0
- package/src/components/checkbox/index.tsx +48 -0
- package/src/components/chip/index.tsx +22 -0
- package/src/components/ellipsis/index.tsx +36 -0
- package/src/components/fileUploader/index.tsx +54 -0
- package/src/components/filterDropdown/index.tsx +49 -0
- package/src/components/icons/arrowLeftSVG/index.tsx +14 -0
- package/src/components/icons/checkSVG/index.tsx +14 -0
- package/src/components/icons/chevDownSVG/index.tsx +14 -0
- package/src/components/icons/chevLeftSVG/index.tsx +14 -0
- package/src/components/icons/chevRightSVG/index.tsx +14 -0
- package/src/components/icons/circleSVG/index.tsx +14 -0
- package/src/components/icons/colorsSVG/index.tsx +21 -0
- package/src/components/icons/coversSVG/index.tsx +21 -0
- package/src/components/icons/crossSVG/index.tsx +16 -0
- package/src/components/icons/dashboardSVG/index.tsx +14 -0
- package/src/components/icons/filterSVG/index.tsx +21 -0
- package/src/components/icons/index.tsx +17 -0
- package/src/components/icons/orderInfoSVG/index.tsx +21 -0
- package/src/components/icons/ordersSVG/index.tsx +21 -0
- package/src/components/icons/productsSVG/index.tsx +21 -0
- package/src/components/icons/signOutSVG/index.tsx +21 -0
- package/src/components/icons/templatesSVG/index.tsx +24 -0
- package/src/components/icons/uploadSVG/index.tsx +21 -0
- package/src/components/input/index.tsx +40 -0
- package/src/components/modal/index.tsx +54 -0
- package/src/components/navBar/index.tsx +161 -0
- package/src/components/pagination/index.tsx +69 -0
- package/src/components/radioButton/index.tsx +44 -0
- package/src/components/selectDropdown/index.tsx +90 -0
- package/src/components/snackBar/index.tsx +46 -0
- package/src/components/state/index.tsx +69 -0
- package/src/components/table/index.tsx +51 -0
- package/src/components/tag/index.tsx +33 -0
- package/src/components/timeLine/index.tsx +99 -0
- package/src/components/tooltip/index.tsx +70 -0
- package/src/index.ts +22 -0
- package/src/templates/component-library/avatars/index.tsx +45 -0
- package/src/templates/component-library/banners/index.tsx +35 -0
- package/src/templates/component-library/buttons/index.tsx +122 -0
- package/src/templates/component-library/carousels/index.tsx +38 -0
- package/src/templates/component-library/checkboxes/index.tsx +19 -0
- package/src/templates/component-library/chips/index.tsx +49 -0
- package/src/templates/component-library/ellipsis/index.tsx +20 -0
- package/src/templates/component-library/fileUploaders/index.tsx +21 -0
- package/src/templates/component-library/filterDropdown/index.tsx +48 -0
- package/src/templates/component-library/icons/index.tsx +23 -0
- package/src/templates/component-library/index.tsx +179 -0
- package/src/templates/component-library/input/index.tsx +35 -0
- package/src/templates/component-library/modals/index.tsx +113 -0
- package/src/templates/component-library/navBars/index.tsx +91 -0
- package/src/templates/component-library/pagination/index.tsx +28 -0
- package/src/templates/component-library/radioButtons/index.tsx +33 -0
- package/src/templates/component-library/selectDropdown/index.tsx +90 -0
- package/src/templates/component-library/snackBars/index.tsx +34 -0
- package/src/templates/component-library/states/index.tsx +24 -0
- package/src/templates/component-library/tables/index.tsx +143 -0
- package/src/templates/component-library/tags/index.tsx +15 -0
- package/src/templates/component-library/timeLines/index.tsx +96 -0
- package/src/templates/component-library/tooltips/index.tsx +61 -0
- package/tsconfig.build.json +16 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Bump Version and Create Release Branch
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: "Version bump type (patch, minor, major, or exact version)"
|
|
8
|
+
required: true
|
|
9
|
+
default: "patch"
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
bump-version:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout code
|
|
16
|
+
uses: actions/checkout@v3
|
|
17
|
+
|
|
18
|
+
- name: Set up Node.js
|
|
19
|
+
uses: actions/setup-node@v3
|
|
20
|
+
with:
|
|
21
|
+
node-version: "18"
|
|
22
|
+
|
|
23
|
+
- name: Configure Git user
|
|
24
|
+
run: |
|
|
25
|
+
git config user.name "github-actions"
|
|
26
|
+
git config user.email "github-actions@github.com"
|
|
27
|
+
|
|
28
|
+
- name: Bump version
|
|
29
|
+
id: bump
|
|
30
|
+
run: |
|
|
31
|
+
set -e
|
|
32
|
+
VERSION_INPUT="${{ github.event.inputs.version }}"
|
|
33
|
+
if [[ "$VERSION_INPUT" =~ ^(patch|minor|major)$ ]]; then
|
|
34
|
+
NEW_VERSION=$(npm version $VERSION_INPUT -m "chore(release): %s")
|
|
35
|
+
else
|
|
36
|
+
NEW_VERSION=$(npm version "$VERSION_INPUT" -m "chore(release): %s")
|
|
37
|
+
fi
|
|
38
|
+
echo "new_version=${NEW_VERSION/v/}" >> $GITHUB_ENV
|
|
39
|
+
echo "NEXT_PUBLIC_APP_VERSION=$(jq -r .version package.json)" > .env
|
|
40
|
+
|
|
41
|
+
- name: Push version tag only (not protected branch)
|
|
42
|
+
run: |
|
|
43
|
+
set -e
|
|
44
|
+
git push origin --tags
|
|
45
|
+
|
|
46
|
+
- name: Create and push release branch
|
|
47
|
+
run: |
|
|
48
|
+
set -e
|
|
49
|
+
git checkout -b release/v${{ env.new_version }}
|
|
50
|
+
git push origin release/v${{ env.new_version }}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- name: Checkout code
|
|
12
|
+
uses: actions/checkout@v3
|
|
13
|
+
|
|
14
|
+
- name: Set up Node.js
|
|
15
|
+
uses: actions/setup-node@v3
|
|
16
|
+
with:
|
|
17
|
+
node-version: "18"
|
|
18
|
+
registry-url: "https://registry.npmjs.org/"
|
|
19
|
+
|
|
20
|
+
- name: Cache Node.js modules
|
|
21
|
+
uses: actions/cache@v3
|
|
22
|
+
with:
|
|
23
|
+
path: ~/.npm
|
|
24
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
25
|
+
restore-keys: |
|
|
26
|
+
${{ runner.os }}-node-
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: npm install
|
|
30
|
+
|
|
31
|
+
- name: Verify package version
|
|
32
|
+
run: npm version
|
|
33
|
+
|
|
34
|
+
- name: Build package
|
|
35
|
+
run: npm run build
|
|
36
|
+
|
|
37
|
+
- name: Dry run publish
|
|
38
|
+
run: npm publish --dry-run
|
|
39
|
+
|
|
40
|
+
- name: Publish package
|
|
41
|
+
run: npm publish --access public
|
|
42
|
+
env:
|
|
43
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @gwanfonseka
|
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
|
2
|
+
|
|
3
|
+
## Getting Started
|
|
4
|
+
|
|
5
|
+
First, run the development server:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev
|
|
9
|
+
# or
|
|
10
|
+
yarn dev
|
|
11
|
+
# or
|
|
12
|
+
pnpm dev
|
|
13
|
+
# or
|
|
14
|
+
bun dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
18
|
+
|
|
19
|
+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
|
20
|
+
|
|
21
|
+
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
|
22
|
+
|
|
23
|
+
## Learn More
|
|
24
|
+
|
|
25
|
+
To learn more about Next.js, take a look at the following resources:
|
|
26
|
+
|
|
27
|
+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
28
|
+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
29
|
+
|
|
30
|
+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
|
31
|
+
|
|
32
|
+
## Deploy on Vercel
|
|
33
|
+
|
|
34
|
+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
|
35
|
+
|
|
36
|
+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
|
37
|
+
|
|
38
|
+
## 🤝 Contributing
|
|
39
|
+
|
|
40
|
+
I welcome contributions via pull requests!\
|
|
41
|
+
However, to keep the project stable and secure:
|
|
42
|
+
|
|
43
|
+
🔒 Direct pushes to the main branch are not allowed\
|
|
44
|
+
✅ All changes must go through a pull request\
|
|
45
|
+
👀 Pull requests require review and approval before merging
|
|
46
|
+
|
|
47
|
+
Want to contribute?
|
|
48
|
+
Fork this repository
|
|
49
|
+
|
|
50
|
+
- Create a feature branch: git checkout -b feature/my-feature
|
|
51
|
+
- Commit your changes and push: git push origin feature/my-feature
|
|
52
|
+
- Open a pull request with a clear description
|
|
53
|
+
|
|
54
|
+
Thanks for helping improve the project! 🙌
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const compat = new FlatCompat({
|
|
9
|
+
baseDirectory: __dirname,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const eslintConfig = [
|
|
13
|
+
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export default eslintConfig;
|
package/next.config.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gwan-design-system",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dev": "next dev",
|
|
6
|
+
"build": "next build",
|
|
7
|
+
"start": "next start",
|
|
8
|
+
"lint": "next lint"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"next": "15.3.2",
|
|
12
|
+
"react": "^19.0.0",
|
|
13
|
+
"react-dom": "^19.0.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@eslint/eslintrc": "^3",
|
|
17
|
+
"@tailwindcss/postcss": "^4.1.5",
|
|
18
|
+
"@types/node": "^20",
|
|
19
|
+
"@types/react": "^19",
|
|
20
|
+
"@types/react-dom": "^19",
|
|
21
|
+
"eslint": "^9",
|
|
22
|
+
"eslint-config-next": "15.3.2",
|
|
23
|
+
"postcss": "^8.5.3",
|
|
24
|
+
"tailwindcss": "^4",
|
|
25
|
+
"typescript": "^5"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/public/file.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
package/public/globe.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/public/next.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
|
Binary file
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght@8..144,100..1000&display=swap");
|
|
2
|
+
@import "tailwindcss";
|
|
3
|
+
|
|
4
|
+
:root {
|
|
5
|
+
--background: #ffffff;
|
|
6
|
+
--foreground: #171717;
|
|
7
|
+
--custom-bg: linear-gradient(
|
|
8
|
+
135deg,
|
|
9
|
+
#9ea593,
|
|
10
|
+
#93a594,
|
|
11
|
+
#93a59c,
|
|
12
|
+
#939fa5,
|
|
13
|
+
#9394a5,
|
|
14
|
+
#9c93a5,
|
|
15
|
+
#a593a4,
|
|
16
|
+
#a59393
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@media (prefers-color-scheme: light) {
|
|
21
|
+
:root {
|
|
22
|
+
--background: #0a0a0a;
|
|
23
|
+
--foreground: #ededed;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
color: var(--foreground);
|
|
29
|
+
background: var(--background);
|
|
30
|
+
font-family: "Roboto Flex", sans-serif;
|
|
31
|
+
font-optical-sizing: auto;
|
|
32
|
+
font-style: normal;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@theme {
|
|
36
|
+
--color-background: var(--background);
|
|
37
|
+
--color-foreground: var(--foreground);
|
|
38
|
+
|
|
39
|
+
--color-primary-50: #f2f3ee;
|
|
40
|
+
--color-primary-100: #e1e3da;
|
|
41
|
+
--color-primary-200: #d0d3c6;
|
|
42
|
+
--color-primary-300: #bec3b2;
|
|
43
|
+
--color-primary-400: #adb39e;
|
|
44
|
+
--color-primary-500: #9ea593;
|
|
45
|
+
--color-primary-600: #8c9382;
|
|
46
|
+
--color-primary-700: #787d6e;
|
|
47
|
+
--color-primary-800: #64675a;
|
|
48
|
+
--color-primary-900: #505146;
|
|
49
|
+
|
|
50
|
+
--color-greenola-50: #e6f7e6;
|
|
51
|
+
--color-greenola-100: #c0eac0;
|
|
52
|
+
--color-greenola-200: #99dc99;
|
|
53
|
+
--color-greenola-300: #73cf73;
|
|
54
|
+
--color-greenola-400: #4cc14c;
|
|
55
|
+
--color-greenola-500: #0ba803;
|
|
56
|
+
--color-greenola-600: #0a9602;
|
|
57
|
+
--color-greenola-700: #087f02;
|
|
58
|
+
--color-greenola-800: #066602;
|
|
59
|
+
--color-greenola-900: #044c01;
|
|
60
|
+
|
|
61
|
+
--color-redola-50: #fde7e7;
|
|
62
|
+
--color-redola-100: #fbc0c0;
|
|
63
|
+
--color-redola-200: #f89999;
|
|
64
|
+
--color-redola-300: #f47373;
|
|
65
|
+
--color-redola-400: #f04c4c;
|
|
66
|
+
--color-redola-500: #df0303;
|
|
67
|
+
--color-redola-600: #c90202;
|
|
68
|
+
--color-redola-700: #a50202;
|
|
69
|
+
--color-redola-800: #800202;
|
|
70
|
+
--color-redola-900: #5c0101;
|
|
71
|
+
|
|
72
|
+
--color-blueola-50: #e6f3fa;
|
|
73
|
+
--color-blueola-100: #bfe1f3;
|
|
74
|
+
--color-blueola-200: #99ceeb;
|
|
75
|
+
--color-blueola-300: #73bce4;
|
|
76
|
+
--color-blueola-400: #4caadc;
|
|
77
|
+
--color-blueola-500: #0369a8;
|
|
78
|
+
--color-blueola-600: #025e97;
|
|
79
|
+
--color-blueola-700: #024d7c;
|
|
80
|
+
--color-blueola-800: #013c61;
|
|
81
|
+
--color-blueola-900: #012b46;
|
|
82
|
+
|
|
83
|
+
--color-yellowla-50: #f9f7e6;
|
|
84
|
+
--color-yellowla-100: #f0efc0;
|
|
85
|
+
--color-yellowla-200: #e6e699;
|
|
86
|
+
--color-yellowla-300: #dcdc73;
|
|
87
|
+
--color-yellowla-400: #d1d14c;
|
|
88
|
+
--color-yellowla-500: #a8a203;
|
|
89
|
+
--color-yellowla-600: #969002;
|
|
90
|
+
--color-yellowla-700: #7c7602;
|
|
91
|
+
--color-yellowla-800: #615c01;
|
|
92
|
+
--color-yellowla-900: #464301;
|
|
93
|
+
|
|
94
|
+
--color-neutrola-50: #f8f8f8;
|
|
95
|
+
--color-neutrola-100: #f0f0f0;
|
|
96
|
+
--color-neutrola-200: #e7e7e7;
|
|
97
|
+
--color-neutrola-300: #dedede;
|
|
98
|
+
--color-neutrola-400: #d9d9d9;
|
|
99
|
+
--color-neutrola-500: #bfbfbf;
|
|
100
|
+
--color-neutrola-600: #a6a6a6;
|
|
101
|
+
--color-neutrola-700: #8c8c8c;
|
|
102
|
+
--color-neutrola-800: #737373;
|
|
103
|
+
--color-neutrola-900: #595959;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.custom-bg {
|
|
107
|
+
background-image: var(--custom-bg);
|
|
108
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import "./globals.css";
|
|
2
|
+
import type { Metadata } from "next";
|
|
3
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "Create Next App",
|
|
17
|
+
description: "Generated by create next app",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default function RootLayout({
|
|
21
|
+
children,
|
|
22
|
+
}: Readonly<{
|
|
23
|
+
children: React.ReactNode;
|
|
24
|
+
}>) {
|
|
25
|
+
return (
|
|
26
|
+
<html lang="en">
|
|
27
|
+
<body
|
|
28
|
+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
33
|
+
);
|
|
34
|
+
}
|
package/src/app/page.tsx
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Image from "next/image";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import Tooltip, { TOOLTIP_POSITION } from "../tooltip";
|
|
4
|
+
|
|
5
|
+
export enum AVATAR_VARIANT {
|
|
6
|
+
IMAGE_WITH_FULL = "image_with_full",
|
|
7
|
+
INITIALS_WITH_FULL = "initials_with_full",
|
|
8
|
+
IMAGE_ONLY = "image-only",
|
|
9
|
+
INITIALS_ONLY = "initials-only",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface IAvatar {
|
|
13
|
+
name: string;
|
|
14
|
+
email: string;
|
|
15
|
+
image?: string;
|
|
16
|
+
variant: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const generatePastelColor = () => {
|
|
20
|
+
const hue = Math.floor(Math.random() * 360);
|
|
21
|
+
const saturation = 60 + Math.random() * 20;
|
|
22
|
+
const lightness = 75 + Math.random() * 10;
|
|
23
|
+
|
|
24
|
+
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const Avatar = ({ name, email, image, variant }: IAvatar) => {
|
|
28
|
+
const [bgColor, setBgColor] = useState<string>("transparent");
|
|
29
|
+
const [isTooltipInitialVisible, setIsTooltipInitialVisible] = useState(false);
|
|
30
|
+
const [isTooltipImageVisible, setIsTooltipImageVisible] = useState(false);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
setBgColor(generatePastelColor());
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
const generateInitials = (name: string) => {
|
|
37
|
+
const nameArray = name.split(" ");
|
|
38
|
+
return nameArray.length > 1
|
|
39
|
+
? `${nameArray[0].charAt(0)}${nameArray[1].charAt(0)}`
|
|
40
|
+
: nameArray[0].charAt(0);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const renderTooltip = (name: string, email: string, isVisible: boolean) => {
|
|
44
|
+
return (
|
|
45
|
+
<Tooltip
|
|
46
|
+
position={TOOLTIP_POSITION.RIGHT}
|
|
47
|
+
label={
|
|
48
|
+
<div className="flex flex-col">
|
|
49
|
+
{name}
|
|
50
|
+
<p className="text-neutrola-300 text-xs">{email}</p>
|
|
51
|
+
</div>
|
|
52
|
+
}
|
|
53
|
+
isVisible={isVisible}
|
|
54
|
+
toolTipWidth="w-36"
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const renderAvatarImage = () => {
|
|
60
|
+
if (image) {
|
|
61
|
+
return (
|
|
62
|
+
<div
|
|
63
|
+
className="relative"
|
|
64
|
+
onMouseEnter={() => setIsTooltipImageVisible(true)}
|
|
65
|
+
onMouseLeave={() => setIsTooltipImageVisible(false)}
|
|
66
|
+
>
|
|
67
|
+
<Image
|
|
68
|
+
className="rounded-full border border-neutrola-400"
|
|
69
|
+
src={image}
|
|
70
|
+
alt="profile"
|
|
71
|
+
width={60}
|
|
72
|
+
height={60}
|
|
73
|
+
/>
|
|
74
|
+
{variant === AVATAR_VARIANT.IMAGE_ONLY &&
|
|
75
|
+
renderTooltip(name, email, isTooltipImageVisible)}
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div
|
|
82
|
+
className="size-[60px] flex items-center justify-center rounded-full font-semibold cursor-default relative"
|
|
83
|
+
style={{ backgroundColor: bgColor }}
|
|
84
|
+
onMouseEnter={() => setIsTooltipInitialVisible(true)}
|
|
85
|
+
onMouseLeave={() => setIsTooltipInitialVisible(false)}
|
|
86
|
+
>
|
|
87
|
+
{generateInitials(name)}
|
|
88
|
+
{variant === AVATAR_VARIANT.INITIALS_ONLY &&
|
|
89
|
+
renderTooltip(name, email, isTooltipInitialVisible)}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div className="flex flex-row items-center gap-2">
|
|
96
|
+
{renderAvatarImage()}
|
|
97
|
+
|
|
98
|
+
{(variant === AVATAR_VARIANT.IMAGE_WITH_FULL ||
|
|
99
|
+
variant === AVATAR_VARIANT.INITIALS_WITH_FULL) && (
|
|
100
|
+
<div className="flex flex-col">
|
|
101
|
+
<p className="text-base font-semibold">{name}</p>
|
|
102
|
+
<p className="text-sm text-neutrola-700">{email}</p>
|
|
103
|
+
</div>
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default Avatar;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface IBanner {
|
|
2
|
+
title?: string;
|
|
3
|
+
titleClassName?: string;
|
|
4
|
+
subTitle?: string;
|
|
5
|
+
subTitleClassName?: string;
|
|
6
|
+
contentPlacement?: "left" | "right";
|
|
7
|
+
backgroundImage?: string;
|
|
8
|
+
backgroundColor?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Banner = ({
|
|
12
|
+
title = "",
|
|
13
|
+
subTitle = "",
|
|
14
|
+
contentPlacement = "left",
|
|
15
|
+
backgroundImage = "",
|
|
16
|
+
backgroundColor = "",
|
|
17
|
+
titleClassName = "",
|
|
18
|
+
subTitleClassName = "",
|
|
19
|
+
}: IBanner) => {
|
|
20
|
+
const handleContentPlacement = () => {
|
|
21
|
+
if (contentPlacement === "left") {
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<div className="flex flex-col gap-2">
|
|
25
|
+
<p className={titleClassName}>{title}</p>
|
|
26
|
+
<p className={subTitleClassName}>{subTitle}</p>
|
|
27
|
+
</div>
|
|
28
|
+
<div></div>
|
|
29
|
+
</>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
<div></div>
|
|
36
|
+
<div className="flex flex-col gap-2">
|
|
37
|
+
<p className={titleClassName}>{title}</p>
|
|
38
|
+
<p className={subTitleClassName}>{subTitle}</p>
|
|
39
|
+
</div>
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div
|
|
46
|
+
className={`w-full h-[484px] grid grid-cols-2 items-center px-16 ${backgroundColor} bg-no-repeat bg-cover bg-center`}
|
|
47
|
+
style={
|
|
48
|
+
backgroundImage !== ""
|
|
49
|
+
? { backgroundImage: `url(${backgroundImage})` }
|
|
50
|
+
: {}
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
{handleContentPlacement()}
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default Banner;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export enum BUTTON_VARIANTS {
|
|
4
|
+
PRIMARY = "primary",
|
|
5
|
+
SECONDARY = "secondary",
|
|
6
|
+
TERTIARY = "tertiary",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface IButton {
|
|
10
|
+
variant?: BUTTON_VARIANTS;
|
|
11
|
+
label?: string;
|
|
12
|
+
onClick: () => void;
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
type?: "button" | "submit";
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Button = ({
|
|
19
|
+
variant = BUTTON_VARIANTS.PRIMARY,
|
|
20
|
+
label,
|
|
21
|
+
onClick,
|
|
22
|
+
icon,
|
|
23
|
+
type = "button",
|
|
24
|
+
disabled = false,
|
|
25
|
+
}: IButton) => {
|
|
26
|
+
const getButtonVariant = (variant: BUTTON_VARIANTS) => {
|
|
27
|
+
switch (variant) {
|
|
28
|
+
case BUTTON_VARIANTS.PRIMARY:
|
|
29
|
+
return disabled
|
|
30
|
+
? "bg-neutrola-300 text-neutrola-800 cursor-not-allowed"
|
|
31
|
+
: "bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700";
|
|
32
|
+
|
|
33
|
+
case BUTTON_VARIANTS.SECONDARY:
|
|
34
|
+
return disabled
|
|
35
|
+
? "bg-neutrola-100 text-neutrola-800 cursor-not-allowed"
|
|
36
|
+
: "bg-neutrola-50 text-primary-700 hover:bg-primary-50 active:bg-primary-100";
|
|
37
|
+
case BUTTON_VARIANTS.TERTIARY:
|
|
38
|
+
return disabled
|
|
39
|
+
? "text-neutrola-300 border border-neutrola-300 cursor-not-allowed"
|
|
40
|
+
: "bg-transparent text-primary-500 border border-primary-500 hover:bg-neutrola-50 active:bg-neutrola-100";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<button
|
|
46
|
+
className={`${getButtonVariant(variant)} px-4 ${
|
|
47
|
+
label ? "py-2" : "py-4"
|
|
48
|
+
} rounded-lg`}
|
|
49
|
+
type={type}
|
|
50
|
+
onClick={onClick}
|
|
51
|
+
disabled={disabled}
|
|
52
|
+
>
|
|
53
|
+
<div className="flex flex-row gap-2 items-center">
|
|
54
|
+
{icon && <div className="size-5">{icon}</div>}
|
|
55
|
+
{label && <p>{label}</p>}
|
|
56
|
+
</div>
|
|
57
|
+
</button>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default Button;
|