Spaces:
Sleeping
Sleeping
Commit ·
5491d8f
0
Parent(s):
Initial commit with current state
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +36 -0
- .gitignore +24 -0
- Dockerfile +9 -0
- README.md +11 -0
- docker-compose.yaml +16 -0
- index.html +13 -0
- package-lock.json +0 -0
- package.json +51 -0
- public/aiXamine-favicon.png +0 -0
- public/assets/aiXamine-logo-dark.png +3 -0
- public/assets/aiXamine-logo-light.png +3 -0
- public/assets/api-logo-dark.png +3 -0
- public/assets/api-logo-light.png +3 -0
- public/assets/claude-logo-dark.png +3 -0
- public/assets/claude-logo-light.png +3 -0
- public/assets/deepseek-logo-dark.png +3 -0
- public/assets/deepseek-logo-light.png +3 -0
- public/assets/fanar-logo-dark.png +3 -0
- public/assets/fanar-logo-light.png +3 -0
- public/assets/gemini-logo-dark.png +3 -0
- public/assets/gemini-logo-light.png +3 -0
- public/assets/grok-logo-dark.png +3 -0
- public/assets/grok-logo-light.png +3 -0
- public/assets/huggingface-logo.png +3 -0
- public/assets/openai-logo-dark.png +3 -0
- public/assets/openai-logo-light.png +3 -0
- public/assets/overview-dark.png +3 -0
- public/assets/overview-light.png +3 -0
- public/assets/report-dark.png +3 -0
- public/assets/report-light.png +3 -0
- public/assets/submission-dark.png +3 -0
- public/assets/submission-light.png +3 -0
- src/constants/theme.js +650 -0
- src/features/app/App.jsx +36 -0
- src/features/app/appSlice.js +92 -0
- src/features/landing/AppAppBar/AppAppBar-styles.js +60 -0
- src/features/landing/AppAppBar/AppAppBar.jsx +167 -0
- src/features/landing/FAQ/FAQ-styles.js +15 -0
- src/features/landing/FAQ/FAQ.jsx +96 -0
- src/features/landing/Features/Features-styles.js +91 -0
- src/features/landing/Features/Features.jsx +203 -0
- src/features/landing/Hero/Hero-styles.js +39 -0
- src/features/landing/Hero/Hero.jsx +39 -0
- src/features/landing/Landing/Landing.jsx +38 -0
- src/features/landing/Reference/Reference-styles.js +48 -0
- src/features/landing/Reference/Reference.jsx +38 -0
- src/features/landing/Services/Services-styles.js +36 -0
- src/features/landing/Services/Services.jsx +112 -0
- src/features/main/CompareModels/CompareModels-styles.js +282 -0
- src/features/main/CompareModels/CompareModelsFullDialog/CompareModelsFullDialog-styles.js +183 -0
.gitattributes
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
public/assets/* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Logs
|
| 2 |
+
logs
|
| 3 |
+
*.log
|
| 4 |
+
npm-debug.log*
|
| 5 |
+
yarn-debug.log*
|
| 6 |
+
yarn-error.log*
|
| 7 |
+
pnpm-debug.log*
|
| 8 |
+
lerna-debug.log*
|
| 9 |
+
|
| 10 |
+
node_modules
|
| 11 |
+
dist
|
| 12 |
+
dist-ssr
|
| 13 |
+
*.local
|
| 14 |
+
|
| 15 |
+
# Editor directories and files
|
| 16 |
+
.vscode/*
|
| 17 |
+
!.vscode/extensions.json
|
| 18 |
+
.idea
|
| 19 |
+
.DS_Store
|
| 20 |
+
*.suo
|
| 21 |
+
*.ntvs*
|
| 22 |
+
*.njsproj
|
| 23 |
+
*.sln
|
| 24 |
+
*.sw?
|
Dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM node:22-alpine
|
| 2 |
+
WORKDIR /app
|
| 3 |
+
COPY . .
|
| 4 |
+
RUN npm install --silent
|
| 5 |
+
|
| 6 |
+
ENV VITE_API_BASE_URL=https://aixamine.qcri.org/api/v1
|
| 7 |
+
ENV VITE_AMPLITUDE_API_KEY=default_key
|
| 8 |
+
|
| 9 |
+
CMD ["npm", "run", "dev"]
|
README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Leaderboard
|
| 3 |
+
emoji: 📈
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: pink
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
short_description: safety leaderboard
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
docker-compose.yaml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
services:
|
| 2 |
+
react:
|
| 3 |
+
build:
|
| 4 |
+
context: .
|
| 5 |
+
args:
|
| 6 |
+
- VITE_API_BASE_URL=https://aixamine.qcri.org/api/v1
|
| 7 |
+
- VITE_AMPLITUDE_API_KEY=${VITE_AMPLITUDE_API_KEY}
|
| 8 |
+
restart: always
|
| 9 |
+
ports:
|
| 10 |
+
- 7860:7860
|
| 11 |
+
volumes:
|
| 12 |
+
- ./:/app
|
| 13 |
+
- node-modules:/app/node_modules
|
| 14 |
+
|
| 15 |
+
volumes:
|
| 16 |
+
node-modules:
|
index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en" style="height: 100%">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<link rel="icon" type="image/png" href="/aiXamine-favicon.png" />
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 7 |
+
<title>aiXamine Leaderboard</title>
|
| 8 |
+
</head>
|
| 9 |
+
<body style="height: 100%">
|
| 10 |
+
<div id="root" style="height: 100%"></div>
|
| 11 |
+
<script type="module" src="/src/index.jsx"></script>
|
| 12 |
+
</body>
|
| 13 |
+
</html>
|
package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "web",
|
| 3 |
+
"private": true,
|
| 4 |
+
"version": "0.0.0",
|
| 5 |
+
"type": "module",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"dev": "vite",
|
| 8 |
+
"build": "vite build",
|
| 9 |
+
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
| 10 |
+
"preview": "vite preview"
|
| 11 |
+
},
|
| 12 |
+
"dependencies": {
|
| 13 |
+
"@emotion/react": "^11.11.4",
|
| 14 |
+
"@emotion/styled": "^11.11.5",
|
| 15 |
+
"@fontsource/inter": "^5.0.18",
|
| 16 |
+
"@huggingface/hub": "^0.15.1",
|
| 17 |
+
"@mui/icons-material": "^5.15.19",
|
| 18 |
+
"@mui/material": "^5.15.18",
|
| 19 |
+
"@mui/x-charts": "^7.11.0",
|
| 20 |
+
"@mui/x-data-grid": "^7.10.0",
|
| 21 |
+
"@reduxjs/toolkit": "^2.2.5",
|
| 22 |
+
"amplitude-js": "^8.21.9",
|
| 23 |
+
"axios": "^1.7.2",
|
| 24 |
+
"chart.js": "^4.4.4",
|
| 25 |
+
"dompurify": "^3.2.7",
|
| 26 |
+
"formik": "^2.4.6",
|
| 27 |
+
"html2pdf.js": "^0.10.3",
|
| 28 |
+
"jspdf": "^3.0.1",
|
| 29 |
+
"jwt-decode": "^4.0.0",
|
| 30 |
+
"marked": "^15.0.6",
|
| 31 |
+
"prop-types": "^15.8.1",
|
| 32 |
+
"react": "^18.2.0",
|
| 33 |
+
"react-chartjs-2": "^5.2.0",
|
| 34 |
+
"react-dom": "^18.2.0",
|
| 35 |
+
"react-helmet-async": "^2.0.5",
|
| 36 |
+
"react-redux": "^9.1.2",
|
| 37 |
+
"react-router-dom": "^6.23.1",
|
| 38 |
+
"react-syntax-highlighter": "^15.5.0",
|
| 39 |
+
"yup": "^1.4.0"
|
| 40 |
+
},
|
| 41 |
+
"devDependencies": {
|
| 42 |
+
"@types/react": "^18.2.66",
|
| 43 |
+
"@types/react-dom": "^18.2.22",
|
| 44 |
+
"@vitejs/plugin-react-swc": "^3.5.0",
|
| 45 |
+
"eslint": "^8.57.0",
|
| 46 |
+
"eslint-plugin-react": "^7.34.1",
|
| 47 |
+
"eslint-plugin-react-hooks": "^4.6.0",
|
| 48 |
+
"eslint-plugin-react-refresh": "^0.4.6",
|
| 49 |
+
"vite": "^5.2.0"
|
| 50 |
+
}
|
| 51 |
+
}
|
public/aiXamine-favicon.png
ADDED
|
|
public/assets/aiXamine-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/aiXamine-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/api-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/api-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/claude-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/claude-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/deepseek-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/deepseek-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/fanar-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/fanar-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/gemini-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/gemini-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/grok-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/grok-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/huggingface-logo.png
ADDED
|
Git LFS Details
|
public/assets/openai-logo-dark.png
ADDED
|
Git LFS Details
|
public/assets/openai-logo-light.png
ADDED
|
Git LFS Details
|
public/assets/overview-dark.png
ADDED
|
Git LFS Details
|
public/assets/overview-light.png
ADDED
|
Git LFS Details
|
public/assets/report-dark.png
ADDED
|
Git LFS Details
|
public/assets/report-light.png
ADDED
|
Git LFS Details
|
public/assets/submission-dark.png
ADDED
|
Git LFS Details
|
public/assets/submission-light.png
ADDED
|
Git LFS Details
|
src/constants/theme.js
ADDED
|
@@ -0,0 +1,650 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { alpha } from '@mui/material/styles';
|
| 2 |
+
import { red } from '@mui/material/colors';
|
| 3 |
+
|
| 4 |
+
export const brand = {
|
| 5 |
+
50: '#F0F7FF',
|
| 6 |
+
100: '#CEE5FD',
|
| 7 |
+
200: '#9CCCFC',
|
| 8 |
+
300: '#55A6F6',
|
| 9 |
+
400: '#0A66C2',
|
| 10 |
+
500: '#0959AA',
|
| 11 |
+
600: '#064079',
|
| 12 |
+
700: '#033363',
|
| 13 |
+
800: '#02294F',
|
| 14 |
+
900: '#021F3B',
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
export const secondary = {
|
| 18 |
+
50: '#F9F0FF',
|
| 19 |
+
100: '#E9CEFD',
|
| 20 |
+
200: '#D49CFC',
|
| 21 |
+
300: '#B355F6',
|
| 22 |
+
400: '#750AC2',
|
| 23 |
+
500: '#6709AA',
|
| 24 |
+
600: '#490679',
|
| 25 |
+
700: '#3B0363',
|
| 26 |
+
800: '#2F024F',
|
| 27 |
+
900: '#23023B',
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
export const gray = {
|
| 31 |
+
50: '#FBFCFE',
|
| 32 |
+
100: '#EAF0F5',
|
| 33 |
+
200: '#D6E2EB',
|
| 34 |
+
300: '#BFCCD9',
|
| 35 |
+
400: '#94A6B8',
|
| 36 |
+
500: '#5B6B7C',
|
| 37 |
+
600: '#4C5967',
|
| 38 |
+
700: '#364049',
|
| 39 |
+
800: '#131B20',
|
| 40 |
+
900: '#090E10',
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
export const green = {
|
| 44 |
+
50: '#F6FEF6',
|
| 45 |
+
100: '#E3FBE3',
|
| 46 |
+
200: '#C7F7C7',
|
| 47 |
+
300: '#A1E8A1',
|
| 48 |
+
400: '#51BC51',
|
| 49 |
+
500: '#1F7A1F',
|
| 50 |
+
600: '#136C13',
|
| 51 |
+
700: '#0A470A',
|
| 52 |
+
800: '#042F04',
|
| 53 |
+
900: '#021D02',
|
| 54 |
+
};
|
| 55 |
+
|
| 56 |
+
const getDesignTokens = (mode) => ({
|
| 57 |
+
palette: {
|
| 58 |
+
mode,
|
| 59 |
+
primary: {
|
| 60 |
+
light: brand[200],
|
| 61 |
+
main: brand[500],
|
| 62 |
+
dark: brand[800],
|
| 63 |
+
contrastText: brand[50],
|
| 64 |
+
...(mode === 'dark' && {
|
| 65 |
+
contrastText: brand[100],
|
| 66 |
+
light: brand[300],
|
| 67 |
+
main: brand[400],
|
| 68 |
+
dark: brand[800],
|
| 69 |
+
}),
|
| 70 |
+
},
|
| 71 |
+
secondary: {
|
| 72 |
+
light: secondary[300],
|
| 73 |
+
main: secondary[500],
|
| 74 |
+
dark: secondary[800],
|
| 75 |
+
...(mode === 'dark' && {
|
| 76 |
+
light: secondary[400],
|
| 77 |
+
main: secondary[500],
|
| 78 |
+
dark: secondary[900],
|
| 79 |
+
}),
|
| 80 |
+
},
|
| 81 |
+
warning: {
|
| 82 |
+
main: '#F7B538',
|
| 83 |
+
dark: '#F79F00',
|
| 84 |
+
...(mode === 'dark' && { main: '#F7B538', dark: '#F79F00' }),
|
| 85 |
+
},
|
| 86 |
+
error: {
|
| 87 |
+
light: red[50],
|
| 88 |
+
main: red[500],
|
| 89 |
+
dark: red[700],
|
| 90 |
+
...(mode === 'dark' && { light: '#D32F2F', main: '#D32F2F', dark: '#B22A2A' }),
|
| 91 |
+
},
|
| 92 |
+
success: {
|
| 93 |
+
light: green[300],
|
| 94 |
+
main: green[400],
|
| 95 |
+
dark: green[800],
|
| 96 |
+
...(mode === 'dark' && {
|
| 97 |
+
light: green[400],
|
| 98 |
+
main: green[500],
|
| 99 |
+
dark: green[700],
|
| 100 |
+
}),
|
| 101 |
+
},
|
| 102 |
+
grey: {
|
| 103 |
+
50: gray[50],
|
| 104 |
+
100: gray[100],
|
| 105 |
+
200: gray[200],
|
| 106 |
+
300: gray[300],
|
| 107 |
+
400: gray[400],
|
| 108 |
+
500: gray[500],
|
| 109 |
+
600: gray[600],
|
| 110 |
+
700: gray[700],
|
| 111 |
+
800: gray[800],
|
| 112 |
+
900: gray[900],
|
| 113 |
+
},
|
| 114 |
+
divider: mode === 'dark' ? alpha(gray[600], 0.3) : alpha(gray[300], 0.5),
|
| 115 |
+
background: {
|
| 116 |
+
default: '#fff',
|
| 117 |
+
paper: gray[50],
|
| 118 |
+
...(mode === 'dark' && { default: gray[900], paper: gray[800] }),
|
| 119 |
+
},
|
| 120 |
+
text: {
|
| 121 |
+
primary: gray[800],
|
| 122 |
+
secondary: gray[600],
|
| 123 |
+
...(mode === 'dark' && { primary: '#fff', secondary: gray[400] }),
|
| 124 |
+
},
|
| 125 |
+
action: {
|
| 126 |
+
selected: `${alpha(brand[200], 0.2)}`,
|
| 127 |
+
...(mode === 'dark' && {
|
| 128 |
+
selected: alpha(brand[800], 0.2),
|
| 129 |
+
}),
|
| 130 |
+
},
|
| 131 |
+
},
|
| 132 |
+
typography: {
|
| 133 |
+
fontFamily: ['"Inter", "sans-serif"'].join(','),
|
| 134 |
+
h1: {
|
| 135 |
+
fontSize: 60,
|
| 136 |
+
fontWeight: 600,
|
| 137 |
+
lineHeight: 78 / 70,
|
| 138 |
+
letterSpacing: -0.2,
|
| 139 |
+
},
|
| 140 |
+
h2: {
|
| 141 |
+
fontSize: 48,
|
| 142 |
+
fontWeight: 600,
|
| 143 |
+
lineHeight: 1.2,
|
| 144 |
+
},
|
| 145 |
+
h3: {
|
| 146 |
+
fontSize: 42,
|
| 147 |
+
lineHeight: 1.2,
|
| 148 |
+
},
|
| 149 |
+
h4: {
|
| 150 |
+
fontSize: 36,
|
| 151 |
+
fontWeight: 500,
|
| 152 |
+
lineHeight: 1.5,
|
| 153 |
+
},
|
| 154 |
+
h5: {
|
| 155 |
+
fontSize: 20,
|
| 156 |
+
fontWeight: 600,
|
| 157 |
+
},
|
| 158 |
+
h6: {
|
| 159 |
+
fontSize: 18,
|
| 160 |
+
},
|
| 161 |
+
subtitle1: {
|
| 162 |
+
fontSize: 18,
|
| 163 |
+
},
|
| 164 |
+
subtitle2: {
|
| 165 |
+
fontSize: 16,
|
| 166 |
+
},
|
| 167 |
+
body1: {
|
| 168 |
+
fontWeight: 400,
|
| 169 |
+
fontSize: 15,
|
| 170 |
+
},
|
| 171 |
+
body2: {
|
| 172 |
+
fontWeight: 400,
|
| 173 |
+
fontSize: 14,
|
| 174 |
+
},
|
| 175 |
+
caption: {
|
| 176 |
+
fontWeight: 400,
|
| 177 |
+
fontSize: 12,
|
| 178 |
+
},
|
| 179 |
+
},
|
| 180 |
+
});
|
| 181 |
+
|
| 182 |
+
export const getTheme = (mode) => {
|
| 183 |
+
return {
|
| 184 |
+
...getDesignTokens(mode),
|
| 185 |
+
components: {
|
| 186 |
+
MuiCssBaseline: {
|
| 187 |
+
styleOverrides: {
|
| 188 |
+
html: {
|
| 189 |
+
scrollbarGutter: 'stable',
|
| 190 |
+
overflowY: 'scroll',
|
| 191 |
+
},
|
| 192 |
+
body: {
|
| 193 |
+
scrollbarGutter: 'stable',
|
| 194 |
+
overflowY: 'scroll',
|
| 195 |
+
},
|
| 196 |
+
},
|
| 197 |
+
},
|
| 198 |
+
MuiPopover: {
|
| 199 |
+
defaultProps: {
|
| 200 |
+
disableScrollLock: true,
|
| 201 |
+
},
|
| 202 |
+
},
|
| 203 |
+
MuiMenu: {
|
| 204 |
+
defaultProps: {
|
| 205 |
+
disableScrollLock: true,
|
| 206 |
+
},
|
| 207 |
+
},
|
| 208 |
+
MuiAccordion: {
|
| 209 |
+
defaultProps: {
|
| 210 |
+
elevation: 0,
|
| 211 |
+
disableGutters: true,
|
| 212 |
+
},
|
| 213 |
+
styleOverrides: {
|
| 214 |
+
root: ({ theme }) => ({
|
| 215 |
+
padding: 8,
|
| 216 |
+
overflow: 'clip',
|
| 217 |
+
backgroundColor: '#fff',
|
| 218 |
+
border: '1px solid',
|
| 219 |
+
borderColor: gray[100],
|
| 220 |
+
':before': {
|
| 221 |
+
backgroundColor: 'transparent',
|
| 222 |
+
},
|
| 223 |
+
'&:first-of-type': {
|
| 224 |
+
borderTopLeftRadius: 10,
|
| 225 |
+
borderTopRightRadius: 10,
|
| 226 |
+
},
|
| 227 |
+
'&:last-of-type': {
|
| 228 |
+
borderBottomLeftRadius: 10,
|
| 229 |
+
borderBottomRightRadius: 10,
|
| 230 |
+
},
|
| 231 |
+
...(theme.palette.mode === 'dark' && {
|
| 232 |
+
backgroundColor: gray[900],
|
| 233 |
+
borderColor: gray[800],
|
| 234 |
+
}),
|
| 235 |
+
}),
|
| 236 |
+
},
|
| 237 |
+
},
|
| 238 |
+
MuiAccordionSummary: {
|
| 239 |
+
styleOverrides: {
|
| 240 |
+
root: ({ theme }) => ({
|
| 241 |
+
border: 'none',
|
| 242 |
+
borderRadius: 8,
|
| 243 |
+
'&:hover': { backgroundColor: gray[100] },
|
| 244 |
+
...(theme.palette.mode === 'dark' && {
|
| 245 |
+
'&:hover': { backgroundColor: gray[800] },
|
| 246 |
+
}),
|
| 247 |
+
}),
|
| 248 |
+
},
|
| 249 |
+
},
|
| 250 |
+
MuiAccordionDetails: {
|
| 251 |
+
styleOverrides: {
|
| 252 |
+
root: { mb: 20, border: 'none' },
|
| 253 |
+
},
|
| 254 |
+
},
|
| 255 |
+
MuiToggleButtonGroup: {
|
| 256 |
+
styleOverrides: {
|
| 257 |
+
root: ({ theme }) => ({
|
| 258 |
+
borderRadius: '10px',
|
| 259 |
+
boxShadow: `0 4px 16px ${alpha(gray[400], 0.2)}`,
|
| 260 |
+
'& .Mui-selected': {
|
| 261 |
+
color: brand[500],
|
| 262 |
+
},
|
| 263 |
+
...(theme.palette.mode === 'dark' && {
|
| 264 |
+
'& .Mui-selected': {
|
| 265 |
+
color: '#fff',
|
| 266 |
+
},
|
| 267 |
+
boxShadow: `0 4px 16px ${alpha(brand[700], 0.5)}`,
|
| 268 |
+
}),
|
| 269 |
+
}),
|
| 270 |
+
},
|
| 271 |
+
},
|
| 272 |
+
MuiToggleButton: {
|
| 273 |
+
styleOverrides: {
|
| 274 |
+
root: ({ theme }) => ({
|
| 275 |
+
padding: '12px 16px',
|
| 276 |
+
textTransform: 'none',
|
| 277 |
+
borderRadius: '10px',
|
| 278 |
+
fontWeight: 500,
|
| 279 |
+
...(theme.palette.mode === 'dark' && {
|
| 280 |
+
color: gray[400],
|
| 281 |
+
boxShadow: '0 4px 16px rgba(0, 0, 0, 0.5)',
|
| 282 |
+
'&.Mui-selected': { color: brand[300] },
|
| 283 |
+
}),
|
| 284 |
+
}),
|
| 285 |
+
},
|
| 286 |
+
},
|
| 287 |
+
MuiButtonBase: {
|
| 288 |
+
defaultProps: {
|
| 289 |
+
disableTouchRipple: true,
|
| 290 |
+
disableRipple: true,
|
| 291 |
+
},
|
| 292 |
+
styleOverrides: {
|
| 293 |
+
root: {
|
| 294 |
+
boxSizing: 'border-box',
|
| 295 |
+
transition: 'all 100ms ease-in',
|
| 296 |
+
'&:focus-visible': {
|
| 297 |
+
outline: `3px solid ${alpha(brand[500], 0.5)}`,
|
| 298 |
+
outlineOffset: '2px',
|
| 299 |
+
},
|
| 300 |
+
},
|
| 301 |
+
},
|
| 302 |
+
},
|
| 303 |
+
MuiButton: {
|
| 304 |
+
styleOverrides: {
|
| 305 |
+
root: ({ theme, ownerState }) => ({
|
| 306 |
+
boxSizing: 'border-box',
|
| 307 |
+
boxShadow: 'unset',
|
| 308 |
+
borderRadius: '10px',
|
| 309 |
+
textTransform: 'none',
|
| 310 |
+
...(ownerState.size === 'small' && {
|
| 311 |
+
maxHeight: '32px',
|
| 312 |
+
}),
|
| 313 |
+
...(ownerState.size === 'medium' && {
|
| 314 |
+
height: '40px',
|
| 315 |
+
}),
|
| 316 |
+
...(ownerState.variant === 'contained' &&
|
| 317 |
+
ownerState.color === 'primary' && {
|
| 318 |
+
color: brand[50],
|
| 319 |
+
background: brand[400],
|
| 320 |
+
'&:hover': {
|
| 321 |
+
background: brand[500],
|
| 322 |
+
backgroundImage: 'none',
|
| 323 |
+
boxShadow: 'unset',
|
| 324 |
+
},
|
| 325 |
+
}),
|
| 326 |
+
...(ownerState.variant === 'contained' &&
|
| 327 |
+
ownerState.color === 'error' && {
|
| 328 |
+
color: brand[50],
|
| 329 |
+
background: red[600],
|
| 330 |
+
'&:hover': {
|
| 331 |
+
background: red[800],
|
| 332 |
+
backgroundImage: 'none',
|
| 333 |
+
boxShadow: 'unset',
|
| 334 |
+
},
|
| 335 |
+
}),
|
| 336 |
+
...(ownerState.variant === 'outlined' && {
|
| 337 |
+
backgroundColor: alpha(brand[300], 0.1),
|
| 338 |
+
borderColor: brand[300],
|
| 339 |
+
color: brand[500],
|
| 340 |
+
'&:hover': {
|
| 341 |
+
backgroundColor: alpha(brand[300], 0.3),
|
| 342 |
+
borderColor: brand[200],
|
| 343 |
+
boxShadow: 'unset',
|
| 344 |
+
},
|
| 345 |
+
}),
|
| 346 |
+
...(ownerState.variant === 'text' && {
|
| 347 |
+
color: brand[500],
|
| 348 |
+
'&:hover': {
|
| 349 |
+
backgroundColor: alpha(brand[300], 0.3),
|
| 350 |
+
borderColor: brand[200],
|
| 351 |
+
boxShadow: 'unset',
|
| 352 |
+
},
|
| 353 |
+
}),
|
| 354 |
+
...(theme.palette.mode === 'dark' && {
|
| 355 |
+
...(ownerState.variant === 'outlined' && {
|
| 356 |
+
backgroundColor: alpha(brand[600], 0.1),
|
| 357 |
+
borderColor: brand[700],
|
| 358 |
+
color: brand[300],
|
| 359 |
+
'&:hover': {
|
| 360 |
+
backgroundColor: alpha(brand[600], 0.3),
|
| 361 |
+
borderColor: brand[700],
|
| 362 |
+
boxShadow: 'unset',
|
| 363 |
+
},
|
| 364 |
+
}),
|
| 365 |
+
...(ownerState.variant === 'text' && {
|
| 366 |
+
color: brand[300],
|
| 367 |
+
'&:hover': {
|
| 368 |
+
backgroundColor: alpha(brand[600], 0.3),
|
| 369 |
+
borderColor: brand[700],
|
| 370 |
+
boxShadow: 'unset',
|
| 371 |
+
},
|
| 372 |
+
}),
|
| 373 |
+
}),
|
| 374 |
+
}),
|
| 375 |
+
},
|
| 376 |
+
},
|
| 377 |
+
MuiCard: {
|
| 378 |
+
styleOverrides: {
|
| 379 |
+
root: ({ theme, ownerState }) => ({
|
| 380 |
+
backgroundColor: gray[50],
|
| 381 |
+
borderRadius: 10,
|
| 382 |
+
border: `1px solid ${alpha(gray[200], 0.8)}`,
|
| 383 |
+
boxShadow: 'none',
|
| 384 |
+
transition: 'background-color, border, 80ms ease',
|
| 385 |
+
...(ownerState.variant === 'outlined' && {
|
| 386 |
+
background: `linear-gradient(to bottom, #FFF, ${gray[50]})`,
|
| 387 |
+
'&:hover': {
|
| 388 |
+
borderColor: brand[300],
|
| 389 |
+
boxShadow: `0 0 24px ${brand[100]}`,
|
| 390 |
+
},
|
| 391 |
+
}),
|
| 392 |
+
...(theme.palette.mode === 'dark' && {
|
| 393 |
+
backgroundColor: alpha(gray[800], 0.6),
|
| 394 |
+
border: `1px solid ${alpha(gray[700], 0.3)}`,
|
| 395 |
+
...(ownerState.variant === 'outlined' && {
|
| 396 |
+
background: `linear-gradient(to bottom, ${gray[900]}, ${alpha(gray[800], 0.5)})`,
|
| 397 |
+
'&:hover': {
|
| 398 |
+
borderColor: brand[700],
|
| 399 |
+
boxShadow: `0 0 24px ${brand[800]}`,
|
| 400 |
+
},
|
| 401 |
+
}),
|
| 402 |
+
}),
|
| 403 |
+
}),
|
| 404 |
+
},
|
| 405 |
+
},
|
| 406 |
+
MuiChip: {
|
| 407 |
+
styleOverrides: {
|
| 408 |
+
root: ({ theme }) => ({
|
| 409 |
+
alignSelf: 'center',
|
| 410 |
+
py: 1.5,
|
| 411 |
+
px: 0.5,
|
| 412 |
+
background: `linear-gradient(to bottom right, ${brand[50]}, ${brand[100]})`,
|
| 413 |
+
border: '1px solid',
|
| 414 |
+
borderColor: `${alpha(brand[500], 0.3)}`,
|
| 415 |
+
fontWeight: '600',
|
| 416 |
+
'&:hover': {
|
| 417 |
+
backgroundColor: brand[500],
|
| 418 |
+
},
|
| 419 |
+
'&:focus-visible': {
|
| 420 |
+
borderColor: brand[800],
|
| 421 |
+
backgroundColor: brand[200],
|
| 422 |
+
},
|
| 423 |
+
'& .MuiChip-label': {
|
| 424 |
+
color: brand[500],
|
| 425 |
+
},
|
| 426 |
+
'& .MuiChip-icon': {
|
| 427 |
+
color: brand[500],
|
| 428 |
+
},
|
| 429 |
+
...(theme.palette.mode === 'dark' && {
|
| 430 |
+
background: `linear-gradient(to bottom right, ${brand[700]}, ${brand[900]})`,
|
| 431 |
+
borderColor: `${alpha(brand[500], 0.5)}`,
|
| 432 |
+
'&:hover': {
|
| 433 |
+
backgroundColor: brand[600],
|
| 434 |
+
},
|
| 435 |
+
'&:focus-visible': {
|
| 436 |
+
borderColor: brand[200],
|
| 437 |
+
backgroundColor: brand[600],
|
| 438 |
+
},
|
| 439 |
+
'& .MuiChip-label': {
|
| 440 |
+
color: brand[200],
|
| 441 |
+
},
|
| 442 |
+
'& .MuiChip-icon': {
|
| 443 |
+
color: brand[200],
|
| 444 |
+
},
|
| 445 |
+
}),
|
| 446 |
+
}),
|
| 447 |
+
},
|
| 448 |
+
},
|
| 449 |
+
MuiDivider: {
|
| 450 |
+
styleOverrides: {
|
| 451 |
+
root: ({ theme }) => ({
|
| 452 |
+
borderColor: `${alpha(gray[200], 0.8)}`,
|
| 453 |
+
...(theme.palette.mode === 'dark' && {
|
| 454 |
+
borderColor: `${alpha(gray[700], 0.4)}`,
|
| 455 |
+
}),
|
| 456 |
+
}),
|
| 457 |
+
},
|
| 458 |
+
},
|
| 459 |
+
MuiLink: {
|
| 460 |
+
defaultProps: {
|
| 461 |
+
underline: 'none',
|
| 462 |
+
},
|
| 463 |
+
styleOverrides: {
|
| 464 |
+
root: ({ theme }) => ({
|
| 465 |
+
color: brand[600],
|
| 466 |
+
fontWeight: 500,
|
| 467 |
+
position: 'relative',
|
| 468 |
+
textDecoration: 'none',
|
| 469 |
+
'&::before': {
|
| 470 |
+
content: '""',
|
| 471 |
+
position: 'absolute',
|
| 472 |
+
width: 0,
|
| 473 |
+
height: '1px',
|
| 474 |
+
bottom: 0,
|
| 475 |
+
left: 0,
|
| 476 |
+
backgroundColor: brand[200],
|
| 477 |
+
opacity: 0.7,
|
| 478 |
+
transition: 'width 0.3s ease, opacity 0.3s ease',
|
| 479 |
+
},
|
| 480 |
+
'&:hover::before': {
|
| 481 |
+
width: '100%',
|
| 482 |
+
opacity: 1,
|
| 483 |
+
},
|
| 484 |
+
...(theme.palette.mode === 'dark' && {
|
| 485 |
+
color: brand[200],
|
| 486 |
+
}),
|
| 487 |
+
}),
|
| 488 |
+
},
|
| 489 |
+
},
|
| 490 |
+
MuiList: {
|
| 491 |
+
styleOverrides: {
|
| 492 |
+
root: ({ theme }) => ({
|
| 493 |
+
backgroundColor: theme.palette.mode === 'dark' ? '#000' : 'transparent',
|
| 494 |
+
}),
|
| 495 |
+
},
|
| 496 |
+
},
|
| 497 |
+
MuiMenuItem: {
|
| 498 |
+
styleOverrides: {
|
| 499 |
+
root: ({ theme }) => ({
|
| 500 |
+
borderRadius: '10px',
|
| 501 |
+
color: gray[500],
|
| 502 |
+
fontWeight: 500,
|
| 503 |
+
...(theme.palette.mode === 'dark' && {
|
| 504 |
+
color: gray[300],
|
| 505 |
+
}),
|
| 506 |
+
}),
|
| 507 |
+
},
|
| 508 |
+
},
|
| 509 |
+
MuiPaper: {
|
| 510 |
+
styleOverrides: {
|
| 511 |
+
root: ({ theme }) => ({
|
| 512 |
+
backgroundImage: 'none',
|
| 513 |
+
backgroundColor: gray[100],
|
| 514 |
+
...(theme.palette.mode === 'dark' && {
|
| 515 |
+
backgroundColor: alpha(gray[900], 0.6),
|
| 516 |
+
}),
|
| 517 |
+
}),
|
| 518 |
+
},
|
| 519 |
+
},
|
| 520 |
+
MuiSwitch: {
|
| 521 |
+
styleOverrides: {
|
| 522 |
+
root: ({ theme }) => ({
|
| 523 |
+
boxSizing: 'border-box',
|
| 524 |
+
width: 36,
|
| 525 |
+
height: 24,
|
| 526 |
+
padding: 0,
|
| 527 |
+
transition: 'background-color 100ms ease-in',
|
| 528 |
+
'&:hover': {
|
| 529 |
+
'& .MuiSwitch-track': {
|
| 530 |
+
backgroundColor: brand[600],
|
| 531 |
+
},
|
| 532 |
+
},
|
| 533 |
+
'& .MuiSwitch-switchBase': {
|
| 534 |
+
'&.Mui-checked': {
|
| 535 |
+
transform: 'translateX(13px)',
|
| 536 |
+
},
|
| 537 |
+
},
|
| 538 |
+
'& .MuiSwitch-track': {
|
| 539 |
+
borderRadius: 50,
|
| 540 |
+
},
|
| 541 |
+
'& .MuiSwitch-thumb': {
|
| 542 |
+
boxShadow: '0 0 2px 2px rgba(0, 0, 0, 0.2)',
|
| 543 |
+
backgroundColor: '#FFF',
|
| 544 |
+
width: 16,
|
| 545 |
+
height: 16,
|
| 546 |
+
margin: 2,
|
| 547 |
+
},
|
| 548 |
+
...(theme.palette.mode === 'dark' && {
|
| 549 |
+
width: 36,
|
| 550 |
+
height: 24,
|
| 551 |
+
padding: 0,
|
| 552 |
+
transition: 'background-color 100ms ease-in',
|
| 553 |
+
'&:hover': {
|
| 554 |
+
'& .MuiSwitch-track': {
|
| 555 |
+
backgroundColor: brand[600],
|
| 556 |
+
},
|
| 557 |
+
},
|
| 558 |
+
'& .MuiSwitch-switchBase': {
|
| 559 |
+
'&.Mui-checked': {
|
| 560 |
+
transform: 'translateX(13px)',
|
| 561 |
+
},
|
| 562 |
+
},
|
| 563 |
+
'& .MuiSwitch-thumb': {
|
| 564 |
+
boxShadow: '0 0 2px 2px rgba(0, 0, 0, 0.2)',
|
| 565 |
+
backgroundColor: '#FFF',
|
| 566 |
+
width: 16,
|
| 567 |
+
height: 16,
|
| 568 |
+
margin: 2,
|
| 569 |
+
},
|
| 570 |
+
}),
|
| 571 |
+
}),
|
| 572 |
+
switchBase: {
|
| 573 |
+
height: 24,
|
| 574 |
+
width: 24,
|
| 575 |
+
padding: 0,
|
| 576 |
+
color: '#fff',
|
| 577 |
+
'&.Mui-checked + .MuiSwitch-track': {
|
| 578 |
+
opacity: 1,
|
| 579 |
+
},
|
| 580 |
+
},
|
| 581 |
+
},
|
| 582 |
+
},
|
| 583 |
+
MuiTextField: {
|
| 584 |
+
styleOverrides: {
|
| 585 |
+
root: ({ theme }) => ({
|
| 586 |
+
'& label .Mui-focused': {
|
| 587 |
+
color: 'white',
|
| 588 |
+
},
|
| 589 |
+
'& .MuiInputBase-input': {
|
| 590 |
+
boxSizing: 'border-box',
|
| 591 |
+
'&::placeholder': {
|
| 592 |
+
opacity: 0.7,
|
| 593 |
+
},
|
| 594 |
+
},
|
| 595 |
+
'& .MuiOutlinedInput-root': {
|
| 596 |
+
boxSizing: 'border-box',
|
| 597 |
+
minWidth: 140,
|
| 598 |
+
minHeight: 40,
|
| 599 |
+
height: '100%',
|
| 600 |
+
borderRadius: '10px',
|
| 601 |
+
border: '1px solid',
|
| 602 |
+
borderColor: gray[200],
|
| 603 |
+
transition: 'border-color 120ms ease-in',
|
| 604 |
+
'& fieldset': {
|
| 605 |
+
border: 'none',
|
| 606 |
+
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)',
|
| 607 |
+
background: `${alpha('#FFF', 0.3)}`,
|
| 608 |
+
},
|
| 609 |
+
'&:hover': {
|
| 610 |
+
borderColor: brand[300],
|
| 611 |
+
},
|
| 612 |
+
'&.Mui-focused': {
|
| 613 |
+
borderColor: brand[400],
|
| 614 |
+
outline: '4px solid',
|
| 615 |
+
outlineColor: brand[200],
|
| 616 |
+
},
|
| 617 |
+
},
|
| 618 |
+
...(theme.palette.mode === 'dark' && {
|
| 619 |
+
'& .MuiOutlinedInput-root': {
|
| 620 |
+
boxSizing: 'border-box',
|
| 621 |
+
minWidth: 140,
|
| 622 |
+
minHeight: 40,
|
| 623 |
+
height: '100%',
|
| 624 |
+
borderRadius: '10px',
|
| 625 |
+
border: '1px solid',
|
| 626 |
+
borderColor: gray[600],
|
| 627 |
+
transition: 'border-color 120ms ease-in',
|
| 628 |
+
'& fieldset': {
|
| 629 |
+
border: 'none',
|
| 630 |
+
boxShadow: ' 0px 2px 4px rgba(0, 0, 0, 0.4)',
|
| 631 |
+
background: `${alpha(gray[800], 0.4)}`,
|
| 632 |
+
},
|
| 633 |
+
'&:hover': {
|
| 634 |
+
borderColor: brand[300],
|
| 635 |
+
},
|
| 636 |
+
'&.Mui-focused': {
|
| 637 |
+
borderColor: brand[400],
|
| 638 |
+
outline: '4px solid',
|
| 639 |
+
outlineColor: alpha(brand[500], 0.5),
|
| 640 |
+
},
|
| 641 |
+
},
|
| 642 |
+
}),
|
| 643 |
+
}),
|
| 644 |
+
},
|
| 645 |
+
},
|
| 646 |
+
},
|
| 647 |
+
};
|
| 648 |
+
};
|
| 649 |
+
|
| 650 |
+
export default getTheme;
|
src/features/app/App.jsx
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useEffect } from 'react';
|
| 2 |
+
import PropTypes from 'prop-types';
|
| 3 |
+
import { useDispatch, useSelector } from 'react-redux';
|
| 4 |
+
import { RouterProvider } from 'react-router-dom';
|
| 5 |
+
|
| 6 |
+
import { CssBaseline } from '@mui/material';
|
| 7 |
+
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
| 8 |
+
import '@fontsource/inter';
|
| 9 |
+
|
| 10 |
+
import getTheme from '../../constants/theme';
|
| 11 |
+
import { hideToast, initApp, selectThemeMode, selectToast } from './appSlice';
|
| 12 |
+
import Toast from '../shared/Toast/Toast';
|
| 13 |
+
|
| 14 |
+
export function App({ router }) {
|
| 15 |
+
const dispatch = useDispatch();
|
| 16 |
+
const themeMode = useSelector(selectThemeMode);
|
| 17 |
+
const toast = useSelector(selectToast);
|
| 18 |
+
|
| 19 |
+
useEffect(() => {
|
| 20 |
+
dispatch(initApp());
|
| 21 |
+
}, [dispatch]);
|
| 22 |
+
|
| 23 |
+
return (
|
| 24 |
+
<ThemeProvider theme={createTheme(getTheme(themeMode))}>
|
| 25 |
+
<CssBaseline />
|
| 26 |
+
<Toast {...toast} onClose={() => dispatch(hideToast())} />
|
| 27 |
+
<RouterProvider router={router} />
|
| 28 |
+
</ThemeProvider>
|
| 29 |
+
);
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
App.propTypes = {
|
| 33 |
+
router: PropTypes.shape({
|
| 34 |
+
subscribe: PropTypes.func.isRequired,
|
| 35 |
+
}).isRequired,
|
| 36 |
+
};
|
src/features/app/appSlice.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { createAppSlice } from '../../store/createAppSlice';
|
| 2 |
+
|
| 3 |
+
const initialState = {
|
| 4 |
+
authToken: '',
|
| 5 |
+
themeMode: 'light',
|
| 6 |
+
toast: {
|
| 7 |
+
open: false,
|
| 8 |
+
autoHideDuration: 3000,
|
| 9 |
+
severity: 'success',
|
| 10 |
+
messageParts: [],
|
| 11 |
+
},
|
| 12 |
+
appbar: { open: false },
|
| 13 |
+
};
|
| 14 |
+
|
| 15 |
+
export const appSlice = createAppSlice({
|
| 16 |
+
name: 'app',
|
| 17 |
+
initialState,
|
| 18 |
+
reducers: (create) => ({
|
| 19 |
+
initApp: create.reducer((state) => {
|
| 20 |
+
const themeMode = localStorage.getItem('themeMode');
|
| 21 |
+
if (themeMode) {
|
| 22 |
+
state.themeMode = themeMode;
|
| 23 |
+
} else {
|
| 24 |
+
state.themeMode = initialState.themeMode;
|
| 25 |
+
localStorage.setItem('themeMode', state.themeMode);
|
| 26 |
+
}
|
| 27 |
+
const authToken = localStorage.getItem('authToken');
|
| 28 |
+
if (authToken) {
|
| 29 |
+
state.authToken = authToken;
|
| 30 |
+
} else {
|
| 31 |
+
state.authToken = initialState.authToken;
|
| 32 |
+
localStorage.setItem('authToken', state.authToken);
|
| 33 |
+
}
|
| 34 |
+
}),
|
| 35 |
+
setAuthToken: create.reducer((state, action) => {
|
| 36 |
+
state.authToken = action.payload;
|
| 37 |
+
localStorage.setItem('authToken', state.authToken);
|
| 38 |
+
}),
|
| 39 |
+
resetAuthToken: create.reducer((state) => {
|
| 40 |
+
state.authToken = initialState.authToken;
|
| 41 |
+
localStorage.setItem('authToken', state.authToken);
|
| 42 |
+
}),
|
| 43 |
+
setThemeMode: create.reducer((state, action) => {
|
| 44 |
+
state.themeMode = action.payload;
|
| 45 |
+
localStorage.setItem('themeMode', state.themeMode);
|
| 46 |
+
}),
|
| 47 |
+
switchThemeMode: create.reducer((state) => {
|
| 48 |
+
state.themeMode = state.themeMode === 'light' ? 'dark' : 'light';
|
| 49 |
+
localStorage.setItem('themeMode', state.themeMode);
|
| 50 |
+
}),
|
| 51 |
+
resetApp: create.reducer((state) => {
|
| 52 |
+
state.authToken = initialState.authToken;
|
| 53 |
+
state.themeMode = initialState.themeMode;
|
| 54 |
+
state.toast = initialState.toast;
|
| 55 |
+
localStorage.setItem('authToken', state.authToken);
|
| 56 |
+
localStorage.setItem('themeMode', state.themeMode);
|
| 57 |
+
}),
|
| 58 |
+
showToast: create.reducer((state, action) => {
|
| 59 |
+
state.toast.open = true;
|
| 60 |
+
state.toast.messageParts = action.payload.messageParts;
|
| 61 |
+
state.toast.severity = action.payload.severity ?? initialState.toast.severity;
|
| 62 |
+
state.toast.autoHideDuration =
|
| 63 |
+
action.payload.autoHideDuration ?? initialState.toast.autoHideDuration;
|
| 64 |
+
}),
|
| 65 |
+
hideToast: create.reducer((state) => {
|
| 66 |
+
state.toast.open = false;
|
| 67 |
+
}),
|
| 68 |
+
switchAppbarOpen: create.reducer((state, action) => {
|
| 69 |
+
state.appbar.open = action.payload;
|
| 70 |
+
}),
|
| 71 |
+
}),
|
| 72 |
+
selectors: {
|
| 73 |
+
selectAuthToken: (app) => app.authToken,
|
| 74 |
+
selectThemeMode: (app) => app.themeMode,
|
| 75 |
+
selectToast: (app) => app.toast,
|
| 76 |
+
selectAppbar: (app) => app.appbar,
|
| 77 |
+
},
|
| 78 |
+
});
|
| 79 |
+
|
| 80 |
+
export const {
|
| 81 |
+
hideToast,
|
| 82 |
+
initApp,
|
| 83 |
+
resetApp,
|
| 84 |
+
resetAuthToken,
|
| 85 |
+
setAuthToken,
|
| 86 |
+
setThemeMode,
|
| 87 |
+
switchThemeMode,
|
| 88 |
+
showToast,
|
| 89 |
+
switchAppbarOpen,
|
| 90 |
+
} = appSlice.actions;
|
| 91 |
+
|
| 92 |
+
export const { selectAuthToken, selectThemeMode, selectToast, selectAppbar } = appSlice.selectors;
|
src/features/landing/AppAppBar/AppAppBar-styles.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const styles = {
|
| 2 |
+
appbar: {
|
| 3 |
+
boxShadow: 0,
|
| 4 |
+
bgcolor: 'transparent',
|
| 5 |
+
backgroundImage: 'none',
|
| 6 |
+
mt: { xs: 3, sm: 4, md: 4 },
|
| 7 |
+
},
|
| 8 |
+
authItemBox: {
|
| 9 |
+
display: { xs: 'none', md: 'flex' },
|
| 10 |
+
gap: 0.5,
|
| 11 |
+
alignItems: 'center',
|
| 12 |
+
},
|
| 13 |
+
largeAppBar: {
|
| 14 |
+
flexGrow: 1,
|
| 15 |
+
display: 'flex',
|
| 16 |
+
alignItems: 'center',
|
| 17 |
+
},
|
| 18 |
+
|
| 19 |
+
largeMenuItem: { py: '6px', px: '12px' },
|
| 20 |
+
largeMenuItemBox: { display: { xs: 'none', md: 'flex' } },
|
| 21 |
+
|
| 22 |
+
logoBox: { pr: 2 },
|
| 23 |
+
|
| 24 |
+
smallAppBar: { display: { sm: '', md: 'none' } },
|
| 25 |
+
smallMenuIconButton: { minWidth: '30px', p: '4px', color: 'primary' },
|
| 26 |
+
smallMenuItem: { width: '100%', color: 'primary' },
|
| 27 |
+
smallMenuItemBox: {
|
| 28 |
+
minWidth: '60dvw',
|
| 29 |
+
p: 2,
|
| 30 |
+
backgroundColor: 'background.paper',
|
| 31 |
+
flexGrow: 1,
|
| 32 |
+
},
|
| 33 |
+
|
| 34 |
+
themeModeToggleBox: {
|
| 35 |
+
display: 'flex',
|
| 36 |
+
flexDirection: 'column',
|
| 37 |
+
alignItems: 'end',
|
| 38 |
+
flexGrow: 1,
|
| 39 |
+
},
|
| 40 |
+
|
| 41 |
+
toolbar: {
|
| 42 |
+
display: 'flex',
|
| 43 |
+
alignItems: 'center',
|
| 44 |
+
justifyContent: 'space-between',
|
| 45 |
+
flexShrink: 0,
|
| 46 |
+
borderRadius: '10px',
|
| 47 |
+
bgcolor: (theme) =>
|
| 48 |
+
theme.palette.mode === 'light' ? 'rgba(255, 255, 255, 0.4)' : 'rgba(0, 0, 0, 0.4)',
|
| 49 |
+
backdropFilter: 'blur(24px)',
|
| 50 |
+
maxHeight: 40,
|
| 51 |
+
border: '1px solid',
|
| 52 |
+
borderColor: 'divider',
|
| 53 |
+
boxShadow: (theme) =>
|
| 54 |
+
theme.palette.mode === 'light'
|
| 55 |
+
? `0 0 1px rgba(85, 166, 246, 0.1), 1px 1.5px 2px -1px rgba(85, 166, 246, 0.15), 4px 4px 12px -2.5px rgba(85, 166, 246, 0.15)`
|
| 56 |
+
: '0 0 1px rgba(2, 31, 59, 0.7), 1px 1.5px 2px -1px rgba(2, 31, 59, 0.65), 4px 4px 12px -2.5px rgba(2, 31, 59, 0.65)',
|
| 57 |
+
},
|
| 58 |
+
};
|
| 59 |
+
|
| 60 |
+
export default styles;
|
src/features/landing/AppAppBar/AppAppBar.jsx
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from "react";
|
| 2 |
+
import PropTypes from "prop-types";
|
| 3 |
+
|
| 4 |
+
import { useSelector } from "react-redux";
|
| 5 |
+
|
| 6 |
+
import {
|
| 7 |
+
AppBar,
|
| 8 |
+
Box,
|
| 9 |
+
Button,
|
| 10 |
+
Container,
|
| 11 |
+
Divider,
|
| 12 |
+
Drawer,
|
| 13 |
+
MenuItem,
|
| 14 |
+
Toolbar,
|
| 15 |
+
Typography,
|
| 16 |
+
} from "@mui/material";
|
| 17 |
+
import { Menu } from "@mui/icons-material";
|
| 18 |
+
|
| 19 |
+
import styles from "./AppAppBar-styles";
|
| 20 |
+
|
| 21 |
+
import { selectAuthToken, selectThemeMode } from "../../app/appSlice";
|
| 22 |
+
|
| 23 |
+
import ThemeModeToggle from "../../shared/ThemeModeToggle/ThemeModeToggle";
|
| 24 |
+
import Logo from "../../shared/Logo/Logo";
|
| 25 |
+
|
| 26 |
+
export const AppAppBar = ({ onClickThemeMode }) => {
|
| 27 |
+
const themeMode = useSelector(selectThemeMode);
|
| 28 |
+
const authToken = useSelector(selectAuthToken);
|
| 29 |
+
const [open, setOpen] = useState(false);
|
| 30 |
+
|
| 31 |
+
const scrollToSection = (sectionId) => {
|
| 32 |
+
const sectionElement = document.getElementById(sectionId);
|
| 33 |
+
const offset = 128;
|
| 34 |
+
if (sectionElement) {
|
| 35 |
+
const targetScroll = sectionElement.offsetTop - offset;
|
| 36 |
+
sectionElement.scrollIntoView({ behavior: "smooth" });
|
| 37 |
+
window.scrollTo({
|
| 38 |
+
top: targetScroll,
|
| 39 |
+
behavior: "smooth",
|
| 40 |
+
});
|
| 41 |
+
setOpen(false);
|
| 42 |
+
}
|
| 43 |
+
};
|
| 44 |
+
|
| 45 |
+
const desktop = (
|
| 46 |
+
<Box sx={styles.largeAppBar}>
|
| 47 |
+
<Box sx={styles.logoBox}>
|
| 48 |
+
<Logo />
|
| 49 |
+
</Box>
|
| 50 |
+
<Box sx={styles.largeMenuItemBox}>
|
| 51 |
+
<MenuItem
|
| 52 |
+
onClick={() => scrollToSection("leaderboard")}
|
| 53 |
+
sx={styles.largeMenuItem}
|
| 54 |
+
>
|
| 55 |
+
<Typography variant="body2" color="text.primary">
|
| 56 |
+
Leaderboard
|
| 57 |
+
</Typography>
|
| 58 |
+
</MenuItem>
|
| 59 |
+
<MenuItem
|
| 60 |
+
onClick={() => scrollToSection("services")}
|
| 61 |
+
sx={styles.largeMenuItem}
|
| 62 |
+
>
|
| 63 |
+
<Typography variant="body2" color="text.primary">
|
| 64 |
+
Services
|
| 65 |
+
</Typography>
|
| 66 |
+
</MenuItem>
|
| 67 |
+
|
| 68 |
+
<MenuItem
|
| 69 |
+
onClick={() => scrollToSection("features")}
|
| 70 |
+
sx={styles.largeMenuItem}
|
| 71 |
+
>
|
| 72 |
+
<Typography variant="body2" color="text.primary">
|
| 73 |
+
Features
|
| 74 |
+
</Typography>
|
| 75 |
+
</MenuItem>
|
| 76 |
+
|
| 77 |
+
<MenuItem
|
| 78 |
+
onClick={() => scrollToSection("faq")}
|
| 79 |
+
sx={styles.largeMenuItem}
|
| 80 |
+
>
|
| 81 |
+
<Typography variant="body2" color="text.primary">
|
| 82 |
+
FAQ
|
| 83 |
+
</Typography>
|
| 84 |
+
</MenuItem>
|
| 85 |
+
</Box>
|
| 86 |
+
</Box>
|
| 87 |
+
);
|
| 88 |
+
|
| 89 |
+
const desktopAuth = (
|
| 90 |
+
<Box sx={styles.authItemBox}>
|
| 91 |
+
<ThemeModeToggle mode={themeMode} onClick={onClickThemeMode} />
|
| 92 |
+
<Button
|
| 93 |
+
color="primary"
|
| 94 |
+
variant="contained"
|
| 95 |
+
size="small"
|
| 96 |
+
component="a"
|
| 97 |
+
href="https://aixamine.qcri.org/main"
|
| 98 |
+
>
|
| 99 |
+
{"Homepage"}
|
| 100 |
+
</Button>
|
| 101 |
+
</Box>
|
| 102 |
+
);
|
| 103 |
+
|
| 104 |
+
const mobile = (
|
| 105 |
+
<Box sx={styles.smallAppBar}>
|
| 106 |
+
<Button
|
| 107 |
+
variant="text"
|
| 108 |
+
onClick={() => setOpen(true)}
|
| 109 |
+
sx={styles.smallMenuIconButton}
|
| 110 |
+
>
|
| 111 |
+
<Menu />
|
| 112 |
+
</Button>
|
| 113 |
+
<Drawer anchor="right" open={open} onClose={() => setOpen(false)}>
|
| 114 |
+
<Box sx={styles.smallMenuItemBox}>
|
| 115 |
+
<Box sx={styles.themeModeToggleBox}>
|
| 116 |
+
<ThemeModeToggle mode={themeMode} onClick={onClickThemeMode} />
|
| 117 |
+
</Box>
|
| 118 |
+
<MenuItem onClick={() => scrollToSection("leaderboard")}>
|
| 119 |
+
Leaderboard
|
| 120 |
+
</MenuItem>
|
| 121 |
+
<MenuItem onClick={() => scrollToSection("services")}>
|
| 122 |
+
Services
|
| 123 |
+
</MenuItem>
|
| 124 |
+
<MenuItem onClick={() => scrollToSection("features")}>
|
| 125 |
+
Features
|
| 126 |
+
</MenuItem>
|
| 127 |
+
<MenuItem onClick={() => scrollToSection("faq")}>FAQ</MenuItem>
|
| 128 |
+
<Box mt={2} mb={2}>
|
| 129 |
+
<Divider />
|
| 130 |
+
</Box>
|
| 131 |
+
|
| 132 |
+
<MenuItem>
|
| 133 |
+
<Button
|
| 134 |
+
color="primary"
|
| 135 |
+
variant="contained"
|
| 136 |
+
size="small"
|
| 137 |
+
component="a"
|
| 138 |
+
href="https://aixamine.qcri.org/main"
|
| 139 |
+
>
|
| 140 |
+
{"Homepage"}
|
| 141 |
+
</Button>
|
| 142 |
+
</MenuItem>
|
| 143 |
+
</Box>
|
| 144 |
+
</Drawer>
|
| 145 |
+
</Box>
|
| 146 |
+
);
|
| 147 |
+
|
| 148 |
+
return (
|
| 149 |
+
<div>
|
| 150 |
+
<AppBar position="fixed" sx={styles.appbar}>
|
| 151 |
+
<Container maxWidth="lg">
|
| 152 |
+
<Toolbar variant="regular" sx={styles.toolbar}>
|
| 153 |
+
{desktop}
|
| 154 |
+
{desktopAuth}
|
| 155 |
+
{mobile}
|
| 156 |
+
</Toolbar>
|
| 157 |
+
</Container>
|
| 158 |
+
</AppBar>
|
| 159 |
+
</div>
|
| 160 |
+
);
|
| 161 |
+
};
|
| 162 |
+
|
| 163 |
+
AppAppBar.propTypes = {
|
| 164 |
+
onClickThemeMode: PropTypes.func.isRequired,
|
| 165 |
+
};
|
| 166 |
+
|
| 167 |
+
export default AppAppBar;
|
src/features/landing/FAQ/FAQ-styles.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const styles = {
|
| 2 |
+
faqBox: { width: "100%" },
|
| 3 |
+
root: { py: { xs: 8, sm: 16 } },
|
| 4 |
+
|
| 5 |
+
description: {
|
| 6 |
+
maxWidth: "100%",
|
| 7 |
+
},
|
| 8 |
+
title: {
|
| 9 |
+
color: "text.primary",
|
| 10 |
+
width: { sm: "100%", md: "60%" },
|
| 11 |
+
textAlign: { sm: "left", md: "center" },
|
| 12 |
+
},
|
| 13 |
+
};
|
| 14 |
+
|
| 15 |
+
export default styles;
|
src/features/landing/FAQ/FAQ.jsx
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from 'react';
|
| 2 |
+
import Accordion from '@mui/material/Accordion';
|
| 3 |
+
|
| 4 |
+
import {
|
| 5 |
+
AccordionDetails,
|
| 6 |
+
AccordionSummary,
|
| 7 |
+
Box,
|
| 8 |
+
Container,
|
| 9 |
+
Link,
|
| 10 |
+
Typography,
|
| 11 |
+
} from '@mui/material';
|
| 12 |
+
|
| 13 |
+
import styles from './FAQ-styles';
|
| 14 |
+
|
| 15 |
+
import { ExpandMore } from '@mui/icons-material';
|
| 16 |
+
|
| 17 |
+
export function FAQ() {
|
| 18 |
+
const [expanded, setExpanded] = useState(false);
|
| 19 |
+
|
| 20 |
+
const handleChange = (panel) => (event, isExpanded) => {
|
| 21 |
+
setExpanded(expanded === panel ? false : panel);
|
| 22 |
+
};
|
| 23 |
+
|
| 24 |
+
const title = (
|
| 25 |
+
<Typography variant="h4" sx={styles.title}>
|
| 26 |
+
Frequently asked questions
|
| 27 |
+
</Typography>
|
| 28 |
+
);
|
| 29 |
+
|
| 30 |
+
return (
|
| 31 |
+
<Container id="faq" sx={styles.root}>
|
| 32 |
+
{title}
|
| 33 |
+
<Box sx={styles.faqBox}>
|
| 34 |
+
<Accordion expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
|
| 35 |
+
<AccordionSummary expandIcon={<ExpandMore />} id="panel1d-header">
|
| 36 |
+
<Typography component="h3" variant="subtitle2">
|
| 37 |
+
How do I submit my model for examination?
|
| 38 |
+
</Typography>
|
| 39 |
+
</AccordionSummary>
|
| 40 |
+
<AccordionDetails>
|
| 41 |
+
<Typography variant="body2" gutterBottom sx={styles.description}>
|
| 42 |
+
We support examination of all models published on Hugging Face. To examine a model,
|
| 43 |
+
simply provide the Hugging Face path to the model, a Hugging Face token with read
|
| 44 |
+
permission, and select the service/test that you want to perform. To examine a private
|
| 45 |
+
model, simply provide the model name, API endpoint, and API token.
|
| 46 |
+
</Typography>
|
| 47 |
+
</AccordionDetails>
|
| 48 |
+
</Accordion>
|
| 49 |
+
<Accordion expanded={expanded === 'panel2'} onChange={handleChange('panel2')}>
|
| 50 |
+
<AccordionSummary expandIcon={<ExpandMore />} id="panel2d-header">
|
| 51 |
+
<Typography component="h3" variant="subtitle2">
|
| 52 |
+
How long does it take to examine my model?
|
| 53 |
+
</Typography>
|
| 54 |
+
</AccordionSummary>
|
| 55 |
+
<AccordionDetails>
|
| 56 |
+
<Typography variant="body2" gutterBottom sx={styles.description}>
|
| 57 |
+
The examination time of a model is dependent on the model's inference time. For a 7B
|
| 58 |
+
parameter model such as LLaMA 2, the average examination time is 15 minutes.
|
| 59 |
+
</Typography>
|
| 60 |
+
</AccordionDetails>
|
| 61 |
+
</Accordion>
|
| 62 |
+
<Accordion expanded={expanded === 'panel3'} onChange={handleChange('panel3')}>
|
| 63 |
+
<AccordionSummary expandIcon={<ExpandMore />} id="panel3d-header">
|
| 64 |
+
<Typography component="h3" variant="subtitle2">
|
| 65 |
+
What makes your services stand out from others in the market?
|
| 66 |
+
</Typography>
|
| 67 |
+
</AccordionSummary>
|
| 68 |
+
<AccordionDetails>
|
| 69 |
+
<Typography variant="body2" gutterBottom sx={styles.description}>
|
| 70 |
+
Our product unifies the broad landscape of model safety and security concerns via a
|
| 71 |
+
single report. We conduct a wide range of tests under each service, providing users
|
| 72 |
+
with detailed breakdowns and insights of the results. Users can compare models via our
|
| 73 |
+
interactive leaderboard and export results as a PDF report.
|
| 74 |
+
</Typography>
|
| 75 |
+
</AccordionDetails>
|
| 76 |
+
</Accordion>
|
| 77 |
+
<Accordion expanded={expanded === 'panel4'} onChange={handleChange('panel4')}>
|
| 78 |
+
<AccordionSummary expandIcon={<ExpandMore />} id="panel4d-header">
|
| 79 |
+
<Typography component="h3" variant="subtitle2">
|
| 80 |
+
How can the examination improve my model?
|
| 81 |
+
</Typography>
|
| 82 |
+
</AccordionSummary>
|
| 83 |
+
<AccordionDetails>
|
| 84 |
+
<Typography variant="body2" gutterBottom sx={styles.description}>
|
| 85 |
+
The examination produces a report of the model's robustness across different areas of
|
| 86 |
+
safety and security. These results reveal threats that the model can be guarded
|
| 87 |
+
against and identify areas where model safety can be improved.
|
| 88 |
+
</Typography>
|
| 89 |
+
</AccordionDetails>
|
| 90 |
+
</Accordion>
|
| 91 |
+
</Box>
|
| 92 |
+
</Container>
|
| 93 |
+
);
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
export default FAQ;
|
src/features/landing/Features/Features-styles.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const styles = {
|
| 2 |
+
root: { py: { xs: 8, sm: 16 } },
|
| 3 |
+
rootBox: { width: { sm: "100%", md: "80%" } },
|
| 4 |
+
|
| 5 |
+
feature: { display: "flex", gap: 2, overflow: "auto" },
|
| 6 |
+
featureBox: {
|
| 7 |
+
display: { xs: "flex", sm: "none" },
|
| 8 |
+
flexDirection: "column",
|
| 9 |
+
gap: 2,
|
| 10 |
+
},
|
| 11 |
+
|
| 12 |
+
descriptionBox: {
|
| 13 |
+
width: "100%",
|
| 14 |
+
display: "flex",
|
| 15 |
+
flexDirection: "column",
|
| 16 |
+
alignItems: "flex-start",
|
| 17 |
+
gap: 1,
|
| 18 |
+
textAlign: "left",
|
| 19 |
+
textTransform: "none",
|
| 20 |
+
},
|
| 21 |
+
desktopImageBox: {
|
| 22 |
+
m: "auto",
|
| 23 |
+
width: "100%",
|
| 24 |
+
height: "100%",
|
| 25 |
+
backgroundSize: "contain",
|
| 26 |
+
backgroundPosition: "center",
|
| 27 |
+
backgroundRepeat: "no-repeat",
|
| 28 |
+
},
|
| 29 |
+
|
| 30 |
+
main: {
|
| 31 |
+
display: { xs: "none", sm: "flex" },
|
| 32 |
+
flexDirection: "column",
|
| 33 |
+
gap: 2,
|
| 34 |
+
height: "100%",
|
| 35 |
+
},
|
| 36 |
+
mainBox: {
|
| 37 |
+
display: "flex",
|
| 38 |
+
flexDirection: { xs: "column", md: "row-reverse" },
|
| 39 |
+
gap: 2,
|
| 40 |
+
},
|
| 41 |
+
mobileBox: {
|
| 42 |
+
display: { xs: "none", sm: "flex" },
|
| 43 |
+
width: { xs: "100%", md: "70%" },
|
| 44 |
+
height: "var(--items-image-height)",
|
| 45 |
+
},
|
| 46 |
+
mobileCard: {
|
| 47 |
+
height: "100%",
|
| 48 |
+
width: "100%",
|
| 49 |
+
display: { xs: "none", sm: "flex" },
|
| 50 |
+
pointerEvents: "none",
|
| 51 |
+
border: "none",
|
| 52 |
+
boxShadow: "none",
|
| 53 |
+
},
|
| 54 |
+
mobileImageBox: {
|
| 55 |
+
mb: 2,
|
| 56 |
+
backgroundSize: "contain",
|
| 57 |
+
backgroundPosition: "center",
|
| 58 |
+
width: "100%",
|
| 59 |
+
height: "100%",
|
| 60 |
+
backgroundRepeat: "no-repeat",
|
| 61 |
+
minHeight: 280,
|
| 62 |
+
},
|
| 63 |
+
|
| 64 |
+
featureChip: (selectedItemIdx, idx) => {
|
| 65 |
+
return {
|
| 66 |
+
borderColor: (theme) => {
|
| 67 |
+
if (theme.palette.mode === "light") {
|
| 68 |
+
return selectedItemIdx === idx ? "primary.light" : "";
|
| 69 |
+
}
|
| 70 |
+
return selectedItemIdx === idx ? "primary.light" : "";
|
| 71 |
+
},
|
| 72 |
+
background: (theme) => {
|
| 73 |
+
if (theme.palette.mode === "light") {
|
| 74 |
+
return selectedItemIdx === idx ? "none" : "";
|
| 75 |
+
}
|
| 76 |
+
return selectedItemIdx === idx ? "none" : "";
|
| 77 |
+
},
|
| 78 |
+
backgroundColor: selectedItemIdx === idx ? "primary.main" : "",
|
| 79 |
+
"& .MuiChip-label": {
|
| 80 |
+
color: selectedItemIdx === idx ? "#fff" : "",
|
| 81 |
+
},
|
| 82 |
+
};
|
| 83 |
+
},
|
| 84 |
+
featureDescription: { px: 2, pb: 2 },
|
| 85 |
+
featureText: { color: "text.primary" },
|
| 86 |
+
subtitle: { mb: { xs: 2, sm: 4 }, color: "text.secondary" },
|
| 87 |
+
textBody: { color: "text.secondary", mb: 1.5 },
|
| 88 |
+
textTitle: { color: "text.primary", fontWeight: "medium" },
|
| 89 |
+
};
|
| 90 |
+
|
| 91 |
+
export default styles;
|
src/features/landing/Features/Features.jsx
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import PropTypes from "prop-types";
|
| 2 |
+
import { useEffect, useState } from "react";
|
| 3 |
+
import { Box, Button, Card, Chip, Container, Typography } from "@mui/material";
|
| 4 |
+
import { VisibilityOff, Search, Assessment } from "@mui/icons-material";
|
| 5 |
+
|
| 6 |
+
import submissionDark from "/assets/submission-dark.png";
|
| 7 |
+
import submissionLight from "/assets/submission-light.png";
|
| 8 |
+
import overviewDark from "/assets/overview-dark.png";
|
| 9 |
+
import overviewLight from "/assets/overview-light.png";
|
| 10 |
+
import reportDark from "/assets/report-dark.png";
|
| 11 |
+
import reportLight from "/assets/report-light.png";
|
| 12 |
+
|
| 13 |
+
import styles from "./Features-styles";
|
| 14 |
+
|
| 15 |
+
const items = [
|
| 16 |
+
{
|
| 17 |
+
icon: <VisibilityOff />,
|
| 18 |
+
title: "Private Submission",
|
| 19 |
+
description:
|
| 20 |
+
"Closed source model? No problem, just provide us with API access. aiXamine is a unified framework for evaluating both proprietary and open-source models without requiring access to model internals or weights.",
|
| 21 |
+
imageLight: [submissionLight],
|
| 22 |
+
imageDark: [submissionDark],
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
icon: <Search />,
|
| 26 |
+
title: "Comprehensive Examination",
|
| 27 |
+
description:
|
| 28 |
+
"Evaluate models across 46 tests in 9 services spanning Safety & Reliability, Security & Robustness, and Privacy & Fairness dimensions.",
|
| 29 |
+
imageLight: [overviewLight],
|
| 30 |
+
imageDark: [overviewDark],
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
icon: <Assessment />,
|
| 34 |
+
title: "Rich Reporting",
|
| 35 |
+
description:
|
| 36 |
+
"Get structured, reproducible reports with category and subcategory-level diagnostics to identify systemic and localized vulnerabilities.",
|
| 37 |
+
imageLight: [reportLight],
|
| 38 |
+
imageDark: [reportDark],
|
| 39 |
+
},
|
| 40 |
+
];
|
| 41 |
+
|
| 42 |
+
export const MobileLayout = ({
|
| 43 |
+
selectedItemIdx,
|
| 44 |
+
selectedImageIdx,
|
| 45 |
+
handleItemClick,
|
| 46 |
+
selectedFeature,
|
| 47 |
+
}) => {
|
| 48 |
+
if (!items[selectedItemIdx]) {
|
| 49 |
+
return null;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
return (
|
| 53 |
+
<Box sx={styles.featureBox}>
|
| 54 |
+
<Box sx={styles.feature}>
|
| 55 |
+
{items.map(({ title }, index) => (
|
| 56 |
+
<Chip
|
| 57 |
+
size="medium"
|
| 58 |
+
key={index}
|
| 59 |
+
label={title}
|
| 60 |
+
onClick={() => handleItemClick(index)}
|
| 61 |
+
selected={selectedItemIdx === index}
|
| 62 |
+
sx={styles.featureChip(selectedItemIdx, index)}
|
| 63 |
+
/>
|
| 64 |
+
))}
|
| 65 |
+
</Box>
|
| 66 |
+
<Card variant="outlined">
|
| 67 |
+
<Box
|
| 68 |
+
sx={(theme) => ({
|
| 69 |
+
...styles.mobileImageBox,
|
| 70 |
+
backgroundImage: `url("${
|
| 71 |
+
theme.palette.mode === "dark"
|
| 72 |
+
? selectedFeature.imageDark[
|
| 73 |
+
selectedImageIdx % selectedFeature.imageDark.length
|
| 74 |
+
]
|
| 75 |
+
: selectedFeature.imageLight[
|
| 76 |
+
selectedImageIdx % selectedFeature.imageLight.length
|
| 77 |
+
]
|
| 78 |
+
}")`,
|
| 79 |
+
})}
|
| 80 |
+
/>
|
| 81 |
+
<Box sx={styles.featureDescription}>
|
| 82 |
+
<Typography gutterBottom sx={styles.textTitle}>
|
| 83 |
+
{selectedFeature.title}
|
| 84 |
+
</Typography>
|
| 85 |
+
<Typography variant="body2" sx={styles.textBody}>
|
| 86 |
+
{selectedFeature.description}
|
| 87 |
+
</Typography>
|
| 88 |
+
</Box>
|
| 89 |
+
</Card>
|
| 90 |
+
</Box>
|
| 91 |
+
);
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
MobileLayout.propTypes = {
|
| 95 |
+
selectedItemIdx: PropTypes.number.isRequired,
|
| 96 |
+
selectedImageIdx: PropTypes.number.isRequired,
|
| 97 |
+
handleItemClick: PropTypes.func.isRequired,
|
| 98 |
+
selectedFeature: PropTypes.object.isRequired,
|
| 99 |
+
};
|
| 100 |
+
|
| 101 |
+
export default function Features() {
|
| 102 |
+
const [selectedItemIdx, setSelectedItemIdx] = useState(0);
|
| 103 |
+
const [selectedImageIdx, setSelectedImageIdx] = useState(0);
|
| 104 |
+
|
| 105 |
+
const handleItemClick = (index) => {
|
| 106 |
+
setSelectedItemIdx(index);
|
| 107 |
+
setSelectedImageIdx(0);
|
| 108 |
+
};
|
| 109 |
+
|
| 110 |
+
const useInterval = (callback, delay) => {
|
| 111 |
+
useEffect(() => {
|
| 112 |
+
const intervalId = setInterval(callback, delay);
|
| 113 |
+
return () => clearInterval(intervalId);
|
| 114 |
+
}, [callback, delay]);
|
| 115 |
+
};
|
| 116 |
+
|
| 117 |
+
useInterval(() => setSelectedImageIdx((prev) => prev + 1), 5000);
|
| 118 |
+
|
| 119 |
+
const selectedFeature = items[selectedItemIdx];
|
| 120 |
+
|
| 121 |
+
return (
|
| 122 |
+
<Container id="features" sx={styles.root}>
|
| 123 |
+
<Box sx={styles.rootBox}>
|
| 124 |
+
<Typography
|
| 125 |
+
component="h2"
|
| 126 |
+
variant="h4"
|
| 127 |
+
gutterBottom
|
| 128 |
+
sx={styles.featureText}
|
| 129 |
+
>
|
| 130 |
+
Features
|
| 131 |
+
</Typography>
|
| 132 |
+
<Typography variant="body1" sx={styles.subtitle}>
|
| 133 |
+
aiXamine provides a unified black-box framework for comprehensive
|
| 134 |
+
evaluation of LLM safety, security, and privacy.
|
| 135 |
+
</Typography>
|
| 136 |
+
</Box>
|
| 137 |
+
<Box sx={styles.mainBox}>
|
| 138 |
+
<div>
|
| 139 |
+
<Box sx={styles.main}>
|
| 140 |
+
{items.map(({ icon, title, description }, index) => (
|
| 141 |
+
<Box
|
| 142 |
+
key={index}
|
| 143 |
+
component={Button}
|
| 144 |
+
onClick={() => handleItemClick(index)}
|
| 145 |
+
sx={[
|
| 146 |
+
(theme) => ({
|
| 147 |
+
p: 2,
|
| 148 |
+
height: "100%",
|
| 149 |
+
width: "100%",
|
| 150 |
+
"&:hover": {
|
| 151 |
+
backgroundColor: theme.palette.action.hover,
|
| 152 |
+
},
|
| 153 |
+
}),
|
| 154 |
+
selectedItemIdx === index && {
|
| 155 |
+
backgroundColor: "action.selected",
|
| 156 |
+
},
|
| 157 |
+
]}
|
| 158 |
+
>
|
| 159 |
+
<Box
|
| 160 |
+
sx={{
|
| 161 |
+
color:
|
| 162 |
+
selectedItemIdx === index
|
| 163 |
+
? "text.primary"
|
| 164 |
+
: "text.secondary",
|
| 165 |
+
...styles.descriptionBox,
|
| 166 |
+
}}
|
| 167 |
+
>
|
| 168 |
+
{icon}
|
| 169 |
+
<Typography variant="h6">{title}</Typography>
|
| 170 |
+
<Typography variant="body2">{description}</Typography>
|
| 171 |
+
</Box>
|
| 172 |
+
</Box>
|
| 173 |
+
))}
|
| 174 |
+
</Box>
|
| 175 |
+
<MobileLayout
|
| 176 |
+
selectedItemIdx={selectedItemIdx}
|
| 177 |
+
selectedImageIdx={selectedImageIdx}
|
| 178 |
+
handleItemClick={handleItemClick}
|
| 179 |
+
selectedFeature={selectedFeature}
|
| 180 |
+
/>
|
| 181 |
+
</div>
|
| 182 |
+
<Box sx={styles.mobileBox}>
|
| 183 |
+
<Card variant="outlined" sx={styles.mobileCard}>
|
| 184 |
+
<Box
|
| 185 |
+
sx={(theme) => ({
|
| 186 |
+
...styles.desktopImageBox,
|
| 187 |
+
backgroundImage: `url("${
|
| 188 |
+
theme.palette.mode === "dark"
|
| 189 |
+
? selectedFeature.imageDark[
|
| 190 |
+
selectedImageIdx % selectedFeature.imageDark.length
|
| 191 |
+
]
|
| 192 |
+
: selectedFeature.imageLight[
|
| 193 |
+
selectedImageIdx % selectedFeature.imageLight.length
|
| 194 |
+
]
|
| 195 |
+
}")`,
|
| 196 |
+
})}
|
| 197 |
+
/>
|
| 198 |
+
</Card>
|
| 199 |
+
</Box>
|
| 200 |
+
</Box>
|
| 201 |
+
</Container>
|
| 202 |
+
);
|
| 203 |
+
}
|
src/features/landing/Hero/Hero-styles.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { alpha } from '@mui/material';
|
| 2 |
+
|
| 3 |
+
export const styles = {
|
| 4 |
+
backgroundBox: {
|
| 5 |
+
width: '100%',
|
| 6 |
+
backgroundImage: (theme) =>
|
| 7 |
+
theme.palette.mode === 'light'
|
| 8 |
+
? 'linear-gradient(180deg, #CEE5FD, #FFF)'
|
| 9 |
+
: `linear-gradient(#02294F, ${alpha('#090E10', 0.0)})`,
|
| 10 |
+
backgroundSize: { xs: '100% 80px', sm: '100% 96px' },
|
| 11 |
+
backgroundRepeat: 'no-repeat',
|
| 12 |
+
},
|
| 13 |
+
root: {
|
| 14 |
+
display: 'flex',
|
| 15 |
+
flexDirection: 'column',
|
| 16 |
+
alignItems: 'center',
|
| 17 |
+
pt: { xs: 20, sm: 28 },
|
| 18 |
+
},
|
| 19 |
+
description: {
|
| 20 |
+
alignSelf: 'center',
|
| 21 |
+
width: { sm: '100%', md: '80%' },
|
| 22 |
+
textAlign: 'center',
|
| 23 |
+
color: 'text.secondary',
|
| 24 |
+
},
|
| 25 |
+
title: {
|
| 26 |
+
display: 'flex',
|
| 27 |
+
flexDirection: { xs: 'column', md: 'column' },
|
| 28 |
+
alignSelf: 'center',
|
| 29 |
+
textAlign: 'center',
|
| 30 |
+
fontSize: 'clamp(1.25rem, 8vw, 2.5rem)',
|
| 31 |
+
},
|
| 32 |
+
heroStack: { width: { xs: '100%', sm: '70%' } },
|
| 33 |
+
subtitle: {
|
| 34 |
+
fontSize: 'clamp(1.25rem, 8vw, 2.5rem)',
|
| 35 |
+
color: (theme) => (theme.palette.mode === 'light' ? 'primary.main' : 'primary.light'),
|
| 36 |
+
},
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
export default styles;
|
src/features/landing/Hero/Hero.jsx
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Box, Container, Stack, Typography, Link } from "@mui/material";
|
| 2 |
+
|
| 3 |
+
import styles from "./Hero-styles";
|
| 4 |
+
|
| 5 |
+
export const Hero = () => {
|
| 6 |
+
return (
|
| 7 |
+
<Box id="hero" sx={styles.backgroundBox}>
|
| 8 |
+
<Container sx={styles.root}>
|
| 9 |
+
<Stack spacing={2} useFlexGap sx={styles.title}>
|
| 10 |
+
<Typography variant="h1" sx={styles.title}>
|
| 11 |
+
{/* Safety, Security, & Privacy Evaluation of LLMs */}
|
| 12 |
+
LLM Safety & Security
|
| 13 |
+
{/* & Privacy */}
|
| 14 |
+
<Typography component="span" variant="h1" sx={styles.subtitle}>
|
| 15 |
+
Simplified
|
| 16 |
+
</Typography>
|
| 17 |
+
</Typography>
|
| 18 |
+
<Typography sx={styles.description}>
|
| 19 |
+
Examines LLMs for a wide range of safety risks and security
|
| 20 |
+
vulnerabilities across nine evaluation services spanning Safety &
|
| 21 |
+
Reliability, Security & Robustness, and Privacy & Fairness
|
| 22 |
+
dimensions. You can explore detailed model evaluation reports, or
|
| 23 |
+
submit and run your own examinations. Visit{" "}
|
| 24 |
+
<Link
|
| 25 |
+
href="https://aixamine.qcri.org/main"
|
| 26 |
+
target="_blank"
|
| 27 |
+
rel="noopener noreferrer"
|
| 28 |
+
>
|
| 29 |
+
the production system
|
| 30 |
+
</Link>{" "}
|
| 31 |
+
to get started.
|
| 32 |
+
</Typography>
|
| 33 |
+
</Stack>
|
| 34 |
+
</Container>
|
| 35 |
+
</Box>
|
| 36 |
+
);
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
export default Hero;
|
src/features/landing/Landing/Landing.jsx
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Box, Divider, Typography } from "@mui/material";
|
| 2 |
+
import { useDispatch } from "react-redux";
|
| 3 |
+
|
| 4 |
+
import { switchThemeMode } from "../../app/appSlice";
|
| 5 |
+
|
| 6 |
+
import AppAppBar from "../AppAppBar/AppAppBar";
|
| 7 |
+
import FAQ from "../FAQ/FAQ";
|
| 8 |
+
import Features from "../Features/Features";
|
| 9 |
+
import Footer from "../../shared/Footer/Footer";
|
| 10 |
+
import Hero from "../Hero/Hero";
|
| 11 |
+
import Services from "../Services/Services";
|
| 12 |
+
import Leaderboard from "../../main/Leaderboard/Leaderboard";
|
| 13 |
+
import Reference from "../Reference/Reference";
|
| 14 |
+
|
| 15 |
+
export function Landing() {
|
| 16 |
+
const dispatch = useDispatch();
|
| 17 |
+
|
| 18 |
+
const onClickThemeMode = () => {
|
| 19 |
+
dispatch(switchThemeMode());
|
| 20 |
+
};
|
| 21 |
+
|
| 22 |
+
return (
|
| 23 |
+
<div>
|
| 24 |
+
<AppAppBar onClickThemeMode={onClickThemeMode} />
|
| 25 |
+
<Hero />
|
| 26 |
+
<Leaderboard />
|
| 27 |
+
<Divider />
|
| 28 |
+
<Services />
|
| 29 |
+
<Features />
|
| 30 |
+
<Divider />
|
| 31 |
+
<FAQ />
|
| 32 |
+
<Reference />
|
| 33 |
+
<Footer />
|
| 34 |
+
</div>
|
| 35 |
+
);
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
export default Landing;
|
src/features/landing/Reference/Reference-styles.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const styles = {
|
| 2 |
+
root: { width: "100%" },
|
| 3 |
+
referenceBox: { width: "100%" },
|
| 4 |
+
stack: { width: "100%" },
|
| 5 |
+
titleBox: {
|
| 6 |
+
width: { sm: "100%", md: "60%" },
|
| 7 |
+
textAlign: { sm: "left", md: "center" },
|
| 8 |
+
},
|
| 9 |
+
iconBox: { opacity: "50%" },
|
| 10 |
+
rootContainer: {
|
| 11 |
+
position: "relative",
|
| 12 |
+
display: "flex",
|
| 13 |
+
flexDirection: "column",
|
| 14 |
+
alignItems: "center",
|
| 15 |
+
gap: { xs: 3, sm: 6 },
|
| 16 |
+
},
|
| 17 |
+
icon: {
|
| 18 |
+
width: "2.5rem",
|
| 19 |
+
height: "2.5rem",
|
| 20 |
+
},
|
| 21 |
+
contentStack: {
|
| 22 |
+
p: 3,
|
| 23 |
+
color: "inherit",
|
| 24 |
+
height: "100%",
|
| 25 |
+
border: "1px solid",
|
| 26 |
+
borderColor: "grey.800",
|
| 27 |
+
background: "transparent",
|
| 28 |
+
backgroundColor: "grey.900",
|
| 29 |
+
},
|
| 30 |
+
paper: {
|
| 31 |
+
backgroundColor: "grey.900",
|
| 32 |
+
borderColor: "grey.800",
|
| 33 |
+
p: 2.5,
|
| 34 |
+
borderRadius: 2,
|
| 35 |
+
overflowX: "auto",
|
| 36 |
+
maxWidth: "100%",
|
| 37 |
+
},
|
| 38 |
+
citation: {
|
| 39 |
+
m: 0,
|
| 40 |
+
fontFamily: "monospace",
|
| 41 |
+
fontSize: "0.9rem",
|
| 42 |
+
color: "grey.300",
|
| 43 |
+
whiteSpace: "pre",
|
| 44 |
+
},
|
| 45 |
+
description: { color: "grey.400" },
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
export default styles;
|
src/features/landing/Reference/Reference.jsx
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Container, Box, Typography, Paper, Stack } from "@mui/material";
|
| 2 |
+
import styles from "./Reference-styles";
|
| 3 |
+
|
| 4 |
+
const Reference = () => {
|
| 5 |
+
return (
|
| 6 |
+
<Container id="reference" sx={styles.root}>
|
| 7 |
+
<Box sx={styles.referenceBox}>
|
| 8 |
+
<Stack spacing={2} sx={styles.stack}>
|
| 9 |
+
<Typography
|
| 10 |
+
variant="h4"
|
| 11 |
+
sx={{
|
| 12 |
+
letterSpacing: "0.5px",
|
| 13 |
+
}}
|
| 14 |
+
>
|
| 15 |
+
Reference
|
| 16 |
+
</Typography>
|
| 17 |
+
<Paper variant="outlined" sx={styles.paper}>
|
| 18 |
+
<Typography component="pre" sx={styles.citation}>
|
| 19 |
+
{`@article{aixamine2025,
|
| 20 |
+
title={aiXamine: Simplified LLM Safety and Security},
|
| 21 |
+
author={Deniz, Fatih and Popovic, Dorde and Boshmaf, Yazan
|
| 22 |
+
and Jeong, Euisuh and Ahmad, Minhaj
|
| 23 |
+
and Chawla, Sanjay and Khalil, Issa},
|
| 24 |
+
journal={arXiv preprint arXiv:2504.14985},
|
| 25 |
+
year={2025}
|
| 26 |
+
}`}
|
| 27 |
+
</Typography>
|
| 28 |
+
</Paper>
|
| 29 |
+
<Typography sx={{ color: "grey.500", mt: 1 }}>
|
| 30 |
+
Please cite aiXamine if you use our framework in your research.
|
| 31 |
+
</Typography>
|
| 32 |
+
</Stack>
|
| 33 |
+
</Box>
|
| 34 |
+
</Container>
|
| 35 |
+
);
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
export default Reference;
|
src/features/landing/Services/Services-styles.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const styles = {
|
| 2 |
+
root: {
|
| 3 |
+
pt: { xs: 4, sm: 12 },
|
| 4 |
+
pb: { xs: 8, sm: 16 },
|
| 5 |
+
color: 'white',
|
| 6 |
+
bgcolor: '#06090a',
|
| 7 |
+
},
|
| 8 |
+
titleBox: {
|
| 9 |
+
width: { sm: '100%', md: '60%' },
|
| 10 |
+
textAlign: { sm: 'left', md: 'center' },
|
| 11 |
+
},
|
| 12 |
+
iconBox: { opacity: '50%' },
|
| 13 |
+
rootContainer: {
|
| 14 |
+
position: 'relative',
|
| 15 |
+
display: 'flex',
|
| 16 |
+
flexDirection: 'column',
|
| 17 |
+
alignItems: 'center',
|
| 18 |
+
gap: { xs: 3, sm: 6 },
|
| 19 |
+
},
|
| 20 |
+
icon: {
|
| 21 |
+
width: '2.5rem',
|
| 22 |
+
height: '2.5rem',
|
| 23 |
+
},
|
| 24 |
+
contentStack: {
|
| 25 |
+
p: 3,
|
| 26 |
+
color: 'inherit',
|
| 27 |
+
height: '100%',
|
| 28 |
+
border: '1px solid',
|
| 29 |
+
borderColor: 'grey.800',
|
| 30 |
+
background: 'transparent',
|
| 31 |
+
backgroundColor: 'grey.900',
|
| 32 |
+
},
|
| 33 |
+
description: { color: 'grey.400' },
|
| 34 |
+
};
|
| 35 |
+
|
| 36 |
+
export default styles;
|
src/features/landing/Services/Services.jsx
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Box, Card, Container, Grid, Stack, Typography } from "@mui/material";
|
| 2 |
+
import {
|
| 3 |
+
AutoAwesome,
|
| 4 |
+
Balance,
|
| 5 |
+
BarChart,
|
| 6 |
+
DoNotDisturbOn,
|
| 7 |
+
Group,
|
| 8 |
+
LensBlur,
|
| 9 |
+
NoEncryption,
|
| 10 |
+
Policy,
|
| 11 |
+
RemoveRedEye,
|
| 12 |
+
Security,
|
| 13 |
+
Terminal,
|
| 14 |
+
} from "@mui/icons-material";
|
| 15 |
+
|
| 16 |
+
import styles from "./Services-styles";
|
| 17 |
+
import { useGetServiceStatsQuery } from "../../main/statApi";
|
| 18 |
+
|
| 19 |
+
export const Services = () => {
|
| 20 |
+
const { data: statServices = [] } = useGetServiceStatsQuery({
|
| 21 |
+
omitTest: true,
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
const services = Array.isArray(statServices.services)
|
| 25 |
+
? statServices.services
|
| 26 |
+
: [];
|
| 27 |
+
|
| 28 |
+
const serviceIcon = {
|
| 29 |
+
"adversarial-robustness": <Security style={styles.icon} />,
|
| 30 |
+
"backdoor-detection": <RemoveRedEye style={styles.icon} />,
|
| 31 |
+
"code-security": <Terminal style={styles.icon} />,
|
| 32 |
+
"fairness-bias": <Balance style={styles.icon} />,
|
| 33 |
+
hallucination: <LensBlur style={styles.icon} />,
|
| 34 |
+
jailbreak: <NoEncryption style={styles.icon} />,
|
| 35 |
+
"model-data-privacy": <Policy style={styles.icon} />,
|
| 36 |
+
"ood-robustness": <BarChart style={styles.icon} />,
|
| 37 |
+
"over-refusal": <DoNotDisturbOn style={styles.icon} />,
|
| 38 |
+
"safety-alignment": <Group style={styles.icon} />,
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
const title = (
|
| 42 |
+
<Box sx={styles.titleBox}>
|
| 43 |
+
<Typography component="h2" variant="h4">
|
| 44 |
+
Services
|
| 45 |
+
</Typography>
|
| 46 |
+
<Typography variant="body1" sx={styles.description}>
|
| 47 |
+
aiXamine provides a comprehensive set of services to evaluate your LLM
|
| 48 |
+
against a broad range of evolving safety risks and security threats.
|
| 49 |
+
</Typography>
|
| 50 |
+
</Box>
|
| 51 |
+
);
|
| 52 |
+
|
| 53 |
+
const content = (
|
| 54 |
+
<Grid container spacing={2.5}>
|
| 55 |
+
{services.map((item, idx) => (
|
| 56 |
+
<Grid item xs={12} sm={6} md={4} key={idx}>
|
| 57 |
+
<Stack
|
| 58 |
+
direction="column"
|
| 59 |
+
component={Card}
|
| 60 |
+
spacing={1}
|
| 61 |
+
useFlexGap
|
| 62 |
+
sx={styles.contentStack}
|
| 63 |
+
>
|
| 64 |
+
<Box sx={styles.iconBox}>
|
| 65 |
+
{serviceIcon[item.value] ?? <Group style={styles.icon} />}
|
| 66 |
+
</Box>
|
| 67 |
+
<div>
|
| 68 |
+
<Typography fontWeight="medium" gutterBottom>
|
| 69 |
+
{item.name}
|
| 70 |
+
</Typography>
|
| 71 |
+
<Typography variant="body2" sx={styles.description}>
|
| 72 |
+
{item.description}
|
| 73 |
+
</Typography>
|
| 74 |
+
</div>
|
| 75 |
+
</Stack>
|
| 76 |
+
</Grid>
|
| 77 |
+
))}
|
| 78 |
+
<Grid item xs={12} sm={6} md={4}>
|
| 79 |
+
<Stack
|
| 80 |
+
direction="column"
|
| 81 |
+
component={Card}
|
| 82 |
+
spacing={1}
|
| 83 |
+
useFlexGap
|
| 84 |
+
sx={styles.contentStack}
|
| 85 |
+
>
|
| 86 |
+
<Box sx={styles.iconBox}>
|
| 87 |
+
<AutoAwesome style={styles.icon} />
|
| 88 |
+
</Box>
|
| 89 |
+
<div>
|
| 90 |
+
<Typography fontWeight="medium" gutterBottom>
|
| 91 |
+
Coming Soon
|
| 92 |
+
</Typography>
|
| 93 |
+
<Typography variant="body2" sx={styles.description}>
|
| 94 |
+
More services are in development and will be available soon.
|
| 95 |
+
</Typography>
|
| 96 |
+
</div>
|
| 97 |
+
</Stack>
|
| 98 |
+
</Grid>
|
| 99 |
+
</Grid>
|
| 100 |
+
);
|
| 101 |
+
|
| 102 |
+
return (
|
| 103 |
+
<Box id="services" sx={styles.root}>
|
| 104 |
+
<Container sx={styles.rootContainer}>
|
| 105 |
+
{title}
|
| 106 |
+
{content}
|
| 107 |
+
</Container>
|
| 108 |
+
</Box>
|
| 109 |
+
);
|
| 110 |
+
};
|
| 111 |
+
|
| 112 |
+
export default Services;
|
src/features/main/CompareModels/CompareModels-styles.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { alpha } from "@mui/material";
|
| 2 |
+
import { brand, gray } from "../../../constants/theme";
|
| 3 |
+
|
| 4 |
+
const selectMenuBase = (theme) => ({
|
| 5 |
+
maxHeight: 300,
|
| 6 |
+
color:
|
| 7 |
+
theme.palette.mode === "dark"
|
| 8 |
+
? "rgba(76, 89, 103, 0.3)"
|
| 9 |
+
: "rgba(191, 204, 217, 0.5)",
|
| 10 |
+
backgroundColor: theme.palette.mode === "dark" ? "black" : "white",
|
| 11 |
+
boxShadow:
|
| 12 |
+
theme.palette.mode === "dark"
|
| 13 |
+
? "0 0 1px rgba(2, 31, 59, 0.7), 1px 1.5px 2px -1px rgba(2, 31, 59, 0.65), 4px 4px 12px -2.5px rgba(2, 31, 59, 0.65)"
|
| 14 |
+
: "0 0 1px rgba(85, 166, 246, 0.1), 1px 1.5px 2px -1px rgba(85, 166, 246, 0.15), 4px 4px 12px -2.5px rgba(85, 166, 246, 0.15)",
|
| 15 |
+
});
|
| 16 |
+
|
| 17 |
+
export const styles = {
|
| 18 |
+
// root
|
| 19 |
+
root: {
|
| 20 |
+
display: "flex",
|
| 21 |
+
flexDirection: "column",
|
| 22 |
+
justifyContent: "space-between",
|
| 23 |
+
alignItems: "center",
|
| 24 |
+
width: "100%",
|
| 25 |
+
pt: { xs: 4, sm: 12 },
|
| 26 |
+
pb: { xs: 8, sm: 16 },
|
| 27 |
+
},
|
| 28 |
+
cardContainer: { height: "100%" },
|
| 29 |
+
circularBox: {
|
| 30 |
+
display: "flex",
|
| 31 |
+
justifyContent: "center",
|
| 32 |
+
alignItems: "center",
|
| 33 |
+
height: "200px",
|
| 34 |
+
},
|
| 35 |
+
disclaimerText: {
|
| 36 |
+
color: gray[400],
|
| 37 |
+
textAlign: "left",
|
| 38 |
+
pt: 2,
|
| 39 |
+
pl: 0.5,
|
| 40 |
+
pb: 2,
|
| 41 |
+
},
|
| 42 |
+
|
| 43 |
+
// datagrid
|
| 44 |
+
formBox: {
|
| 45 |
+
display: "flex",
|
| 46 |
+
justifyContent: "space-between",
|
| 47 |
+
alignItems: "flex-start",
|
| 48 |
+
width: "100%",
|
| 49 |
+
mb: 2,
|
| 50 |
+
},
|
| 51 |
+
formCard: { p: 3, overflow: "auto", width: "100%" },
|
| 52 |
+
landingText: { color: "text.primary" },
|
| 53 |
+
|
| 54 |
+
formTitle: { fontSize: "22.5px", mb: 2 },
|
| 55 |
+
titleLink: { "&:before": { height: 0 } },
|
| 56 |
+
datagrid: {
|
| 57 |
+
"& .MuiDataGrid-columnHeaderTitle": {
|
| 58 |
+
fontWeight: "600",
|
| 59 |
+
},
|
| 60 |
+
"& .MuiDataGrid-columnHeader": {
|
| 61 |
+
backgroundColor: (theme) =>
|
| 62 |
+
theme.palette.mode === "light"
|
| 63 |
+
? alpha(brand[500], 0.08)
|
| 64 |
+
: alpha(brand[400], 0.16),
|
| 65 |
+
borderBottom: "2px solid",
|
| 66 |
+
borderColor: (theme) => theme.palette.divider,
|
| 67 |
+
"&:hover": { outline: "none" },
|
| 68 |
+
"&:focus-within": { outline: "none" },
|
| 69 |
+
},
|
| 70 |
+
"& .MuiDataGrid-cell": {
|
| 71 |
+
"&:hover": { outline: "none" },
|
| 72 |
+
"&:focus-within": { outline: "none" },
|
| 73 |
+
},
|
| 74 |
+
"& .MuiDataGrid-cellContent": {
|
| 75 |
+
overflow: "hidden",
|
| 76 |
+
textOverflow: "ellipsis",
|
| 77 |
+
whiteSpace: "nowrap",
|
| 78 |
+
minWidth: 0,
|
| 79 |
+
},
|
| 80 |
+
"& .MuiDataGrid-main": {
|
| 81 |
+
borderRadius: "10px",
|
| 82 |
+
border: "1px solid",
|
| 83 |
+
borderColor: (theme) =>
|
| 84 |
+
theme.palette.mode === "light"
|
| 85 |
+
? alpha(brand[500], 0.08)
|
| 86 |
+
: alpha(brand[400], 0.16),
|
| 87 |
+
},
|
| 88 |
+
"& .MuiDataGrid-row": {
|
| 89 |
+
bgcolor: (theme) =>
|
| 90 |
+
theme.palette.mode === "light"
|
| 91 |
+
? "rgba(255, 255, 255, 0.4)"
|
| 92 |
+
: "rgba(0, 0, 0, 0.4)",
|
| 93 |
+
},
|
| 94 |
+
"& .MuiDataGrid-row:hover": {
|
| 95 |
+
cursor: "pointer",
|
| 96 |
+
},
|
| 97 |
+
},
|
| 98 |
+
datagridFooterIcon: { fontSize: "18px" },
|
| 99 |
+
datagridScoreCell: {
|
| 100 |
+
textAlign: "right",
|
| 101 |
+
display: "block",
|
| 102 |
+
width: "100%",
|
| 103 |
+
overflow: "hidden",
|
| 104 |
+
textOverflow: "ellipsis",
|
| 105 |
+
whiteSpace: "nowrap",
|
| 106 |
+
},
|
| 107 |
+
datagridModelName: {
|
| 108 |
+
display: "flex",
|
| 109 |
+
alignItems: "center",
|
| 110 |
+
width: "100%",
|
| 111 |
+
minWidth: 0,
|
| 112 |
+
gap: 0.5,
|
| 113 |
+
},
|
| 114 |
+
datagridModelText: {
|
| 115 |
+
flex: 1,
|
| 116 |
+
minWidth: 0,
|
| 117 |
+
overflow: "hidden",
|
| 118 |
+
textOverflow: "ellipsis",
|
| 119 |
+
whiteSpace: "nowrap",
|
| 120 |
+
},
|
| 121 |
+
datagridModelIcon: { width: 16, height: 16, marginRight: 4 },
|
| 122 |
+
|
| 123 |
+
select: (theme) => ({
|
| 124 |
+
borderRadius: "10px",
|
| 125 |
+
height: "40px",
|
| 126 |
+
"& .MuiSelect-select": {
|
| 127 |
+
borderColor:
|
| 128 |
+
theme.palette.mode === "dark"
|
| 129 |
+
? "rgba(76, 89, 103, 0.3)"
|
| 130 |
+
: "rgba(191, 204, 217, 0.5)",
|
| 131 |
+
backgroundColor: "transparent",
|
| 132 |
+
whiteSpace: "nowrap",
|
| 133 |
+
},
|
| 134 |
+
}),
|
| 135 |
+
selectMenu: selectMenuBase,
|
| 136 |
+
selectMenuModels: (theme) => ({
|
| 137 |
+
...selectMenuBase(theme),
|
| 138 |
+
width: "auto",
|
| 139 |
+
[theme.breakpoints.up("lg")]: {
|
| 140 |
+
width: "28ch",
|
| 141 |
+
},
|
| 142 |
+
}),
|
| 143 |
+
selectMenuServices: (theme) => ({
|
| 144 |
+
...selectMenuBase(theme),
|
| 145 |
+
width: "auto",
|
| 146 |
+
[theme.breakpoints.up("lg")]: {
|
| 147 |
+
width: "30ch",
|
| 148 |
+
},
|
| 149 |
+
}),
|
| 150 |
+
selectMenuItem: (theme) => ({
|
| 151 |
+
height: "32px",
|
| 152 |
+
minHeight: "32px",
|
| 153 |
+
borderColor:
|
| 154 |
+
theme.palette.mode === "dark"
|
| 155 |
+
? "rgba(76, 89, 103, 0.3)"
|
| 156 |
+
: "rgba(191, 204, 217, 0.5)",
|
| 157 |
+
backgroundColor: theme.palette.mode === "dark" ? "black" : "white",
|
| 158 |
+
"&.Mui-selected": {
|
| 159 |
+
backgroundColor: theme.palette.mode === "dark" ? "black" : "white",
|
| 160 |
+
},
|
| 161 |
+
}),
|
| 162 |
+
selectMenuServiceItem: (theme) => ({
|
| 163 |
+
height: "32px",
|
| 164 |
+
minHeight: "32px",
|
| 165 |
+
maxHeight: "32px",
|
| 166 |
+
pl: 4,
|
| 167 |
+
borderColor:
|
| 168 |
+
theme.palette.mode === "dark"
|
| 169 |
+
? "rgba(76, 89, 103, 0.3)"
|
| 170 |
+
: "rgba(191, 204, 217, 0.5)",
|
| 171 |
+
backgroundColor: theme.palette.mode === "dark" ? "black" : "white",
|
| 172 |
+
"&.Mui-selected": {
|
| 173 |
+
backgroundColor: theme.palette.mode === "dark" ? "black" : "white",
|
| 174 |
+
},
|
| 175 |
+
}),
|
| 176 |
+
|
| 177 |
+
filterFormSources: { width: { xs: "100%", lg: "18ch" } },
|
| 178 |
+
filterFormModels: { width: { xs: "100%", lg: "26ch" } },
|
| 179 |
+
filterFormServices: { width: { xs: "100%", lg: "30ch" } },
|
| 180 |
+
filterFormCheck: { padding: "4px" },
|
| 181 |
+
filterLabel: {
|
| 182 |
+
display: "flex",
|
| 183 |
+
alignItems: "center",
|
| 184 |
+
fontWeight: 500,
|
| 185 |
+
},
|
| 186 |
+
filterControlGroup: (theme) => ({
|
| 187 |
+
display: "flex",
|
| 188 |
+
alignItems: "center",
|
| 189 |
+
gap: 0.75,
|
| 190 |
+
flex: "0 0 auto",
|
| 191 |
+
[theme.breakpoints.down("lg")]: {
|
| 192 |
+
width: "100%",
|
| 193 |
+
flex: "1 1 100%",
|
| 194 |
+
},
|
| 195 |
+
}),
|
| 196 |
+
filterStepBadge: (theme) => {
|
| 197 |
+
const background = theme.palette.mode === "light" ? brand[500] : brand[300];
|
| 198 |
+
return {
|
| 199 |
+
display: "inline-flex",
|
| 200 |
+
alignItems: "center",
|
| 201 |
+
justifyContent: "center",
|
| 202 |
+
width: 28,
|
| 203 |
+
height: 28,
|
| 204 |
+
borderRadius: "50%",
|
| 205 |
+
fontSize: 14,
|
| 206 |
+
fontWeight: 600,
|
| 207 |
+
lineHeight: 1,
|
| 208 |
+
flexShrink: 0,
|
| 209 |
+
backgroundColor: background,
|
| 210 |
+
color: theme.palette.getContrastText(background),
|
| 211 |
+
};
|
| 212 |
+
},
|
| 213 |
+
filterPanel: (theme) => ({
|
| 214 |
+
mb: 2,
|
| 215 |
+
display: "flex",
|
| 216 |
+
alignItems: "center",
|
| 217 |
+
flexDirection: "row",
|
| 218 |
+
flexWrap: "nowrap",
|
| 219 |
+
columnGap: theme.spacing(3),
|
| 220 |
+
[theme.breakpoints.down("lg")]: {
|
| 221 |
+
flexDirection: "column",
|
| 222 |
+
alignItems: "stretch",
|
| 223 |
+
rowGap: 2,
|
| 224 |
+
},
|
| 225 |
+
}),
|
| 226 |
+
|
| 227 |
+
gridContainer: { overflow: "auto", mt: -1 },
|
| 228 |
+
gridItem: { mt: 1 },
|
| 229 |
+
learnMoreLink: {
|
| 230 |
+
color: brand[300],
|
| 231 |
+
},
|
| 232 |
+
|
| 233 |
+
// report
|
| 234 |
+
reportCard: { p: 3, overflow: "auto", flex: 1, minHeight: "755px" },
|
| 235 |
+
reportList: {
|
| 236 |
+
pt: 0,
|
| 237 |
+
mb: -1,
|
| 238 |
+
backgroundColor: "transparent",
|
| 239 |
+
},
|
| 240 |
+
reportListSubheader: {
|
| 241 |
+
color: (theme) =>
|
| 242 |
+
theme.palette.mode === "light" ? brand[500] : brand[300],
|
| 243 |
+
fontWeight: 500,
|
| 244 |
+
px: 0,
|
| 245 |
+
mt: -1.75,
|
| 246 |
+
mb: -1,
|
| 247 |
+
fontSize: "16px",
|
| 248 |
+
},
|
| 249 |
+
|
| 250 |
+
// metric
|
| 251 |
+
metricBox: { textAlign: "center" },
|
| 252 |
+
metricCard: { p: 3, overflow: "auto", width: "100%", mb: { xs: 3, sm: 4 } },
|
| 253 |
+
metricLabel: { fontSize: "14px", color: "text.secondary" },
|
| 254 |
+
metricLabelBox: { display: "flex", alignItems: "flex-start", fontSize: 14 },
|
| 255 |
+
metricLabelIcon: { ml: 0.5, fontSize: 14 },
|
| 256 |
+
metricNumber: {
|
| 257 |
+
fontSize: "18px",
|
| 258 |
+
color: (theme) =>
|
| 259 |
+
theme.palette.mode === "light" ? brand[500] : brand[300],
|
| 260 |
+
},
|
| 261 |
+
|
| 262 |
+
searchField: {
|
| 263 |
+
mb: { xs: 3, sm: 4 },
|
| 264 |
+
borderRadius: "10px",
|
| 265 |
+
boxShadow: (theme) =>
|
| 266 |
+
theme.palette.mode === "light"
|
| 267 |
+
? `0 0 1px rgba(85, 166, 246, 0.1), 1px 1.5px 2px -1px rgba(85, 166, 246, 0.15), 4px 4px 12px -2.5px rgba(85, 166, 246, 0.15)`
|
| 268 |
+
: "0 0 1px rgba(2, 31, 59, 0.7), 1px 1.5px 2px -1px rgba(2, 31, 59, 0.65), 4px 4px 12px -2.5px rgba(2, 31, 59, 0.65)",
|
| 269 |
+
},
|
| 270 |
+
searchFieldIcon: { ml: -1 },
|
| 271 |
+
searchFieldCloseIcon: { mr: -1 },
|
| 272 |
+
|
| 273 |
+
tooltipBox: { display: "flex", alignItems: "center" },
|
| 274 |
+
tooltipText: {
|
| 275 |
+
ml: 1,
|
| 276 |
+
whiteSpace: "nowrap",
|
| 277 |
+
overflow: "hidden",
|
| 278 |
+
textOverflow: "ellipsis",
|
| 279 |
+
},
|
| 280 |
+
};
|
| 281 |
+
|
| 282 |
+
export default styles;
|
src/features/main/CompareModels/CompareModelsFullDialog/CompareModelsFullDialog-styles.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { alpha } from '@mui/material';
|
| 2 |
+
import { brand } from '../../../../constants/theme';
|
| 3 |
+
|
| 4 |
+
export const styles = {
|
| 5 |
+
circularBox: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '200px' },
|
| 6 |
+
closeButton: { p: 0 },
|
| 7 |
+
|
| 8 |
+
// datagrid
|
| 9 |
+
formBox: {
|
| 10 |
+
display: 'flex',
|
| 11 |
+
justifyContent: 'space-between',
|
| 12 |
+
alignItems: 'center',
|
| 13 |
+
width: '100%',
|
| 14 |
+
mb: 2,
|
| 15 |
+
},
|
| 16 |
+
|
| 17 |
+
// dialog
|
| 18 |
+
dialogRoot: { '& .MuiDialog-paper': { padding: { sm: 1, md: 2 } }, backdropFilter: 'blur(24px)' },
|
| 19 |
+
dialogPaper: {
|
| 20 |
+
margin: '40px',
|
| 21 |
+
width: 'calc(100% - 80px)',
|
| 22 |
+
height: 'calc(100% - 80px)',
|
| 23 |
+
maxWidth: 'calc(100% - 80px)',
|
| 24 |
+
maxHeight: 'calc(100% - 80px)',
|
| 25 |
+
|
| 26 |
+
backdropFilter: 'blur(24px)',
|
| 27 |
+
bgcolor: (theme) =>
|
| 28 |
+
theme.palette.mode === 'light' ? 'rgba(255, 255, 255, 1)' : 'rgba(0, 0, 0, 0.4)',
|
| 29 |
+
boxShadow: (theme) =>
|
| 30 |
+
theme.palette.mode === 'light'
|
| 31 |
+
? `0 0 1px rgba(85, 166, 246, 0.1), 1px 1.5px 2px -1px rgba(85, 166, 246, 0.15), 4px 4px 12px -2.5px rgba(85, 166, 246, 0.15)`
|
| 32 |
+
: '0 0 1px rgba(2, 31, 59, 0.7), 1px 1.5px 2px -1px rgba(2, 31, 59, 0.65), 4px 4px 12px -2.5px rgba(2, 31, 59, 0.65)',
|
| 33 |
+
borderRadius: '10px',
|
| 34 |
+
border: '1px solid',
|
| 35 |
+
borderColor: 'divider',
|
| 36 |
+
backgroundImage: 'none',
|
| 37 |
+
},
|
| 38 |
+
|
| 39 |
+
formTitle: { fontSize: '22.5px' },
|
| 40 |
+
datagrid: {
|
| 41 |
+
'& .MuiDataGrid-columnHeaderTitle': {
|
| 42 |
+
fontWeight: '600',
|
| 43 |
+
},
|
| 44 |
+
'& .MuiDataGrid-columnHeader': {
|
| 45 |
+
backgroundColor: (theme) =>
|
| 46 |
+
theme.palette.mode === 'light' ? alpha(brand[500], 0.08) : alpha(brand[400], 0.16),
|
| 47 |
+
borderBottom: '2px solid',
|
| 48 |
+
borderColor: (theme) => theme.palette.divider,
|
| 49 |
+
'&:hover': { outline: 'none' },
|
| 50 |
+
'&:focus-within': { outline: 'none' },
|
| 51 |
+
},
|
| 52 |
+
'& .MuiDataGrid-cell': {
|
| 53 |
+
'&:hover': { outline: 'none' },
|
| 54 |
+
'&:focus-within': { outline: 'none' },
|
| 55 |
+
},
|
| 56 |
+
'& .MuiDataGrid-cellContent': {
|
| 57 |
+
overflow: 'hidden',
|
| 58 |
+
textOverflow: 'ellipsis',
|
| 59 |
+
whiteSpace: 'nowrap',
|
| 60 |
+
minWidth: 0,
|
| 61 |
+
},
|
| 62 |
+
'& .MuiDataGrid-main': {
|
| 63 |
+
borderRadius: '10px',
|
| 64 |
+
border: '1px solid',
|
| 65 |
+
borderColor: (theme) =>
|
| 66 |
+
theme.palette.mode === 'light' ? alpha(brand[500], 0.08) : alpha(brand[400], 0.16),
|
| 67 |
+
},
|
| 68 |
+
'& .MuiDataGrid-row': {
|
| 69 |
+
bgcolor: (theme) =>
|
| 70 |
+
theme.palette.mode === 'light' ? 'rgba(255, 255, 255, 0.4)' : 'rgba(0, 0, 0, 0.4)',
|
| 71 |
+
},
|
| 72 |
+
},
|
| 73 |
+
datagridFooterIcon: { fontSize: '18px' },
|
| 74 |
+
datagridScoreCell: {
|
| 75 |
+
textAlign: 'right',
|
| 76 |
+
display: 'block',
|
| 77 |
+
width: '100%',
|
| 78 |
+
overflow: 'hidden',
|
| 79 |
+
textOverflow: 'ellipsis',
|
| 80 |
+
whiteSpace: 'nowrap',
|
| 81 |
+
},
|
| 82 |
+
datagridModelName: {
|
| 83 |
+
display: 'flex',
|
| 84 |
+
alignItems: 'center',
|
| 85 |
+
width: '100%',
|
| 86 |
+
minWidth: 0,
|
| 87 |
+
gap: 0.5,
|
| 88 |
+
},
|
| 89 |
+
datagridModelText: {
|
| 90 |
+
flex: 1,
|
| 91 |
+
minWidth: 0,
|
| 92 |
+
overflow: 'hidden',
|
| 93 |
+
textOverflow: 'ellipsis',
|
| 94 |
+
whiteSpace: 'nowrap',
|
| 95 |
+
},
|
| 96 |
+
datagridModelIcon: { width: 16, height: 16, marginRight: 4 },
|
| 97 |
+
|
| 98 |
+
select: (theme) => ({
|
| 99 |
+
borderRadius: '10px',
|
| 100 |
+
height: '40px',
|
| 101 |
+
'& .MuiSelect-select': {
|
| 102 |
+
borderColor:
|
| 103 |
+
theme.palette.mode === 'dark' ? 'rgba(76, 89, 103, 0.3)' : 'rgba(191, 204, 217, 0.5)',
|
| 104 |
+
backgroundColor: 'transparent',
|
| 105 |
+
},
|
| 106 |
+
}),
|
| 107 |
+
selectMenu: (theme) => ({
|
| 108 |
+
maxHeight: 300,
|
| 109 |
+
color: theme.palette.mode === 'dark' ? 'rgba(76, 89, 103, 0.3)' : 'rgba(191, 204, 217, 0.5)',
|
| 110 |
+
backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white',
|
| 111 |
+
boxShadow:
|
| 112 |
+
theme.palette.mode === 'dark'
|
| 113 |
+
? '0 0 1px rgba(2, 31, 59, 0.7), 1px 1.5px 2px -1px rgba(2, 31, 59, 0.65), 4px 4px 12px -2.5px rgba(2, 31, 59, 0.65)'
|
| 114 |
+
: '0 0 1px rgba(85, 166, 246, 0.1), 1px 1.5px 2px -1px rgba(85, 166, 246, 0.15), 4px 4px 12px -2.5px rgba(85, 166, 246, 0.15)',
|
| 115 |
+
}),
|
| 116 |
+
selectMenuItem: (theme) => ({
|
| 117 |
+
height: '32px',
|
| 118 |
+
minHeight: '32px',
|
| 119 |
+
borderColor:
|
| 120 |
+
theme.palette.mode === 'dark' ? 'rgba(76, 89, 103, 0.3)' : 'rgba(191, 204, 217, 0.5)',
|
| 121 |
+
backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white',
|
| 122 |
+
'&.Mui-selected': {
|
| 123 |
+
backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white',
|
| 124 |
+
},
|
| 125 |
+
}),
|
| 126 |
+
selectMenuServiceItem: (theme) => ({
|
| 127 |
+
height: '32px',
|
| 128 |
+
minHeight: '32px',
|
| 129 |
+
maxHeight: '32px',
|
| 130 |
+
pl: 4,
|
| 131 |
+
borderColor:
|
| 132 |
+
theme.palette.mode === 'dark' ? 'rgba(76, 89, 103, 0.3)' : 'rgba(191, 204, 217, 0.5)',
|
| 133 |
+
backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white',
|
| 134 |
+
'&.Mui-selected': {
|
| 135 |
+
backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white',
|
| 136 |
+
},
|
| 137 |
+
}),
|
| 138 |
+
|
| 139 |
+
filterForm: { minWidth: 180 },
|
| 140 |
+
filterFormCheck: { padding: '4px' },
|
| 141 |
+
filterPanel: (theme) => ({
|
| 142 |
+
mb: 2,
|
| 143 |
+
display: 'flex',
|
| 144 |
+
alignItems: 'center',
|
| 145 |
+
flexDirection: 'row',
|
| 146 |
+
flexWrap: 'nowrap',
|
| 147 |
+
columnGap: theme.spacing(3),
|
| 148 |
+
[theme.breakpoints.down('lg')]: {
|
| 149 |
+
flexDirection: 'column',
|
| 150 |
+
alignItems: 'stretch',
|
| 151 |
+
rowGap: 2,
|
| 152 |
+
},
|
| 153 |
+
}),
|
| 154 |
+
filterControlGroup: (theme) => ({
|
| 155 |
+
display: 'flex',
|
| 156 |
+
alignItems: 'center',
|
| 157 |
+
gap: 0.75,
|
| 158 |
+
flex: '0 0 auto',
|
| 159 |
+
[theme.breakpoints.down('lg')]: {
|
| 160 |
+
width: '100%',
|
| 161 |
+
flex: '1 1 100%',
|
| 162 |
+
},
|
| 163 |
+
}),
|
| 164 |
+
filterStepBadge: (theme) => {
|
| 165 |
+
const background = theme.palette.mode === 'light' ? brand[500] : brand[300];
|
| 166 |
+
return {
|
| 167 |
+
display: 'inline-flex',
|
| 168 |
+
alignItems: 'center',
|
| 169 |
+
justifyContent: 'center',
|
| 170 |
+
width: 28,
|
| 171 |
+
height: 28,
|
| 172 |
+
borderRadius: '50%',
|
| 173 |
+
fontSize: 14,
|
| 174 |
+
fontWeight: 600,
|
| 175 |
+
lineHeight: 1,
|
| 176 |
+
flexShrink: 0,
|
| 177 |
+
backgroundColor: background,
|
| 178 |
+
color: theme.palette.getContrastText(background),
|
| 179 |
+
};
|
| 180 |
+
},
|
| 181 |
+
};
|
| 182 |
+
|
| 183 |
+
export default styles;
|