From 213cef22f71454895a4a69101349c94334219f38 Mon Sep 17 00:00:00 2001 From: yuzhantian <2205129388@qq.com> Date: Fri, 24 Apr 2026 16:08:37 +0800 Subject: [PATCH] =?UTF-8?q?0424=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 18 + .gitignore | 56 +- .prettierrc.js | 6 + .vite/deps/_metadata.json | 8 + .vite/deps/package.json | 3 + .vite/deps_temp_7089090e/package.json | 3 + README.md | 2 - design/BaseInfo.md | 65 ++ design/{meta => }/DESIGN.md | 0 design/Page.md | 131 +++ design/figma/DESIGN.md | 220 ---- design/figma/README.md | 24 - design/figma/preview-dark.html | 822 ------------- design/figma/preview.html | 832 ------------- design/mintlify/DESIGN.md | 326 ------ design/mintlify/README.md | 24 - design/mintlify/preview-dark.html | 409 ------- design/mintlify/preview.html | 398 ------- design/pages/auth.md | 82 ++ design/pages/project.md | 38 + design/pages/setting.md | 37 + design/pages/systemLayout.md | 39 + design/stripe/DESIGN.md | 322 ----- design/stripe/README.md | 24 - design/stripe/preview-dark.html | 428 ------- design/stripe/preview.html | 419 ------- design/verge/DESIGN-dark.md | 373 ------ design/verge/DESIGN.md | 315 ----- design/verge/preview-dark.html | 1239 -------------------- design/verge/preview.html | 1145 ------------------ index.html | 2 +- package-lock.json | 1483 +++++++++++++----------- package.json | 34 +- postcss.config.js | 6 + src/App.css | 26 - src/App.tsx | 28 +- src/assets/react.svg | 1 - src/components/AIChatPanel.css | 528 --------- src/components/AIChatPanel.tsx | 313 ----- src/components/ConnectionLines.tsx | 93 -- src/components/ContextModal.css | 224 ---- src/components/ContextModal.tsx | 91 -- src/components/DesignFrame.tsx | 735 ------------ src/components/Icons.tsx | 170 --- src/components/LanguageSwitchModal.css | 194 ---- src/components/LanguageSwitchModal.tsx | 78 -- src/components/SideBar.css | 475 -------- src/components/SideBar.tsx | 225 ---- src/components/TopBar.css | 116 -- src/components/TopBar.tsx | 46 - src/components/layout/Layout.tsx | 109 ++ src/components/ui/Button.tsx | 62 + src/components/ui/Checkbox.tsx | 25 + src/components/ui/Icon.tsx | 61 + src/components/ui/Input.tsx | 49 + src/constants/language.ts | 13 - src/i18n/en.json | 167 +++ src/i18n/index.ts | 47 +- src/i18n/keys.ts | 27 - src/i18n/zh.json | 167 +++ src/index.css | 681 +---------- src/main.tsx | 8 +- src/messages/en.json | 184 --- src/messages/zh.json | 184 --- src/pages/app/CanvasArea.css | 973 ---------------- src/pages/app/CanvasArea.tsx | 794 ------------- src/pages/app/MainApp.tsx | 106 -- src/pages/app/Projects.tsx | 129 --- src/pages/auth/Auth.css | 225 ---- src/pages/auth/ForgotPassword.tsx | 181 +++ src/pages/auth/Login.tsx | 191 ++- src/pages/auth/Register.tsx | 214 ++-- src/pages/dashboard/Dashboard.tsx | 121 ++ src/pages/projects/ProjectList.tsx | 384 ++++++ src/pages/settings/Settings.tsx | 334 ++++++ src/routes.tsx | 21 + src/services/api.ts | 45 - src/services/designs.ts | 62 - src/services/queryClient.ts | 15 - src/types/canvas.types.ts | 128 -- src/utils/gridLayout.ts | 434 ------- src/vite-env.d.ts | 6 - tailwind.config.js | 76 ++ 生成页面提示词.md | 112 +- 84 files changed, 3340 insertions(+), 15671 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .prettierrc.js create mode 100644 .vite/deps/_metadata.json create mode 100644 .vite/deps/package.json create mode 100644 .vite/deps_temp_7089090e/package.json delete mode 100644 README.md create mode 100644 design/BaseInfo.md rename design/{meta => }/DESIGN.md (100%) create mode 100644 design/Page.md delete mode 100644 design/figma/DESIGN.md delete mode 100644 design/figma/README.md delete mode 100644 design/figma/preview-dark.html delete mode 100644 design/figma/preview.html delete mode 100644 design/mintlify/DESIGN.md delete mode 100644 design/mintlify/README.md delete mode 100644 design/mintlify/preview-dark.html delete mode 100644 design/mintlify/preview.html create mode 100644 design/pages/auth.md create mode 100644 design/pages/project.md create mode 100644 design/pages/setting.md create mode 100644 design/pages/systemLayout.md delete mode 100644 design/stripe/DESIGN.md delete mode 100644 design/stripe/README.md delete mode 100644 design/stripe/preview-dark.html delete mode 100644 design/stripe/preview.html delete mode 100644 design/verge/DESIGN-dark.md delete mode 100644 design/verge/DESIGN.md delete mode 100644 design/verge/preview-dark.html delete mode 100644 design/verge/preview.html create mode 100644 postcss.config.js delete mode 100644 src/App.css delete mode 100644 src/assets/react.svg delete mode 100644 src/components/AIChatPanel.css delete mode 100644 src/components/AIChatPanel.tsx delete mode 100644 src/components/ConnectionLines.tsx delete mode 100644 src/components/ContextModal.css delete mode 100644 src/components/ContextModal.tsx delete mode 100644 src/components/DesignFrame.tsx delete mode 100644 src/components/Icons.tsx delete mode 100644 src/components/LanguageSwitchModal.css delete mode 100644 src/components/LanguageSwitchModal.tsx delete mode 100644 src/components/SideBar.css delete mode 100644 src/components/SideBar.tsx delete mode 100644 src/components/TopBar.css delete mode 100644 src/components/TopBar.tsx create mode 100644 src/components/layout/Layout.tsx create mode 100644 src/components/ui/Button.tsx create mode 100644 src/components/ui/Checkbox.tsx create mode 100644 src/components/ui/Icon.tsx create mode 100644 src/components/ui/Input.tsx delete mode 100644 src/constants/language.ts create mode 100644 src/i18n/en.json delete mode 100644 src/i18n/keys.ts create mode 100644 src/i18n/zh.json delete mode 100644 src/messages/en.json delete mode 100644 src/messages/zh.json delete mode 100644 src/pages/app/CanvasArea.css delete mode 100644 src/pages/app/CanvasArea.tsx delete mode 100644 src/pages/app/MainApp.tsx delete mode 100644 src/pages/app/Projects.tsx delete mode 100644 src/pages/auth/Auth.css create mode 100644 src/pages/auth/ForgotPassword.tsx create mode 100644 src/pages/dashboard/Dashboard.tsx create mode 100644 src/pages/projects/ProjectList.tsx create mode 100644 src/pages/settings/Settings.tsx create mode 100644 src/routes.tsx delete mode 100644 src/services/api.ts delete mode 100644 src/services/designs.ts delete mode 100644 src/services/queryClient.ts delete mode 100644 src/types/canvas.types.ts delete mode 100644 src/utils/gridLayout.ts delete mode 100644 src/vite-env.d.ts create mode 100644 tailwind.config.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..acd891a --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.js'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 76901d6..11c0c44 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,27 @@ -# Dependencies -node_modules/ -demo/ - -# Build output -dist/ - # Logs +logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? # Environment variables .env @@ -18,15 +30,25 @@ yarn-error.log* .env.test.local .env.production.local -# Editor directories and files -.vscode/ -.idea/ -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +# Testing +coverage +.nyc_output -# OS files +# Production +build + +# Misc .DS_Store -Thumbs.db \ No newline at end of file +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Package manager +.npm +.yarn-integrity \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..7d519a3 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,6 @@ +module.exports = { + trailingComma: "es5", + tabWidth: 2, + semi: true, + singleQuote: true, +} \ No newline at end of file diff --git a/.vite/deps/_metadata.json b/.vite/deps/_metadata.json new file mode 100644 index 0000000..e1b5791 --- /dev/null +++ b/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "5f8903bf", + "configHash": "996545d1", + "lockfileHash": "e3b0c442", + "browserHash": "9c575c4d", + "optimized": {}, + "chunks": {} +} \ No newline at end of file diff --git a/.vite/deps/package.json b/.vite/deps/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/.vite/deps_temp_7089090e/package.json b/.vite/deps_temp_7089090e/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/.vite/deps_temp_7089090e/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/README.md b/README.md deleted file mode 100644 index 8be0179..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# uitocode - diff --git a/design/BaseInfo.md b/design/BaseInfo.md new file mode 100644 index 0000000..a7e1f0c --- /dev/null +++ b/design/BaseInfo.md @@ -0,0 +1,65 @@ +## 项目结构 +``` +project-root/ +├── design/ # 设计文档 +│ ├── DESIGN.md # 设计规范 +│ └── Page.md # 页面设计 +├── public/ # 静态资源 +├── src/ +│ ├── assets/ # 项目资源文件 +│ │ ├── images/ # 图片资源 +│ │ └── icons/ # 图标资源 +│ ├── components/ # 公共组件 +│ │ ├── ui/ # 基础UI组件 +│ │ └── layout/ # 布局组件 +│ ├── pages/ # 页面组件 +│ │ ├── auth/ # 认证相关页面 +│ │ │ ├── Login.tsx # 登录页面 +│ │ │ └── Register.tsx # 注册页面 +│ │ ├── dashboard/ # 首页 +│ │ ├── project/ # 项目管理 +│ │ │ ├── _components/ # 页面级组件 +│ │ │ ├── ProjectList.tsx # 项目列表 +│ │ │ └── ProjectDetail.tsx # 项目详情 +│ │ └── settings/ # 设置页面 +│ ├── services/ # 服务层 +│ │ ├── api/ # API 调用 +│ │ └── auth/ # 认证服务 +│ ├── utils/ # 工具函数 +│ ├── constants/ # 常量定义 +│ ├── hooks/ # 自定义 hooks +│ ├── types/ # TypeScript 类型定义 +│ ├── i18n/ # 国际化文件 +│ │ ├── en.json # 英语 +│ │ └── zh.json # 中文 +│ ├── App.tsx # 应用入口组件 +│ ├── main.tsx # 入口文件 +│ └── routes.tsx # 路由配置 +├── .gitignore # 忽略文件 +├── .eslintrc.js # ESLint 配置 +├── .prettierrc.js # Prettier 配置 +├── tsconfig.json # TypeScript 配置 +├── vite.config.ts # Vite 配置 +├── package.json # 项目依赖 +└── README.md # 项目说明 +``` + +## 设计规范 +### 整体风格 +- 风格:meta-light 风格,严格按照design/DESIGN.md中的light-mode设计规范 +- 布局:响应式设计,以 1920*1080 分辨率为主 + +### 组件规范 +- 设计规范:严格按照design/DESIGN.md中的设计规范 + +## 国际化 +- 支持语言:中文、英语,默认使用中文 +- 实现方式:i18next +- 翻译文件位置:src/i18n/ +- 组件内使用:useTranslation hook + +## 性能优化 +- 代码分割:使用 React.lazy 和 Suspense +- 状态管理优化:合理使用 memo、useCallback、useMemo +- 图片优化:使用适当的图片格式和大小 +- 网络请求优化:使用 axios 拦截器,合理缓存 \ No newline at end of file diff --git a/design/meta/DESIGN.md b/design/DESIGN.md similarity index 100% rename from design/meta/DESIGN.md rename to design/DESIGN.md diff --git a/design/Page.md b/design/Page.md new file mode 100644 index 0000000..d450e50 --- /dev/null +++ b/design/Page.md @@ -0,0 +1,131 @@ +## 项目结构 +``` +project-root/ +├── design/ # 设计文档 +│ ├── DESIGN.md # 设计规范 +│ └── Page.md # 页面设计 +├── public/ # 静态资源 +├── src/ +│ ├── assets/ # 项目资源文件 +│ │ ├── images/ # 图片资源 +│ │ └── icons/ # 图标资源 +│ ├── components/ # 公共组件 +│ │ ├── ui/ # 基础UI组件 +│ │ └── layout/ # 布局组件 +│ ├── pages/ # 页面组件 +│ │ ├── auth/ # 认证相关页面 +│ │ │ ├── Login.tsx # 登录页面 +│ │ │ └── Register.tsx # 注册页面 +│ │ ├── dashboard/ # 首页 +│ │ ├── project/ # 项目管理 +│ │ │ ├── _components/ # 页面级组件 +│ │ │ ├── ProjectList.tsx # 项目列表 +│ │ │ └── ProjectDetail.tsx # 项目详情 +│ │ └── settings/ # 设置页面 +│ ├── services/ # 服务层 +│ │ ├── api/ # API 调用 +│ │ └── auth/ # 认证服务 +│ ├── utils/ # 工具函数 +│ ├── constants/ # 常量定义 +│ ├── hooks/ # 自定义 hooks +│ ├── types/ # TypeScript 类型定义 +│ ├── i18n/ # 国际化文件 +│ │ ├── en.json # 英语 +│ │ └── zh.json # 中文 +│ ├── App.tsx # 应用入口组件 +│ ├── main.tsx # 入口文件 +│ └── routes.tsx # 路由配置 +├── .gitignore # 忽略文件 +├── .eslintrc.js # ESLint 配置 +├── .prettierrc.js # Prettier 配置 +├── tsconfig.json # TypeScript 配置 +├── vite.config.ts # Vite 配置 +├── package.json # 项目依赖 +└── README.md # 项目说明 +``` + +## 设计规范 +### 整体风格 +- 风格:meta-light 风格,严格按照design/DESIGN.md中的light-mode设计规范 +- 布局:响应式设计,以 1920*1080 分辨率为主 + +### 组件规范 +- 设计规范:严格按照design/DESIGN.md中的设计规范 + +## 数据流转 +- 认证流程: + - 登录 → 验证 credentials → 生成 token → 存储 token → 跳转到首页 + - 注册 → 验证表单 → 创建用户 → 登录 → 跳转到首页 +- 项目流程: + - 创建项目 → 保存到服务器 → 更新项目列表 + - 编辑项目 → 保存到服务器 → 更新项目详情 + - 删除项目 → 确认对话框 → 从服务器删除 → 更新项目列表 + +## 国际化 +- 支持语言:中文、英语,默认使用中文 +- 实现方式:i18next +- 翻译文件位置:src/i18n/ +- 组件内使用:useTranslation hook + +## 安全考虑 +- 密码加密:使用 bcrypt 或类似算法 +- 认证:JWT token +- CSRF 防护:使用 CSRF token +- XSS 防护:使用 React 的内置防护 +- 数据验证:前端和后端双重验证 + +## 性能优化 +- 代码分割:使用 React.lazy 和 Suspense +- 状态管理优化:合理使用 memo、useCallback、useMemo +- 图片优化:使用适当的图片格式和大小 +- 网络请求优化:使用 axios 拦截器,合理缓存 + +## 页面组成 +详见design/pages/中各页面的md文件 + +### 6. 项目详情 +进入详情后,不显示左侧菜单树、顶部导航栏,只显示画布区域、左侧工具栏、右侧顶部工具栏、右侧AI对话框。 + +- 画布区域: + - 以固定外框,将html以iframe嵌套的方式显示出来 + - iframe内的元素可在画布区域内选择和高亮 + - 添加、删除、修改元素 + - 拖拽功能 + - 预览功能 + - 选中元素后,可将元素的id加入到AI对话框的问题中 +- 左侧工具栏(绝对定位,距离屏幕左侧 10px,顶部 10px),抽取为单独组件: + - 工具栏可展开/收起,垂直布局,工具栏只显示图标,不显示文字描述,鼠标悬停显示文字描述 + - 页面:查看项目内所有页面,点击切换到该页面,切换前会弹窗提示,是否确认切换,用户确认后保存当前页面,切换到新页面 + - 原型库:查看项目内所有原型,点击弹窗显示详情 + - 备注:添加、删除、修改项目元素的备注,需先选中iframe中的元素,否则会提示用户先选中元素 + - 资源管理:查看项目内所有资源,点击弹窗显示详情 + - 全屏预览:查看设计稿的全屏预览 + - 提示词库:查看项目内所有提示词,点击弹窗显示详情 +- 右侧AI对话框(绝对定位,距离屏幕右侧10px,底部10px),抽取为单独组件: + - 对话框可展开/收起,垂直布局 + - 顶部标题: + - 显示“AI助手”; + - 对话历史按钮:点击后展开/收起对话历史列表,图标为“历史图标”; + - 对话历史列表:显示用户之前与AI助手的对话记录,只显示标题和时间,不显示回复内容 + - 点击对话记录,中间输出框展开显示该对话记录的详细内容 + - 展开时,对话历史列表紧贴着AI对话框,对话历史列表的右侧距离AI对话框的左侧 10px,顶部与AI对话框的顶部对齐;收起时隐藏对话历史列表 + - 右侧切换模型下拉框,可选择不同AI模型 + - 中间输出框:显示用户输入的问题和AI回复 + - 每个问题和回复占一行,问题和回复之间用空行隔开,可滚动查看 + - 回复内容可复制、重新生成、点赞、踩,图标为“复制图标”、“重新生成图标”、“点赞图标”、“踩下图标” + - 问题可点击删除,删除该问题和对应的回复内容 + - 问题可点击编辑,修改该问题的内容 + - 问题可点击重试,重新触发AI回复,图标为“重试图标” + - 底部输入框:用户输入问题,AI回复会显示在输出框中 + - 底部输入框按钮组(相对于底部输入框绝对定位,距离底部 10px): + - 上传附件按钮:点击后调用浏览器上传文件功能,支持上传图片、doc、docx、pdf、PDF、MD等类型文件,上传后显示在输出框中。 + - 快捷命令按钮:点击后显示快捷命令,图标为“/” + - 语音输入图标:点击后调起语音输入功能,支持中文和英文语音,图标为“语音图标” + - 发送按钮:点击后触发AI回复,图标为“发送图标” +- 右侧顶部工具栏(绝对定位,距离屏幕右侧10px,顶部10px),抽取为单独组件: + - 顶部工具栏可展开/收起,横向布局,工具栏只显示图标,不显示文字描述,鼠标悬停显示文字描述 + - 新建页面:提供新建画布的能力 + - 保存页面:提供保存画布的能力 + - 导入页面:提供导入html创建画布的能力 + - 导出页面:提供导出为html、导出为XD文件的能力 + - 退出:返回到项目,返回前如果有未保存的更改,会弹窗提示,是否确认退出 \ No newline at end of file diff --git a/design/figma/DESIGN.md b/design/figma/DESIGN.md deleted file mode 100644 index 9a022e2..0000000 --- a/design/figma/DESIGN.md +++ /dev/null @@ -1,220 +0,0 @@ -# Design System Inspiration of Figma - -## 1. Visual Theme & Atmosphere - -Figma's interface is the design tool that designed itself — a masterclass in typographic sophistication where a custom variable font (figmaSans) modulates between razor-thin (weight 320) and bold (weight 700) with stops at unusual intermediates (330, 340, 450, 480, 540) that most type systems never explore. This granular weight control gives every text element a precisely calibrated visual weight, creating hierarchy through micro-differences rather than the blunt instrument of "regular vs bold." - -The page presents a fascinating duality: the interface chrome is strictly black-and-white (literally only `#000000` and `#ffffff` detected as colors), while the hero section and product showcases explode with vibrant multi-color gradients — electric greens, bright yellows, deep purples, hot pinks. This separation means the design system itself is colorless, treating the product's colorful output as the hero content. Figma's marketing page is essentially a white gallery wall displaying colorful art. - -What makes Figma distinctive beyond the variable font is its circle-and-pill geometry. Buttons use 50px radius (pill) or 50% (perfect circle for icon buttons), creating an organic, tool-palette-like feel. The dashed-outline focus indicator (`dashed 2px`) is a deliberate design choice that echoes selection handles in the Figma editor itself — the website's UI language references the product's UI language. - -**Key Characteristics:** -- Custom variable font (figmaSans) with unusual weight stops: 320, 330, 340, 450, 480, 540, 700 -- Strictly black-and-white interface chrome — color exists only in product content -- figmaMono for uppercase technical labels with wide letter-spacing -- Pill (50px) and circular (50%) button geometry -- Dashed focus outlines echoing Figma's editor selection handles -- Vibrant multi-color hero gradients (green, yellow, purple, pink) -- OpenType `"kern"` feature enabled globally -- Negative letter-spacing throughout — even body text at -0.14px to -0.26px - -## 2. Color Palette & Roles - -### Primary -- **Pure Black** (`#000000`): All text, all solid buttons, all borders. The sole "color" of the interface. -- **Pure White** (`#ffffff`): All backgrounds, white buttons, text on dark surfaces. The other half of the binary. - -*Note: Figma's marketing site uses ONLY these two colors for its interface layer. All vibrant colors appear exclusively in product screenshots, hero gradients, and embedded content.* - -### Surface & Background -- **Pure White** (`#ffffff`): Primary page background and card surfaces. -- **Glass Black** (`rgba(0, 0, 0, 0.08)`): Subtle dark overlay for secondary circular buttons and glass effects. -- **Glass White** (`rgba(255, 255, 255, 0.16)`): Frosted glass overlay for buttons on dark/colored surfaces. - -### Gradient System -- **Hero Gradient**: A vibrant multi-stop gradient using electric green, bright yellow, deep purple, and hot pink. This gradient is the visual signature of the hero section — it represents the creative possibilities of the tool. -- **Product Section Gradients**: Individual product areas (Design, Dev Mode, Prototyping) may use distinct color themes in their showcases. - -## 3. Typography Rules - -### Font Family -- **Primary**: `figmaSans`, with fallbacks: `figmaSans Fallback, SF Pro Display, system-ui, helvetica` -- **Monospace / Labels**: `figmaMono`, with fallbacks: `figmaMono Fallback, SF Mono, menlo` - -### Hierarchy - -| Role | Font | Size | Weight | Line Height | Letter Spacing | Notes | -|------|------|------|--------|-------------|----------------|-------| -| Display / Hero | figmaSans | 86px (5.38rem) | 400 | 1.00 (tight) | -1.72px | Maximum impact, extreme tracking | -| Section Heading | figmaSans | 64px (4rem) | 400 | 1.10 (tight) | -0.96px | Feature section titles | -| Sub-heading | figmaSans | 26px (1.63rem) | 540 | 1.35 | -0.26px | Emphasized section text | -| Sub-heading Light | figmaSans | 26px (1.63rem) | 340 | 1.35 | -0.26px | Light-weight section text | -| Feature Title | figmaSans | 24px (1.5rem) | 700 | 1.45 | normal | Bold card headings | -| Body Large | figmaSans | 20px (1.25rem) | 330–450 | 1.30–1.40 | -0.1px to -0.14px | Descriptions, intros | -| Body / Button | figmaSans | 16px (1rem) | 330–400 | 1.40–1.45 | -0.14px to normal | Standard body, nav, buttons | -| Body Light | figmaSans | 18px (1.13rem) | 320 | 1.45 | -0.26px to normal | Light-weight body text | -| Mono Label | figmaMono | 18px (1.13rem) | 400 | 1.30 (tight) | 0.54px | Uppercase section labels | -| Mono Small | figmaMono | 12px (0.75rem) | 400 | 1.00 (tight) | 0.6px | Uppercase tiny tags | - -### Principles -- **Variable font precision**: figmaSans uses weights that most systems never touch — 320, 330, 340, 450, 480, 540. This creates hierarchy through subtle weight differences rather than dramatic jumps. The difference between 330 and 340 is nearly imperceptible but structurally significant. -- **Light as the base**: Most body text uses 320–340 (lighter than typical 400 "regular"), creating an ethereal, airy reading experience that matches the design-tool aesthetic. -- **Kern everywhere**: Every text element enables OpenType `"kern"` feature — kerning is not optional, it's structural. -- **Negative tracking by default**: Even body text uses -0.1px to -0.26px letter-spacing, creating universally tight text. Display text compresses further to -0.96px and -1.72px. -- **Mono for structure**: figmaMono in uppercase with positive letter-spacing (0.54px–0.6px) creates technical signpost labels. - -## 4. Component Stylings - -### Buttons - -**Black Solid (Pill)** -- Background: Pure Black (`#000000`) -- Text: Pure White (`#ffffff`) -- Radius: circle (50%) for icon buttons -- Focus: dashed 2px outline -- Maximum emphasis - -**White Pill** -- Background: Pure White (`#ffffff`) -- Text: Pure Black (`#000000`) -- Padding: 8px 18px 10px (asymmetric vertical) -- Radius: pill (50px) -- Focus: dashed 2px outline -- Standard CTA on dark/colored surfaces - -**Glass Dark** -- Background: `rgba(0, 0, 0, 0.08)` (subtle dark overlay) -- Text: Pure Black -- Radius: circle (50%) -- Focus: dashed 2px outline -- Secondary action on light surfaces - -**Glass Light** -- Background: `rgba(255, 255, 255, 0.16)` (frosted glass) -- Text: Pure White -- Radius: circle (50%) -- Focus: dashed 2px outline -- Secondary action on dark/colored surfaces - -### Cards & Containers -- Background: Pure White -- Border: none or minimal -- Radius: 6px (small containers), 8px (images, cards, dialogs) -- Shadow: subtle to medium elevation effects -- Product screenshots as card content - -### Navigation -- Clean horizontal nav on white -- Logo: Figma wordmark in black -- Product tabs: pill-shaped (50px) tab navigation -- Links: black text, underline 1px decoration -- CTA: Black pill button -- Hover: text color via CSS variable - -### Distinctive Components - -**Product Tab Bar** -- Horizontal pill-shaped tabs (50px radius) -- Each tab represents a Figma product area (Design, Dev Mode, Prototyping, etc.) -- Active tab highlighted - -**Hero Gradient Section** -- Full-width vibrant multi-color gradient background -- White text overlay with 86px display heading -- Product screenshots floating within the gradient - -**Dashed Focus Indicators** -- All interactive elements use `dashed 2px` outline on focus -- References the selection handles in the Figma editor -- A meta-design choice connecting website and product - -## 5. Layout Principles - -### Spacing System -- Base unit: 8px -- Scale: 1px, 2px, 4px, 4.5px, 8px, 10px, 12px, 16px, 18px, 24px, 32px, 40px, 46px, 48px, 50px - -### Grid & Container -- Max container width: up to 1920px -- Hero: full-width gradient with centered content -- Product sections: alternating showcases -- Footer: dark full-width section -- Responsive from 559px to 1920px - -### Whitespace Philosophy -- **Gallery-like pacing**: Generous spacing lets each product section breathe as its own exhibit. -- **Color sections as visual breathing**: The gradient hero and product showcases provide chromatic relief between the monochrome interface sections. - -### Border Radius Scale -- Minimal (2px): Small link elements -- Subtle (6px): Small containers, dividers -- Comfortable (8px): Cards, images, dialogs -- Pill (50px): Tab buttons, CTAs -- Circle (50%): Icon buttons, circular elements - -## 6. Depth & Elevation - -| Level | Treatment | Use | -|-------|-----------|-----| -| Flat (Level 0) | No shadow | Page background, most text | -| Surface (Level 1) | White card on gradient/dark section | Cards, product showcases | -| Elevated (Level 2) | Subtle shadow | Floating cards, hover states | - -**Shadow Philosophy**: Figma uses shadows sparingly. The primary depth mechanisms are **background contrast** (white content on colorful/dark sections) and the inherent dimensionality of the product screenshots themselves. - -## 7. Do's and Don'ts - -### Do -- Use figmaSans with precise variable weights (320–540) — the granular weight control IS the design -- Keep the interface strictly black-and-white — color comes from product content only -- Use pill (50px) and circular (50%) geometry for all interactive elements -- Apply dashed 2px focus outlines — the signature accessibility pattern -- Enable `"kern"` feature on all text -- Use figmaMono in uppercase with positive letter-spacing for labels -- Apply negative letter-spacing throughout (-0.1px to -1.72px) - -### Don't -- Don't add interface colors — the monochrome palette is absolute -- Don't use standard font weights (400, 500, 600, 700) — use the variable font's unique stops (320, 330, 340, 450, 480, 540) -- Don't use sharp corners on buttons — pill and circular geometry only -- Don't use solid focus outlines — dashed is the signature -- Don't increase body font weight above 450 — the light-weight aesthetic is core -- Don't use positive letter-spacing on body text — it's always negative - -## 8. Responsive Behavior - -### Breakpoints -| Name | Width | Key Changes | -|------|-------|-------------| -| Small Mobile | <560px | Compact layout, stacked | -| Tablet | 560–768px | Minor adjustments | -| Small Desktop | 768–960px | 2-column layouts | -| Desktop | 960–1280px | Standard layout | -| Large Desktop | 1280–1440px | Expanded | -| Ultra-wide | 1440–1920px | Maximum width | - -### Collapsing Strategy -- Hero text: 86px → 64px → 48px -- Product tabs: horizontal scroll on mobile -- Feature sections: stacked single column -- Footer: multi-column → stacked - -## 9. Agent Prompt Guide - -### Quick Color Reference -- Everything: "Pure Black (#000000)" and "Pure White (#ffffff)" -- Glass Dark: "rgba(0, 0, 0, 0.08)" -- Glass Light: "rgba(255, 255, 255, 0.16)" - -### Example Component Prompts -- "Create a hero on a vibrant multi-color gradient (green, yellow, purple, pink). Headline at 86px figmaSans weight 400, line-height 1.0, letter-spacing -1.72px. White text. White pill CTA button (50px radius, 8px 18px padding)." -- "Design a product tab bar with pill-shaped buttons (50px radius). Active: Black bg, white text. Inactive: transparent, black text. figmaSans at 20px weight 480." -- "Build a section label: figmaMono 18px, uppercase, letter-spacing 0.54px, black text. Kern enabled." -- "Create body text at 20px figmaSans weight 330, line-height 1.40, letter-spacing -0.14px. Pure Black on white." - -### Iteration Guide -1. Use variable font weight stops precisely: 320, 330, 340, 450, 480, 540, 700 -2. Interface is always black + white — never add colors to chrome -3. Dashed focus outlines, not solid -4. Letter-spacing is always negative on body, always positive on mono labels -5. Pill (50px) for buttons/tabs, circle (50%) for icon buttons diff --git a/design/figma/README.md b/design/figma/README.md deleted file mode 100644 index 3fdfbe3..0000000 --- a/design/figma/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Figma Inspired Design System - -[DESIGN.md](https://github.com/VoltAgent/awesome-design-md/blob/main/design-md/figma/DESIGN.md) extracted from the public [Figma](https://figma.com/) website. This is not the official design system. Colors, fonts, and spacing may not be 100% accurate. But it's a good starting point for building something similar. - -## Files - -| File | Description | -|------|-------------| -| `DESIGN.md` | Complete design system documentation (9 sections) | -| `preview.html` | Interactive design token catalog (light) | -| `preview-dark.html` | Interactive design token catalog (dark) | - - -Use [DESIGN.md](https://github.com/VoltAgent/awesome-design-md/blob/main/design-md/figma/DESIGN.md) to use as a reference for AI agents (Claude, Cursor, Stitch) to generate UI that looks like the Figma design language. - -## Preview - -A sample landing page built with DESIGN.md. It shows the actual colors, typography, buttons, cards, spacing, and elevation, all in one page. - -### Dark Mode -![Figma Design System — Dark Mode](https://pub-2e4ecbcbc9b24e7b93f1a6ab5b2bc71f.r2.dev/designs/figma/preview-dark-screenshot.png) - -### Light Mode -![Figma Design System — Light Mode](https://pub-2e4ecbcbc9b24e7b93f1a6ab5b2bc71f.r2.dev/designs/figma/preview-screenshot.png) diff --git a/design/figma/preview-dark.html b/design/figma/preview-dark.html deleted file mode 100644 index 58d2df3..0000000 --- a/design/figma/preview-dark.html +++ /dev/null @@ -1,822 +0,0 @@ - - - - - -Design System Inspired by Figma - - - - - - - - - - - -
-
- - - - -
-

Design System
Inspired by Figma

-

Auto-generated design token catalog from DESIGN.md

-
- - -
-
- -
- - -
-
01 / COLOR PALETTE
-

Color Palette & Roles

- -
-

Primary

-
-
-
-
-
Pure Black
-
#000000
-
Page background, dark surface. The foundation of the dark theme.
-
-
-
-
-
-
Pure White
-
#ffffff
-
All text, solid buttons, primary interface color on dark.
-
-
-
-
- -
-

Surface & Glass

-
-
-
-
-
Glass White
-
rgba(255,255,255,0.16)
-
Frosted glass overlays, secondary buttons on dark surfaces.
-
-
-
-
-
-
Glass Subtle
-
rgba(255,255,255,0.08)
-
Card surfaces, grouped content areas on dark background.
-
-
-
-
- -
-

Gradient System

-
-
-
-
Hero Gradient -- Electric Green, Purple, Orange, Pink, Cyan
-

Color exists only in hero gradients and product showcases. The interface layer remains strictly monochrome.

-
-
- -
- - -
-
02 / TYPOGRAPHY SCALE
-

Typography Rules

- -
-
Variable Weight Spectrum
-
- The quick brown fox jumps - Weight 320 -
-
- The quick brown fox jumps - Weight 330 -
-
- The quick brown fox jumps - Weight 340 -
-
- The quick brown fox jumps - Weight 400 -
-
- The quick brown fox jumps - Weight 450 -
-
- The quick brown fox jumps - Weight 480 -
-
- The quick brown fox jumps - Weight 540 -
-
- The quick brown fox jumps - Weight 700 -
-
- -
-
Display Hero
-
Display / Hero -- 86px / wt 400 / lh 1.00 / ls -1.72px -- figmaSans
-
- -
-
Section Heading
-
Section Heading -- 64px / wt 400 / lh 1.10 / ls -0.96px -- figmaSans
-
- -
-
Sub-heading Medium
-
Sub-heading -- 26px / wt 540 / lh 1.35 / ls -0.26px -- figmaSans
-
- -
-
Sub-heading Light
-
Sub-heading Light -- 26px / wt 340 / lh 1.35 / ls -0.26px -- figmaSans
-
- -
-
Feature Title Bold
-
Feature Title -- 24px / wt 700 / lh 1.45 / ls normal -- figmaSans
-
- -
-
Body large text for descriptions and introductions. The light weight creates an airy, ethereal reading experience that matches the design-tool aesthetic.
-
Body Large -- 20px / wt 330 / lh 1.40 / ls -0.14px -- figmaSans
-
- -
-
Body light text at the lightest variable weight. Nearly imperceptible thinness for secondary content and delicate UI copy.
-
Body Light -- 18px / wt 320 / lh 1.45 / ls -0.26px -- figmaSans
-
- -
-
Standard body text for paragraphs, navigation links, and button labels. The default reading weight for all UI copy.
-
Body / Button -- 16px / wt 400 / lh 1.45 / ls -0.14px -- figmaSans
-
- -
-
MONO SECTION LABEL
-
Mono Label -- 18px / wt 400 / lh 1.30 / ls 0.54px / uppercase -- figmaMono
-
- -
-
MONO SMALL TAG
-
Mono Small -- 12px / wt 400 / lh 1.00 / ls 0.6px / uppercase -- figmaMono
-
-
- -
- - -
-
03 / BUTTON VARIANTS
-

Buttons

- -
-
- -
White Pill CTA
-
-
- -
Outline Pill
-
-
- -
White Circle
-
-
- -
Glass Light
-
-
- -
Glass Dark
-
-
- -
-
-
Dashed Focus Indicator
-

All interactive elements use dashed 2px outline on focus, echoing the selection handles in the Figma editor.

-
-
- - -
-
-
- -
- - -
-
04 / CARD EXAMPLES
-

Cards & Containers

- -
-
-
STANDARD CARD
-

Border Contained

-

Standard content card with subtle white-alpha border and 8px radius. The default container on the black surface.

-
-
-
ELEVATED CARD
-

Subtle Glow

-

Floating card with subtle luminous shadow. Used for product showcases and hover states that lift off the dark surface.

-
-
-
GLASS SURFACE
-

Glass Overlay

-

Glass-effect card using rgba(255,255,255,0.08) background. Secondary containers with a translucent frosted feel.

-
-
-
- -
- - -
-
05 / SPACING SCALE
-

Spacing System

-

Base unit: 8px. Scale from 1px to 50px.

- -
-
1px
-
2px
-
4px
-
8px
-
10px
-
12px
-
16px
-
18px
-
24px
-
32px
-
40px
-
48px
-
50px
-
-
- -
- - -
-
06 / BORDER RADIUS SCALE
-

Border Radius

- -
-
2px
Small links
-
6px
Small containers
-
8px
Cards, images
-
50px
Pill buttons
-
50%
Circle / Icon
-
-
- -
- - -
-
07 / ELEVATION & DEPTH
-

Depth & Elevation

- -
-
-
Flat
No shadow. Pure black page background and most text. The default dark surface.
-
Level 0
-
-
-
Surface
Glass white card on black background. Primary depth through translucent layering.
-
Level 1
-
-
-
Elevated
Subtle luminous shadow for floating cards and hover states on dark surfaces.
-
Level 2
-
-
-
- -
- - - diff --git a/design/figma/preview.html b/design/figma/preview.html deleted file mode 100644 index b82aab5..0000000 --- a/design/figma/preview.html +++ /dev/null @@ -1,832 +0,0 @@ - - - - - -Design System Inspired by Figma - - - - - - - - - - - -
-
- - - - -
-

Design System
Inspired by Figma

-

Auto-generated design token catalog from DESIGN.md

-
- - -
-
- -
- - -
-
01 / COLOR PALETTE
-

Color Palette & Roles

- -
-

Primary

-
-
-
-
-
Pure Black
-
#000000
-
All text, solid buttons, all borders. The sole interface color.
-
-
-
-
-
-
Pure White
-
#ffffff
-
All backgrounds, white buttons, text on dark surfaces.
-
-
-
-
- -
-

Surface & Glass

-
-
-
-
-
Glass Black
-
rgba(0,0,0,0.08)
-
Secondary circular buttons, glass overlays on light surfaces.
-
-
-
-
-
-
-
-
-
Glass White
-
rgba(255,255,255,0.16)
-
Frosted glass overlay for buttons on dark or colored surfaces.
-
-
-
-
- -
-

Gradient System

-
-
-
-
Hero Gradient -- Electric Green, Purple, Orange, Pink, Cyan
-

Color exists only in hero gradients and product showcases. The interface layer remains strictly monochrome.

-
-
- -
- - -
-
02 / TYPOGRAPHY SCALE
-

Typography Rules

- -
-
Variable Weight Spectrum
-
- The quick brown fox jumps - Weight 320 -
-
- The quick brown fox jumps - Weight 330 -
-
- The quick brown fox jumps - Weight 340 -
-
- The quick brown fox jumps - Weight 400 -
-
- The quick brown fox jumps - Weight 450 -
-
- The quick brown fox jumps - Weight 480 -
-
- The quick brown fox jumps - Weight 540 -
-
- The quick brown fox jumps - Weight 700 -
-
- -
-
Display Hero
-
Display / Hero -- 86px / wt 400 / lh 1.00 / ls -1.72px -- figmaSans
-
- -
-
Section Heading
-
Section Heading -- 64px / wt 400 / lh 1.10 / ls -0.96px -- figmaSans
-
- -
-
Sub-heading Medium
-
Sub-heading -- 26px / wt 540 / lh 1.35 / ls -0.26px -- figmaSans
-
- -
-
Sub-heading Light
-
Sub-heading Light -- 26px / wt 340 / lh 1.35 / ls -0.26px -- figmaSans
-
- -
-
Feature Title Bold
-
Feature Title -- 24px / wt 700 / lh 1.45 / ls normal -- figmaSans
-
- -
-
Body large text for descriptions and introductions. The light weight creates an airy, ethereal reading experience that matches the design-tool aesthetic.
-
Body Large -- 20px / wt 330 / lh 1.40 / ls -0.14px -- figmaSans
-
- -
-
Body light text at the lightest variable weight. Nearly imperceptible thinness for secondary content and delicate UI copy.
-
Body Light -- 18px / wt 320 / lh 1.45 / ls -0.26px -- figmaSans
-
- -
-
Standard body text for paragraphs, navigation links, and button labels. The default reading weight for all UI copy.
-
Body / Button -- 16px / wt 400 / lh 1.45 / ls -0.14px -- figmaSans
-
- -
-
MONO SECTION LABEL
-
Mono Label -- 18px / wt 400 / lh 1.30 / ls 0.54px / uppercase -- figmaMono
-
- -
-
MONO SMALL TAG
-
Mono Small -- 12px / wt 400 / lh 1.00 / ls 0.6px / uppercase -- figmaMono
-
-
- -
- - -
-
03 / BUTTON VARIANTS
-

Buttons

- -
-
- -
Black Pill CTA
-
-
- -
White Pill
-
-
- -
Black Circle
-
-
- -
Glass Dark
-
-
-
- -
-
Glass Light
-
-
- -
-
-
Dashed Focus Indicator
-

All interactive elements use dashed 2px outline on focus, echoing the selection handles in the Figma editor.

-
-
- - -
-
-
- -
- - -
-
04 / CARD EXAMPLES
-

Cards & Containers

- -
-
-
STANDARD CARD
-

Minimal Border

-

Standard content card with subtle border and 8px radius. The default container for features and content sections on the white gallery surface.

-
-
-
ELEVATED CARD
-

Subtle Shadow

-

Floating card with subtle shadow elevation. Used for product showcases and hover states where the card lifts off the surface.

-
-
-
GLASS SURFACE
-

Glass Overlay

-

Glass-effect card using rgba(0,0,0,0.08) background. Secondary containers and grouped content areas with a translucent feel.

-
-
-
- -
- - -
-
05 / SPACING SCALE
-

Spacing System

-

Base unit: 8px. Scale from 1px to 50px.

- -
-
1px
-
2px
-
4px
-
8px
-
10px
-
12px
-
16px
-
18px
-
24px
-
32px
-
40px
-
48px
-
50px
-
-
- -
- - -
-
06 / BORDER RADIUS SCALE
-

Border Radius

- -
-
2px
Small links
-
6px
Small containers
-
8px
Cards, images
-
50px
Pill buttons
-
50%
Circle / Icon
-
-
- -
- - -
-
07 / ELEVATION & DEPTH
-

Depth & Elevation

- -
-
-
Flat
No shadow. Page background and most text. The default surface.
-
Level 0
-
-
-
Surface
White card on gradient or dark section. Primary depth through background contrast.
-
Level 1
-
-
-
Elevated
Subtle shadow for floating cards and hover states. Sparingly applied.
-
Level 2
-
-
-
- -
- - - diff --git a/design/mintlify/DESIGN.md b/design/mintlify/DESIGN.md deleted file mode 100644 index 0eb4b10..0000000 --- a/design/mintlify/DESIGN.md +++ /dev/null @@ -1,326 +0,0 @@ -# Design System Inspiration of Mintlify - -## 1. Visual Theme & Atmosphere - -Mintlify's website is a study in documentation-as-product design — a white, airy, information-rich surface that treats clarity as its highest aesthetic value. The page opens with a luminous white (`#ffffff`) background, near-black (`#0d0d0d`) text, and a signature green brand accent (`#18E299`) that signals freshness and intelligence without dominating the palette. The overall mood is calm, confident, and engineered for legibility — a design system that whispers "we care about your developer experience" in every pixel. - -The Inter font family carries the entire typographic load. At display sizes (40–64px), it uses tight negative letter-spacing (-0.8px to -1.28px) and semibold weight (600), creating headlines that feel focused and compressed like well-written documentation headers. Body text at 16–18px with 150% line-height provides generous reading comfort. Geist Mono appears exclusively for code and technical labels — uppercase, tracked-out, small — the voice of the terminal inside the marketing page. - -What distinguishes Mintlify from other documentation platforms is its atmospheric gradient hero. A soft, cloud-like green-to-white gradient wash behind the hero content creates a sense of ethereal intelligence — documentation that floats above the noise. Below the hero, the page settles into a disciplined alternation of white sections separated by subtle 5% opacity borders. Cards use generous padding (24px+) with large radii (16px–24px) and whisper-thin borders, creating containers that feel open rather than boxed. - -**Key Characteristics:** -- Inter with tight negative tracking at display sizes (-0.8px to -1.28px) — compressed yet readable -- Geist Mono for code labels: uppercase, 12px, tracked-out, the terminal voice -- Brand green (`#18E299`) used sparingly — CTAs, hover states, focus rings, and accent touches -- Atmospheric gradient hero with cloud-like green-white wash -- Ultra-round corners: 16px for containers, 24px for featured cards, full-round (9999px) for buttons and pills -- Subtle 5% opacity borders (`rgba(0,0,0,0.05)`) creating barely-there separation -- 8px base spacing system with generous section padding (48px–96px) -- Clean white canvas — no gray backgrounds, no color sections, depth through borders and whitespace alone - -## 2. Color Palette & Roles - -### Primary -- **Near Black** (`#0d0d0d`): Primary text, headings, dark surfaces. Not pure black — the micro-softness improves reading comfort. -- **Pure White** (`#ffffff`): Page background, card surfaces, input backgrounds. -- **Brand Green** (`#18E299`): The signature accent — CTAs, links on hover, focus rings, brand identity. - -### Secondary Accents -- **Brand Green Light** (`#d4fae8`): Tinted green surface for badges, hover states, subtle backgrounds. -- **Brand Green Deep** (`#0fa76e`): Darker green for text on light-green badges, hover states on brand elements. -- **Warm Amber** (`#c37d0d`): Warning states, caution badges — `--twoslash-warn-bg`. -- **Soft Blue** (`#3772cf`): Tag backgrounds, informational annotations — `--twoslash-tag-bg`. -- **Error Red** (`#d45656`): Error states, destructive actions — `--twoslash-error-bg`. - -### Neutral Scale -- **Gray 900** (`#0d0d0d`): Primary heading text, nav links. -- **Gray 700** (`#333333`): Secondary text, descriptions, body copy. -- **Gray 500** (`#666666`): Tertiary text, muted labels. -- **Gray 400** (`#888888`): Placeholder text, disabled states, code annotations. -- **Gray 200** (`#e5e5e5`): Borders, dividers, card outlines. -- **Gray 100** (`#f5f5f5`): Subtle surface backgrounds, hover states. -- **Gray 50** (`#fafafa`): Near-white surface tint. - -### Interactive -- **Link Default** (`#0d0d0d`): Links match text color, relying on underline/context. -- **Link Hover** (`#18E299`): Brand green on hover — `var(--color-brand)`. -- **Focus Ring** (`#18E299`): Brand green focus outline for inputs and interactive elements. - -### Surface & Overlay -- **Card Background** (`#ffffff`): White cards on white background, separated by borders. -- **Border Subtle** (`rgba(0,0,0,0.05)`): 5% black opacity borders — the primary separation mechanism. -- **Border Medium** (`rgba(0,0,0,0.08)`): Slightly stronger borders for interactive elements. -- **Input Border Focus** (`var(--color-brand)`): Green ring on focused inputs. - -### Shadows & Depth -- **Card Shadow** (`rgba(0,0,0,0.03) 0px 2px 4px`): Barely-there ambient shadow for subtle lift. -- **Button Shadow** (`rgba(0,0,0,0.06) 0px 1px 2px`): Micro-shadow for button depth. -- **No heavy shadows**: Mintlify relies on borders, not shadows, for depth. - -## 3. Typography Rules - -### Font Family -- **Primary**: `Inter`, with fallback: `Inter Fallback, system-ui, -apple-system, sans-serif` -- **Monospace**: `Geist Mono`, with fallback: `Geist Mono Fallback, ui-monospace, SFMono-Regular, monospace` - -### Hierarchy - -| Role | Font | Size | Weight | Line Height | Letter Spacing | Notes | -|------|------|------|--------|-------------|----------------|-------| -| Display Hero | Inter | 64px (4.00rem) | 600 | 1.15 (tight) | -1.28px | Maximum impact, hero headlines | -| Section Heading | Inter | 40px (2.50rem) | 600 | 1.10 (tight) | -0.8px | Feature section titles | -| Sub-heading | Inter | 24px (1.50rem) | 500 | 1.30 (tight) | -0.24px | Card headings, sub-sections | -| Card Title | Inter | 20px (1.25rem) | 600 | 1.30 (tight) | -0.2px | Feature card titles | -| Card Title Light | Inter | 20px (1.25rem) | 500 | 1.30 (tight) | -0.2px | Secondary card headings | -| Body Large | Inter | 18px (1.13rem) | 400 | 1.50 | normal | Hero descriptions, introductions | -| Body | Inter | 16px (1.00rem) | 400 | 1.50 | normal | Standard reading text | -| Body Medium | Inter | 16px (1.00rem) | 500 | 1.50 | normal | Navigation, emphasized text | -| Button | Inter | 15px (0.94rem) | 500 | 1.50 | normal | Button labels | -| Link | Inter | 14px (0.88rem) | 500 | 1.50 | normal | Navigation links, small CTAs | -| Caption | Inter | 14px (0.88rem) | 400–500 | 1.50–1.71 | normal | Metadata, descriptions | -| Label Uppercase | Inter | 13px (0.81rem) | 500 | 1.50 | 0.65px | `text-transform: uppercase`, section labels | -| Small | Inter | 13px (0.81rem) | 400–500 | 1.50 | -0.26px | Small body text | -| Mono Code | Geist Mono | 12px (0.75rem) | 500 | 1.50 | 0.6px | `text-transform: uppercase`, technical labels | -| Mono Badge | Geist Mono | 12px (0.75rem) | 600 | 1.50 | 0.6px | `text-transform: uppercase`, status badges | -| Mono Micro | Geist Mono | 10px (0.63rem) | 500 | 1.50 | normal | `text-transform: uppercase`, tiny labels | - -### Principles -- **Tight tracking at display sizes**: Inter at 40–64px uses -0.8px to -1.28px letter-spacing. This compression creates headlines that feel deliberate and space-efficient — documentation headings, not billboard copy. -- **Relaxed reading at body sizes**: 16–18px body text uses normal tracking with 150% line-height, creating generous reading lanes. Documentation demands comfort. -- **Two-font system**: Inter for all human-readable content, Geist Mono exclusively for technical/code contexts. The boundary is strict — no mixing. -- **Uppercase as hierarchy signal**: Section labels and technical tags use uppercase + positive tracking (0.6px–0.65px) as a clear visual delimiter between content types. -- **Three weights**: 400 (body/reading), 500 (UI/navigation/emphasis), 600 (headings/titles). No bold (700) in the system. - -## 4. Component Stylings - -### Buttons - -**Primary Brand (Full-round)** -- Background: `#0d0d0d` (near-black) -- Text: `#ffffff` -- Padding: 8px 24px -- Radius: 9999px (full pill) -- Font: Inter 15px weight 500 -- Shadow: `rgba(0,0,0,0.06) 0px 1px 2px` -- Hover: opacity 0.9 -- Use: Primary CTA ("Get Started", "Start Building") - -**Secondary / Ghost (Full-round)** -- Background: `#ffffff` -- Text: `#0d0d0d` -- Padding: 4.5px 12px -- Radius: 9999px (full pill) -- Border: `1px solid rgba(0,0,0,0.08)` -- Font: Inter 15px weight 500 -- Hover: opacity 0.9 -- Use: Secondary actions ("Request Demo", "View Docs") - -**Transparent / Nav Button** -- Background: transparent -- Text: `#0d0d0d` -- Padding: 5px 6px -- Radius: 8px -- Border: none or `1px solid rgba(0,0,0,0.05)` -- Use: Navigation items, icon buttons - -**Brand Accent Button** -- Background: `#18E299` -- Text: `#0d0d0d` -- Padding: 8px 24px -- Radius: 9999px -- Use: Special promotional CTAs - -### Cards & Containers - -**Standard Card** -- Background: `#ffffff` -- Border: `1px solid rgba(0,0,0,0.05)` -- Radius: 16px -- Padding: 24px -- Shadow: `rgba(0,0,0,0.03) 0px 2px 4px` -- Hover: subtle border darkening to `rgba(0,0,0,0.08)` - -**Featured Card** -- Background: `#ffffff` -- Border: `1px solid rgba(0,0,0,0.05)` -- Radius: 24px -- Padding: 32px -- Inner content areas may have their own 16px radius containers - -**Logo/Trust Card** -- Background: `#fafafa` or `#ffffff` -- Border: `1px solid rgba(0,0,0,0.05)` -- Radius: 16px -- Centered logo/icon with consistent sizing - -### Inputs & Forms - -**Email Input** -- Background: transparent or `#ffffff` -- Text: `#0d0d0d` -- Padding: 0px 12px (height controlled by line-height) -- Border: `1px solid rgba(0,0,0,0.08)` -- Radius: 9999px (full pill, matching buttons) -- Focus: `1px solid var(--color-brand)` + `outline: 1px solid var(--color-brand)` -- Placeholder: `#888888` - -### Navigation -- Clean horizontal nav on white, sticky with backdrop blur -- Brand logotype left-aligned -- Links: Inter 14–15px weight 500, `#0d0d0d` text -- Hover: color shifts to brand green `var(--color-brand)` -- CTA: dark pill button right-aligned ("Get Started") -- Mobile: hamburger menu collapse at 768px - -### Image Treatment -- Product screenshots with subtle 1px borders -- Rounded containers: 16px–24px radius -- Atmospheric gradient backgrounds behind hero images -- Cloud/sky imagery with soft green tinting - -### Distinctive Components - -**Atmospheric Hero** -- Full-width gradient wash: soft green-to-white cloud-like gradient -- Centered headline with tight tracking -- Subtitle in muted gray -- Dual CTA buttons (dark primary + ghost secondary) -- The gradient creates a sense of elevation and intelligence - -**Trust Bar / Logo Grid** -- "Loved by your favorite companies" section -- Company logos in muted grayscale -- Grid or horizontal layout with consistent sizing -- Subtle border separation between logos - -**Feature Cards with Icons** -- Icon or illustration at top -- Title at 20px weight 600 -- Description at 14–16px in gray -- Consistent padding and border treatment -- Grid layout: 2–3 columns on desktop - -**CTA Footer Section** -- Dark or gradient background -- Large headline: "Make documentation your winning advantage" -- Email input with pill styling -- Brand green accent on CTAs - -## 5. Layout Principles - -### Spacing System -- Base unit: 8px -- Scale: 2px, 4px, 5px, 6px, 7px, 8px, 10px, 12px, 16px, 24px, 32px, 48px, 64px -- Section padding: 48px–96px vertical -- Card padding: 24px–32px -- Component gaps: 8px–16px - -### Grid & Container -- Max content width: approximately 1200px -- Hero: centered single-column with generous top padding (96px+) -- Feature sections: 2–3 column CSS Grid for cards -- Full-width sections with contained content -- Consistent horizontal padding: 24px (mobile) to 32px (desktop) - -### Whitespace Philosophy -- **Documentation-grade breathing room**: Every element has generous surrounding whitespace. Mintlify sells documentation, so the marketing page itself demonstrates reading comfort. -- **Sections as chapters**: Each feature section is a self-contained unit with 48px–96px vertical padding, creating clear "chapter breaks." -- **Content density is low**: Unlike developer tools that pack the page, Mintlify uses 1–2 key messages per section with supporting imagery. - -### Border Radius Scale -- Small (4px): Inline code, small tags, tooltips -- Medium (8px): Nav buttons, transparent buttons, small containers -- Standard (16px): Cards, content containers, image wrappers -- Large (24px): Featured cards, hero containers, section panels -- Full Pill (9999px): Buttons, inputs, badges, pills — the signature shape - -## 6. Depth & Elevation - -| Level | Treatment | Use | -|-------|-----------|-----| -| Flat (Level 0) | No shadow, no border | Page background, text blocks | -| Subtle Border (Level 1) | `1px solid rgba(0,0,0,0.05)` | Standard card borders, dividers | -| Medium Border (Level 1b) | `1px solid rgba(0,0,0,0.08)` | Interactive elements, input borders | -| Ambient Shadow (Level 2) | `rgba(0,0,0,0.03) 0px 2px 4px` | Cards with subtle lift | -| Button Shadow (Level 2b) | `rgba(0,0,0,0.06) 0px 1px 2px` | Button micro-depth | -| Focus Ring (Accessibility) | `1px solid #18E299` outline | Focused inputs, active interactive elements | - -**Shadow Philosophy**: Mintlify barely uses shadows. The depth system is almost entirely border-driven — ultra-subtle 5% opacity borders create separation without visual weight. When shadows appear, they're atmospheric whispers (`0.03 opacity, 2px blur, 4px spread`) that add the barest sense of lift. This restraint keeps the page feeling flat and paper-like — appropriate for a documentation company whose product is about clarity and readability. - -### Decorative Depth -- Hero gradient: atmospheric green-white cloud gradient behind hero content -- No background color alternation — white on white throughout -- Depth comes from border opacity variation (5% → 8%) and whitespace - -## 7. Dark Mode - -### Color Inversions -- **Background**: `#0d0d0d` (near-black) -- **Text Primary**: `#ededed` (near-white) -- **Text Secondary**: `#a0a0a0` (muted gray) -- **Brand Green**: `#18E299` (unchanged — the green works on both backgrounds) -- **Border**: `rgba(255,255,255,0.08)` (white at 8% opacity) -- **Card Background**: `#141414` (slightly lighter than page) -- **Shadow**: `rgba(0,0,0,0.4) 0px 2px 4px` (stronger shadow for contrast) - -### Key Adjustments -- Buttons invert: white background dark text becomes dark background light text -- Badge backgrounds shift to deeper tones with lighter text -- Focus ring remains brand green -- Hero gradient shifts to dark-tinted green atmospheric wash - -## 8. Responsive Behavior - -### Breakpoints -| Name | Width | Key Changes | -|------|-------|-------------| -| Mobile | <768px | Single column, stacked layout, hamburger nav | -| Tablet | 768–1024px | Two-column grids begin, expanded padding | -| Desktop | >1024px | Full layout, 3-column grids, maximum content width | - -### Touch Targets -- Buttons with full-pill shape have comfortable 8px+ vertical padding -- Navigation links spaced with adequate 16px+ gaps -- Mobile menu provides full-width tap targets - -### Collapsing Strategy -- Hero: 64px → 40px headline, maintains tight tracking proportionally -- Navigation: horizontal links + CTA → hamburger menu at 768px -- Feature cards: 3-column → 2-column → single column stacked -- Section spacing: 96px → 48px on mobile -- Footer: multi-column → stacked single column -- Trust bar: grid → horizontal scroll or stacked - -### Image Behavior -- Product screenshots maintain aspect ratio with responsive containers -- Hero gradient simplifies on mobile -- Full-width sections maintain edge-to-edge treatment - -## 9. Agent Prompt Guide - -### Quick Color Reference -- Primary CTA: Near Black (`#0d0d0d`) -- Background: Pure White (`#ffffff`) -- Heading text: Near Black (`#0d0d0d`) -- Body text: Gray 700 (`#333333`) -- Border: `rgba(0,0,0,0.05)` (5% opacity) -- Brand accent: Green (`#18E299`) -- Link hover: Brand Green (`#18E299`) -- Focus ring: Brand Green (`#18E299`) - -### Example Component Prompts -- "Create a hero section on white background with atmospheric green-white gradient wash. Headline at 64px Inter weight 600, line-height 1.15, letter-spacing -1.28px, color #0d0d0d. Subtitle at 18px Inter weight 400, line-height 1.50, color #666666. Dark pill CTA (#0d0d0d, 9999px radius, 8px 24px padding) and ghost pill button (white, 1px solid rgba(0,0,0,0.08), 9999px radius)." -- "Design a card: white background, 1px solid rgba(0,0,0,0.05) border, 16px radius, 24px padding, shadow rgba(0,0,0,0.03) 0px 2px 4px. Title at 20px Inter weight 600, letter-spacing -0.2px. Body at 14px weight 400, #666666." -- "Build a pill badge: #d4fae8 background, #0fa76e text, 9999px radius, 4px 12px padding, 13px Inter weight 500, uppercase." -- "Create navigation: white sticky header with backdrop-filter blur(12px). Inter 15px weight 500 for links, #0d0d0d text. Dark pill CTA 'Get Started' right-aligned, 9999px radius. Bottom border: 1px solid rgba(0,0,0,0.05)." -- "Design a trust section showing company logos in muted gray. Grid layout with 16px radius containers, 1px border at 5% opacity. Label above: 'Loved by your favorite companies' at 13px Inter weight 500, uppercase, tracking 0.65px." - -### Iteration Guide -1. Always use full-pill radius (9999px) for buttons and inputs — this is Mintlify's signature shape -2. Keep borders at 5% opacity (`rgba(0,0,0,0.05)`) — stronger borders break the airy feeling -3. Letter-spacing scales with font size: -1.28px at 64px, -0.8px at 40px, -0.24px at 24px, normal at 16px -4. Three weights only: 400 (read), 500 (interact), 600 (announce) -5. Brand green (`#18E299`) is used sparingly — CTAs and hover states only, never for decorative fills -6. Geist Mono uppercase for technical labels, Inter for everything else -7. Section padding is generous: 64px–96px on desktop, 48px on mobile -8. No gray background sections — white throughout, separation through borders and whitespace diff --git a/design/mintlify/README.md b/design/mintlify/README.md deleted file mode 100644 index 9535ce5..0000000 --- a/design/mintlify/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Mintlify Inspired Design System - -[DESIGN.md](https://github.com/VoltAgent/awesome-design-md/blob/main/design-md/mintlify/DESIGN.md) extracted from the public [Mintlify](https://mintlify.com/) website. This is not the official design system. Colors, fonts, and spacing may not be 100% accurate. But it's a good starting point for building something similar. - -## Files - -| File | Description | -|------|-------------| -| `DESIGN.md` | Complete design system documentation (9 sections) | -| `preview.html` | Interactive design token catalog (light) | -| `preview-dark.html` | Interactive design token catalog (dark) | - - -Use [DESIGN.md](https://github.com/VoltAgent/awesome-design-md/blob/main/design-md/mintlify/DESIGN.md) to use as a reference for AI agents (Claude, Cursor, Stitch) to generate UI that looks like the Mintlify design language. - -## Preview - -A sample landing page built with DESIGN.md. It shows the actual colors, typography, buttons, cards, spacing, and elevation, all in one page. - -### Dark Mode -![Mintlify Design System — Dark Mode](https://pub-2e4ecbcbc9b24e7b93f1a6ab5b2bc71f.r2.dev/designs/mintlify/preview-dark-screenshot.png) - -### Light Mode -![Mintlify Design System — Light Mode](https://pub-2e4ecbcbc9b24e7b93f1a6ab5b2bc71f.r2.dev/designs/mintlify/preview-screenshot.png) diff --git a/design/mintlify/preview-dark.html b/design/mintlify/preview-dark.html deleted file mode 100644 index 906f49e..0000000 --- a/design/mintlify/preview-dark.html +++ /dev/null @@ -1,409 +0,0 @@ - - - - - -Design System Inspired by Mintlify - - - - - - - -
Dark Mode
- - - -
-

Design System
Inspired by Mintlify

-

A design token catalog generated from DESIGN.md. Every color, font, component, and spacing value — visualized.

-
- Get Started - View Documentation -
-
- -
- -
-
01 / Colors
-

Color Palette

- -
Primary
-
-
Near Black
#0d0d0d
Dark background
-
Near White
#ededed
Primary text (dark)
-
Brand Green
#18E299
Brand accent, CTAs
-
- -
Brand Extended
-
-
Green Dark
#0d3d2a
Badge bg (dark)
-
Green Light
#5eedb8
Badge text (dark)
-
Annotate Green
#1ba673
Code annotations
-
- -
Semantic
-
-
Info Blue
#5b94e0
Tags, annotations
-
Warn Amber
#e6a733
Warnings, caution
-
Error Red
#e06b6b
Errors, destructive
-
- -
Neutral Scale (Dark)
-
-
Gray 700
#a0a0a0
Secondary text
-
Gray 500
#888888
Tertiary text
-
Gray 400
#666666
Placeholders
-
Gray 200
#2a2a2a
Borders
-
Gray 100
#1a1a1a
Surface
-
Gray 50
#141414
Card background
-
-
- -
- -
-
02 / Typography
-

Typography Scale

- -
Display Hero
Display Hero — 56px / 600 / 1.10 / -1.28px / Inter
-
Section Heading
Section Heading — 40px / 600 / 1.10 / -0.8px / Inter
-
Sub-heading
Sub-heading — 24px / 500 / 1.30 / -0.24px / Inter
-
Card Title
Card Title — 20px / 600 / 1.30 / -0.2px / Inter
-
Body Large — The intelligent knowledge platform that powers your documentation, APIs, and guides.
Body Large — 18px / 400 / 1.50 / normal / Inter
-
Body — Standard reading text for documentation and content.
Body — 16px / 400 / 1.50 / normal / Inter
-
Body Medium — Navigation and emphasized text
Body Medium — 16px / 500 / 1.50 / Inter
-
Button Label
Button — 15px / 500 / 1.50 / Inter
-
Link / Caption
Link / Caption — 14px / 500 / 1.50 / Inter
-
Section Label
Label Uppercase — 13px / 500 / uppercase / 0.65px / Inter
-
MONO TECHNICAL LABEL
Mono Code — 12px / 500 / uppercase / 0.6px / Geist Mono
-
MICRO LABEL
Mono Micro — 10px / 500 / uppercase / Geist Mono
-
- -
- -
-
03 / Buttons
-

Button Variants

-
- -
Documentation
Ghost / Outline
-
Start Building
Brand Accent
-
Documentation
Pill Badge
-
Info
Info Badge
-
Warning
Warning Badge
-
-
- -
- -
-
04 / Cards
-

Card Examples

-
-
-
Docs
-

Intelligent Search

-

AI-powered search that understands your documentation and delivers precise answers to developer questions.

-
-
-
API
-

API Reference

-

Auto-generated API documentation with interactive examples, authentication flows, and code snippets.

-
-
-
Analytics
-

Documentation Analytics

-

Track what developers search for, which pages perform best, and where they get stuck.

-
-
- -
-
Featured Card (24px radius)
- -
-
- -
- -
-
05 / Forms
-

Form Elements

-
Default (pill shape)
-
Focus (green ring)
-
Error (red ring)
-
-
- -
- -
-
06 / Spacing
-

Spacing Scale

-
-
2
-
4
-
6
-
8
-
10
-
12
-
16
-
24
-
32
-
48
-
64
-
-
- -
- -
-
07 / Radius
-

Border Radius Scale

-
-
4px
Code, tags
-
8px
Nav buttons
-
16px
Cards
-
24px
Featured
-
9999px
Buttons, pills
-
-
- -
- -
-
08 / Elevation
-

Elevation & Depth

-
-
Level 0: Flat
No shadow
-
Level 1: Subtle
6% border + ambient
-
Level 2: Medium
10% border + ambient
-
Level 3: Raised
Stronger shadow
-
Focus Ring
Brand green ring
-
-
- - - - - diff --git a/design/mintlify/preview.html b/design/mintlify/preview.html deleted file mode 100644 index 572afa5..0000000 --- a/design/mintlify/preview.html +++ /dev/null @@ -1,398 +0,0 @@ - - - - - -Design System Inspired by Mintlify - - - - - - - - - -
-

Design System
Inspired by Mintlify

-

A design token catalog generated from DESIGN.md. Every color, font, component, and spacing value — visualized.

-
- Get Started - View Documentation -
-
- -
- -
-
01 / Colors
-

Color Palette

- -
Primary
-
-
Near Black
#0d0d0d
Primary text, headings
-
Pure White
#ffffff
Page background
-
Brand Green
#18E299
Brand accent, CTAs
-
- -
Brand Extended
-
-
Green Light
#d4fae8
Badge backgrounds
-
Green Deep
#0fa76e
Badge text
-
Annotate Green
#1ba673
Code annotations
-
- -
Semantic
-
-
Info Blue
#3772cf
Tags, annotations
-
Warn Amber
#c37d0d
Warnings, caution
-
Error Red
#d45656
Errors, destructive
-
- -
Neutral Scale
-
-
Gray 700
#333333
Secondary text
-
Gray 500
#666666
Tertiary text
-
Gray 400
#888888
Placeholders
-
Gray 200
#e5e5e5
Borders
-
Gray 100
#f5f5f5
Subtle surface
-
Gray 50
#fafafa
Near-white tint
-
-
- -
- -
-
02 / Typography
-

Typography Scale

- -
Display Hero
Display Hero — 56px / 600 / 1.10 / -1.28px / Inter
-
Section Heading
Section Heading — 40px / 600 / 1.10 / -0.8px / Inter
-
Sub-heading
Sub-heading — 24px / 500 / 1.30 / -0.24px / Inter
-
Card Title
Card Title — 20px / 600 / 1.30 / -0.2px / Inter
-
Body Large — The intelligent knowledge platform that powers your documentation, APIs, and guides.
Body Large — 18px / 400 / 1.50 / normal / Inter
-
Body — Standard reading text for documentation and content.
Body — 16px / 400 / 1.50 / normal / Inter
-
Body Medium — Navigation and emphasized text
Body Medium — 16px / 500 / 1.50 / Inter
-
Button Label
Button — 15px / 500 / 1.50 / Inter
-
Link / Caption
Link / Caption — 14px / 500 / 1.50 / Inter
-
Section Label
Label Uppercase — 13px / 500 / uppercase / 0.65px / Inter
-
MONO TECHNICAL LABEL
Mono Code — 12px / 500 / uppercase / 0.6px / Geist Mono
-
MICRO LABEL
Mono Micro — 10px / 500 / uppercase / Geist Mono
-
- -
- -
-
03 / Buttons
-

Button Variants

-
-
Get Started
Primary Dark
-
Documentation
Ghost / Outline
-
Start Building
Brand Accent
-
Documentation
Pill Badge
-
Info
Info Badge
-
Warning
Warning Badge
-
-
- -
- -
-
04 / Cards
-

Card Examples

-
-
-
Docs
-

Intelligent Search

-

AI-powered search that understands your documentation and delivers precise answers to developer questions.

-
-
-
API
-

API Reference

-

Auto-generated API documentation with interactive examples, authentication flows, and code snippets.

-
-
-
Analytics
-

Documentation Analytics

-

Track what developers search for, which pages perform best, and where they get stuck.

-
-
- -
-
Featured Card (24px radius)
- -
-
- -
- -
-
05 / Forms
-

Form Elements

-
Default (pill shape)
-
Focus (green ring)
-
Error (red ring)
-
-
- -
- -
-
06 / Spacing
-

Spacing Scale

-
-
2
-
4
-
6
-
8
-
10
-
12
-
16
-
24
-
32
-
48
-
64
-
-
- -
- -
-
07 / Radius
-

Border Radius Scale

-
-
4px
Code, tags
-
8px
Nav buttons
-
16px
Cards
-
24px
Featured
-
9999px
Buttons, pills
-
-
- -
- -
-
08 / Elevation
-

Elevation & Depth

-
-
Level 0: Flat
No shadow
-
Level 1: Subtle
5% border + ambient
-
Level 2: Medium
8% border + ambient
-
Level 3: Raised
Stronger shadow
-
Focus Ring
Brand green ring
-
-
- - - - - diff --git a/design/pages/auth.md b/design/pages/auth.md new file mode 100644 index 0000000..9f17b64 --- /dev/null +++ b/design/pages/auth.md @@ -0,0 +1,82 @@ +# 任务 +按照/design/BaseInfo.md中要求,将登录页面、注册页面和忘记密码页面的元素和交互设计为 React 组件,如果有可以提取为公共组件的元素,先检查是否已存在,没有则放入 /src/components/ 目录下。 + +## 强制规则 +- 支持国际化 + - 语言:中文、英语,默认使用中文 + - 实现方式:i18next + - 翻译文件位置:src/i18n/zh.json、src/i18n/en.json + - 组件内使用:useTranslation hook + - 组件内必须使用翻译函数进行文本渲染 + - 组件内不能直接使用硬编码的文本 +- 样式规范 + - 组件内必须使用 tailwindcss 进行样式设计 + - 组件内不能使用内联样式 + +## 页面组成 +### 1. 登录页面 +- 元素: + - 系统 logo + - 用户名输入框(带校验) + - 密码输入框(带校验,显示/隐藏密码功能) + - 记住我 checkbox + - 登录按钮 + - 注册(超链接) + - 忘记密码(超链接) +- 交互: + - 用户名:必填,格式校验 + - 密码:必填,长度至少 6 位 + - 点击登录:提交表单,显示加载状态 + - 登录失败:显示错误信息 + - 注册链接(超链接):点击跳转到注册页面 + +### 2. 注册页面 +- 元素: + - 系统 logo + - 用户名输入框(带校验) + - 密码输入框(带校验) + - 确认密码输入框(带校验) + - 取消按钮 + - 注册按钮 + - 返回登录(超链接) +- 交互: + - 用户名:必填,格式校验,唯一性检查 + - 密码:必填,长度至少 6 位,包含字母和数字 + - 确认密码:必须与密码一致 + - 点击注册:提交表单,显示加载状态 + - 注册失败:显示错误信息 + - 取消按钮:返回登录页面 + +### 3. 忘记密码页面 +- 元素: + - 系统 logo + - 用户名输入框(带校验) + - 密码输入框(带校验) + - 确认密码输入框(带校验) + - 取消按钮 + - 重置密码按钮 + - 返回登录(超链接) +- 交互: + - 用户名:必填,格式校验,唯一性检查 + - 密码:必填,长度至少 6 位,包含字母和数字 + - 确认密码:必须与密码一致 + - 点击重置密码:提交表单,显示加载状态 + - 重置密码失败:显示错误信息 + - 取消按钮:返回登录页面 + +## 安全考虑 +- 密码加密:使用 bcrypt 或类似算法 +- 认证:JWT token +- CSRF 防护:使用 CSRF token +- XSS 防护:使用 React 的内置防护 +- 数据验证:前端和后端双重验证 + +## 国际化 +- 支持语言:中文、英语,默认使用中文 +- 实现方式:i18next +- 翻译文件位置:src/i18n/zh.json、src/i18n/en.json +- 组件内使用:useTranslation hook + + +## 检查样式 +完成组件生成后,严格按照 /design/DESIGN.md 中的设计规范,使用light-mode模式,检查本项目中的样式设置,修复不符合设计规范的样式 \ No newline at end of file diff --git a/design/pages/project.md b/design/pages/project.md new file mode 100644 index 0000000..f6c7752 --- /dev/null +++ b/design/pages/project.md @@ -0,0 +1,38 @@ +# 任务 +按照/design/BaseInfo.md中要求,将项目管理页面的元素和交互设计为 React 组件; +如果有可以提取为公共组件的元素, + 1、先检查是否公共组件已存在,不存在则放入 /src/components/ 目录下。 + 2、如果已存在,是否有新的需求或改进,如果需要更新,更新组件代码,同时检查用到该组件的页面是否需要更新引用。 + 3、如果已存在但不需要更新,则直接使用已有的组件。 + +## 强制规则 +- 支持国际化 + - 语言:中文、英语,默认使用中文 + - 实现方式:i18next + - 翻译文件位置:src/i18n/zh.json、src/i18n/en.json + - 组件内使用:useTranslation hook + - 组件内必须使用翻译函数进行文本渲染 + - 组件内不能直接使用硬编码的文本 +- 样式规范 + - 组件内必须使用 tailwindcss 进行样式设计 + - 组件内不能使用内联样式 + +## 页面组成 +### 5. 项目管理 +- 项目列表: + - 卡片的形式展示 + - 显示项目名称、创建时间、卡片背景为图片,先占位,后续根据需求调整 + - 卡片底部操作:默认不显示,鼠标悬停在卡片上显示操作按钮 + - 编辑按钮:点击后跳转到项目编辑页 + - 删除按钮:点击后弹窗提示,是否确认删除项目,用户确认后,删除项目,确认删除后刷新页面 +- 搜索和筛选功能: + - 搜索框:输入项目名称搜索项目,输入完成按下enter键后请求后端搜索项目,返回搜索结果 + - 筛选框:根据项目状态筛选项目,选择项目状态后请求后端筛选项目,返回筛选结果 +- 分页功能: + - 显示当前页码、每页显示项目数、总项目数 + - 分页按钮:点击后切换到对应页码 +- 批量操作:选中项目后,弹窗提示,用户确认删除选中项目,用户确认删除后,删除选中项目,确认删除后刷新页面,预留向后端发送请求删除选中项目 +- 创建新项目按钮,点击后打开创建新项目的弹窗,弹窗内容: + - 项目名称输入框 + - 项目描述输入框 + - 保存按钮:点击后创建新项目,并刷新页面,预留向后端发送请求创建新项目 diff --git a/design/pages/setting.md b/design/pages/setting.md new file mode 100644 index 0000000..672e74f --- /dev/null +++ b/design/pages/setting.md @@ -0,0 +1,37 @@ +# 任务 +按照/design/BaseInfo.md中要求,将设置页面的元素和交互设计为 React 组件; +如果有可以提取为公共组件的元素, + 1、先检查是否公共组件已存在,不存在则放入 /src/components/ 目录下。 + 2、如果已存在,是否有新的需求或改进,如果需要更新,更新组件代码,同时检查用到该组件的页面是否需要更新引用。 + 3、如果已存在但不需要更新,则直接使用已有的组件。 + +## 强制规则 +- 支持国际化 + - 语言:中文、英语,默认使用中文 + - 实现方式:i18next + - 翻译文件位置:src/i18n/zh.json、src/i18n/en.json + - 组件内使用:useTranslation hook + - 组件内必须使用翻译函数进行文本渲染 + - 组件内不能直接使用硬编码的文本 +- 样式规范 + - 组件内必须使用 tailwindcss 进行样式设计 + - 组件内不能使用内联样式 + +## 页面组成 +### 1. 设置页面 +分成4个tab: +- 个人信息: + - 用户名、邮箱、头像等 + - 保存按钮:点击后更新个人信息,并刷新页面,预留向后端发送请求更新个人信息 +- 密码修改: + - 旧密码输入框 + - 新密码输入框 + - 确认新密码输入框 + - 保存按钮:点击后更新密码,并刷新页面,预留向后端发送请求更新密码 +- 语言设置: + - 中文、英语切换 + - 保存按钮:点击后切换语言,并刷新页面,预留向后端发送请求更新语言 +- 通知设置: + - 邮件通知开关 + - 系统通知开关 + - 保存按钮:点击后更新通知设置,并刷新页面,预留向后端发送请求更新通知设置 diff --git a/design/pages/systemLayout.md b/design/pages/systemLayout.md new file mode 100644 index 0000000..685db0e --- /dev/null +++ b/design/pages/systemLayout.md @@ -0,0 +1,39 @@ +# 任务 +按照/design/BaseInfo.md中要求,将系统布局、首页的元素和交互设计为 React 组件; +如果有可以提取为公共组件的元素, + 1、先检查是否公共组件已存在,不存在则放入 /src/components/ 目录下。 + 2、如果已存在,是否有新的需求或改进,如果需要更新,更新组件代码,同时检查用到该组件的页面是否需要更新引用。 + 3、如果已存在但不需要更新,则直接使用已有的组件。 + +## 强制规则 +- 支持国际化 + - 语言:中文、英语,默认使用中文 + - 实现方式:i18next + - 翻译文件位置:src/i18n/zh.json、src/i18n/en.json + - 组件内使用:useTranslation hook + - 组件内必须使用翻译函数进行文本渲染 + - 组件内不能直接使用硬编码的文本 +- 样式规范 + - 组件内必须使用 tailwindcss 进行样式设计 + - 组件内不能使用内联样式 + +## 页面组成 +### 1. 系统布局 +- 左侧菜单树: + - 菜单项:首页、项目管理、设置 + - 展开/收起功能 +- 顶部导航栏: + - 系统标题 + - 右侧:通知图标、用户菜单 +- 主体区域:显示当前选中的页面内容 +- 响应式:在小屏幕设备上,左侧菜单可折叠 + +### 2. 首页 +- 欢迎信息:显示当前用户名 +- 项目统计: + - 总项目数 + - 活跃项目数 + - 最近创建的项目 +- 快捷操作:创建新项目、查看所有项目 +- 系统状态:显示系统运行状态 +- 更新登录按钮逻辑:登录成功后:点击后跳转到首页 diff --git a/design/stripe/DESIGN.md b/design/stripe/DESIGN.md deleted file mode 100644 index ba4f1bf..0000000 --- a/design/stripe/DESIGN.md +++ /dev/null @@ -1,322 +0,0 @@ -# Design System Inspiration of Stripe - -## 1. Visual Theme & Atmosphere - -Stripe's website is the gold standard of fintech design -- a system that manages to feel simultaneously technical and luxurious, precise and warm. The page opens on a clean white canvas (`#ffffff`) with deep navy headings (`#061b31`) and a signature purple (`#533afd`) that functions as both brand anchor and interactive accent. This isn't the cold, clinical purple of enterprise software; it's a rich, saturated violet that reads as confident and premium. The overall impression is of a financial institution redesigned by a world-class type foundry. - -The custom `sohne-var` variable font is the defining element of Stripe's visual identity. Every text element enables the OpenType `"ss01"` stylistic set, which modifies character shapes for a distinctly geometric, modern feel. At display sizes (48px-56px), sohne-var runs at weight 300 -- an extraordinarily light weight for headlines that creates an ethereal, almost whispered authority. This is the opposite of the "bold hero headline" convention; Stripe's headlines feel like they don't need to shout. The negative letter-spacing (-1.4px at 56px, -0.96px at 48px) tightens the text into dense, engineered blocks. At smaller sizes, the system also uses weight 300 with proportionally reduced tracking, and tabular numerals via `"tnum"` for financial data display. - -What truly distinguishes Stripe is its shadow system. Rather than the flat or single-layer approach of most sites, Stripe uses multi-layer, blue-tinted shadows: the signature `rgba(50,50,93,0.25)` combined with `rgba(0,0,0,0.1)` creates shadows with a cool, almost atmospheric depth -- like elements are floating in a twilight sky. The blue-gray undertone of the primary shadow color (50,50,93) ties directly to the navy-purple brand palette, making even elevation feel on-brand. - -**Key Characteristics:** -- sohne-var with OpenType `"ss01"` on all text -- a custom stylistic set that defines the brand's letterforms -- Weight 300 as the signature headline weight -- light, confident, anti-convention -- Negative letter-spacing at display sizes (-1.4px at 56px, progressive relaxation downward) -- Blue-tinted multi-layer shadows using `rgba(50,50,93,0.25)` -- elevation that feels brand-colored -- Deep navy (`#061b31`) headings instead of black -- warm, premium, financial-grade -- Conservative border-radius (4px-8px) -- nothing pill-shaped, nothing harsh -- Ruby (`#ea2261`) and magenta (`#f96bee`) accents for gradient and decorative elements -- `SourceCodePro` as the monospace companion for code and technical labels - -## 2. Color Palette & Roles - -### Primary -- **Stripe Purple** (`#533afd`): Primary brand color, CTA backgrounds, link text, interactive highlights. A saturated blue-violet that anchors the entire system. -- **Deep Navy** (`#061b31`): `--hds-color-heading-solid`. Primary heading color. Not black, not gray -- a very dark blue that adds warmth and depth to text. -- **Pure White** (`#ffffff`): Page background, card surfaces, button text on dark backgrounds. - -### Brand & Dark -- **Brand Dark** (`#1c1e54`): `--hds-color-util-brand-900`. Deep indigo for dark sections, footer backgrounds, and immersive brand moments. -- **Dark Navy** (`#0d253d`): `--hds-color-core-neutral-975`. The darkest neutral -- almost-black with a blue undertone for maximum depth without harshness. - -### Accent Colors -- **Ruby** (`#ea2261`): `--hds-color-accentColorMode-ruby-icon-solid`. Warm red-pink for icons, alerts, and accent elements. -- **Magenta** (`#f96bee`): `--hds-color-accentColorMode-magenta-icon-gradientMiddle`. Vivid pink-purple for gradients and decorative highlights. -- **Magenta Light** (`#ffd7ef`): `--hds-color-util-accent-magenta-100`. Tinted surface for magenta-themed cards and badges. - -### Interactive -- **Primary Purple** (`#533afd`): Primary link color, active states, selected elements. -- **Purple Hover** (`#4434d4`): Darker purple for hover states on primary elements. -- **Purple Deep** (`#2e2b8c`): `--hds-color-button-ui-iconHover`. Dark purple for icon hover states. -- **Purple Light** (`#b9b9f9`): `--hds-color-action-bg-subduedHover`. Soft lavender for subdued hover backgrounds. -- **Purple Mid** (`#665efd`): `--hds-color-input-selector-text-range`. Range selector and input highlight color. - -### Neutral Scale -- **Heading** (`#061b31`): Primary headings, nav text, strong labels. -- **Label** (`#273951`): `--hds-color-input-text-label`. Form labels, secondary headings. -- **Body** (`#64748d`): Secondary text, descriptions, captions. -- **Success Green** (`#15be53`): Status badges, success indicators (with 0.2-0.4 alpha for backgrounds/borders). -- **Success Text** (`#108c3d`): Success badge text color. -- **Lemon** (`#9b6829`): `--hds-color-core-lemon-500`. Warning and highlight accent. - -### Surface & Borders -- **Border Default** (`#e5edf5`): Standard border color for cards, dividers, and containers. -- **Border Purple** (`#b9b9f9`): Active/selected state borders on buttons and inputs. -- **Border Soft Purple** (`#d6d9fc`): Subtle purple-tinted borders for secondary elements. -- **Border Magenta** (`#ffd7ef`): Pink-tinted borders for magenta-themed elements. -- **Border Dashed** (`#362baa`): Dashed borders for drop zones and placeholder elements. - -### Shadow Colors -- **Shadow Blue** (`rgba(50,50,93,0.25)`): The signature -- blue-tinted primary shadow color. -- **Shadow Dark Blue** (`rgba(3,3,39,0.25)`): Deeper blue shadow for elevated elements. -- **Shadow Black** (`rgba(0,0,0,0.1)`): Secondary shadow layer for depth reinforcement. -- **Shadow Ambient** (`rgba(23,23,23,0.08)`): Soft ambient shadow for subtle elevation. -- **Shadow Soft** (`rgba(23,23,23,0.06)`): Minimal ambient shadow for light lift. - -## 3. Typography Rules - -### Font Family -- **Primary**: `sohne-var`, with fallback: `SF Pro Display` -- **Monospace**: `SourceCodePro`, with fallback: `SFMono-Regular` -- **OpenType Features**: `"ss01"` enabled globally on all sohne-var text; `"tnum"` for tabular numbers on financial data and captions. - -### Hierarchy - -| Role | Font | Size | Weight | Line Height | Letter Spacing | Features | Notes | -|------|------|------|--------|-------------|----------------|----------|-------| -| Display Hero | sohne-var | 56px (3.50rem) | 300 | 1.03 (tight) | -1.4px | ss01 | Maximum size, whisper-weight authority | -| Display Large | sohne-var | 48px (3.00rem) | 300 | 1.15 (tight) | -0.96px | ss01 | Secondary hero headlines | -| Section Heading | sohne-var | 32px (2.00rem) | 300 | 1.10 (tight) | -0.64px | ss01 | Feature section titles | -| Sub-heading Large | sohne-var | 26px (1.63rem) | 300 | 1.12 (tight) | -0.26px | ss01 | Card headings, sub-sections | -| Sub-heading | sohne-var | 22px (1.38rem) | 300 | 1.10 (tight) | -0.22px | ss01 | Smaller section heads | -| Body Large | sohne-var | 18px (1.13rem) | 300 | 1.40 | normal | ss01 | Feature descriptions, intro text | -| Body | sohne-var | 16px (1.00rem) | 300-400 | 1.40 | normal | ss01 | Standard reading text | -| Button | sohne-var | 16px (1.00rem) | 400 | 1.00 (tight) | normal | ss01 | Primary button text | -| Button Small | sohne-var | 14px (0.88rem) | 400 | 1.00 (tight) | normal | ss01 | Secondary/compact buttons | -| Link | sohne-var | 14px (0.88rem) | 400 | 1.00 (tight) | normal | ss01 | Navigation links | -| Caption | sohne-var | 13px (0.81rem) | 400 | normal | normal | ss01 | Small labels, metadata | -| Caption Small | sohne-var | 12px (0.75rem) | 300-400 | 1.33-1.45 | normal | ss01 | Fine print, timestamps | -| Caption Tabular | sohne-var | 12px (0.75rem) | 300-400 | 1.33 | -0.36px | tnum | Financial data, numbers | -| Micro | sohne-var | 10px (0.63rem) | 300 | 1.15 (tight) | 0.1px | ss01 | Tiny labels, axis markers | -| Micro Tabular | sohne-var | 10px (0.63rem) | 300 | 1.15 (tight) | -0.3px | tnum | Chart data, small numbers | -| Nano | sohne-var | 8px (0.50rem) | 300 | 1.07 (tight) | normal | ss01 | Smallest labels | -| Code Body | SourceCodePro | 12px (0.75rem) | 500 | 2.00 (relaxed) | normal | -- | Code blocks, syntax | -| Code Bold | SourceCodePro | 12px (0.75rem) | 700 | 2.00 (relaxed) | normal | -- | Bold code, keywords | -| Code Label | SourceCodePro | 12px (0.75rem) | 500 | 2.00 (relaxed) | normal | uppercase | Technical labels | -| Code Micro | SourceCodePro | 9px (0.56rem) | 500 | 1.00 (tight) | normal | ss01 | Tiny code annotations | - -### Principles -- **Light weight as signature**: Weight 300 at display sizes is Stripe's most distinctive typographic choice. Where others use 600-700 to command attention, Stripe uses lightness as luxury -- the text is so confident it doesn't need weight to be authoritative. -- **ss01 everywhere**: The `"ss01"` stylistic set is non-negotiable. It modifies specific glyphs (likely alternate `a`, `g`, `l` forms) to create a more geometric, contemporary feel across all sohne-var text. -- **Two OpenType modes**: `"ss01"` for display/body text, `"tnum"` for tabular numerals in financial data. These never overlap -- a number in a paragraph uses ss01, a number in a data table uses tnum. -- **Progressive tracking**: Letter-spacing tightens proportionally with size: -1.4px at 56px, -0.96px at 48px, -0.64px at 32px, -0.26px at 26px, normal at 16px and below. -- **Two-weight simplicity**: Primarily 300 (body and headings) and 400 (UI/buttons). No bold (700) in the primary font -- SourceCodePro uses 500/700 for code contrast. - -## 4. Component Stylings - -### Buttons - -**Primary Purple** -- Background: `#533afd` -- Text: `#ffffff` -- Padding: 8px 16px -- Radius: 4px -- Font: 16px sohne-var weight 400, `"ss01"` -- Hover: `#4434d4` background -- Use: Primary CTA ("Start now", "Contact sales") - -**Ghost / Outlined** -- Background: transparent -- Text: `#533afd` -- Padding: 8px 16px -- Radius: 4px -- Border: `1px solid #b9b9f9` -- Font: 16px sohne-var weight 400, `"ss01"` -- Hover: background shifts to `rgba(83,58,253,0.05)` -- Use: Secondary actions - -**Transparent Info** -- Background: transparent -- Text: `#2874ad` -- Padding: 8px 16px -- Radius: 4px -- Border: `1px solid rgba(43,145,223,0.2)` -- Use: Tertiary/info-level actions - -**Neutral Ghost** -- Background: transparent (`rgba(255,255,255,0)`) -- Text: `rgba(16,16,16,0.3)` -- Padding: 8px 16px -- Radius: 4px -- Outline: `1px solid rgb(212,222,233)` -- Use: Disabled or muted actions - -### Cards & Containers -- Background: `#ffffff` -- Border: `1px solid #e5edf5` (standard) or `1px solid #061b31` (dark accent) -- Radius: 4px (tight), 5px (standard), 6px (comfortable), 8px (featured) -- Shadow (standard): `rgba(50,50,93,0.25) 0px 30px 45px -30px, rgba(0,0,0,0.1) 0px 18px 36px -18px` -- Shadow (ambient): `rgba(23,23,23,0.08) 0px 15px 35px 0px` -- Hover: shadow intensifies, often adding the blue-tinted layer - -### Badges / Tags / Pills -**Neutral Pill** -- Background: `#ffffff` -- Text: `#000000` -- Padding: 0px 6px -- Radius: 4px -- Border: `1px solid #f6f9fc` -- Font: 11px weight 400 - -**Success Badge** -- Background: `rgba(21,190,83,0.2)` -- Text: `#108c3d` -- Padding: 1px 6px -- Radius: 4px -- Border: `1px solid rgba(21,190,83,0.4)` -- Font: 10px weight 300 - -### Inputs & Forms -- Border: `1px solid #e5edf5` -- Radius: 4px -- Focus: `1px solid #533afd` or purple ring -- Label: `#273951`, 14px sohne-var -- Text: `#061b31` -- Placeholder: `#64748d` - -### Navigation -- Clean horizontal nav on white, sticky with blur backdrop -- Brand logotype left-aligned -- Links: sohne-var 14px weight 400, `#061b31` text with `"ss01"` -- Radius: 6px on nav container -- CTA: purple button right-aligned ("Sign in", "Start now") -- Mobile: hamburger toggle with 6px radius - -### Decorative Elements -**Dashed Borders** -- `1px dashed #362baa` (purple) for placeholder/drop zones -- `1px dashed #ffd7ef` (magenta) for magenta-themed decorative borders - -**Gradient Accents** -- Ruby-to-magenta gradients (`#ea2261` to `#f96bee`) for hero decorations -- Brand dark sections use `#1c1e54` backgrounds with white text - -## 5. Layout Principles - -### Spacing System -- Base unit: 8px -- Scale: 1px, 2px, 4px, 6px, 8px, 10px, 11px, 12px, 14px, 16px, 18px, 20px -- Notable: The scale is dense at the small end (every 2px from 4-12), reflecting Stripe's precision-oriented UI for financial data - -### Grid & Container -- Max content width: approximately 1080px -- Hero: centered single-column with generous padding, lightweight headlines -- Feature sections: 2-3 column grids for feature cards -- Full-width dark sections with `#1c1e54` background for brand immersion -- Code/dashboard previews as contained cards with blue-tinted shadows - -### Whitespace Philosophy -- **Precision spacing**: Unlike the vast emptiness of minimalist systems, Stripe uses measured, purposeful whitespace. Every gap is a deliberate typographic choice. -- **Dense data, generous chrome**: Financial data displays (tables, charts) are tightly packed, but the UI chrome around them is generously spaced. This creates a sense of controlled density -- like a well-organized spreadsheet in a beautiful frame. -- **Section rhythm**: White sections alternate with dark brand sections (`#1c1e54`), creating a dramatic light/dark cadence that prevents monotony without introducing arbitrary color. - -### Border Radius Scale -- Micro (1px): Fine-grained elements, subtle rounding -- Standard (4px): Buttons, inputs, badges, cards -- the workhorse -- Comfortable (5px): Standard card containers -- Relaxed (6px): Navigation, larger interactive elements -- Large (8px): Featured cards, hero elements -- Compound: `0px 0px 6px 6px` for bottom-rounded containers (tab panels, dropdown footers) - -## 6. Depth & Elevation - -| Level | Treatment | Use | -|-------|-----------|-----| -| Flat (Level 0) | No shadow | Page background, inline text | -| Ambient (Level 1) | `rgba(23,23,23,0.06) 0px 3px 6px` | Subtle card lift, hover hints | -| Standard (Level 2) | `rgba(23,23,23,0.08) 0px 15px 35px` | Standard cards, content panels | -| Elevated (Level 3) | `rgba(50,50,93,0.25) 0px 30px 45px -30px, rgba(0,0,0,0.1) 0px 18px 36px -18px` | Featured cards, dropdowns, popovers | -| Deep (Level 4) | `rgba(3,3,39,0.25) 0px 14px 21px -14px, rgba(0,0,0,0.1) 0px 8px 17px -8px` | Modals, floating panels | -| Ring (Accessibility) | `2px solid #533afd` outline | Keyboard focus ring | - -**Shadow Philosophy**: Stripe's shadow system is built on a principle of chromatic depth. Where most design systems use neutral gray or black shadows, Stripe's primary shadow color (`rgba(50,50,93,0.25)`) is a deep blue-gray that echoes the brand's navy palette. This creates shadows that don't just add depth -- they add brand atmosphere. The multi-layer approach pairs this blue-tinted shadow with a pure black secondary layer (`rgba(0,0,0,0.1)`) at a different offset, creating a parallax-like depth where the branded shadow sits farther from the element and the neutral shadow sits closer. The negative spread values (-30px, -18px) ensure shadows don't extend beyond the element's footprint horizontally, keeping elevation vertical and controlled. - -### Decorative Depth -- Dark brand sections (`#1c1e54`) create immersive depth through background color contrast -- Gradient overlays with ruby-to-magenta transitions for hero decorations -- Shadow color `rgba(0,55,112,0.08)` (`--hds-color-shadow-sm-top`) for top-edge shadows on sticky elements - -## 7. Do's and Don'ts - -### Do -- Use sohne-var with `"ss01"` on every text element -- the stylistic set IS the brand -- Use weight 300 for all headlines and body text -- lightness is the signature -- Apply blue-tinted shadows (`rgba(50,50,93,0.25)`) for all elevated elements -- Use `#061b31` (deep navy) for headings instead of `#000000` -- the warmth matters -- Keep border-radius between 4px-8px -- conservative rounding is intentional -- Use `"tnum"` for any tabular/financial number display -- Layer shadows: blue-tinted far + neutral close for depth parallax -- Use `#533afd` purple as the primary interactive/CTA color - -### Don't -- Don't use weight 600-700 for sohne-var headlines -- weight 300 is the brand voice -- Don't use large border-radius (12px+, pill shapes) on cards or buttons -- Stripe is conservative -- Don't use neutral gray shadows -- always tint with blue (`rgba(50,50,93,...)`) -- Don't skip `"ss01"` on any sohne-var text -- the alternate glyphs define the personality -- Don't use pure black (`#000000`) for headings -- always `#061b31` deep navy -- Don't use warm accent colors (orange, yellow) for interactive elements -- purple is primary -- Don't apply positive letter-spacing at display sizes -- Stripe tracks tight -- Don't use the magenta/ruby accents for buttons or links -- they're decorative/gradient only - -## 8. Responsive Behavior - -### Breakpoints -| Name | Width | Key Changes | -|------|-------|-------------| -| Mobile | <640px | Single column, reduced heading sizes, stacked cards | -| Tablet | 640-1024px | 2-column grids, moderate padding | -| Desktop | 1024-1280px | Full layout, 3-column feature grids | -| Large Desktop | >1280px | Centered content with generous margins | - -### Touch Targets -- Buttons use comfortable padding (8px-16px vertical) -- Navigation links at 14px with adequate spacing -- Badges have 6px horizontal padding minimum for tap targets -- Mobile nav toggle with 6px radius button - -### Collapsing Strategy -- Hero: 56px display -> 32px on mobile, weight 300 maintained -- Navigation: horizontal links + CTAs -> hamburger toggle -- Feature cards: 3-column -> 2-column -> single column stacked -- Dark brand sections: maintain full-width treatment, reduce internal padding -- Financial data tables: horizontal scroll on mobile -- Section spacing: 64px+ -> 40px on mobile -- Typography scale compresses: 56px -> 48px -> 32px hero sizes across breakpoints - -### Image Behavior -- Dashboard/product screenshots maintain blue-tinted shadow at all sizes -- Hero gradient decorations simplify on mobile -- Code blocks maintain `SourceCodePro` treatment, may horizontally scroll -- Card images maintain consistent 4px-6px border-radius - -## 9. Agent Prompt Guide - -### Quick Color Reference -- Primary CTA: Stripe Purple (`#533afd`) -- CTA Hover: Purple Dark (`#4434d4`) -- Background: Pure White (`#ffffff`) -- Heading text: Deep Navy (`#061b31`) -- Body text: Slate (`#64748d`) -- Label text: Dark Slate (`#273951`) -- Border: Soft Blue (`#e5edf5`) -- Link: Stripe Purple (`#533afd`) -- Dark section: Brand Dark (`#1c1e54`) -- Success: Green (`#15be53`) -- Accent decorative: Ruby (`#ea2261`), Magenta (`#f96bee`) - -### Example Component Prompts -- "Create a hero section on white background. Headline at 48px sohne-var weight 300, line-height 1.15, letter-spacing -0.96px, color #061b31, font-feature-settings 'ss01'. Subtitle at 18px weight 300, line-height 1.40, color #64748d. Purple CTA button (#533afd, 4px radius, 8px 16px padding, white text) and ghost button (transparent, 1px solid #b9b9f9, #533afd text, 4px radius)." -- "Design a card: white background, 1px solid #e5edf5 border, 6px radius. Shadow: rgba(50,50,93,0.25) 0px 30px 45px -30px, rgba(0,0,0,0.1) 0px 18px 36px -18px. Title at 22px sohne-var weight 300, letter-spacing -0.22px, color #061b31, 'ss01'. Body at 16px weight 300, #64748d." -- "Build a success badge: rgba(21,190,83,0.2) background, #108c3d text, 4px radius, 1px 6px padding, 10px sohne-var weight 300, border 1px solid rgba(21,190,83,0.4)." -- "Create navigation: white sticky header with backdrop-filter blur(12px). sohne-var 14px weight 400 for links, #061b31 text, 'ss01'. Purple CTA 'Start now' right-aligned (#533afd bg, white text, 4px radius). Nav container 6px radius." -- "Design a dark brand section: #1c1e54 background, white text. Headline 32px sohne-var weight 300, letter-spacing -0.64px, 'ss01'. Body 16px weight 300, rgba(255,255,255,0.7). Cards inside use rgba(255,255,255,0.1) border with 6px radius." - -### Iteration Guide -1. Always enable `font-feature-settings: "ss01"` on sohne-var text -- this is the brand's typographic DNA -2. Weight 300 is the default; use 400 only for buttons/links/navigation -3. Shadow formula: `rgba(50,50,93,0.25) 0px Y1 B1 -S1, rgba(0,0,0,0.1) 0px Y2 B2 -S2` where Y1/B1 are larger (far shadow) and Y2/B2 are smaller (near shadow) -4. Heading color is `#061b31` (deep navy), body is `#64748d` (slate), labels are `#273951` (dark slate) -5. Border-radius stays in the 4px-8px range -- never use pill shapes or large rounding -6. Use `"tnum"` for any numbers in tables, charts, or financial displays -7. Dark sections use `#1c1e54` -- not black, not gray, but a deep branded indigo -8. SourceCodePro for code at 12px/500 with 2.00 line-height (very generous for readability) diff --git a/design/stripe/README.md b/design/stripe/README.md deleted file mode 100644 index c7364a4..0000000 --- a/design/stripe/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Stripe Inspired Design System - -[DESIGN.md](https://github.com/VoltAgent/awesome-design-md/blob/main/design-md/stripe/DESIGN.md) extracted from the public [Stripe](https://stripe.com/) website. This is not the official design system. Colors, fonts, and spacing may not be 100% accurate. But it's a good starting point for building something similar. - -## Files - -| File | Description | -|------|-------------| -| `DESIGN.md` | Complete design system documentation (9 sections) | -| `preview.html` | Interactive design token catalog (light) | -| `preview-dark.html` | Interactive design token catalog (dark) | - - -Use [DESIGN.md](https://github.com/VoltAgent/awesome-design-md/blob/main/design-md/stripe/DESIGN.md) to use as a reference for AI agents (Claude, Cursor, Stitch) to generate UI that looks like the Stripe design language. - -## Preview - -A sample landing page built with DESIGN.md. It shows the actual colors, typography, buttons, cards, spacing, and elevation, all in one page. - -### Dark Mode -![Stripe Design System — Dark Mode](https://pub-2e4ecbcbc9b24e7b93f1a6ab5b2bc71f.r2.dev/designs/stripe/preview-dark-screenshot.png) - -### Light Mode -![Stripe Design System — Light Mode](https://pub-2e4ecbcbc9b24e7b93f1a6ab5b2bc71f.r2.dev/designs/stripe/preview-screenshot.png) diff --git a/design/stripe/preview-dark.html b/design/stripe/preview-dark.html deleted file mode 100644 index 11dc46f..0000000 --- a/design/stripe/preview-dark.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - -Design System Inspired by Stripe - - - - - - - - -
Dark Mode
- -
-

Design System
Inspired by Stripe

-

A design token catalog generated from DESIGN.md. Every color, font, component, and spacing value -- visualized.

-
- Start now - View Documentation -
-
- -
- -
-
01 / Colors
-

Color Palette

- -
Primary
-
-
Stripe Purple
#533afd
Primary brand, CTA
-
Deep Navy
#061b31
Headings
-
White
#ffffff
Page background
-
- -
Brand & Dark
-
-
Brand Dark
#1c1e54
Dark sections
-
Dark Navy
#0d253d
Darkest neutral
-
- -
Accent
-
-
Ruby
#ea2261
Accent, alerts
-
Magenta
#f96bee
Gradients, decorative
-
Magenta Light
#ffd7ef
Tinted surface
-
- -
Interactive Purple Scale
-
-
Purple Hover
#4434d4
CTA hover state
-
Purple Mid
#665efd
Range selectors
-
Purple Light
#b9b9f9
Subdued hover bg
-
Purple Deep
#2e2b8c
Icon hover
-
- -
Neutral & Status
-
-
Dark Slate
#273951
Labels
-
Slate
#64748d
Body text
-
Border
#e5edf5
Default border
-
Success
#15be53
Status, badges
-
Lemon
#9b6829
Warning accent
-
- -
Border & Surface
-
-
Border Soft
#d6d9fc
Purple-tinted border
-
Dashed Border
#362baa
Drop zones
-
-
- -
- -
-
02 / Typography
-

Typography Scale

- -
Display Hero
Display Hero -- 56px / 300 / 1.03 / -1.4px / sohne-var "ss01"
-
Display Large
Display Large -- 48px / 300 / 1.15 / -0.96px / sohne-var "ss01"
-
Section Heading
Section Heading -- 32px / 300 / 1.10 / -0.64px / sohne-var "ss01"
-
Sub-heading Large
Sub-heading -- 26px / 300 / 1.12 / -0.26px / sohne-var "ss01"
-
Sub-heading
Sub-heading -- 22px / 300 / 1.10 / -0.22px / sohne-var "ss01"
-
Body Large -- Financial infrastructure for the internet. Millions of companies use Stripe to accept payments.
Body Large -- 18px / 300 / 1.40 / normal / sohne-var "ss01"
-
Body -- Standard reading text for descriptions and content.
Body -- 16px / 300 / 1.40 / normal / sohne-var "ss01"
-
Button Text
Button -- 16px / 400 / 1.00 / normal / sohne-var "ss01"
-
Link / Navigation
Link -- 14px / 400 / 1.00 / normal / sohne-var "ss01"
-
Caption -- Small labels and metadata
Caption -- 12px / 300 / 1.45 / normal / sohne-var "ss01"
-
$1,234,567.89
Tabular Numbers -- 12px / 300 / 1.33 / -0.36px / sohne-var "tnum"
-
const stripe = require('stripe')('sk_test_...');
Code Body -- 12px / 500 / 2.00 / Source Code Pro
-
API VERSION
Code Label -- 12px / 500 / uppercase / Source Code Pro
-
- -
- -
-
03 / Buttons
-

Button Variants

-
-
Start now
Primary Purple
-
Documentation
Ghost / Outlined
-
Learn more
Transparent Info
-
Disabled
Neutral Ghost
-
Active
Success Badge
-
v2024-12
Neutral Badge
-
-
- -
- -
-
04 / Cards
-

Card Examples

-
-
-
Payments
-

Online Payments

-

Accept payments online with a fully integrated suite of payment products. Optimized for conversion with pre-built checkout pages.

-
-
-
Elevated
-

Revenue Recognition

-

Automate your revenue reporting. Card shown with full shadow stack for elevated importance.

-
-
-
Connect
-

Platform Payments

-

Build a marketplace or platform with multi-party payments, instant payouts, and flexible revenue sharing.

-
-
-
- -
- -
-
05 / Forms
-

Form Elements

-
Default
-
Focus (purple ring)
-
Error (ruby ring)
-
-
- -
- -
-
06 / Spacing
-

Spacing Scale

-
-
2
-
4
-
6
-
8
-
10
-
12
-
14
-
16
-
18
-
20
-
-
- -
- -
-
07 / Radius
-

Border Radius

-
-
1px
Micro
-
4px
Buttons, inputs
-
5px
Standard cards
-
6px
Nav, large cards
-
8px
Featured
-
-
- -
- -
-
08 / Elevation
-

Elevation

-
-
Level 0: Flat
No shadow
-
Level 1: Subtle
Ambient soft
-
Level 2: Standard
Ambient card
-
Level 3: Elevated
Dual layer deep
-
Level 4: Deep
Dark deep
-
Focus
Purple ring
-
-
- - - - - diff --git a/design/stripe/preview.html b/design/stripe/preview.html deleted file mode 100644 index 674db92..0000000 --- a/design/stripe/preview.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - -Design System Inspired by Stripe - - - - - - - - - -
-

Design System
Inspired by Stripe

-

A design token catalog generated from DESIGN.md. Every color, font, component, and spacing value -- visualized.

-
- Start now - View Documentation -
-
- -
- -
-
01 / Colors
-

Color Palette

- -
Primary
-
-
Stripe Purple
#533afd
Primary brand, CTA
-
Deep Navy
#061b31
Headings
-
White
#ffffff
Page background
-
- -
Brand & Dark
-
-
Brand Dark
#1c1e54
Dark sections
-
Dark Navy
#0d253d
Darkest neutral
-
- -
Accent
-
-
Ruby
#ea2261
Accent, alerts
-
Magenta
#f96bee
Gradients, decorative
-
Magenta Light
#ffd7ef
Tinted surface
-
- -
Interactive Purple Scale
-
-
Purple Hover
#4434d4
CTA hover state
-
Purple Mid
#665efd
Range selectors
-
Purple Light
#b9b9f9
Subdued hover bg
-
Purple Deep
#2e2b8c
Icon hover
-
- -
Neutral & Status
-
-
Dark Slate
#273951
Labels
-
Slate
#64748d
Body text
-
Border
#e5edf5
Default border
-
Success
#15be53
Status, badges
-
Lemon
#9b6829
Warning accent
-
- -
Border & Surface
-
-
Border Soft
#d6d9fc
Purple-tinted border
-
Dashed Border
#362baa
Drop zones
-
-
- -
- -
-
02 / Typography
-

Typography Scale

- -
Display Hero
Display Hero -- 56px / 300 / 1.03 / -1.4px / sohne-var "ss01"
-
Display Large
Display Large -- 48px / 300 / 1.15 / -0.96px / sohne-var "ss01"
-
Section Heading
Section Heading -- 32px / 300 / 1.10 / -0.64px / sohne-var "ss01"
-
Sub-heading Large
Sub-heading -- 26px / 300 / 1.12 / -0.26px / sohne-var "ss01"
-
Sub-heading
Sub-heading -- 22px / 300 / 1.10 / -0.22px / sohne-var "ss01"
-
Body Large -- Financial infrastructure for the internet. Millions of companies use Stripe to accept payments.
Body Large -- 18px / 300 / 1.40 / normal / sohne-var "ss01"
-
Body -- Standard reading text for descriptions and content.
Body -- 16px / 300 / 1.40 / normal / sohne-var "ss01"
-
Button Text
Button -- 16px / 400 / 1.00 / normal / sohne-var "ss01"
-
Link / Navigation
Link -- 14px / 400 / 1.00 / normal / sohne-var "ss01"
-
Caption -- Small labels and metadata
Caption -- 12px / 300 / 1.45 / normal / sohne-var "ss01"
-
$1,234,567.89
Tabular Numbers -- 12px / 300 / 1.33 / -0.36px / sohne-var "tnum"
-
const stripe = require('stripe')('sk_test_...');
Code Body -- 12px / 500 / 2.00 / Source Code Pro
-
API VERSION
Code Label -- 12px / 500 / uppercase / Source Code Pro
-
- -
- -
-
03 / Buttons
-

Button Variants

-
-
Start now
Primary Purple
-
Documentation
Ghost / Outlined
-
Learn more
Transparent Info
-
Disabled
Neutral Ghost
-
Active
Success Badge
-
v2024-12
Neutral Badge
-
-
- -
- -
-
04 / Cards
-

Card Examples

-
-
-
Payments
-

Online Payments

-

Accept payments online with a fully integrated suite of payment products. Optimized for conversion with pre-built checkout pages.

-
-
-
Elevated
-

Revenue Recognition

-

Automate your revenue reporting. Card shown with full blue-tinted shadow stack for elevated importance.

-
-
-
Connect
-

Platform Payments

-

Build a marketplace or platform with multi-party payments, instant payouts, and flexible revenue sharing.

-
-
-
- -
- -
-
05 / Forms
-

Form Elements

-
Default
-
Focus (purple ring)
-
Error (ruby ring)
-
-
- -
- -
-
06 / Spacing
-

Spacing Scale

-
-
2
-
4
-
6
-
8
-
10
-
12
-
14
-
16
-
18
-
20
-
-
- -
- -
-
07 / Radius
-

Border Radius

-
-
1px
Micro
-
4px
Buttons, inputs
-
5px
Standard cards
-
6px
Nav, large cards
-
8px
Featured
-
-
- -
- -
-
08 / Elevation
-

Elevation

-
-
Level 0: Flat
No shadow
-
Level 1: Subtle
Ambient soft
-
Level 2: Standard
Ambient card
-
Level 3: Elevated
Blue-tinted dual layer
-
Level 4: Deep
Dark blue-tinted
-
Focus
Purple ring
-
-
- - - - - diff --git a/design/verge/DESIGN-dark.md b/design/verge/DESIGN-dark.md deleted file mode 100644 index 3ddd831..0000000 --- a/design/verge/DESIGN-dark.md +++ /dev/null @@ -1,373 +0,0 @@ -# Design System Inspired by The Verge - -## 1. Visual Theme & Atmosphere - -The Verge's 2024 redesign feels like somebody wired a Condé Nast magazine to a chiptune soundboard. The canvas is almost-black (`#131313`), the headlines are built from a brutally heavy display face (Manuka) that runs up to 107px, and the whole page is peppered with acid-mint `#3cffd0` and ultraviolet `#5200ff` that behave less like brand colors and more like hazard tape. Story tiles are not quiet gray cards — they're saturated, full-bleed color blocks (yellow, pink, orange, blue, purple) that feel like pasted-up rave flyers arranged into a timeline. The mood is "developer console meets club night meets tech tabloid": serious enough to cover a congressional hearing, loud enough to review a synthesizer. - -What makes this system unmistakable is the **StoryStream** timeline: a vertical feed where every post is a rounded rectangle — often 20–40px radius — filled edge-to-edge with color, framed by a thin border, and marked by a mono-uppercase timestamp on its left rail. Stories don't float on a grid; they stack on a dashed vertical rule like commits in a git log. Above that, a massive **"The Verge" wordmark** dominates the masthead in Manuka at hero scale, letting the reader know before any headline loads that this is editorial territory, not a template. - -There is no "light mode" on the homepage — the dark canvas is the product, and the only time the palette inverts is when a single story tile takes a mint or yellow fill. The depth is almost entirely flat: **hairline 1px borders** (`#ffffff`, `#3cffd0`, or `#5200ff`) do the work that shadows would do on a Material-flavored site. Every container is either `#131313` with a 1px outline, a fully saturated accent block, or a slate-gray `#2d2d2d` secondary surface. - -**Key Characteristics:** - -- Near-black editorial canvas (`#131313`) as the default surface — no light mode on the homepage -- Acid-mint `#3cffd0` + ultraviolet `#5200ff` as hazard-tape accents, never quiet background wash -- Massive Manuka display headlines up to 107px — the single loudest type move in mainstream tech media -- Rounded pill-card everything: 20/24/30/40px corner radii, never square -- Fully saturated color-block story tiles (mint, purple, yellow, pink, orange, electric blue) on a dark page -- Timeline "StoryStream" feed with mono uppercase timestamps rather than a traditional magazine grid -- Flat depth — 1px borders in white, mint, purple do the work that shadows would do elsewhere - -## 2. Color Palette & Roles - -### Primary (Brand Hazards) - -- **Jelly Mint** (`#3cffd0`): The Verge's signature acid-mint accent. Used as CTA button fill, link underlines, active tab borders, and high-attention story-tile backgrounds. Treat it as the visual equivalent of neon safety paint — applied sparingly to the most important element on screen. -- **Verge Ultraviolet** (`#5200ff`): The complementary brand hazard. Used for secondary color-block tiles, promotional spans, and the occasional outlined button. Often applied at 0.9 alpha to soften its cathode intensity. - -### Secondary & Accent - -- **Console Mint Border** (`#309875`): A darker variant of the jelly mint used on card outlines and button borders where pure mint would over-saturate. -- **Deep Link Blue** (`#3860be`): The link *hover* color — the one moment blue appears on the site. It replaces mint/white/black on hover across every link style. -- **Focus Cyan** (`#1eaedb`): Reserved for button focus rings. Never shown outside a keyboard-focus state. -- **Purple Rule** (`#3d00bf`): A darker ultraviolet variant used as the vertical border on StoryStream `
  • ` items. - -### Surface & Background - -- **Canvas Black** (`#131313`): The default dark surface for the entire homepage. Almost-but-not-quite pure black — has just enough warmth to feel like a printed newsprint negative rather than an OLED void. -- **Surface Slate** (`#2d2d2d`): Secondary card background, used when a story tile doesn't need to be a saturated color block. -- **Image Frame** (`#313131`): The 1px border that wraps inline imagery. -- **Hazard White** (`#ffffff`): Used as story-tile fill, button border, and primary text. When white appears as a large block, it's an editorial decision — a "spotlight" on that tile. -- **Absolute Black** (`#000000`): Reserved for text on the mint/yellow/white tiles — the only place it appears. - -### Neutrals & Text - -- **Primary Text** (`#ffffff`): Headlines and display text on the canvas. -- **Secondary Text** (`#949494`): Bylines, timestamps, photo credits. The mid-gray that anchors the metadata layer. -- **Muted Text** (`#e9e9e9`): Button text on dark slate buttons. Slightly off-white to reduce screen glare. -- **Inverted Text** (`#131313`): Used only on accent tiles (mint, yellow, white) to keep contrast legible. - -### Semantic & Accent - -- **Focus Ring** (`#1eaedb`): Keyboard focus only. -- **Overlay Black** (`rgba(0, 0, 0, 0.33)`): Subtle 1px ring used as the quiet shadow alternative on stacked cards. -- **Dim Gray** (`#8c8c8c`): Active/pressed button background — the "pressed down" state. - -### Gradient System - -The Verge uses **zero decorative gradients**. The only gradient-like treatment is the transition from a saturated accent story tile (mint/purple/yellow) back to the `#131313` canvas between rows. Color is applied in solid blocks, not as washes. This is a deliberate choice — the site's hazard-tape visual identity would dissolve if anything faded. - -## 3. Typography Rules - -### Font Family - -- **Manuka** (Klim Type Foundry) — fallback: Impact, Helvetica. The signature display face for The Verge wordmark and feature headlines. A heavy-weight (900) industrial sans-serif with a condensed, almost-athletic stance. Runs at 60–107px on the homepage, never smaller. -- **PolySans** (PanGram Pangram / Nikolas Wrobel) — fallback: Helvetica, Arial. The UI and secondary headline workhorse. Covers weights 300 / 500 / 700 across the system — everything from kicker captions to body decks. -- **PolySans Mono** — fallback: Courier New, Courier. The monospaced sibling, used exclusively for ALL-CAPS labels: kickers, timestamps, category tags, button labels. This mono-uppercase usage is the second-most-identifiable Verge detail after Manuka. -- **FK Roman Standard** (Florian Karsten) — fallback: Georgia. A serif used sparingly for specific body/caption treatments (article excerpts, certain review pulls). Adds a "print-magazine" counterpoint to the PolySans stack. -- **Roboto** — fallback: `-apple-system`, `system-ui`. Utility UI font for widgets and legacy modules. - -### Hierarchy - -| Role | Font | Size | Weight | Line Height | Letter Spacing | Notes | -| ----------------------- | ----------------- | --------------- | ------- | ----------- | -------------- | ----------------------------------------------------------- | -| Hero Wordmark / Display | Manuka | 107px / 6.69rem | 900 | 0.80 | 1.07px | The top-of-page "The Verge" logo and feature headlines | -| Secondary Display | Manuka | 90px / 5.63rem | 900 | 0.80 | — | Section-level feature headlines | -| Tertiary Display | Manuka | 60px / 3.75rem | 900 | 0.80 | — | Inline feature callouts | -| Large Headline | PolySans | 34px / 2.13rem | 700 | 1.00 | — | Section and module headlines | -| Heading Wide | PolySans | 32px / 2.00rem | 400 | 1.10 | 0.32px | Sub-heroes, promotional units | -| Heading Medium | PolySans | 24px / 1.50rem | 700 | 1.00 | — | Story tile headlines in the main feed | -| Heading Small | PolySans | 20px / 1.25rem | 700 | 1.00 | — | Compact tile headlines | -| Light Capitalized Label | PolySans | 19px / 1.19rem | 300 | 1.20 | 1.9px | Thin-weight capitalized eyebrows — a distinctive Verge move | -| All-Caps Label XL | PolySans | 18px / 1.13rem | 400 | 1.10 | 1.8px | UPPERCASE section kickers | -| Bold Body | PolySans | 16px / 1.00rem | 700 | 1.00 | — | Emphasis within decks | -| Body Relaxed | PolySans | 16px / 1.00rem | 500 | 1.60 | — | Long-form reading body | -| Inline Label | PolySans | 15px / 0.94rem | 400 | 1.20 | 0.15px | UI labels and secondary headlines | -| Body Compact | PolySans | 13px / 0.81rem | 400 | 1.60 | — | Secondary captions and decks | -| Eyebrow All-Caps | PolySans | 12px / 0.75rem | 400 | 1.30 | 1.8px | UPPERCASE kicker above tile headlines | -| Tag Label | PolySans | 12px / 0.75rem | 400 | 1.20 | 0.72px | UPPERCASE category tag | -| Caption Micro | PolySans | 11px / 0.69rem | 400 | 1.20 | 1.1px | UPPERCASE bylines | -| Meta Nano | PolySans | 10px / 0.63rem | 500 | 1.40 | 1.5px | UPPERCASE timestamp microtext | -| Mono Button Label | PolySans Mono | 12px / 0.75rem | 600 | 2.00 | 1.5px | UPPERCASE button text, very open leading | -| Mono Timestamp | PolySans Mono | 11px / 0.69rem | 500/600 | 1.20 | 1.1–1.8px | UPPERCASE StoryStream timestamps | -| Serif Body | FK Roman Standard | 16px / 1.00rem | 400 | 1.30 | -0.16px | Review decks, print-voice excerpts | -| Serif Caption | FK Roman Standard | 20px / 1.25rem | 400 | 1.20 | — | Magazine-style pull quotes | - -### Principles - -- **Manuka is always the hero, never the UI.** If you see Manuka below 60px you're looking at a bug. It exists to *shout the brand*, not to label a button. -- **PolySans is the workhorse, PolySans Mono is its uniformed sibling.** Mono is used exclusively for UPPERCASE labels, timestamps, tags, and certain buttons. Lowercase mono doesn't exist in this system. -- **Thin-weight (300) capitalized headlines** are a signature Verge move. The 19–20px weight-300 with 1.9px tracking creates a "fashion magazine whisper" that contrasts with the 107px Manuka shout above it. This whisper-vs-shout contrast is the typographic fingerprint. -- **Letter-spacing has two registers**: positive (0.72–1.9px) for ALL-CAPS mono and sans labels, negative (`-0.16px`) for the rare serif appearances, barely-positive (0.32px, 1.07px) for massive display. Plain 0 letter-spacing is rare. -- **FK Roman Standard is the editorial exception**, not the rule. Reserve it for long-form print-voice moments — reviews, critic pulls, masthead essays. Never use it in UI. -- **Line heights are tight** (0.80–1.30) for every display and label, relaxed (1.60–2.00) only for reading body and mono button labels. The leading jump is intentional — it gives the page a "telegraph ticker" rhythm. - -### Note on Font Substitutes - -The 0.80 line-height on Manuka display (107px, 90px, 60px) assumes the **proprietary Manuka face from Klim Type Foundry**, which has aggressively tight vertical metrics designed for athletic stance at large sizes. If you substitute with wide-metric open-source condensed displays like **Anton**, **Oswald**, **Bebas Neue**, or **Archivo Black**, loosen display line-heights by approximately **+0.10 to +0.15** to prevent ascender/descender collisions (e.g., 0.80 → 0.95). PolySans substitutes (Space Grotesk, DM Sans, Hanken Grotesk) work at the token values without adjustment — their metrics are close enough. PolySans Mono substitutes (Space Mono, JetBrains Mono) and FK Roman substitutes (Newsreader, Literata) also work without adjustment. - -## 4. Component Stylings - -### Buttons - -**Primary — Jelly Mint Pill** - -- Background: `#3cffd0` (Jelly Mint) -- Text: `#000000` (Absolute Black), PolySans 16px / 700 or PolySans Mono 12px / 600 UPPERCASE -- Border: none (pure fill) -- Border radius: `24px` — fully rounded pill -- Padding: `10px 24px` -- Outline: `none` at rest -- Hover: background shifts to `rgba(255, 255, 255, 0.2)` (translucent white), text stays black, adds a 1px `#c2c2c2` ring shadow -- Active: background `rgba(140, 140, 140, 0.87)`, opacity `0.5`, ring shadow `#8c8c8c` -- Focus: background `#1eaedb`, white text, 1px solid `#0500ff` border, translucent white focus ring -- Transition: \~180ms ease on background and shadow - -**Secondary — Dark Slate Pill** - -- Background: `#2d2d2d` (Surface Slate) -- Text: `#e9e9e9` (Muted Text), PolySans 16px / 400 -- Border: none -- Border radius: `24px` -- Padding: `10px 24px` -- Outline: `rgb(233, 233, 233) none 0px` -- Hover: same translucent white invert as primary — `rgba(255, 255, 255, 0.2)` bg, black text, 1px `#c2c2c2` ring -- Focus: same cyan focus treatment as primary - -**Tertiary — Outlined Mint** - -- Background: transparent -- Text: `#3cffd0`, PolySans Mono 12px / 600 UPPERCASE, 1.5px tracking -- Border: `1px solid #3cffd0` -- Border radius: `40px` — larger pill for secondary outline style -- Padding: \~`10px 20px` -- Hover: inverts to mint fill, black text -- Transition: 150ms ease - -**Outlined Ultraviolet (Promotional)** - -- Background: transparent -- Text: `#5200ff` or `#ffffff` -- Border: `1px solid #5200ff` -- Border radius: `30px` -- Used for "Subscribe" or "Join the Stream" style promotional callouts - -**Pill Tag (Non-interactive)** - -- Background: saturated accent (`#3cffd0`, `#5200ff`, yellow, etc.) -- Text: black or white depending on background luminance -- Border radius: `20px` (tighter radius than buttons — this is the *text pill*) -- Font: PolySans Mono 11px / 600 UPPERCASE, 1.8px tracking -- Padding: \~`4px 10px` - -### Cards & Containers - -**StoryStream Tile** - -- Background: either `#131313` + 1px white border, OR a saturated accent fill (mint, purple, yellow, pink, orange, white) -- Border radius: `20px` (standard) or `24px` (feature) -- Border: `1px solid #ffffff` (on dark) or `0px 0px 1px solid #3cffd0` (on mint) or nothing (on saturated fill) -- Padding: \~24–32px interior -- Hover: no lift, no scale — the headline text color transitions from white to `#3860be` (deep link blue) -- Transition: 150ms ease on color only - -**Feature Card (Top Story)** - -- Background: `#131313` with 1px hairline border, OR full-bleed color accent -- Border radius: `24px` -- Padding: 32px+ -- Image inside: clipped to match the outer radius (`3px` or `4px` inner radius when nested) -- Hover: text color shift only; the image remains static - -**StoryStream Rail (Timeline)** - -- A vertical dashed or solid rule (1px `#3d00bf` or `#ffffff`) runs along the left edge of each item, marking the timeline spine -- Timestamps sit on the left rail in PolySans Mono 11px / 500 / UPPERCASE / 1.1px tracking -- Each entry is a pill-cornered rectangle separated from its neighbors by 12–16px vertical gap - -### Inputs & Forms - -- **Default**: `#131313` background, 1px solid `#ffffff` or `#949494` border, `2px` border radius (tight, newspaper-form feel), PolySans 15px text in `#ffffff`, placeholder in `#949494`. -- **Focus**: border transitions to `#3cffd0` (jelly mint) with optional `1px solid #5200ff` inner ring on deep focus. No glow. -- **Error**: border turns `#5200ff` (ultraviolet — used as error/alert accent here, not the usual red). -- **Transition**: \~150ms ease on border-color. - -### Navigation - -- **Top nav**: thin `#131313` bar with the Verge wordmark (Manuka) left-aligned, a search icon and a few UPPERCASE mono category links (12–14px, PolySans Mono, 1.5–1.8px tracking), and a single mint-pill CTA (usually "Subscribe") pinned right. -- **Wordmark**: massive on first scroll — the homepage treats the "The Verge" logo as a hero element, not a 32px corner logo. -- **Hover**: every link transitions from `#ffffff` to `#3860be` (deep link blue). No underline — it's a color-only response. -- **Active section**: marked by a 1px mint underline (inset box-shadow `0px -1px 0px 0px inset #3cffd0`) -- **Mobile**: the wordmark shrinks, category nav collapses into a hamburger drawer. Inside the drawer, links are mono-uppercase and stack with 16–20px gaps. - -### Image Treatment - -- **Aspect ratios**: 16:9 dominates for hero and feature images, 4:3 for mid-feed, 1:1 for thumbnails and author avatars. -- **Corners**: always rounded to match the parent card — `3px`, `4px`, or inherit `20px` / `24px` from the tile. -- **Frame**: 1px `#313131` or `#ffffff` hairline around photography, giving a "contained Polaroid" feel. -- **Full-bleed**: only within the color-block tiles, where the image runs to the padded edge of the accent fill. -- **Hover**: static — no zoom, no scale, no opacity shift. The headline below is the only interactive response. -- **Lazy loading**: `loading="lazy"` on everything below the first fold; eager on the masthead hero only. - -### StoryStream Timeline Item (Distinctive) - -- Vertical rail line (1px `#3d00bf` or `#ffffff` on `#131313`) -- Mono timestamp on the left in PolySans Mono 11px / UPPERCASE -- Pill-cornered body card (20px radius) with kicker, headline, and optional deck -- Stacked vertically with 12–16px gap, the rail continuing between them -- Often interleaved with full-bleed accent tiles that "break" the timeline rhythm for emphasis - -## 5. Layout Principles - -### Spacing System - -- **Base unit**: 8px. -- **Scale**: 1, 2, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 20, 24, 25px. -- **Section padding**: 32–64px vertical between major feed sections. StoryStream items themselves are tighter — 12–16px gaps. -- **Card padding**: 20–32px interior. Feature cards expand to 40–48px. -- **Inline spacing**: kickers sit \~6–10px above headlines; headlines sit \~10–14px above decks; timestamps sit \~6–8px below decks. -- **Micro-scale**: The 2/4/5/6/9/10px values are used inside buttons, pills, and tight label clusters, not in the editorial grid. - -### Grid & Container - -- **Max width**: \~1280–1300px (dembrandt detected breakpoints at 1200/1280/1300). -- **Column patterns**: a 12-column underlying grid that resolves into 3-column hero + 1-column StoryStream rail + feature panels. The homepage feels freeform because color-block tiles frequently span 2–3 columns on a whim. -- **Container padding**: 24px mobile / 48px desktop on the outer edges. -- **Gutters**: 16–24px between columns, tighter (8–12px) inside StoryStream items. - -### Whitespace Philosophy - -The Verge treats whitespace like a club DJ treats silence — as a dramatic reset between loud moments. The canvas is so dark and the accents are so saturated that even 32px of empty `#131313` between two tiles acts as a palette cleanser. The page is not airy like Apple or Stripe; it's **paced**, with loud hazard-color blocks interrupting stretches of near-black. Whitespace carries the rhythm, not the elegance. - -### Border Radius Scale - -- **2px** — inputs, small badges (feels like a typewriter tag) -- **3px** — inline images (just enough to soften against the canvas) -- **4px** — nested card images and small button variants -- **20px** — standard pill cards and color-block tiles -- **24px** — feature tile radius and primary button pill -- **30px** — large promotional buttons -- **40px** — outlined CTA pills (the loudest pill in the system) -- **50%** — avatar circles, icon buttons, and certain round badges - -Eight discrete radius values — a **lot** for a single site. This is deliberate: the rhythm between 2px typewriter tags, 20px pill cards, and 40px outlined buttons creates a "nested scale" feel where every component announces its hierarchy through its corners. - -## 6. Depth & Elevation - -| Level | Treatment | Use | -| ----- | ----------------------------------------------------------------- | -------------------------------------------------------- | -| 0 | No border, no shadow | Default `#131313` canvas text | -| 1 | `rgba(0,0,0,0) 0px 0px 0px 0px inset` (placeholder) | Reset state for interactive elements | -| 2 | `1px solid #ffffff` or `#313131` hairline | Image frames and quiet card outlines | -| 3 | `1px solid #3cffd0` hairline | Active button outlines, focused story tiles | -| 4 | `1px solid #5200ff` hairline | Promotional/alternate state outlines | -| 5 | `rgba(0, 0, 0, 0.33) 0px 0px 0px 1px` | The single "atmospheric" ring — applied to layered cards | -| 6 | `0px -1px 0px 0px inset` (mint/black/white) | Active tab underline — a signature Verge move | -| 7 | Saturated accent fill (`#3cffd0`, `#5200ff`, white, yellow, pink) | Story-tile elevation via color, not shadow | - -The Verge's depth philosophy is **color-as-elevation**. When something needs to stand out, it doesn't get a shadow — it gets a mint fill or a 1px hazard-color border. There are 14 shadow entries in the extracted tokens, but all of them are either inset underlines (0px -1px inset) or near-transparent 1px rings — none of them are traditional elevation shadows. The `#131313` canvas stays perfectly flat throughout, and hierarchy is carried by color saturation. - -### Decorative Depth - -- **1px inset underline** on active tabs/nav links (mint, black, or white depending on context) -- **Subtle** **`rgba(0, 0, 0, 0.33)`** **1px ring** on stacked cards — the only effect that faintly resembles a shadow -- **No gradients, no glows, no atmospheric blurs** anywhere. The hazard-tape aesthetic would break if anything faded softly. - -## 7. Do's and Don'ts - -### Do - -- **Do** use `#131313` as the canvas for every view. There is no light mode. -- **Do** use Jelly Mint (`#3cffd0`) and Verge Ultraviolet (`#5200ff`) as hazard accents — buttons, borders, active states, and saturated color-block tiles. -- **Do** use Manuka exclusively at 60px+ for hero headlines. Treat anything smaller as a bug. -- **Do** round everything: 20px for cards, 24px for feature cards, 30–40px for pill buttons. -- **Do** use PolySans Mono for UPPERCASE labels, timestamps, kickers, and button text. Lowercase mono doesn't exist here. -- **Do** apply 1.5–1.9px letter-spacing to every ALL-CAPS label — this is a Verge signature. -- **Do** use saturated color-block tiles (mint, purple, yellow, pink, orange, white) to elevate a story — never a drop shadow. -- **Do** use `#3860be` (deep link blue) as the hover color on every link, regardless of base color. -- **Do** apply the StoryStream timeline rail (1px dashed/solid `#3d00bf` or white) on feed views. -- **Do** use thin-weight (300) PolySans at 19–20px with 1.9px tracking for "fashion-whisper" capitalized eyebrows — the contrast with the 107px Manuka shout is the whole voice. - -### Don't - -- **Don't** use a light background. The dark canvas is the product. -- **Don't** add `box-shadow` for elevation. Use 1px borders or saturated accent fills instead. -- **Don't** use square corners. Every interactive and content container is rounded. -- **Don't** use Manuka for UI, buttons, or body copy. It's strictly display. -- **Don't** use lowercase mono. PolySans Mono is always UPPERCASE. -- **Don't** let mint and ultraviolet appear as background washes — they're hazard accents, not canvas tints. -- **Don't** use gradients anywhere. The system is solid color blocks only. -- **Don't** introduce new accent colors outside the declared mint / purple / yellow / pink / orange tile palette. -- **Don't** pair Manuka with FK Roman Standard in the same headline cluster — Manuka is the only display shout, serif pulls are reserved for body moments. -- **Don't** use `#3cffd0` text on a `#131313` background at under 16px — the contrast vibrates at small sizes. - -## 8. Responsive Behavior - -### Breakpoints - -| Name | Width | Key Changes | -| ------------- | ----------- | ---------------------------------------------------------------------------------------------------- | -| Small Mobile | <400px | Single column, Manuka hero scales down to \~48–54px, StoryStream rail collapses to inline timestamps | -| Mobile | 400–549px | Single column, color-block tiles stack full-width, nav is a hamburger drawer | -| Large Mobile | 550–767px | Still single column but padding opens up, tile radii stay at 20px | -| Tablet | 768–1023px | 2-column StoryStream with feature card spanning, wordmark shrinks \~50% | -| Small Desktop | 1024–1179px | Full 3–4 column editorial grid, mint pill CTA restored to nav | -| Desktop | 1180–1299px | Max padding, Manuka wordmark at full hero scale | -| Large Desktop | ≥1300px | Container caps at \~1280–1300px, whitespace expands at the margins, no further scaling | - -The dembrandt sweep detected 26 intermediate breakpoints (1300 → 1280 → 1200 → 1181 → 1180 → 1179 → 1024 → 1023 → 901 → 900 → 897 → 896 → 890 → 769 → 768 → 620 → 605 → 600 → 550 → 549 → 530 → 426 → 425 → 400 → 320). The Verge tunes its grid at virtually every major device boundary — an unusually aggressive responsive strategy. - -### Touch Targets - -- Primary pill buttons are \~44px minimum height (10px vertical padding + 16px text + 2px border) — meets WCAG AA. -- Mono uppercase nav links are smaller (\~28–32px tall) — for derivative work, pad to 44px on mobile. -- Circle icon buttons are 40–44px circles, touch-friendly. - -### Collapsing Strategy - -- **Nav**: wordmark scales from hero (Manuka 60–107px) to \~24–32px on mobile. Category links collapse to a hamburger drawer below 900px. -- **Grid**: 4-col → 3-col → 2-col → 1-col. Feature cards that span 2 columns on desktop reflow to full-width single-column on mobile. -- **Spacing**: section padding tightens from 64px → 32px → 20px. Tile interior padding tightens from 32px → 20px. -- **Type**: Manuka hero scales from 107px to \~48–54px on mobile. PolySans headlines scale from 34px → 24px. Mono labels stay pinned at 11–12px (they don't shrink further or they become unreadable). -- **Color tiles**: accent story blocks never lose saturation on mobile — they just reflow to full width. - -### Image Behavior - -- Responsive raster via `srcset`, aspect ratios preserved. -- No art-direction swaps — same crop scales across all viewports. -- `loading="lazy"` on everything below the fold, `eager` on the masthead hero. -- Images inside color-block tiles inherit the tile's inner radius (4px or 20px nested). - -## 9. Agent Prompt Guide - -### Quick Color Reference - -- **Primary CTA**: "Jelly Mint (`#3cffd0`)" -- **Background (Canvas)**: "Canvas Black (`#131313`)" -- **Accent (Secondary Hazard)**: "Verge Ultraviolet (`#5200ff`)" -- **Heading Text**: "Hazard White (`#ffffff`)" -- **Body Text**: "Hazard White (`#ffffff`)" (primary) or "Muted Text (`#e9e9e9`)" -- **Secondary Text / Metadata**: "Secondary Text (`#949494`)" -- **Card Border**: "Hazard White (`#ffffff`)" hairline on dark, "Console Mint Border (`#309875`)" on mint variants -- **Link Hover**: "Deep Link Blue (`#3860be`)" - -### Example Component Prompts - -1. *"Create a StoryStream timeline item on a* *`#131313`* *canvas: a 20px-radius rectangle with a 1px solid* *`#ffffff`* *border, a PolySans Mono 11px / 600 / UPPERCASE / 1.1px tracking timestamp on the left rail, a 12px PolySans UPPERCASE kicker in mint (`#3cffd0`), and a 24px / 700 PolySans headline in white below. No shadow, no lift — hover only shifts the headline color to* *`#3860be`."* -2. *"Design a primary subscribe button with a Jelly Mint (`#3cffd0`) fill, black text in PolySans Mono 12px / 600 / UPPERCASE / 1.5px tracking, 24px border radius, 10px × 24px padding. Hover state shifts to* *`rgba(255, 255, 255, 0.2)`* *background with a 1px* *`#c2c2c2`* *ring shadow, 180ms ease."* -3. *"Build a feature hero with a 107px Manuka 900 headline in white with 1.07px letter-spacing and 0.80 line-height, a thin-weight 300 PolySans 20px capitalized kicker above with 1.9px tracking, on a* *`#131313`* *canvas with 64px vertical padding."* -4. *"Create a color-block accent tile filled with Verge Ultraviolet (`#5200ff`) at 0.9 alpha, 24px border radius, white text, a PolySans Mono 11px UPPERCASE category label with 1.5px tracking at the top, and a 32px PolySans 400 capitalized headline with 0.32px tracking below."* -5. *"Design a dark slate secondary button with a* *`#2d2d2d`* *background,* *`#e9e9e9`* *PolySans 16px text, 24px radius pill shape, 10px × 24px padding. Hover matches the primary button — translucent white* *`rgba(255, 255, 255, 0.2)`* *bg with black text."* - -### Iteration Guide - -When refining existing screens generated with this design system: - -1. **Audit the canvas.** If you see a light background anywhere on the homepage, flatten it to `#131313`. There is no light mode. -2. **Audit corners.** Every rectangle should land on 2/3/4/20/24/30/40px or 50%. Square corners break the voice. -3. **Audit shadows.** Strip every `box-shadow` that isn't a 1px inset underline or a 1px hazard-color border. The Verge uses color for elevation, not shadow. -4. **Audit type roles.** Manuka only ≥60px. PolySans Mono only UPPERCASE. PolySans 300 at 19–20px should have 1.9px tracking. FK Roman only for body/magazine moments, never UI. -5. **Audit accent usage.** Mint and ultraviolet should appear as hazard accents — buttons, 1px borders, active underlines, saturated tile fills. If they're appearing as background washes or gradient fades, correct to solid blocks. -6. **Audit labels.** Every kicker, timestamp, category tag, and button label should be ALL CAPS with 1.1–1.9px letter-spacing. Missing tracking = missing voice. -7. **Audit link hover.** Every link, regardless of its base color, should hover to `#3860be` deep link blue with no underline. Any other hover color is drift. - diff --git a/design/verge/DESIGN.md b/design/verge/DESIGN.md deleted file mode 100644 index 1a17925..0000000 --- a/design/verge/DESIGN.md +++ /dev/null @@ -1,315 +0,0 @@ - -# Design System Inspired by The Verge (Light Mode) - -## 1. Visual Theme & Atmosphere - -The Verge's light mode maintains the same bold editorial identity but on a clean white canvas (`#ffffff`). The headlines remain impactful with heavy display faces, and the acid-mint `#3cffd0` and ultraviolet `#5200ff` accents still function as visual hazard tape. Story tiles continue to be saturated color blocks, creating a vibrant contrast against the light background. The mood remains "developer console meets club night meets tech tabloid," but with a brighter, more open feel that enhances readability during daytime use. - -The StoryStream timeline remains a key identifier: a vertical feed where every post is a rounded rectangle with saturated color, framed by a thin border, and marked by a mono-uppercase timestamp. The massive wordmark still dominates the masthead, asserting the editorial territory. - -Depth is achieved through subtle 1px borders (`#131313`, `#3cffd0`, or `#5200ff`) rather than shadows, maintaining the flat, clean aesthetic while providing clear visual hierarchy. - -**Key Characteristics:** -- Clean white editorial canvas (`#ffffff`) as the default surface -- Acid-mint `#3cffd0` + ultraviolet `#5200ff` as hazard-tape accents -- Impactful display headlines up to 107px -- Rounded pill-card everything: 20/24/30/40px corner radii -- Fully saturated color-block story tiles on a light page -- Timeline "StoryStream" feed with mono uppercase timestamps -- Flat depth — 1px borders in black, mint, purple for visual hierarchy - -## 2. Color Palette & Roles - -### Primary (Brand Hazards) -- **Jelly Mint** (`#3cffd0`): The Verge's signature acid-mint accent. Used as CTA button fill, link underlines, active tab borders, and high-attention story-tile backgrounds. -- **Verge Ultraviolet** (`#5200ff`): The complementary brand hazard. Used for secondary color-block tiles, promotional spans, and outlined buttons. - -### Secondary & Accent -- **Console Mint Border** (`#309875`): A darker variant of the jelly mint used on card outlines and button borders. -- **Deep Link Blue** (`#3860be`): The link *hover* color — the one moment blue appears on the site. -- **Focus Cyan** (`#1eaedb`): Reserved for button focus rings. Never shown outside a keyboard-focus state. -- **Purple Rule** (`#3d00bf`): A darker ultraviolet variant used as the vertical border on StoryStream `
  • ` items. -- **Dim Gray** (`#8c8c8c`): Active/pressed button background — the "pressed down" state. - -### Surface & Background -- **Canvas White** (`#ffffff`): The default light surface for the entire homepage. Clean, bright, and optimized for readability. -- **Surface Slate** (`#f2f2f2`): Secondary card background, used when a story tile doesn't need to be a saturated color block. -- **Surface Slate 2** (`#e6e6e6`): Tertiary background for nested components. -- **Image Frame** (`#d4d4d4`): The 1px border that wraps inline imagery. -- **Hazard White** (`#ffffff`): Used as story-tile fill, button border, and primary text. -- **Absolute Black** (`#000000`): Reserved for text on the mint/yellow/white tiles. - -### Neutrals & Text -- **Primary Text** (`#131313`): Headlines and display text on the canvas. -- **Secondary Text** (`#6a6a6a`): Bylines, timestamps, photo credits. -- **Muted Text** (`#8c8c8c`): Button text on light slate buttons. -- **Inverted Text** (`#ffffff`): Used only on dark accent tiles (purple, black) to keep contrast legible. - -### Semantic & Accent -- **Focus Ring** (`#1eaedb`): Keyboard focus only. -- **Overlay Black** (`rgba(19, 19, 19, 0.1)`): Subtle 1px ring used as the quiet shadow alternative on stacked cards. - -### Gradient System -The Verge uses **zero decorative gradients** in light mode as well. Color is applied in solid blocks, not as washes, maintaining the hazard-tape visual identity. - -## 3. Typography Rules - -### Font Family -- **Anton** (Google Fonts) — fallback: Impact, Helvetica. The signature display face for The Verge wordmark and feature headlines. A heavy-weight industrial sans-serif with a condensed stance. Runs at 60–107px on the homepage. -- **Space Grotesk** (Google Fonts) — fallback: Helvetica, Arial. The UI and secondary headline workhorse. Covers weights 300 / 500 / 700. -- **Space Mono** (Google Fonts) — fallback: Courier New, Courier. The monospaced sibling, used exclusively for ALL-CAPS labels: kickers, timestamps, category tags, button labels. -- **Newsreader** (Google Fonts) — fallback: Georgia. A serif used sparingly for specific body/caption treatments. - -### Hierarchy -| Role | Font | Size | Weight | Line Height | Letter Spacing | Notes | -| ----------------------- | ------------- | --------------- | ------- | ----------- | -------------- | ----------------------------------------------------------- | -| Hero Wordmark / Display | Anton | 104px / 6.5rem | 400 | 0.95 | 1px | The top-of-page logo and feature headlines | -| Secondary Display | Anton | 72px / 4.5rem | 400 | 0.85 | 0.5px | Section-level feature headlines | -| Large Headline | Space Grotesk | 34px / 2.13rem | 700 | 1.00 | — | Section and module headlines | -| Heading Wide | Space Grotesk | 32px / 2.00rem | 700 | 1.00 | -0.3px | Story tile headlines | -| Heading Medium | Space Grotesk | 24px / 1.50rem | 700 | 1.00 | — | Compact tile headlines | -| Light Capitalized Label | Space Grotesk | 19px / 1.19rem | 300 | 1.20 | 1.9px | Thin-weight capitalized eyebrows | -| All-Caps Label XL | Space Grotesk | 18px / 1.13rem | 300 | 1.40 | 1.8px | UPPERCASE section kickers | -| Body Relaxed | Space Grotesk | 16px / 1.00rem | 500 | 1.60 | — | Long-form reading body | -| Eyebrow All-Caps | Space Grotesk | 12px / 0.75rem | 400 | 1.30 | 1.8px | UPPERCASE kicker above tile headlines | -| Mono Timestamp | Space Mono | 11px / 0.69rem | 700 | 1.20 | 1.1px | UPPERCASE StoryStream timestamps | -| Mono Button Label | Space Mono | 12px / 0.75rem | 700 | 2.00 | 1.5px | UPPERCASE button text, very open leading | -| Serif Body | Newsreader | 16px / 1.00rem | 400 | 1.30 | -0.16px | Review decks, print-voice excerpts | - -### Principles -- **Anton is always the hero, never the UI.** If you see Anton below 60px you're looking at a bug. -- **Space Grotesk is the workhorse, Space Mono is its uniformed sibling.** Mono is used exclusively for UPPERCASE labels, timestamps, tags, and certain buttons. -- **Thin-weight (300) capitalized headlines** are a signature Verge move. The 19–20px weight-300 with 1.9px tracking creates a "fashion magazine whisper" that contrasts with the large Anton shout above it. -- **Letter-spacing has two registers**: positive (0.72–1.9px) for ALL-CAPS mono and sans labels, negative (`-0.16px`) for serif appearances. -- **Newsreader is the editorial exception**, not the rule. Reserve it for long-form print-voice moments. -- **Line heights are tight** (0.85–1.30) for every display and label, relaxed (1.60–2.00) only for reading body and mono button labels. - -## 4. Component Stylings - -### Buttons - -**Primary — Jelly Mint Pill** -- Background: `#3cffd0` (Jelly Mint) -- Text: `#000000` (Absolute Black), Space Mono 12px / 700 UPPERCASE -- Border: none (pure fill) -- Border radius: `24px` — fully rounded pill -- Padding: `12px 28px` -- Hover: background shifts to `rgba(60, 255, 208, 0.3)`, adds a 1px `#309875` ring -- Active: background `rgba(140, 140, 140, 0.87)`, opacity `0.5` -- Focus: background `#1eaedb`, white text, 1px solid `#0500ff` border -- Transition: ~180ms ease on background and shadow - -**Secondary — Dark Pill** -- Background: `#131313` (Primary Text) -- Text: `#ffffff` (Hazard White), Space Mono 12px / 700 UPPERCASE -- Border: none -- Border radius: `24px` -- Padding: `12px 28px` -- Hover: background `rgba(19, 19, 19, 0.2)`, text `#131313`, 1px `#8c8c8c` ring -- Focus: same cyan focus treatment as primary - -**Tertiary — Outlined Mint** -- Background: transparent -- Text: `#309875` (Console Mint Border), Space Mono 12px / 700 UPPERCASE -- Border: `1px solid #309875` -- Border radius: `40px` — larger pill for secondary outline style -- Padding: ~`12px 24px` -- Hover: inverts to mint fill, black text -- Transition: 150ms ease - -**Outlined Ultraviolet (Promotional)** -- Background: transparent -- Text: `#5200ff` (Verge Ultraviolet) -- Border: `1px solid #5200ff` -- Border radius: `30px` -- Used for "Subscribe" or "Join the Stream" style promotional callouts - -**Pill Tag (Non-interactive)** -- Background: `#3cffd0` (Jelly Mint) -- Text: `#000000` (Absolute Black), Space Mono 11px / 700 UPPERCASE -- Border radius: `20px` (tighter radius than buttons) -- Padding: ~`6px 14px` - -### Cards & Containers - -**StoryStream Tile** -- Background: either `#ffffff` + 1px `rgba(19, 19, 19, 0.1)` border, OR a saturated accent fill (mint, purple, yellow, pink, orange, white) -- Border radius: `20px` (standard) or `24px` (feature) -- Border: `1px solid rgba(19, 19, 19, 0.1)` (on light) or `1px solid #309875` (on mint) -- Padding: ~24–32px interior -- Hover: no lift, no scale — the headline text color transitions from `#131313` to `#3860be` (deep link blue) -- Transition: 150ms ease on color only - -**Feature Card (Top Story)** -- Background: `#ffffff` with 1px hairline border, OR full-bleed color accent -- Border radius: `24px` -- Padding: 32px+ -- Image inside: clipped to match the outer radius -- Hover: text color shift only; the image remains static - -**StoryStream Rail (Timeline)** -- A vertical dashed or solid rule (1px `#3d00bf` or `rgba(19, 19, 19, 0.1)` on `#ffffff`) runs along the left edge of each item -- Timestamps sit on the left rail in Space Mono 11px / 700 / UPPERCASE / 1.1px tracking -- Each entry is a pill-cornered rectangle separated from its neighbors by 12–16px vertical gap - -### Inputs & Forms -- **Default**: `#f2f2f2` (Surface Slate) background, 1px solid `rgba(19, 19, 19, 0.15)` border, `2px` border radius, Space Grotesk 15px text in `#131313`, placeholder in `#8c8c8c`. -- **Focus**: border transitions to `#3cffd0` (jelly mint) with optional `1px solid #5200ff` inner ring on deep focus. -- **Error**: border turns `#5200ff` (ultraviolet — used as error/alert accent here). -- **Transition**: ~150ms ease on border-color. - -### Navigation -- **Top nav**: white background, 1px solid `rgba(19, 19, 19, 0.1)` border, with the Verge wordmark (Anton) left-aligned, a search icon and a few UPPERCASE mono category links (11px, Space Mono, 1.1px tracking), and a single mint-pill CTA (usually "Subscribe") pinned right. -- **Wordmark**: massive on first scroll — treated as a hero element. -- **Hover**: every link transitions from `#131313` to `#3860be` (deep link blue). No underline — it's a color-only response. -- **Active section**: marked by a 1px mint underline (inset box-shadow `0px -1px 0px 0px inset #3cffd0`) -- **Mobile**: the wordmark shrinks, category nav collapses into a hamburger drawer. Inside the drawer, links are mono-uppercase and stack with 16–20px gaps. - -### Image Treatment -- **Aspect ratios**: 16:9 dominates for hero and feature images, 4:3 for mid-feed, 1:1 for thumbnails and author avatars. -- **Corners**: always rounded to match the parent card — `3px`, `4px`, or inherit `20px` / `24px` from the tile. -- **Frame**: 1px `#d4d4d4` or `rgba(19, 19, 19, 0.08)` hairline around photography. -- **Full-bleed**: only within the color-block tiles, where the image runs to the padded edge of the accent fill. -- **Hover**: static — no zoom, no scale, no opacity shift. The headline below is the only interactive response. -- **Lazy loading**: `loading="lazy"` on everything below the first fold; eager on the masthead hero only. - -### StoryStream Timeline Item (Distinctive) -- Vertical rail line (1px `#3d00bf` or `rgba(19, 19, 19, 0.1)` on `#ffffff`) -- Mono timestamp on the left in Space Mono 11px / UPPERCASE -- Pill-cornered body card (20px radius) with kicker, headline, and optional deck -- Stacked vertically with 12–16px gap, the rail continuing between them -- Often interleaved with full-bleed accent tiles that "break" the timeline rhythm for emphasis - -## 5. Layout Principles - -### Spacing System -- **Base unit**: 8px. -- **Scale**: 1, 2, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 20, 24, 25px. -- **Section padding**: 32–72px vertical between major feed sections. StoryStream items themselves are tighter — 12–16px gaps. -- **Card padding**: 20–32px interior. Feature cards expand to 40–48px. -- **Inline spacing**: kickers sit ~6–10px above headlines; headlines sit ~10–14px above decks; timestamps sit ~6–8px below decks. -- **Micro-scale**: The 2/4/5/6/9/10px values are used inside buttons, pills, and tight label clusters, not in the editorial grid. - -### Grid & Container -- **Max width**: ~1280–1300px. -- **Column patterns**: a 12-column underlying grid that resolves into 3-column hero + 1-column StoryStream rail + feature panels. Color-block tiles frequently span 2–3 columns. -- **Container padding**: 24px mobile / 48px desktop on the outer edges. -- **Gutters**: 16–24px between columns, tighter (8–12px) inside StoryStream items. - -### Whitespace Philosophy -The Verge treats whitespace as a dramatic reset between loud moments. The light canvas allows for more breathing room, creating a balanced rhythm between content and empty space. The page is airy but still maintains the Verge's characteristic boldness through color and typography. - -### Border Radius Scale -- **2px** — inputs, small badges (feels like a typewriter tag) -- **3px** — inline images (just enough to soften against the canvas) -- **4px** — nested card images and small button variants -- **20px** — standard pill cards and color-block tiles -- **24px** — feature tile radius and primary button pill -- **30px** — large promotional buttons -- **40px** — outlined CTA pills (the loudest pill in the system) -- **50%** — avatar circles, icon buttons, and certain round badges - -## 6. Depth & Elevation - -| Level | Treatment | Use | -| ----- | ----------------------------------------------------------------- | -------------------------------------------------------- | -| 0 | No border, no shadow | Default `#ffffff` canvas text | -| 1 | `rgba(0,0,0,0) 0px 0px 0px 0px inset` (placeholder) | Reset state for interactive elements | -| 2 | `1px solid rgba(19, 19, 19, 0.1)` or `#d4d4d4` hairline | Image frames and quiet card outlines | -| 3 | `1px solid #3cffd0` hairline | Active button outlines, focused story tiles | -| 4 | `1px solid #5200ff` hairline | Promotional/alternate state outlines | -| 5 | `rgba(19, 19, 19, 0.33) 0px 0px 0px 1px` | The single "atmospheric" ring — applied to layered cards | -| 6 | `0px -1px 0px 0px inset` (mint/black/white) | Active tab underline — a signature Verge move | -| 7 | Saturated accent fill (`#3cffd0`, `#5200ff`, white, yellow, pink) | Story-tile elevation via color, not shadow | - -The Verge's depth philosophy in light mode remains **color-as-elevation**. When something needs to stand out, it gets a mint fill or a 1px hazard-color border rather than a shadow. The `#ffffff` canvas stays clean and flat, with hierarchy carried by color saturation. - -### Decorative Depth -- **1px inset underline** on active tabs/nav links (mint, black, or white depending on context) -- **Subtle** **`rgba(19, 19, 19, 0.33)`** **1px ring** on stacked cards — the only effect that faintly resembles a shadow -- **No gradients, no glows, no atmospheric blurs** anywhere. The hazard-tape aesthetic would break if anything faded softly. - -## 7. Do's and Don'ts - -### Do -- **Do** use `#ffffff` as the canvas for every view in light mode. -- **Do** use Jelly Mint (`#3cffd0`) and Verge Ultraviolet (`#5200ff`) as hazard accents — buttons, borders, active states, and saturated color-block tiles. -- **Do** use Anton exclusively at 60px+ for hero headlines. Treat anything smaller as a bug. -- **Do** round everything: 20px for cards, 24px for feature cards, 30–40px for pill buttons. -- **Do** use Space Mono for UPPERCASE labels, timestamps, kickers, and button text. Lowercase mono doesn't exist here. -- **Do** apply 1.5–1.9px letter-spacing to every ALL-CAPS label — this is a Verge signature. -- **Do** use saturated color-block tiles (mint, purple, yellow, pink, orange, white) to elevate a story — never a drop shadow. -- **Do** use `#3860be` (deep link blue) as the hover color on every link, regardless of base color. -- **Do** apply the StoryStream timeline rail (1px dashed/solid `#3d00bf` or `rgba(19, 19, 19, 0.1)`) on feed views. -- **Do** use thin-weight (300) Space Grotesk at 19–20px with 1.9px tracking for "fashion-whisper" capitalized eyebrows. - -### Don't -- **Don't** use a dark background in light mode. The white canvas is the product. -- **Don't** add `box-shadow` for elevation. Use 1px borders or saturated accent fills instead. -- **Don't** use square corners. Every interactive and content container is rounded. -- **Don't** use Anton for UI, buttons, or body copy. It's strictly display. -- **Don't** use lowercase mono. Space Mono is always UPPERCASE. -- **Don't** let mint and ultraviolet appear as background washes — they're hazard accents, not canvas tints. -- **Don't** use gradients anywhere. The system is solid color blocks only. -- **Don't** introduce new accent colors outside the declared mint / purple / yellow / pink / orange tile palette. -- **Don't** pair Anton with Newsreader in the same headline cluster — Anton is the only display shout, serif pulls are reserved for body moments. - -## 8. Responsive Behavior - -### Breakpoints -| Name | Width | Key Changes | -| ------------- | ----------- | ---------------------------------------------------------------------------------------------------- | -| Small Mobile | <400px | Single column, Anton hero scales down to ~48–54px, StoryStream rail collapses to inline timestamps | -| Mobile | 400–549px | Single column, color-block tiles stack full-width, nav is a hamburger drawer | -| Large Mobile | 550–767px | Still single column but padding opens up, tile radii stay at 20px | -| Tablet | 768–1023px | 2-column StoryStream with feature card spanning, wordmark shrinks ~50% | -| Small Desktop | 1024–1179px | Full 3–4 column editorial grid, mint pill CTA restored to nav | -| Desktop | 1180–1299px | Max padding, Anton wordmark at full hero scale | -| Large Desktop | ≥1300px | Container caps at ~1280–1300px, whitespace expands at the margins, no further scaling | - -### Touch Targets -- Primary pill buttons are ~44px minimum height (12px vertical padding + 13px text + 2px border) — meets WCAG AA. -- Mono uppercase nav links are smaller (~28–32px tall) — for derivative work, pad to 44px on mobile. -- Circle icon buttons are 40–44px circles, touch-friendly. - -### Collapsing Strategy -- **Nav**: wordmark scales from hero (Anton 60–104px) to ~24–32px on mobile. Category links collapse to a hamburger drawer below 900px. -- **Grid**: 4-col → 3-col → 2-col → 1-col. Feature cards that span 2 columns on desktop reflow to full-width single-column on mobile. -- **Spacing**: section padding tightens from 72px → 56px → 48px. Tile interior padding tightens from 32px → 20px. -- **Type**: Anton hero scales from 104px to ~48–54px on mobile. Space Grotesk headlines scale from 34px → 24px. Mono labels stay pinned at 11–12px (they don't shrink further or they become unreadable). -- **Color tiles**: accent story blocks never lose saturation on mobile — they just reflow to full width. - -### Image Behavior -- Responsive raster via `srcset`, aspect ratios preserved. -- No art-direction swaps — same crop scales across all viewports. -- `loading="lazy"` on everything below the fold, `eager` on the masthead hero. -- Images inside color-block tiles inherit the tile's inner radius (4px or 20px nested). - -## 9. Agent Prompt Guide - -### Quick Color Reference -- **Primary CTA**: "Jelly Mint (`#3cffd0`)" -- **Background (Canvas)**: "Canvas White (`#ffffff`)" -- **Accent (Secondary Hazard)**: "Verge Ultraviolet (`#5200ff`)" -- **Heading Text**: "Primary Text (`#131313`)" -- **Body Text**: "Primary Text (`#131313`)" (primary) or "Secondary Text (`#6a6a6a`)" -- **Secondary Text / Metadata**: "Secondary Text (`#6a6a6a`)" -- **Card Border**: "`rgba(19, 19, 19, 0.1)`" hairline on light, "Console Mint Border (`#309875`)" on mint variants -- **Link Hover**: "Deep Link Blue (`#3860be`)" - -### Example Component Prompts -1. *"Create a StoryStream timeline item on a* *`#ffffff`* *canvas: a 20px-radius rectangle with a 1px solid* *`rgba(19, 19, 19, 0.1)`* *border, a Space Mono 11px / 700 / UPPERCASE / 1.1px tracking timestamp on the left rail, a 12px Space Grotesk UPPERCASE kicker in mint (`#3cffd0`), and a 24px / 700 Space Grotesk headline in black below. No shadow, no lift — hover only shifts the headline color to* *`#3860be`."* -2. *"Design a primary subscribe button with a Jelly Mint (`#3cffd0`) fill, black text in Space Mono 12px / 700 / UPPERCASE / 1.5px tracking, 24px border radius, 12px × 28px padding. Hover state shifts to* *`rgba(60, 255, 208, 0.3)`* *background with a 1px* *`#309875`* *ring, 180ms ease."* -3. *"Build a feature hero with a 104px Anton 400 headline in black with 1px letter-spacing and 0.95 line-height, a thin-weight 300 Space Grotesk 19px capitalized kicker above with 1.9px tracking, on a* *`#ffffff`* *canvas with 72px vertical padding."* -4. *"Create a color-block accent tile filled with Verge Ultraviolet (`#5200ff`), 24px border radius, white text, a Space Mono 11px UPPERCASE category label with 1.5px tracking at the top, and a 32px Space Grotesk 700 headline below."* -5. *"Design a dark secondary button with a* *`#131313`* *background,* *`#ffffff`* *Space Mono 12px text, 24px radius pill shape, 12px × 28px padding. Hover matches the primary button —* *`rgba(19, 19, 19, 0.2)`* *bg with black text."* - -### Iteration Guide -When refining existing screens generated with this design system: -1. **Audit the canvas.** If you see a dark background anywhere in light mode, flatten it to `#ffffff`. -2. **Audit corners.** Every rectangle should land on 2/3/4/20/24/30/40px or 50%. Square corners break the voice. -3. **Audit shadows.** Strip every `box-shadow` that isn't a 1px inset underline or a 1px hazard-color border. The Verge uses color for elevation, not shadow. -4. **Audit type roles.** Anton only ≥60px. Space Mono only UPPERCASE. Space Grotesk 300 at 19–20px should have 1.9px tracking. Newsreader only for body/magazine moments, never UI. -5. **Audit accent usage.** Mint and ultraviolet should appear as hazard accents — buttons, 1px borders, active underlines, saturated tile fills. If they're appearing as background washes or gradient fades, correct to solid blocks. -6. **Audit labels.** Every kicker, timestamp, category tag, and button label should be ALL CAPS with 1.1–1.9px letter-spacing. Missing tracking = missing voice. -7. **Audit link hover.** Every link, regardless of its base color, should hover to `#3860be` deep link blue with no underline. Any other hover color is drift. \ No newline at end of file diff --git a/design/verge/preview-dark.html b/design/verge/preview-dark.html deleted file mode 100644 index 099f65a..0000000 --- a/design/verge/preview-dark.html +++ /dev/null @@ -1,1239 +0,0 @@ - - - - - -Design System Inspiration of The Verge - - - - - - - - - -
    - Design System / Editorial Hazard -

    Design System Inspiration of The Verge

    -

    Hazard-tape editorial. Massive Manuka headlines, acid-mint + ultraviolet accents, and a StoryStream timeline that feels like a git log for the news. Generated from DESIGN.md.

    -
    - - -
    -
    - -
    - Section 01 / Palette -

    Color Palette

    -

    Canvas black, jelly mint, verge ultraviolet — hazard colors on a near-black surface.

    - -
    -
    Primary — Brand Hazards
    -
    -
    -
    -
    -
    Jelly Mint
    -
    #3CFFD0
    -
    The signature acid-mint accent. CTA fills, active borders, hazard spotlights.
    -
    -
    -
    -
    -
    -
    Verge Ultraviolet
    -
    #5200FF
    -
    The complementary hazard. Secondary tiles, outlined buttons, alert borders.
    -
    -
    -
    -
    - -
    -
    Secondary & Accent
    -
    -
    -
    -
    -
    Console Mint Border
    -
    #309875
    -
    Darker mint for card outlines and button borders.
    -
    -
    -
    -
    -
    -
    Deep Link Blue
    -
    #3860BE
    -
    The one moment blue appears — every link's hover state.
    -
    -
    -
    -
    -
    -
    Focus Cyan
    -
    #1EAEDB
    -
    Reserved for button focus rings. Keyboard-only visibility.
    -
    -
    -
    -
    -
    -
    Purple Rule
    -
    #3D00BF
    -
    Darker ultraviolet for StoryStream timeline rails.
    -
    -
    -
    -
    - -
    -
    Surface & Background
    -
    -
    -
    -
    -
    Canvas Black
    -
    #131313
    -
    The default dark surface for the entire homepage. Newsprint-negative warmth.
    -
    -
    -
    -
    -
    -
    Surface Slate
    -
    #2D2D2D
    -
    Secondary card background when a tile stays quiet.
    -
    -
    -
    -
    -
    -
    Image Frame
    -
    #313131
    -
    1px border around inline photography.
    -
    -
    -
    -
    -
    -
    Hazard White
    -
    #FFFFFF
    -
    Tile fill, primary text, and the loudest "spotlight" surface.
    -
    -
    -
    -
    - -
    -
    Neutrals & Text
    -
    -
    -
    -
    -
    Primary Text
    -
    #FFFFFF
    -
    Headlines and display text on the canvas.
    -
    -
    -
    -
    -
    -
    Secondary Text
    -
    #949494
    -
    Bylines, timestamps, photo credits.
    -
    -
    -
    -
    -
    -
    Muted Text
    -
    #E9E9E9
    -
    Button text on dark slate — slightly off-white to reduce glare.
    -
    -
    -
    -
    -
    - -
    - Section 02 / Typography -

    Typographic Hierarchy

    -

    Manuka shouts, PolySans works, PolySans Mono labels, FK Roman whispers.

    - -
    -
    Hero WordmarkManuka · 107px / 900 / 0.80 / 1.07px
    -
    The Verge
    -
    -
    -
    Display SecondaryManuka · 60px / 900 / 0.80
    -
    Feature Callout Headline
    -
    -
    -
    Large HeadlinePolySans · 34px / 700 / 1.00
    -
    Section and module headlines
    -
    -
    -
    Heading WidePolySans · 32px / 400 / 1.10 / 0.32px
    -
    Sub-heroes and promotional units
    -
    -
    -
    Heading MediumPolySans · 24px / 700 / 1.00
    -
    Story tile headlines in the main feed
    -
    -
    -
    Fashion WhisperPolySans · 19px / 300 / 1.20 / 1.9px / CAPITALIZE
    -
    The Thin Weight Kicker Above The Shout
    -
    -
    -
    All-Caps XLPolySans · 18px / 400 / 1.10 / 1.8px / UPPER
    -
    Section Kicker Label
    -
    -
    -
    Body RelaxedPolySans · 16px / 500 / 1.60
    -
    Long-form reading body. The default rhythm for article decks and extended captions — relaxed leading to carry the density of a dark canvas.
    -
    -
    -
    Eyebrow All-CapsPolySans · 12px / 400 / 1.30 / 1.8px / UPPER
    -
    Policy · Transportation · Apple
    -
    -
    -
    Mono TimestampPolySans Mono · 11px / 500 / 1.20 / 1.1px / UPPER
    -
    21m ago · 3h ago · Yesterday
    -
    -
    -
    Mono ButtonPolySans Mono · 12px / 600 / 2.00 / 1.5px / UPPER
    -
    Subscribe Now
    -
    -
    -
    Serif BodyFK Roman Standard · 16px / 400 / 1.30 / -0.16px
    -
    The rare serif moment — used for review decks and critic pulls, a print-voice counterpoint to the PolySans workhorse.
    -
    -
    - -
    - Section 03 / Buttons -

    Button Variants

    -

    Pills only. 24–40px radius, hazard-color fills, mono UPPERCASE labels.

    -
    -
    - Primary — Jelly Mint Pill -
    -
    -
    - Secondary — Dark Pill -
    -
    -
    - Outlined — Mint 40px -
    -
    -
    - Outlined — Ultraviolet 30px -
    -
    -
    - Icon — Round 50% -
    -
    -
    - Pill Tag — Non-interactive -
    Breaking
    -
    -
    -
    - -
    - Section 04 / Story Tiles -

    Hazard-Color Tiles

    -

    Saturated accent blocks with rounded 20–24px corners. Color is elevation.

    -
    -
    - Policy · Feature -

    The Next Browser War Is Already Over And Nobody Noticed

    -

    A long-form deck on why the market moved from standards to distribution while the press was still benchmarking rendering engines.

    - -
    -
    - Hardware -

    A Mechanical Keyboard Reviewed At Rave Volume

    - -
    -
    -
    -
    -
    - Gaming -

    The Indie That Ate The Big Studios Alive

    - -
    -
    - Science -

    Inside The Lab Running A Synthetic Atmosphere

    - -
    -
    -
    - -
    - Section 05 / StoryStream -

    Timeline Rail

    -

    Every post is a pill-cornered tile, pinned to a dashed rail by a mono uppercase timestamp.

    -
    -
    -
    21m ago
    -
    - Breaking -

    A regulator has opened an investigation into the platform merger

    -
    -
    -
    -
    1h ago
    -
    - Apple -

    The iOS update everyone is quietly rolling back

    -
    -
    -
    -
    3h ago
    -
    - Transportation -

    The EV startup that outlasted its own hype cycle

    -
    -
    -
    -
    Yesterday
    -
    - Gaming -

    A handheld that actually earns the price tag

    -
    -
    -
    -
    - -
    - Section 06 / Forms -

    Inputs & Newsletter

    -

    Tight 2px radius, mint focus border, ultraviolet error border — newspaper-form minimalism.

    -
    -
    - - -
    -
    - - -
    -
    - - - Please enter a valid address -
    -
    - - -
    -
    -
    - -
    - Section 07 / Spacing -

    Spacing Scale (8px System)

    -

    Fine micro-scale (2/4/5/6/9/10) for pills, editorial scale (12/16/20/24) for the grid.

    -
    -
    2px
    -
    4px
    -
    6px
    -
    8px · base
    -
    10px
    -
    12px
    -
    16px
    -
    20px
    -
    24px
    -
    25px
    -
    -
    - -
    - Section 08 / Radius -

    Border Radius Scale

    -

    Eight radii — from 2px typewriter tags to 40px outlined shout-pills.

    -
    -
    -
    - 2pxInputs, badges -
    -
    -
    - 3pxInline images -
    -
    -
    - 4pxNested imagery -
    -
    -
    - 20pxStory tiles -
    -
    -
    - 24pxFeature cards, primary button -
    -
    -
    - 30pxPromo buttons -
    -
    -
    - 40pxOutlined pill CTAs -
    -
    -
    - 50%Avatars, icon buttons -
    -
    -
    - -
    - Section 09 / Elevation -

    Depth & Elevation

    -

    Color is elevation. 1px hazard borders do the work shadows would do elsewhere.

    -
    -
    - Level 0 -
    Plain canvas text — no border, no shadow
    -
    -
    - Level 2 -
    1px hairline frame — image outlines
    -
    -
    - Level 3 -
    1px Jelly Mint outline — active tile
    -
    -
    - Level 4 -
    1px Ultraviolet outline — promo state
    -
    -
    - Level 5 -
    Subtle atmospheric 1px ring — stacked cards
    -
    -
    - Level 6 -
    Inset mint underline — active tab signature
    -
    -
    - Level 7 -
    Saturated Jelly Mint fill — loudest emphasis
    -
    -
    -
    - - - - - - -
    \ No newline at end of file diff --git a/design/verge/preview.html b/design/verge/preview.html deleted file mode 100644 index 65305f5..0000000 --- a/design/verge/preview.html +++ /dev/null @@ -1,1145 +0,0 @@ - - - - - - -Design System Inspiration of The Verge - - - - - - - - - -
    - Design System / Editorial Hazard -

    Design System Inspiration of The Verge

    -

    Hazard-tape editorial. Massive Manuka headlines, acid-mint + ultraviolet accents, and a StoryStream timeline that feels like a git log for the news. Generated from DESIGN.md.

    -
    - - -
    -
    - - -
    - Section 01 / Palette -

    Color Palette

    -

    Canvas black, jelly mint, verge ultraviolet — hazard colors on a near-black surface.

    - -
    -
    Primary — Brand Hazards
    -
    -
    -
    -
    -
    Jelly Mint
    -
    #3CFFD0
    -
    The signature acid-mint accent. CTA fills, active borders, hazard spotlights.
    -
    -
    -
    -
    -
    -
    Verge Ultraviolet
    -
    #5200FF
    -
    The complementary hazard. Secondary tiles, outlined buttons, alert borders.
    -
    -
    -
    -
    - -
    -
    Secondary & Accent
    -
    -
    -
    -
    -
    Console Mint Border
    -
    #309875
    -
    Darker mint for card outlines and button borders.
    -
    -
    -
    -
    -
    -
    Deep Link Blue
    -
    #3860BE
    -
    The one moment blue appears — every link's hover state.
    -
    -
    -
    -
    -
    -
    Focus Cyan
    -
    #1EAEDB
    -
    Reserved for button focus rings. Keyboard-only visibility.
    -
    -
    -
    -
    -
    -
    Purple Rule
    -
    #3D00BF
    -
    Darker ultraviolet for StoryStream timeline rails.
    -
    -
    -
    -
    - -
    -
    Surface & Background
    -
    -
    -
    -
    -
    Canvas Black
    -
    #131313
    -
    The default dark surface for the entire homepage. Newsprint-negative warmth.
    -
    -
    -
    -
    -
    -
    Surface Slate
    -
    #2D2D2D
    -
    Secondary card background when a tile stays quiet.
    -
    -
    -
    -
    -
    -
    Image Frame
    -
    #313131
    -
    1px border around inline photography.
    -
    -
    -
    -
    -
    -
    Hazard White
    -
    #FFFFFF
    -
    Tile fill, primary text, and the loudest "spotlight" surface.
    -
    -
    -
    -
    - -
    -
    Neutrals & Text
    -
    -
    -
    -
    -
    Primary Text
    -
    #FFFFFF
    -
    Headlines and display text on the canvas.
    -
    -
    -
    -
    -
    -
    Secondary Text
    -
    #949494
    -
    Bylines, timestamps, photo credits.
    -
    -
    -
    -
    -
    -
    Muted Text
    -
    #E9E9E9
    -
    Button text on dark slate — slightly off-white to reduce glare.
    -
    -
    -
    -
    -
    - - -
    - Section 02 / Typography -

    Typographic Hierarchy

    -

    Manuka shouts, PolySans works, PolySans Mono labels, FK Roman whispers.

    - -
    -
    Hero WordmarkManuka · 107px / 900 / 0.80 / 1.07px
    -
    The Verge
    -
    -
    -
    Display SecondaryManuka · 60px / 900 / 0.80
    -
    Feature Callout Headline
    -
    -
    -
    Large HeadlinePolySans · 34px / 700 / 1.00
    -
    Section and module headlines
    -
    -
    -
    Heading WidePolySans · 32px / 400 / 1.10 / 0.32px
    -
    Sub-heroes and promotional units
    -
    -
    -
    Heading MediumPolySans · 24px / 700 / 1.00
    -
    Story tile headlines in the main feed
    -
    -
    -
    Fashion WhisperPolySans · 19px / 300 / 1.20 / 1.9px / CAPITALIZE
    -
    The Thin Weight Kicker Above The Shout
    -
    -
    -
    All-Caps XLPolySans · 18px / 400 / 1.10 / 1.8px / UPPER
    -
    Section Kicker Label
    -
    -
    -
    Body RelaxedPolySans · 16px / 500 / 1.60
    -
    Long-form reading body. The default rhythm for article decks and extended captions — relaxed leading to carry the density of a dark canvas.
    -
    -
    -
    Eyebrow All-CapsPolySans · 12px / 400 / 1.30 / 1.8px / UPPER
    -
    Policy · Transportation · Apple
    -
    -
    -
    Mono TimestampPolySans Mono · 11px / 500 / 1.20 / 1.1px / UPPER
    -
    21m ago · 3h ago · Yesterday
    -
    -
    -
    Mono ButtonPolySans Mono · 12px / 600 / 2.00 / 1.5px / UPPER
    -
    Subscribe Now
    -
    -
    -
    Serif BodyFK Roman Standard · 16px / 400 / 1.30 / -0.16px
    -
    The rare serif moment — used for review decks and critic pulls, a print-voice counterpoint to the PolySans workhorse.
    -
    -
    - - -
    - Section 03 / Buttons -

    Button Variants

    -

    Pills only. 24–40px radius, hazard-color fills, mono UPPERCASE labels.

    -
    -
    - Primary — Jelly Mint Pill -
    -
    -
    - Secondary — Dark Pill -
    -
    -
    - Outlined — Mint 40px -
    -
    -
    - Outlined — Ultraviolet 30px -
    -
    -
    - Icon — Round 50% -
    -
    -
    - Pill Tag — Non-interactive -
    Breaking
    -
    -
    -
    - - -
    - Section 04 / Story Tiles -

    Hazard-Color Tiles

    -

    Saturated accent blocks with rounded 20–24px corners. Color is elevation.

    -
    -
    - Policy · Feature -

    The Next Browser War Is Already Over And Nobody Noticed

    -

    A long-form deck on why the market moved from standards to distribution while the press was still benchmarking rendering engines.

    - -
    -
    - Hardware -

    A Mechanical Keyboard Reviewed At Rave Volume

    - -
    -
    -
    -
    -
    - Gaming -

    The Indie That Ate The Big Studios Alive

    - -
    -
    - Science -

    Inside The Lab Running A Synthetic Atmosphere

    - -
    -
    -
    - - -
    - Section 05 / StoryStream -

    Timeline Rail

    -

    Every post is a pill-cornered tile, pinned to a dashed rail by a mono uppercase timestamp.

    -
    -
    -
    21m ago
    -
    - Breaking -

    A regulator has opened an investigation into the platform merger

    -
    -
    -
    -
    1h ago
    -
    - Apple -

    The iOS update everyone is quietly rolling back

    -
    -
    -
    -
    3h ago
    -
    - Transportation -

    The EV startup that outlasted its own hype cycle

    -
    -
    -
    -
    Yesterday
    -
    - Gaming -

    A handheld that actually earns the price tag

    -
    -
    -
    -
    - - -
    - Section 06 / Forms -

    Inputs & Newsletter

    -

    Tight 2px radius, mint focus border, ultraviolet error border — newspaper-form minimalism.

    -
    -
    - - -
    -
    - - -
    -
    - - - Please enter a valid address -
    -
    - - -
    -
    -
    - - -
    - Section 07 / Spacing -

    Spacing Scale (8px System)

    -

    Fine micro-scale (2/4/5/6/9/10) for pills, editorial scale (12/16/20/24) for the grid.

    -
    -
    2px
    -
    4px
    -
    6px
    -
    8px · base
    -
    10px
    -
    12px
    -
    16px
    -
    20px
    -
    24px
    -
    25px
    -
    -
    - - -
    - Section 08 / Radius -

    Border Radius Scale

    -

    Eight radii — from 2px typewriter tags to 40px outlined shout-pills.

    -
    -
    -
    - 2pxInputs, badges -
    -
    -
    - 3pxInline images -
    -
    -
    - 4pxNested imagery -
    -
    -
    - 20pxStory tiles -
    -
    -
    - 24pxFeature cards, primary button -
    -
    -
    - 30pxPromo buttons -
    -
    -
    - 40pxOutlined pill CTAs -
    -
    -
    - 50%Avatars, icon buttons -
    -
    -
    - - -
    - Section 09 / Elevation -

    Depth & Elevation

    -

    Color is elevation. 1px hazard borders do the work shadows would do elsewhere.

    -
    -
    - Level 0 -
    Plain canvas text — no border, no shadow
    -
    -
    - Level 2 -
    1px hairline frame — image outlines
    -
    -
    - Level 3 -
    1px Jelly Mint outline — active tile
    -
    -
    - Level 4 -
    1px Ultraviolet outline — promo state
    -
    -
    - Level 5 -
    Subtle atmospheric 1px ring — stacked cards
    -
    -
    - Level 6 -
    Inset mint underline — active tab signature
    -
    -
    - Level 7 -
    Saturated Jelly Mint fill — loudest emphasis
    -
    -
    -
    - - - - - - diff --git a/index.html b/index.html index 52a5e9b..4c7e272 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - UIToCode + 项目名称
    diff --git a/package-lock.json b/package-lock.json index a487ed1..4d56c7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,38 +1,49 @@ { - "name": "UIToCode", + "name": "project-name", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "UIToCode", + "name": "project-name", "version": "0.0.0", "dependencies": { - "@tanstack/react-query": "^5.99.2", - "@types/js-cookie": "^3.0.6", - "axios": "^1.15.1", - "i18next": "^26.0.6", - "i18next-browser-languagedetector": "^8.2.1", - "js-cookie": "^3.0.5", - "posthog-js": "^1.369.3", - "posthog-node": "^5.29.2", + "@radix-ui/react-icons": "^1.3.2", + "axios": "^1.6.7", + "i18next": "^23.10.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^7.14.2", - "react-i18next": "^17.0.4", - "react-zoom-pan-pinch": "^4.0.3" + "react-i18next": "^14.1.0", + "react-router-dom": "^6.22.3" }, "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.55.0", + "autoprefixer": "^10.4.17", + "eslint": "^8.56.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", + "postcss": "^8.4.35", + "prettier": "^3.2.5", + "tailwindcss": "^3.4.1", "typescript": "^5.2.2", - "vite": "^5.0.8" + "vite": "^5.1.4" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@babel/code-frame": { @@ -974,328 +985,24 @@ "node": ">= 8" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", - "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.208.0.tgz", - "integrity": "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/core": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz", - "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, + "node_modules/@radix-ui/react-icons": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", + "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", + "license": "MIT", "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.208.0.tgz", - "integrity": "sha512-jOv40Bs9jy9bZVLo/i8FwUiuCvbjWDI+ZW13wimJm4LjnlwJxGgB+N/VWOZUTpM+ah/awXeQqKdNlpLf2EjvYg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.208.0", - "@opentelemetry/core": "2.2.0", - "@opentelemetry/otlp-exporter-base": "0.208.0", - "@opentelemetry/otlp-transformer": "0.208.0", - "@opentelemetry/sdk-logs": "0.208.0" - }, + "node_modules/@remix-run/router": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", + "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", + "license": "MIT", "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=14.0.0" } }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.208.0.tgz", - "integrity": "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/otlp-transformer": "0.208.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.208.0.tgz", - "integrity": "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.208.0", - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0", - "@opentelemetry/sdk-logs": "0.208.0", - "@opentelemetry/sdk-metrics": "2.2.0", - "@opentelemetry/sdk-trace-base": "2.2.0", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.0.tgz", - "integrity": "sha512-K+oi0hNMv94EpZbnW3eyu2X6SGVpD3O5DhG2NIp65Hc7lhAj9brRXTAVzh3wB82+q3ThakEf7Zd7RsFUqcTc7A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.7.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.0.tgz", - "integrity": "sha512-DT12SXVwV2eoJrGf4nnsvZojxxeQo+LlNAsoYGRRObPWTeN6APiqZ2+nqDCQDvQX40eLi1AePONS0onoASp3yQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.208.0.tgz", - "integrity": "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.208.0", - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz", - "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", - "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz", - "integrity": "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@posthog/core": { - "version": "1.25.2", - "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.25.2.tgz", - "integrity": "sha512-h2FO7ut/BbfwpAXWpwdDHTzQgUo9ibDFEs6ZO+3cI3KPWQt5XwczK1OLAuPprcjm8T/jl0SH8jSFo5XdU4RbTg==", - "license": "MIT" - }, - "node_modules/@posthog/types": { - "version": "1.369.3", - "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.369.3.tgz", - "integrity": "sha512-Ywqvs4513PixR2TIA5O3GMEyK4F65uefwxPfsIUeHr9ruGylyXp00YJ4CEbp8U0DMzCkeF+LsMKVnHgN3pAXcA==", - "license": "MIT" - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1692,32 +1399,6 @@ "win32" ] }, - "node_modules/@tanstack/query-core": { - "version": "5.99.2", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.99.2.tgz", - "integrity": "sha512-1HunU0bXVsR1ZJMZbcOPE6VtaBJxsW809RE9xPe4Gz7MlB0GWwQvuTPhMoEmQ/hIzFKJ/DWAuttIe7BOaWx0tA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.99.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.99.2.tgz", - "integrity": "sha512-vM91UEe45QUS9ED6OklsVL15i8qKcRqNwpWzPTVWvRPRSEgDudDgHpvyTjcdlwHcrKNa80T+xXYcchT2noPnZA==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.99.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1770,28 +1451,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/js-cookie": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", - "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.19.0" - } - }, "node_modules/@types/prop-types": { "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", @@ -1820,49 +1479,33 @@ "@types/react": "^18.0.0" } }, - "node_modules/@types/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1871,27 +1514,27 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1900,17 +1543,17 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1918,26 +1561,26 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1946,13 +1589,13 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1960,23 +1603,23 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1989,43 +1632,40 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2084,9 +1724,9 @@ } }, "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -2126,6 +1766,34 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2149,10 +1817,47 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/axios": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.1.tgz", - "integrity": "sha512-WOG+Jj8ZOvR0a3rAn+Tuf1UQJRxw5venr6DgdbJzngJE3qG7X0kL83CZGpdHMxEm+ZK3seAbvFsw4FfOfP9vxg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz", + "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", @@ -2168,9 +1873,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.20", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.20.tgz", - "integrity": "sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ==", + "version": "2.10.21", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.21.tgz", + "integrity": "sha512-Q+rUQ7Uz8AHM7DEaNdwvfFCTq7a43lNTzuS94eiWqwyxfV/wJv+oUivef51T91mmRY4d4A1u9rcSvkeufCVXlA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2180,6 +1885,19 @@ "node": ">=6.0.0" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", @@ -2260,10 +1978,20 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { - "version": "1.0.30001788", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz", - "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==", + "version": "1.0.30001790", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz", + "integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==", "dev": true, "funding": [ { @@ -2298,6 +2026,44 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2330,6 +2096,16 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2344,30 +2120,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/core-js": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", - "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2383,6 +2135,19 @@ "node": ">= 8" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -2424,6 +2189,13 @@ "node": ">=0.4.0" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2437,6 +2209,13 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2450,15 +2229,6 @@ "node": ">=6.0.0" } }, - "node_modules/dompurify": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.0.tgz", - "integrity": "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2474,9 +2244,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.340.tgz", - "integrity": "sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA==", + "version": "1.5.344", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz", + "integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==", "dev": true, "license": "ISC" }, @@ -2846,12 +2616,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fflate": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", - "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", - "license": "MIT" - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2953,6 +2717,20 @@ "node": ">= 6" } }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3205,41 +2983,24 @@ } }, "node_modules/i18next": { - "version": "26.0.6", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.6.tgz", - "integrity": "sha512-A4U6eCXodIbrhf8EarRurB9/4ebyaurH4+fu4gig9bqxmpSt+fCAFm/GpRQDcN1Xzu/LdFCx4nYHsnM1edIIbg==", + "version": "23.16.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", + "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", "funding": [ { "type": "individual", - "url": "https://www.locize.com/i18next" + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" }, { "type": "individual", "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" - }, - { - "type": "individual", - "url": "https://www.locize.com" } ], "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.29.2" - }, - "peerDependencies": { - "typescript": "^5 || ^6" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/i18next-browser-languagedetector": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz", - "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==", - "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" } @@ -3300,6 +3061,35 @@ "dev": true, "license": "ISC" }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3350,13 +3140,14 @@ "dev": true, "license": "ISC" }, - "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=14" + "bin": { + "jiti": "bin/jiti.js" } }, "node_modules/js-tokens": { @@ -3449,6 +3240,26 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3472,12 +3283,6 @@ "dev": true, "license": "MIT" }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3555,13 +3360,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -3577,6 +3382,18 @@ "dev": true, "license": "MIT" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -3604,12 +3421,42 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.37", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", - "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3713,6 +3560,13 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -3743,6 +3597,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/postcss": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", @@ -3772,57 +3646,140 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/posthog-js": { - "version": "1.369.3", - "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.369.3.tgz", - "integrity": "sha512-t4vk8mgkSdhIYr8YDRdLG45uJYH58MC7bPL83lKTEeDgoejyXbJ1/G77GZB/aWVQDST055GkgjQtUtK5DiYGkg==", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/api-logs": "^0.208.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-logs": "^0.208.0", - "@posthog/core": "1.25.2", - "@posthog/types": "1.369.3", - "core-js": "^3.38.1", - "dompurify": "^3.3.2", - "fflate": "^0.4.8", - "preact": "^10.28.2", - "query-selector-shadow-dom": "^1.0.1", - "web-vitals": "^5.1.0" - } - }, - "node_modules/posthog-node": { - "version": "5.29.2", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.29.2.tgz", - "integrity": "sha512-rI7kkF0XqDc0G1qjx+Hb4iuY9NAlL+XQNoGOpnEpRNTUcXvjY6WlsRGZ9m2whgc39emrrYdszi/YT8wZkr2xsg==", + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, "license": "MIT", "dependencies": { - "@posthog/core": "1.25.2" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" }, "engines": { - "node": "^20.20.0 || >=22.22.0" + "node": ">=14.0.0" }, "peerDependencies": { - "rxjs": "^7.0.0" + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { - "rxjs": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { "optional": true } } }, - "node_modules/preact": { - "version": "10.29.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", - "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" } }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3833,28 +3790,20 @@ "node": ">= 0.8.0" } }, - "node_modules/protobufjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz", - "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=12.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/proxy-from-env": { @@ -3876,12 +3825,6 @@ "node": ">=6" } }, - "node_modules/query-selector-shadow-dom": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", - "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3929,19 +3872,17 @@ } }, "node_modules/react-i18next": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.4.tgz", - "integrity": "sha512-hQipmK4EF0y6RO6tt6WuqnmWpWYEXmQUUzecmMBuNsIgYd3smXcG4GtYPWhvgxn0pqMOItKlEO8H24HCs5hc3g==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", + "integrity": "sha512-wZnpfunU6UIAiJ+bxwOiTmBOAaB14ha97MjOEnLGac2RJ+h/maIYXZuTHlmyqQVX1UVHmU1YDTQ5vxLmwfXTjw==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.29.2", - "html-parse-stringify": "^3.0.1", - "use-sync-external-store": "^1.6.0" + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" }, "peerDependencies": { - "i18next": ">= 26.0.1", - "react": ">= 16.8.0", - "typescript": "^5 || ^6" + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" }, "peerDependenciesMeta": { "react-dom": { @@ -3949,9 +3890,6 @@ }, "react-native": { "optional": true - }, - "typescript": { - "optional": true } } }, @@ -3966,55 +3904,80 @@ } }, "node_modules/react-router": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.14.2.tgz", - "integrity": "sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz", + "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", "license": "MIT", "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" + "@remix-run/router": "1.23.2" }, "engines": { - "node": ">=20.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } + "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.14.2.tgz", - "integrity": "sha512-YZcM5ES8jJSM+KrJ9BdvHHqlnGTg5tH3sC5ChFRj4inosKctdyzBDhOyyHdGk597q2OT6NTrCA1OvB/YDwfekQ==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz", + "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", "license": "MIT", "dependencies": { - "react-router": "7.14.2" + "@remix-run/router": "1.23.2", + "react-router": "6.30.3" }, "engines": { - "node": ">=20.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/react-zoom-pan-pinch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-4.0.3.tgz", - "integrity": "sha512-N2Hi6L78fFmhRra+ORpFSW7WST5x6kxpOPplIvtB0b7b+U2anpo1z1wLgaWRPS2kUSqcraRG+JgBCIlDJnqqAg==", + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=8", - "npm": ">=5" + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" }, - "peerDependencies": { - "react": "*", - "react-dom": "*" + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve-from": { @@ -4146,12 +4109,6 @@ "node": ">=10" } }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4221,6 +4178,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4234,6 +4214,57 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4241,6 +4272,77 @@ "dev": true, "license": "MIT" }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4267,6 +4369,13 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4297,7 +4406,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -4307,12 +4416,6 @@ "node": ">=14.17" } }, - "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", - "license": "MIT" - }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -4354,14 +4457,12 @@ "punycode": "^2.1.0" } }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" }, "node_modules/vite": { "version": "5.4.21", @@ -4432,12 +4533,6 @@ "node": ">=0.10.0" } }, - "node_modules/web-vitals": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-5.2.0.tgz", - "integrity": "sha512-i2z98bEmaCqSDiHEDu+gHl/dmR4Q+TxFmG3/13KkMO+o8UxQzCqWaDRCiLgEa41nlO4VpXSI0ASa1xWmO9sBlA==", - "license": "Apache-2.0" - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 03b266d..9e55c5f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "UIToCode", + "name": "project-name", "private": true, "version": "0.0.0", "type": "module", @@ -10,30 +10,28 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/react-query": "^5.99.2", - "@types/js-cookie": "^3.0.6", - "axios": "^1.15.1", - "i18next": "^26.0.6", - "i18next-browser-languagedetector": "^8.2.1", - "js-cookie": "^3.0.5", - "posthog-js": "^1.369.3", - "posthog-node": "^5.29.2", + "@radix-ui/react-icons": "^1.3.2", + "axios": "^1.6.7", + "i18next": "^23.10.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^7.14.2", - "react-i18next": "^17.0.4", - "react-zoom-pan-pinch": "^4.0.3" + "react-i18next": "^14.1.0", + "react-router-dom": "^6.22.3" }, "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.55.0", + "autoprefixer": "^10.4.17", + "eslint": "^8.56.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", + "postcss": "^8.4.35", + "prettier": "^3.2.5", + "tailwindcss": "^3.4.1", "typescript": "^5.2.2", - "vite": "^5.0.8" + "vite": "^5.1.4" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..e99ebc2 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} \ No newline at end of file diff --git a/src/App.css b/src/App.css deleted file mode 100644 index 8a5f70a..0000000 --- a/src/App.css +++ /dev/null @@ -1,26 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - margin: 0; - font-family: var(--font-family-primary); - font-weight: var(--font-weight-regular); - letter-spacing: var(--letter-spacing-normal); - font-kerning: normal; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - overflow: hidden; - background-color: var(--color-background); - color: var(--color-text-primary); -} - -.app-container { - position: relative; - width: 100vw; - height: 100vh; - overflow: hidden; - background-color: var(--color-background); -} diff --git a/src/App.tsx b/src/App.tsx index 6b4b6bf..6cfffd5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,31 +1,27 @@ - import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom' import Login from './pages/auth/Login' import Register from './pages/auth/Register' -import Projects from './pages/app/Projects' -import MainApp from './pages/app/MainApp' -import './App.css' - - - -// 路由保护组件 -const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const isLoggedIn = localStorage.getItem('isLoggedIn') - return isLoggedIn ? <>{children} : -} +import ForgotPassword from './pages/auth/ForgotPassword' +import Layout from './components/layout/Layout' +import Dashboard from './pages/dashboard/Dashboard' +import Settings from './pages/settings/Settings' +import ProjectList from './pages/projects/ProjectList' function App() { return ( + } /> } /> } /> - } /> - } /> - } /> + } /> + } /> + } /> + } /> + } /> ) } -export default App +export default App \ No newline at end of file diff --git a/src/assets/react.svg b/src/assets/react.svg deleted file mode 100644 index 2cc8ac0..0000000 --- a/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/AIChatPanel.css b/src/components/AIChatPanel.css deleted file mode 100644 index 9c01c19..0000000 --- a/src/components/AIChatPanel.css +++ /dev/null @@ -1,528 +0,0 @@ -.ai-chat-panel { - position: absolute; - top: 100px; - right: 20px; - bottom: 20px; - width: 350px; - background-color: var(--color-white); - border: 1px solid var(--color-border-subtle); - border-radius: var(--radius-card); - display: flex; - flex-direction: column; - z-index: 99; - box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1); -} - -.chat-content { - position: relative; - display: flex; - flex: 1; - overflow: hidden; - z-index: 20; - border-radius: var(--radius-card); - background-color: var(--color-white); -} - -.chat-header { - padding: var(--space-7) var(--space-9); - border-bottom: 1px solid var(--color-border-subtle); - display: flex; - justify-content: space-between; - align-items: center; - border-radius: var(--radius-card) var(--radius-card) 0 0; -} - -.chat-header h3 { - margin: 0; - font-size: var(--font-size-heading-3); - font-weight: var(--font-weight-bold); - color: var(--color-text-primary); - letter-spacing: var(--letter-spacing-normal); - font-family: var(--font-family-primary); - font-feature-settings: "ss01", "ss02"; -} - -.header-left { - display: flex; - align-items: center; - gap: var(--space-4); -} - -.header-right { - display: flex; - align-items: center; - gap: var(--space-4); -} - -.new-chat-btn { - padding: var(--space-3); - background-color: var(--color-soft-gray); - border: 1px solid var(--color-border-subtle); - border-radius: var(--radius-circle); - cursor: pointer; - transition: all 0.15s ease; - display: flex; - align-items: center; - justify-content: center; - color: var(--color-text-primary); -} - -.new-chat-btn:hover { - background-color: var(--color-button-hover); - color: var(--color-white); - border-color: var(--color-meta-blue); -} - -.new-chat-btn:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.history-btn { - padding: var(--space-3); - background-color: var(--color-soft-gray); - border: 1px solid var(--color-border-subtle); - border-radius: var(--radius-circle); - cursor: pointer; - transition: all 0.15s ease; - display: flex; - align-items: center; - justify-content: center; - color: var(--color-text-primary); -} - -.history-btn:hover { - background-color: var(--color-button-hover); - color: var(--color-white); - border-color: var(--color-meta-blue); -} - -.history-btn:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.history-btn.active { - background-color: var(--color-meta-blue); - border-color: var(--color-meta-blue); - color: var(--color-white); -} - -.model-selector { - position: relative; -} - -.model-select { - padding: var(--space-3) var(--space-5); - background-color: var(--color-soft-gray); - border: 1px solid var(--color-border-medium); - border-radius: var(--radius-small); - color: var(--color-text-primary); - font-size: var(--font-size-caption); - font-family: var(--font-family-primary); - letter-spacing: var(--letter-spacing-tighter); - cursor: pointer; - outline: none; - transition: border-color 200ms ease, box-shadow 200ms ease; -} - -.model-select:hover { - border-color: var(--color-meta-blue); -} - -.model-select:focus { - border-color: hsl(214, 89%, 52%); - box-shadow: 0 0 0 3px rgba(0, 100, 224, 0.1); -} - -.model-select:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.conversation-sidebar { - position: absolute; - left: 0; - top: 0; - width: 250px; - height: 200px; - transform: translateX(0); - background-color: var(--color-white); - border: 1px solid var(--color-border-subtle); - border-radius: var(--radius-card); - transition: transform 0.3s ease; - z-index: 10; - overflow: hidden; - display: flex; - flex-direction: column; - box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1); -} - -.conversation-sidebar.visible { - transform: translateX(-101%); -} - -.conversation-sidebar h4 { - margin: 0; - padding: var(--space-5) var(--space-7); - font-family: var(--font-family-primary); - font-size: var(--font-size-caption-bold); - font-weight: var(--font-weight-bold); - color: var(--color-text-primary); - border-bottom: 1px solid var(--color-border-subtle); - flex-shrink: 0; - letter-spacing: var(--letter-spacing-normal); -} - -.conversation-list { - overflow-y: auto; - flex: 1; -} - -.conversation-item { - padding: var(--space-4) var(--space-7); - cursor: pointer; - transition: background-color 0.15s ease; - border-bottom: 1px solid var(--color-border-subtle); - color: var(--color-text-primary); -} - -.conversation-item:hover { - background-color: var(--color-soft-gray); -} - -.conversation-item:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.conversation-item.active { - background-color: var(--color-meta-blue); - color: var(--color-white); -} - -.conversation-title { - font-size: var(--font-size-body); - font-weight: var(--font-weight-medium); - margin-bottom: var(--space-2); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - letter-spacing: var(--letter-spacing-normal); - font-family: var(--font-family-primary); -} - -.conversation-time { - font-family: var(--font-family-secondary); - font-size: var(--font-size-small); - color: var(--color-text-muted); - letter-spacing: var(--letter-spacing-normal); -} - -.conversation-item.active .conversation-time { - color: var(--color-white); - opacity: 0.8; -} - -.chat-main { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; - border-radius: var(--radius-card) var(--radius-card) 0 0; -} - -.bottom-model-selector { - padding: 0 var(--space-7) var(--space-3); - display: flex; - justify-content: center; - align-items: center; -} - -.chat-messages { - flex: 1; - overflow-y: auto; - padding: var(--space-9); - display: flex; - flex-direction: column; - gap: var(--space-7); -} - -.message { - display: flex; - flex-direction: column; -} - -.message.user { - align-items: flex-end; -} - -.message.ai { - align-items: flex-start; -} - -.message-content { - max-width: 80%; - padding: var(--space-5) var(--space-7); - border-radius: var(--radius-card); - font-size: var(--font-size-body); - line-height: var(--line-height-body); - letter-spacing: var(--letter-spacing-normal); - font-family: var(--font-family-primary); - box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1); -} - -.message.user .message-content { - background-color: var(--color-meta-blue); - color: var(--color-white); - border: 1px solid var(--color-meta-blue); -} - -.message.ai .message-content { - background-color: var(--color-soft-gray); - color: var(--color-text-primary); - border: 1px solid var(--color-border-subtle); -} - -.message.ai.loading .message-content { - background-color: var(--color-soft-gray); - color: var(--color-text-primary); - opacity: 0.7; - border: 1px solid var(--color-border-subtle); -} - -.loading-indicator { - display: flex; - align-items: center; - gap: var(--space-3); -} - -.loading-indicator span { - animation: pulse 1.5s infinite; -} - -.loading-indicator span:nth-child(2) { - animation-delay: 0.2s; -} - -.loading-indicator span:nth-child(3) { - animation-delay: 0.4s; -} - -@keyframes pulse { - 0%, 100% { opacity: 0.5; } - 50% { opacity: 1; } -} - -.upload-progress { - padding: var(--space-5) var(--space-9); - background-color: var(--color-soft-gray); - border-bottom: 1px solid var(--color-border-subtle); - color: var(--color-text-primary); -} - -.upload-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: var(--space-3) 0; - font-size: var(--font-size-body); - letter-spacing: var(--letter-spacing-normal); - font-family: var(--font-family-primary); -} - -.upload-status { - font-family: var(--font-family-secondary); - font-size: var(--font-size-small); - color: var(--color-text-muted); - letter-spacing: var(--letter-spacing-normal); -} - -.context-display { - padding: var(--space-5) var(--space-9); - background-color: var(--color-soft-gray); - border-bottom: 1px solid var(--color-border-subtle); - display: flex; - align-items: center; - gap: var(--space-4); -} - -.context-icon { - font-size: 16px; - color: var(--color-meta-blue); -} - -.context-text { - flex: 1; - font-size: var(--font-size-body); - color: var(--color-text-primary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - letter-spacing: var(--letter-spacing-normal); - font-family: var(--font-family-primary); -} - -.context-clear { - background: none; - border: none; - color: var(--color-text-primary); - font-size: 18px; - cursor: pointer; - padding: var(--space-2); - line-height: 1; - transition: all 0.15s ease; - border-radius: var(--radius-circle); -} - -.context-clear:hover { - background-color: var(--color-button-hover); - color: var(--color-white); -} - -.context-clear:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.chat-input { - padding: var(--space-7); - border-top: 1px solid var(--color-border-subtle); - display: flex; - flex-direction: column; - gap: var(--space-5); -} - -.input-container { - position: relative; - width: 100%; -} - -.chat-input textarea { - width: 100%; - padding: var(--space-5); - background-color: var(--color-white); - border: 1px solid var(--color-border-medium); - border-radius: var(--radius-small); - color: var(--color-text-primary); - font-size: var(--font-size-body); - resize: none; - font-family: var(--font-family-primary); - height: 120px; - padding-bottom: 50px; - letter-spacing: var(--letter-spacing-normal); - transition: border-color 200ms ease, box-shadow 200ms ease; - box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1); -} - -.chat-input textarea:focus { - outline: none; - border-color: hsl(214, 89%, 52%); - box-shadow: 0 0 0 3px rgba(0, 100, 224, 0.1); -} - -.chat-input textarea:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.chat-input textarea::placeholder { - color: var(--color-text-placeholder); -} - -.absolute-btn { - position: absolute; - bottom: 15px; - background-color: var(--color-soft-gray); - border: 1px solid var(--color-border-subtle); - border-radius: var(--radius-pill); - cursor: pointer; - transition: all 0.15s ease; - display: flex; - align-items: center; - justify-content: center; - z-index: 10; - color: var(--color-text-primary); -} - -.absolute-btn:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.absolute-btn.upload-btn { - left: 12px; - padding: var(--space-3); - border-radius: var(--radius-circle); -} - -.absolute-btn.upload-btn:hover { - background-color: var(--color-button-hover); - color: var(--color-white); - border-color: var(--color-meta-blue); -} - -.absolute-btn.model-selector-btn { - left: 50%; - transform: translateX(-50%); - padding: 0; - background: none; - border: none; -} - -.absolute-btn.model-selector-btn .model-select { - padding: var(--space-3) var(--space-5); - background-color: var(--color-soft-gray); - border: 1px solid var(--color-border-medium); - border-radius: var(--radius-small); - color: var(--color-text-primary); - font-size: var(--font-size-caption); - font-family: var(--font-family-primary); - letter-spacing: var(--letter-spacing-tighter); - cursor: pointer; - outline: none; - transition: border-color 200ms ease, box-shadow 200ms ease; -} - -.absolute-btn.send-btn { - right: 12px; - padding: var(--space-3) var(--space-7); - background-color: var(--color-meta-blue); - color: var(--color-white); - border-color: var(--color-meta-blue); - font-family: var(--font-family-primary); - font-size: var(--font-size-button); - font-weight: var(--font-weight-regular); - letter-spacing: var(--letter-spacing-tighter); - transition: background 200ms ease, transform 150ms ease; -} - -.absolute-btn.send-btn:hover:not(:disabled) { - background-color: var(--color-meta-blue-hover); - transform: scale(1.05); -} - -.absolute-btn.send-btn:focus-visible { - outline: 3px ring var(--color-meta-blue); - outline: auto 2px var(--color-meta-blue); - outline-offset: 2px; -} - -.absolute-btn.send-btn:disabled { - background-color: var(--color-soft-gray); - border-color: var(--color-border-subtle); - color: var(--color-text-muted); - opacity: 0.6; - cursor: not-allowed; -} - -.file-upload-hidden { - display: none; -} diff --git a/src/components/AIChatPanel.tsx b/src/components/AIChatPanel.tsx deleted file mode 100644 index 75eeabc..0000000 --- a/src/components/AIChatPanel.tsx +++ /dev/null @@ -1,313 +0,0 @@ -import React, { useState, useRef } from 'react' -import { useTranslation } from 'react-i18next' -import { NewChatIcon, PaperclipIcon, HistoryIcon } from './Icons' -import './AIChatPanel.css' - -const AIChatPanel = () => { - // 消息状态 - const { t } = useTranslation() - const [messages, setMessages] = useState([ - { id: 1, type: 'ai', content: t('aiChatPanel.greeting') } - ]) - const [inputValue, setInputValue] = useState('') - const [isLoading, setIsLoading] = useState(false) - - // 上传功能状态 - const [uploadingFiles, setUploadingFiles] = useState([]) - const [_pendingFiles, setPendingFiles] = useState<{ fileName: string; originalName: string; fullPath: string }[]>([]) - const [currentContext, setCurrentContext] = useState<{ fileName: string; type: string } | null>(null) - - // 模型切换状态 - const [selectedModel, setSelectedModel] = useState('gpt-4o') - - // 对话历史状态 - const [conversations, setConversations] = useState([{ - id: 1, - title: t('aiChatPanel.newChat'), - messages: messages, - createdAt: new Date() - }]) - const [currentConversationId, setCurrentConversationId] = useState(1) - - // 侧边栏显示状态 - const [isSidebarVisible, setIsSidebarVisible] = useState(false) - - // 输入框引用 - const inputRef = useRef(null) - - // 发送消息 - const handleSendMessage = () => { - if (!inputValue.trim()) return - - // 添加用户消息 - const userMessage = { - id: Date.now(), - type: 'user' as const, - content: inputValue - } - - setMessages(prev => [...prev, userMessage]) - setInputValue('') - setIsLoading(true) - - // 模拟AI回复 - setTimeout(() => { - const aiMessage = { - id: Date.now() + 1, - type: 'ai' as const, - content: t('aiChatPanel.response') - } - setMessages(prev => [...prev, aiMessage]) - setIsLoading(false) - }, 1000) - } - - // 处理文件上传 - const handleFileUpload = (e: React.ChangeEvent) => { - const files = e.target.files - if (!files) return - - Array.from(files).forEach(file => { - const fileName = file.name - setUploadingFiles(prev => [...prev, fileName]) - - // 模拟上传过程 - setTimeout(() => { - setUploadingFiles(prev => prev.filter(f => f !== fileName)) - setPendingFiles(prev => [...prev, { - fileName: fileName, - originalName: fileName, - fullPath: `./uploads/${fileName}` - }]) - }, 1000) - }) - } - - // 清除上下文 - const handleClearContext = () => { - setCurrentContext(null) - } - - // 处理键盘事件 - const handleKeyPress = (e: React.KeyboardEvent) => { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault() - handleSendMessage() - } - } - - // 拖拽上传事件处理 - const handleDragOver = (e: React.DragEvent) => { - e.preventDefault() - e.stopPropagation() - e.dataTransfer.dropEffect = 'copy' - } - - const handleDragEnter = (e: React.DragEvent) => { - e.preventDefault() - e.stopPropagation() - } - - const handleDragLeave = (e: React.DragEvent) => { - e.preventDefault() - e.stopPropagation() - } - - const handleDrop = (e: React.DragEvent) => { - e.preventDefault() - e.stopPropagation() - - if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { - // const files = Array.from(e.dataTransfer.files) - } - } - - // 处理新对话 - const handleNewChat = () => { - const newId = conversations.length + 1 - const newConversation = { - id: newId, - title: t('aiChatPanel.newChat'), - messages: [{ - id: 1, - type: 'ai', - content: t('aiChatPanel.greeting') - }], - createdAt: new Date() - } - - setConversations(prev => [...prev, newConversation]) - setCurrentConversationId(newId) - setMessages(newConversation.messages) - } - - // 处理模型选择 - const handleModelChange = (model: string) => { - setSelectedModel(model) - } - - // 处理对话选择 - const handleConversationSelect = (id: number) => { - const conversation = conversations.find(c => c.id === id) - if (conversation) { - setCurrentConversationId(id) - setMessages(conversation.messages) - } - } - - // 切换侧边栏显示 - const toggleSidebar = () => { - setIsSidebarVisible(!isSidebarVisible) - } - - return ( -
    -
    -

    {t('aiChatPanel.conversationHistory')}

    -
    - {conversations.map(conversation => ( -
    handleConversationSelect(conversation.id)} - > -
    {conversation.title}
    -
    - {conversation.createdAt.toLocaleTimeString()} -
    -
    - ))} -
    -
    - -
    -
    -
    -
    -

    {t('aiChatPanel.aiAssistant')}

    -
    -
    - - -
    -
    - - - {currentContext && ( -
    - 📄 - - {currentContext.type === 'design' ? 'Design file: ' : 'Other file: '} - {currentContext.fileName} - - -
    - )} - - {uploadingFiles.length > 0 && ( -
    - {uploadingFiles.map(file => ( -
    - {file} - {t('aiChatPanel.uploading')} -
    - ))} -
    - )} - -
    - {messages.map(message => ( -
    -
    - {message.content} -
    -
    - ))} - - {isLoading && ( -
    -
    -
    - {t('aiChatPanel.loading')} - . - . - . -
    -
    -
    - )} -
    - -
    -
    - -
    - -
    -
    - - -
    -
    -
    - ) -} - -export default ContextModal \ No newline at end of file diff --git a/src/components/DesignFrame.tsx b/src/components/DesignFrame.tsx deleted file mode 100644 index 4ec1fd3..0000000 --- a/src/components/DesignFrame.tsx +++ /dev/null @@ -1,735 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { DesignFile, ViewportMode, GridPosition, FrameDimensions } from '../types/canvas.types'; -import { MobileIcon, TabletIcon, DesktopIcon, GlobeIcon } from './Icons'; -import { useTranslation } from 'react-i18next'; - -interface DesignFrameProps { - file: DesignFile; - position: GridPosition; - dimensions: FrameDimensions; - isSelected: boolean; - onSelect: (fileName: string) => void; - renderMode?: 'placeholder' | 'iframe' | 'html'; - showMetadata?: boolean; - viewport?: ViewportMode; - viewportDimensions?: FrameDimensions; - onViewportChange?: (fileName: string, viewport: ViewportMode) => void; - useGlobalViewport?: boolean; - onDragStart?: (fileName: string, startPos: GridPosition, mouseEvent: React.MouseEvent) => void; - isDragging?: boolean; - nonce?: string | null; - onSendToChat?: (fileName: string, prompt: string) => void; -} - -const DesignFrame: React.FC = ({ - file, - position, - dimensions, - isSelected, - onSelect, - renderMode = 'placeholder', - showMetadata = true, - viewport = 'desktop', - viewportDimensions, - onViewportChange, - useGlobalViewport = false, - onDragStart, - isDragging = false, - nonce = null, - onSendToChat -}) => { - const { t } = useTranslation() - const [isLoading, setIsLoading] = useState(renderMode === 'iframe'); - const [hasError, setHasError] = useState(false); - const [dragPreventOverlay, setDragPreventOverlay] = useState(false); - const [showCopyDropdown, setShowCopyDropdown] = useState(false); - const [copyButtonState, setCopyButtonState] = useState<{ text: string; isSuccess: boolean }>({ text: t('designFrame.floatingActions.copyPromptBtn'), isSuccess: false }); - const [copyPathButtonState, setCopyPathButtonState] = useState<{ text: string; isSuccess: boolean }>({ text: t('designFrame.floatingActions.copyPathBtn'), isSuccess: false }); - - const handleClick = () => { - onSelect(file.name); - }; - - const handleMouseDown = (e: React.MouseEvent) => { - if (onDragStart && e.button === 0) { - e.preventDefault(); - e.stopPropagation(); - - setDragPreventOverlay(true); - - onDragStart(file.name, position, e); - } - }; - - useEffect(() => { - if (!isDragging) { - setDragPreventOverlay(false); - } - }, [isDragging]); - - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (showCopyDropdown) { - const target = event.target as Element; - const dropdownElement = target.closest('.copy-prompt-dropdown'); - if (!dropdownElement) { - setShowCopyDropdown(false); - } - } - }; - - if (showCopyDropdown) { - document.addEventListener('mousedown', handleClickOutside); - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - } - }, [showCopyDropdown]); - - const handleViewportToggle = (newViewport: ViewportMode) => { - if (onViewportChange && !useGlobalViewport) { - onViewportChange(file.name, newViewport); - } - }; - - const handleCopyPrompt = async (e: React.MouseEvent, platform?: string) => { - e.preventDefault(); - e.stopPropagation(); - - let promptText = ''; - let platformName = ''; - - switch (platform) { - case 'cursor': - promptText = `${file.content}\n\n${t('designFrame.prompts.cursor')}`; - platformName = t('designFrame.platforms.cursor'); - break; - case 'windsurf': - promptText = `${file.content}\n\n${t('designFrame.prompts.windsurf')}`; - platformName = t('designFrame.platforms.windsurf'); - break; - case 'lovable': - promptText = `${file.content}\n\n${t('designFrame.prompts.lovable')}`; - platformName = t('designFrame.platforms.lovable'); - break; - case 'bolt': - promptText = `${file.content}\n\n${t('designFrame.prompts.bolt')}`; - platformName = t('designFrame.platforms.bolt'); - break; - default: - promptText = `${file.content}\n\n${t('designFrame.prompts.default')}`; - platformName = ''; - } - - try { - await navigator.clipboard.writeText(promptText); - - setCopyButtonState({ text: t('designFrame.floatingActions.copiedSuccessWithPlatform', { platform: platformName }), isSuccess: true }); - setTimeout(() => { - setCopyButtonState({ text: t('designFrame.floatingActions.copyPromptBtn'), isSuccess: false }); - }, 2000); - - setShowCopyDropdown(false); - } catch (err) { - const textarea = document.createElement('textarea'); - textarea.value = promptText; - document.body.appendChild(textarea); - textarea.select(); - document.execCommand('copy'); - document.body.removeChild(textarea); - - setCopyButtonState({ text: t('designFrame.floatingActions.copiedSuccessWithPlatform', { platform: platformName }), isSuccess: true }); - setTimeout(() => { - setCopyButtonState({ text: t('designFrame.floatingActions.copyPromptBtn'), isSuccess: false }); - }, 2000); - - setShowCopyDropdown(false); - } - }; - - const handleCopyDropdownToggle = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - setShowCopyDropdown(!showCopyDropdown); - }; - - const handleCopyDesignPath = async (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - - const designPath = `Design file: ${file.path}`; - - try { - await navigator.clipboard.writeText(designPath); - - setCopyPathButtonState({ text: t('designFrame.floatingActions.copiedSuccess'), isSuccess: true }); - setTimeout(() => { - setCopyPathButtonState({ text: t('designFrame.floatingActions.copyPathBtn'), isSuccess: false }); - }, 2000); - - } catch (err) { - const textarea = document.createElement('textarea'); - textarea.value = designPath; - document.body.appendChild(textarea); - textarea.select(); - document.execCommand('copy'); - document.body.removeChild(textarea); - - setCopyPathButtonState({ text: t('designFrame.floatingActions.copiedSuccess'), isSuccess: true }); - setTimeout(() => { - setCopyPathButtonState({ text: t('designFrame.floatingActions.copyPathBtn'), isSuccess: false }); - }, 2000); - } - }; - - const handleCreateVariations = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - - if (onSendToChat) { - onSendToChat(file.name, t('designFrame.prompts.createVariations')); - } - }; - - const handleIterateWithFeedback = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - - if (onSendToChat) { - onSendToChat(file.name, t('designFrame.prompts.iterateWithFeedback')); - } - }; - - const getViewportIcon = (mode: ViewportMode): React.ReactElement => { - switch (mode) { - case 'mobile': return ; - case 'tablet': return ; - case 'desktop': return ; - default: return ; - } - }; - - const getViewportLabel = (mode: ViewportMode): string => { - switch (mode) { - case 'mobile': return t('designFrame.viewport.mobile'); - case 'tablet': return t('designFrame.viewport.tablet'); - case 'desktop': return t('designFrame.viewport.desktop'); - default: return t('designFrame.viewport.desktop'); - } - }; - - const renderContent = () => { - switch (renderMode) { - case 'iframe': - if (file.fileType === 'svg') { - const svgHtml = ` - - - - - - ${viewportDimensions ? `` : ''} - - - - ${file.content} - - - - `; - - return ( -