├── .changelogrc.js ├── .dumi ├── theme │ └── builtins │ │ └── Features │ │ └── index.tsx └── tsconfig.json ├── .dumirc.ts ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .fatherrc.ts ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md └── workflows │ ├── preview.yml │ ├── release.yml │ ├── static.yml │ └── test.yml ├── .gitignore ├── .gitpod.yml ├── .husky └── pre-commit ├── .i18nrc.js ├── .npmrc ├── .prettierignore ├── .prettierrc.js ├── .releaserc.js ├── .stylelintrc.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README.zh-CN.md ├── commitlint.config.js ├── docs ├── api │ ├── create-instance.en-US.md │ ├── create-instance.zh-CN.md │ ├── create-styles.en-US.md │ ├── create-styles.zh-CN.md │ ├── create-stylish.en-US.md │ ├── create-stylish.zh-CN.md │ ├── global-styles.en-US.md │ ├── global-styles.zh-CN.md │ ├── setup-styled.en-US.md │ ├── setup-styled.zh-CN.md │ ├── style-provider.en-US.md │ ├── style-provider.zh-CN.md │ ├── theme-provider.en-US.md │ ├── theme-provider.zh-CN.md │ ├── use-responsive.en-US.md │ ├── use-responsive.zh-CN.md │ ├── use-theme-mode.en-US.md │ ├── use-theme-mode.zh-CN.md │ ├── use-theme.en-US.md │ └── use-theme.zh-CN.md ├── best-practice │ ├── antd-based-components.en-US.md │ ├── antd-based-components.zh-CN.md │ ├── antd-override.en-US.md │ ├── antd-override.zh-CN.md │ ├── clay.en-US.md │ ├── clay.zh-CN.md │ ├── custom-token-types.en-US.md │ ├── custom-token-types.zh-CN.md │ ├── demos │ │ ├── ConfigProviderOverride.tsx │ │ ├── DefaultOverride.tsx │ │ ├── InputclassNames.tsx │ │ ├── NestElements.tsx │ │ ├── OverrideWeight.tsx │ │ ├── StaticMethod │ │ │ ├── index.tsx │ │ │ ├── layout.tsx │ │ │ └── request.ts │ │ └── tsconfig.json │ ├── fix-switch-theme-fouc.en-US.md │ ├── fix-switch-theme-fouc.zh-CN.md │ ├── index.en-US.md │ ├── index.zh-CN.md │ ├── mac-select.en-US.md │ ├── mac-select.zh-CN.md │ ├── mirgration-less-global-style.en-US.md │ ├── mirgration-less-global-style.zh-CN.md │ ├── nest-element-style.en-US.md │ ├── nest-element-style.zh-CN.md │ ├── static-message.en-US.md │ ├── static-message.zh-CN.md │ ├── styled.en-US.md │ └── styled.zh-CN.md ├── changelog.en-US.md ├── changelog.zh-CN.md ├── demos │ ├── StyleProvider │ │ ├── customContainer.tsx │ │ ├── insertpoint.tsx │ │ └── speedy.tsx │ ├── ThemeProvider │ │ ├── AppGlobalStyle.tsx │ │ ├── SwitchTheme.tsx │ │ ├── TSSupport.tsx │ │ ├── WithApp.tsx │ │ ├── WithProvider.tsx │ │ ├── _app.tsx │ │ ├── customToken.tsx │ │ ├── default.tsx │ │ ├── demo.tsx │ │ ├── nested-prefixCls.tsx │ │ ├── staticMethod.tsx │ │ └── style.ts │ ├── api │ │ ├── createInstance │ │ │ ├── withContainer.tsx │ │ │ └── withStyleProviderContainer.tsx │ │ ├── createStyles │ │ │ ├── Responsive.tsx │ │ │ ├── default.tsx │ │ │ ├── label.tsx │ │ │ └── with-antd-cp.tsx │ │ ├── useResponsive │ │ │ ├── Demo │ │ │ │ ├── DisplayTag.tsx │ │ │ │ └── index.tsx │ │ │ ├── custom.tsx │ │ │ ├── default.tsx │ │ │ └── style.ts │ │ └── useTheme.tsx │ ├── cases │ │ ├── HeroButton │ │ │ ├── Shape.tsx │ │ │ ├── index.tsx │ │ │ ├── settings.ts │ │ │ └── style.ts │ │ ├── MacSelect │ │ │ ├── ScrollArrow │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── Select │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── SelectItem │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── data.ts │ │ │ └── index.tsx │ │ ├── Typography │ │ │ └── default.tsx │ │ └── clay │ │ │ ├── default.tsx │ │ │ └── theme.tsx │ ├── common │ │ ├── ThemeController.tsx │ │ ├── Typography │ │ │ ├── ActionPanel.tsx │ │ │ ├── Avatar.tsx │ │ │ ├── GroupCollapse.tsx │ │ │ ├── GroupTitle.tsx │ │ │ ├── SubTitle.tsx │ │ │ ├── Title.tsx │ │ │ └── index.ts │ │ └── demo.tsx │ ├── createStyles │ │ ├── AntdToken.tsx │ │ ├── Command │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── Keyframes.tsx │ │ ├── SimpleObject.tsx │ │ ├── default.tsx │ │ └── withProps.tsx │ ├── createStylish │ │ ├── commonStylish.ts │ │ └── default.tsx │ ├── globalStyles │ │ ├── AntdToken.tsx │ │ └── default.tsx │ ├── guide │ │ ├── component-usage │ │ │ ├── Button │ │ │ │ ├── Default.tsx │ │ │ │ └── WithWhere.tsx │ │ │ ├── CustomInstance.tsx │ │ │ ├── CustomTheme │ │ │ │ ├── Button.tsx │ │ │ │ └── styles.ts │ │ │ └── demo.tsx │ │ ├── custom-theme │ │ │ └── CustomAppearance.tsx │ │ ├── styled │ │ │ ├── EmotionStyledProps.tsx │ │ │ ├── SetupStyled │ │ │ │ ├── App.tsx │ │ │ │ └── index.tsx │ │ │ └── StyledComponentsProps.tsx │ │ └── switch-theme │ │ │ ├── AntdTheme │ │ │ ├── CustomDark.tsx │ │ │ └── index.tsx │ │ │ ├── AutoSwitch.tsx │ │ │ ├── ControlledSwitch │ │ │ ├── Controller.tsx │ │ │ ├── index.tsx │ │ │ └── useStore.ts │ │ │ ├── GlobalSwitch │ │ │ ├── Controller.tsx │ │ │ └── index.tsx │ │ │ └── default.tsx │ ├── migration │ │ ├── CSSinJSMode │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── LessMode │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ └── ProComponentsStatic │ │ │ ├── CSSinJS.tsx │ │ │ ├── CSSinJSComponent │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ │ ├── LessComponent │ │ │ ├── index.less │ │ │ └── index.tsx │ │ │ └── less.tsx │ ├── styled │ │ └── basic.tsx │ ├── tsconfig.json │ └── typings.d.ts ├── guide │ ├── babel-plugin.en-US.md │ ├── babel-plugin.zh-CN.md │ ├── compare.en-US.md │ ├── compare.zh-CN.md │ ├── components-usage.en-US.md │ ├── components-usage.zh-CN.md │ ├── create-styles.en-US.md │ ├── create-styles.zh-CN.md │ ├── css-in-js-intro.en-US.md │ ├── css-in-js-intro.zh-CN.md │ ├── cssinjs-compiler-difference.en-US.md │ ├── cssinjs-compiler-difference.zh-CN.md │ ├── custom-theme.en-US.md │ ├── custom-theme.zh-CN.md │ ├── demos │ │ ├── benchmark │ │ │ ├── dynamic-value.tsx │ │ │ └── large-content.tsx │ │ └── tsconfig.json │ ├── index.en-US.md │ ├── index.zh-CN.md │ ├── migrate-less-application.en-US.md │ ├── migrate-less-application.zh-CN.md │ ├── migrate-less-codemod.en-US.md │ ├── migrate-less-codemod.zh-CN.md │ ├── migrate-less-component.en-US.md │ ├── migrate-less-component.zh-CN.md │ ├── performance-comparsion.en-US.md │ ├── performance-comparsion.zh-CN.md │ ├── ssr.en-US.md │ ├── ssr.zh-CN.md │ ├── strategy.en-US.md │ ├── strategy.zh-CN.md │ ├── styled.en-US.md │ ├── styled.zh-CN.md │ ├── stylish.en-US.md │ ├── stylish.zh-CN.md │ ├── switch-theme.en-US.md │ └── switch-theme.zh-CN.md ├── index.md └── index.zh-CN.md ├── package.json ├── public └── fonts │ └── RocherColorGX.woff2 ├── src ├── context │ ├── ThemeModeContext.test.ts │ ├── ThemeModeContext.ts │ └── index.ts ├── core │ ├── CacheManager.ts │ ├── createCSS.ts │ ├── createEmotion.ts │ ├── createSerializeStyles.ts │ ├── index.ts │ └── insertStyles.ts ├── factories │ ├── createEmotionContext.ts │ ├── createGlobalStyle.tsx │ ├── createStyish.ts │ ├── createStyleProvider │ │ └── index.tsx │ ├── createStyledThemeProvider.tsx │ ├── createStyles │ │ ├── index.ts │ │ ├── response.ts │ │ └── types.ts │ ├── createThemeProvider │ │ ├── AntdProvider.tsx │ │ ├── ThemeSwitcher.test.tsx │ │ ├── ThemeSwitcher.tsx │ │ ├── TokenContainer.tsx │ │ ├── index.tsx │ │ └── type.ts │ └── createUseTheme.ts ├── functions │ ├── createInstance.ts │ ├── extractStaticStyle.tsx │ ├── index.ts │ ├── setupStyled.test.ts │ └── setupStyled.ts ├── hooks │ ├── index.ts │ ├── useAntdStylish.ts │ ├── useAntdTheme.ts │ ├── useAntdToken.ts │ ├── useResponsive.ts │ └── useThemeMode.ts ├── index.ts ├── stylish │ └── button.ts ├── types │ ├── appearance.ts │ ├── css.ts │ ├── function.ts │ ├── genericUtils.ts │ ├── index.ts │ ├── response.ts │ ├── styleManager.ts │ ├── styled.ts │ └── theme.ts └── utils │ ├── convertStylish.ts │ ├── createEmotionServer │ └── index.ts │ ├── css.test.ts │ ├── css.ts │ ├── index.ts │ ├── matchBrowserPrefers.test.ts │ ├── matchBrowserPrefers.ts │ ├── responsive.ts │ └── safeStartTransition.ts ├── tests ├── components │ ├── StyledProvider.test.tsx │ ├── ThemeProvider.test.tsx │ └── __snapshots__ │ │ └── ThemeProvider.test.tsx.snap ├── functions │ ├── __snapshots__ │ │ ├── createInstance.test.tsx.snap │ │ ├── createStyish.test.tsx.snap │ │ ├── createStyles.test.tsx.snap │ │ └── styled.test.tsx.snap │ ├── createGlobalStyle.test.tsx │ ├── createInstance.test.tsx │ ├── createStyish.test.tsx │ ├── createStyles.test.tsx │ ├── extractStaticStyle.test.tsx │ └── styled.test.tsx ├── hooks │ ├── __snapshots__ │ │ ├── useAntdStylish.test.tsx.snap │ │ └── useTheme.test.tsx.snap │ ├── useAntdStylish.test.tsx │ ├── useResponsive.test.ts │ ├── useTheme.test.tsx │ ├── useThemeMode.test.tsx │ └── useToken.test.ts ├── test-setup.ts └── tsconfig.json ├── tsconfig-check.json ├── tsconfig.json └── vitest.config.ts /.changelogrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayTypes: ['feat', 'fix', 'styles', 'pref'], 3 | }; 4 | -------------------------------------------------------------------------------- /.dumi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "esModuleInterop": true, 6 | "resolveJsonModule": true, 7 | "baseUrl": "..", 8 | "paths": { 9 | "@@/*": ["./.dumi/tmp/*"], 10 | "dumi/theme-original/builtins/*": ["./.dumi/tmp/dumi/theme/builtins/*"], 11 | "antd-style": ["es"] 12 | } 13 | }, 14 | "include": ["./**/*"] 15 | } 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /lambda/mock/** 2 | /scripts 3 | /config 4 | /example 5 | _test_ 6 | __test__ 7 | 8 | /node_modules 9 | jest* 10 | /es 11 | /lib 12 | /docs 13 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@umijs/lint/dist/config/eslint'); 2 | -------------------------------------------------------------------------------- /.fatherrc.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'father'; 2 | 3 | export default defineConfig({ 4 | esm: { output: 'es' }, 5 | cjs: { output: 'lib', platform: 'browser' }, 6 | }); 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '报告Bug 🐛' 3 | about: 报告 antd-style 的 bug 4 | title: '🐛[BUG]' 5 | labels: '🐛 BUG' 6 | assignees: '' 7 | --- 8 | 9 | ### 🐛 bug 描述 10 | 11 | 14 | 15 | ### 📷 复现步骤 16 | 17 | 20 | 21 | ### 🏞 期望结果 22 | 23 | 26 | 27 | ### 💻 复现代码 28 | 29 | 33 | 34 | [可复现 demo](https://codesandbox.io/s/html2ksetch-demo-m53be?file=/src/Demo.tsx) 35 | 36 | ### © 版本信息 37 | 38 | - antd-style 版本: [e.g. 1.0.0] 39 | - 浏览器环境 40 | - 开发环境 [e.g. mac OS] 41 | 42 | ### 🚑 其他信息 43 | 44 | 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '功能需求 ✨' 3 | about: 对 antd-style 的需求或建议 4 | title: '👑 [需求]' 5 | labels: '👑 Feature' 6 | assignees: '' 7 | --- 8 | 9 | ### 🥰 需求描述 10 | 11 | 14 | 15 | ### 🧐 解决方案 16 | 17 | 20 | 21 | ### 🚑 其他信息 22 | 23 | 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '疑问或需要帮助 ❓' 3 | about: 对 antd-style 使用的疑问或需要帮助 4 | title: '🧐[问题]' 5 | labels: '🧐 Question' 6 | assignees: '' 7 | --- 8 | 9 | ### 🧐 问题描述 10 | 11 | 14 | 15 | ### 💻 示例代码 16 | 17 | 20 | 21 | ### 🚑 其他信息 22 | 23 | 26 | -------------------------------------------------------------------------------- /.github/workflows/preview.yml: -------------------------------------------------------------------------------- 1 | name: Surge PR Preview 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | preview: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | 11 | - name: Install pnpm 12 | uses: pnpm/action-setup@v2 13 | with: 14 | version: 7 15 | 16 | - uses: afc163/surge-preview@v1 17 | with: 18 | surge_token: ${{ secrets.SURGE_TOKEN }} 19 | github_token: ${{ secrets.GITHUB_TOKEN }} 20 | build: | 21 | pnpm i 22 | pnpm run docs:preview 23 | dist: dist 24 | 25 | - name: Get the preview_url 26 | run: echo "url => ${{ steps.preview_step.outputs.preview_url }}" 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - alpha 7 | - beta 8 | - rc 9 | 10 | jobs: 11 | test: 12 | name: Test 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Install pnpm 18 | uses: pnpm/action-setup@v2 19 | with: 20 | version: 7 21 | 22 | - name: Setup Node.js environment 23 | uses: actions/setup-node@v3 24 | with: 25 | node-version: '16' 26 | 27 | - name: Install deps 28 | run: pnpm install 29 | 30 | - name: Test 31 | run: pnpm run test 32 | 33 | release: 34 | needs: test 35 | name: Release 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v3 39 | 40 | - name: Install pnpm 41 | uses: pnpm/action-setup@v2 42 | with: 43 | version: 7 44 | 45 | - name: Setup Node.js environment 46 | uses: actions/setup-node@v3 47 | with: 48 | node-version: '16' 49 | 50 | - name: Install deps 51 | run: pnpm install 52 | 53 | - name: build 54 | run: pnpm run build 55 | 56 | - name: release 57 | run: pnpm run release 58 | env: 59 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 60 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 61 | -------------------------------------------------------------------------------- /.github/workflows/static.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ['master'] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: 'pages' 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v3 33 | - name: Install pnpm 34 | uses: pnpm/action-setup@v2 35 | with: 36 | version: 7 37 | 38 | - name: Setup Node.js environment 39 | uses: actions/setup-node@v3 40 | with: 41 | node-version: '16' 42 | 43 | - name: Install deps 44 | run: pnpm install 45 | 46 | - name: Build Pages 47 | run: pnpm run docs:build 48 | 49 | - name: Setup Pages 50 | uses: actions/configure-pages@v3 51 | 52 | - name: Upload artifact 53 | uses: actions/upload-pages-artifact@v1 54 | with: 55 | # Upload entire repository 56 | path: 'dist' 57 | 58 | - name: Deploy to GitHub Pages 59 | id: deployment 60 | uses: actions/deploy-pages@v1 61 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test CI 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | 7 | steps: 8 | - uses: actions/checkout@v3 9 | 10 | - name: Install pnpm 11 | uses: pnpm/action-setup@v2 12 | with: 13 | version: 8 14 | 15 | - name: Setup Node.js environment 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: '18' 19 | 20 | - name: Install deps 21 | run: pnpm install 22 | 23 | - name: lint 24 | run: pnpm run ci 25 | 26 | - name: Test and coverage 27 | run: pnpm run test:coverage 28 | 29 | - name: Upload coverage to Codecov 30 | uses: codecov/codecov-action@v3 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | **/node_modules 5 | # roadhog-api-doc ignore 6 | /src/utils/request-temp.js 7 | _roadhog-api-doc 8 | 9 | # production 10 | **/dist 11 | /.vscode 12 | /es 13 | /lib 14 | 15 | # misc 16 | .DS_Store 17 | storybook-static 18 | npm-debug.log* 19 | yarn-error.log 20 | 21 | /coverage 22 | .idea 23 | package-lock.json 24 | *bak 25 | .vscode 26 | 27 | # visual studio code 28 | .history 29 | *.log 30 | functions/* 31 | lambda/mock/index.js 32 | .temp/** 33 | 34 | # umi 35 | .dumi/tmp* 36 | 37 | # screenshot 38 | screenshot 39 | .firebase 40 | example/.temp/* 41 | .eslintcache 42 | techUI* 43 | server 44 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - init: pnpm install 3 | command: pnpm run start 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /.i18nrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import("@lobehub/i18n-cli").Config} 3 | */ 4 | module.exports = { 5 | markdown: { 6 | entry: ['docs/**/**.md', './README.zh-CN.md'], 7 | entryLocale: 'zh-CN', 8 | entryExtension: '.zh-CN.md', 9 | outputLocales: ['en-US'], 10 | }, 11 | modelName: 'gpt-3.5-turbo-1106', 12 | }; 13 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | lockfile=false 2 | resolution-mode=highest 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.svg 2 | .umi 3 | .umi-production 4 | /dist 5 | .dockerignore 6 | .DS_Store 7 | .eslintignore 8 | *.png 9 | *.toml 10 | docker 11 | .editorconfig 12 | Dockerfile* 13 | .gitignore 14 | .prettierignore 15 | LICENSE 16 | .eslintcache 17 | *.lock 18 | yarn-error.log 19 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | pluginSearchDirs: false, 3 | plugins: [ 4 | require.resolve('prettier-plugin-organize-imports'), 5 | require.resolve('prettier-plugin-packagejson'), 6 | ], 7 | printWidth: 100, 8 | proseWrap: 'never', 9 | singleQuote: true, 10 | trailingComma: 'all', 11 | overrides: [ 12 | { 13 | files: '*.md', 14 | options: { 15 | proseWrap: 'preserve', 16 | }, 17 | }, 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /.releaserc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['semantic-release-config-gitmoji'], 3 | }; 4 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@umijs/lint/dist/config/stylelint'); 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022-current Arvin Xu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['gitmoji'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/api/create-stylish.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 createStylish 3 | order: 10 4 | group: 5 | title: Creating Styles 6 | order: 0 7 | --- 8 | 9 | ## Introduction 10 | 11 | For general styling needs, basic requirements can be met through [createStyles](/usage/create-styles), while `createStylish` is considered an advanced usage. 12 | 13 | In a complex business system, there may be some common styles with finer granularity that are not enough to form a component. However, repeatedly writing these styles is not only time-consuming but also results in a lot of duplicate code. Moreover, if a designer requests a unified adjustment of the design style, the cost of making multiple modifications is extremely high. To address this issue, `createStylish` was developed. 14 | 15 | `createStylish` can create reusable styles. In concept, it is similar to the popular tailwindcss in recent years, but it is more flexible and practical. When combined with Ant Design V5 Token System, it can achieve a highly efficient and flexible user experience. 16 | 17 | :::success{title=Applicable Scenarios} 18 | Used for organizing reusable styles in batches. 19 | ::: 20 | 21 | ## Typical Example 22 | 23 | 24 | 25 | ## Detailed Introduction 26 | 27 | ## API 28 | -------------------------------------------------------------------------------- /docs/api/create-stylish.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 createStylish 3 | order: 10 4 | group: 5 | title: 创建样式 6 | order: 0 7 | --- 8 | 9 | ## 简介 10 | 11 | 对于一般的样式诉求,通过 [createStyles](/zh-CN/usage/create-styles) 就可以基本满足,`createStylish` 属于进阶用法。 12 | 13 | 在一个复杂的业务系统中,可能会存在一些通用的样式,这些样式颗粒度更细,并不足以形成一个组件。但是如果每次都重复书写即耗费精力,又会有很多重复的代码,一旦设计师要求统一调整设计风格,多次修改的成本极高。为了解决这个问题,`createStylish` 应运而生。 14 | 15 | `createStylish` 可以创建一个可以被复用的的样式。它在理念上会和近年来比较流行的 tailwindcss 比较接近,但是具有更加好的灵活度和实用性。 同时结合 Ant Design V5 Token System,能达到非常高效与灵活的使用体验。 16 | 17 | :::success{title=适用场景} 18 | 用于批量组织可复用样式。 19 | ::: 20 | 21 | ## 典型示例 22 | 23 | 24 | 25 | ## 详细介绍 26 | 27 | ## API 28 | -------------------------------------------------------------------------------- /docs/api/global-styles.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: createGlobalStyle 3 | description: Create global styles 4 | order: 10 5 | group: Creating Styles 6 | --- 7 | 8 | ## Introduction 9 | 10 | Using `createGlobalStyle` allows you to create styles that are injected globally. The usage of this method is almost identical to `styled-component`, but it is implemented based on `@emotion/react` and `@emotion/serialize`. 11 | 12 | ## Default Usage 13 | 14 | 15 | 16 | ## Using with antd tokens 17 | 18 | By utilizing the token system in antd v5, we can organize and implement a Button style that does not exist in Ant Design. 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/api/global-styles.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: createGlobalStyle 3 | description: 创建全局样式 4 | order: 10 5 | group: 创建样式 6 | --- 7 | 8 | ## 简介 9 | 10 | 使用 `createGlobalStyle` 可以创建注入到全局的样式。 该方法的使用和 `styled-component` 基本没有区别,但实现上是基于 `@emotion/react` 和 `@emotion/serialize` 做的封装。 11 | 12 | ## 默认用法 13 | 14 | 15 | 16 | ## 结合 antd 的 token 使用 17 | 18 | 利用 antd v5 的 token 系统,我们可以自行组织实现一个在 Ant Design 中并不存在的 Button 样式。 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/api/setup-styled.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 setupStyled 3 | description: Set up global Styled data container 4 | group: Advanced Settings 5 | --- 6 | 7 | TBD 8 | -------------------------------------------------------------------------------- /docs/api/setup-styled.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 setupStyled 3 | description: 设置全局 Styled 数据容器 4 | group: 高级设置 5 | --- 6 | 7 | TBD 8 | -------------------------------------------------------------------------------- /docs/api/style-provider.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: StyleProvider 3 | description: 用于全局管理样式插入相关的配置 4 | order: 2 5 | group: 容器组件 6 | demo: 7 | tocDepth: 4 8 | --- 9 | 10 | ## 修改 container 11 | 12 | 指定 `container` 即可使得所有生成的样式(antd、antd-style)均插入到该节点下。 13 | 14 | 15 | 16 | ## 修改样式注入点 17 | 18 | 一般情况下不太需要用到,如果你需要兼容组件覆写样式的需求时,可以考虑设定组件样式的注入点,使得其在该节点之后注入。 19 | 20 | 21 | 22 | ## 开启 speedy 极速模式 23 | 24 | 开启 emotion 的 speedy 模式。建议独立应用可以开启。 25 | 26 | 27 | 28 | :::info{title=Speedy模式} 29 | 30 | 早期的 cssinjs 方案中,样式的插入是一个 style 标签对应一个样式,浏览器解析较慢,但便于修改与调试。 31 | 32 | 目前 emotion 默认使用现代化的 CSSOM api 插入样式,会把一堆 css 放到一个 标签里,插入后移除相应的内容。这种方式性能很好,支持万级别的样式插入。但与微应用(qiankun)兼容性较差。 33 | 34 | antd-style 中默认关闭了 speedy 模式,如果需要,配置 `speedy` 为 `true` 即可。 35 | ::: 36 | 37 | ## API 38 | 39 | 继承 `ant-design/cssinjs` 的 [StyleProvider](https://github.com/ant-design/cssinjs#styleprovider) ,其余 API 如下: 40 | 41 | | 属性名 | 类型 | 描述 | 42 | | --------------- | -------------------------------------- | -------------------------------------------------------------------- | 43 | | prefix | `string` | emotion 样式前缀,默认值为 acss | 44 | | nonce | `string` | 随机数,用于 CSP | 45 | | stylisPlugins | `StylisPlugin[]` | Stylis 插件数组 | 46 | | container | `Element` | 渲染样式的容器 | 47 | | speedy | `boolean` | 是否开启极速模式,极速模式下不会插入真实的样式 style,默认为 `false` | 48 | | insertionPoint | `HTMLElement` | 样式插入点,用于控制第一个样式的插入位置 | 49 | | getStyleManager | `(styleManager: StyleManager) => void` | 获取到 styleManager 实例的回调函数 | 50 | | children | `ReactNode` | 子组件 | 51 | -------------------------------------------------------------------------------- /docs/api/use-responsive.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useResponsive 3 | order: 4 4 | group: Hooks 5 | --- 6 | 7 | ## Introduction 8 | 9 | Get the result of responsive media queries. It is encapsulated based on antd's [Grid.useBreakpoint](https://ant.design/components/grid) . 10 | 11 | ## Usage 12 | 13 | ```tsx | pure 14 | import { useResponsive } from 'antd-style'; 15 | 16 | function Theme() { 17 | const { mobile } = useResponsive(); 18 | 19 | // Use JavaScript to distinguish between mobile and desktop 20 | return mobile ?
mobile
:
desktop
; 21 | } 22 | ``` 23 | 24 | ## Example 25 | 26 | 27 | 28 | ## Custom Breakpoints 29 | 30 | Customize responsive breakpoints by passing in antd's breakpoint configuration. 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/api/use-responsive.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useResponsive 3 | order: 4 4 | group: Hooks 5 | --- 6 | 7 | ## 简介 8 | 9 | 获取响应式媒体查询的结果。基于 antd 的 [Grid.useBreakpoint](https://ant.design/components/grid-cn#components-grid-demo-usebreakpoint) 封装。 10 | 11 | ## 用法 12 | 13 | ```tsx | pure 14 | import { useResponsive } from 'antd-style'; 15 | 16 | function Theme() { 17 | const { mobile } = useResponsive(); 18 | 19 | // 使用 js 来区分显示移动端 20 | return mobile ?
mobile
:
desktop
; 21 | } 22 | ``` 23 | 24 | ## 示例 25 | 26 | 27 | 28 | ## 自定义断点 29 | 30 | 通过传入 antd 的断点配置,来自定义响应断点。 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/api/use-theme-mode.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useThemeMode 3 | order: 2 4 | group: 5 | title: Hooks 6 | order: 3 7 | --- 8 | 9 | ## Introduction 10 | 11 | Obtain the theme appearance mode under `ThemeProvider`. 12 | 13 | ## Usage 14 | 15 | ```tsx 16 | /** 17 | * inherit: true 18 | * defaultShowCode: true 19 | */ 20 | import { Divider, Typography } from 'antd'; 21 | import { useThemeMode } from 'antd-style'; 22 | import { Flexbox } from 'react-layout-kit'; 23 | const { Text } = Typography; 24 | 25 | export default () => { 26 | const { themeMode, appearance, browserPrefers } = useThemeMode(); 27 | 28 | return ( 29 | 30 | Theme Mode: 31 | {themeMode} 32 | 33 | Appearance Mode: 34 | {appearance} 35 | 36 | Browser Appearance: 37 | {browserPrefers} 38 | 39 | ); 40 | }; 41 | ``` 42 | 43 | ## API 44 | 45 | ### Typescript 46 | 47 | ```ts 48 | useThemeMode: () => ThemeContextState; 49 | ``` 50 | 51 | ### ThemeContextState 52 | 53 | | Parameter | Type | Default | Description | 54 | | -------------- | ------------------------------------- | ------- | ----------------------- | 55 | | browserPrefers | [`BrowserPrefers`](#themeappearance) | `light` | Browser appearance | 56 | | themeMode | [`ThemeMode`](#thememode) | `light` | Theme mode | 57 | | appearance | [`ThemeAppearance`](#themeappearance) | `light` | Display appearance | 58 | | isDarkMode | `boolean` | `false` | Whether it is dark mode | 59 | 60 | ### BrowserPrefers 61 | 62 | Browser appearance, only `dark` or `light`. 63 | 64 | ### ThemeAppearance 65 | 66 | Appearance mode, can be `dark`, `light`, or a custom string. 67 | 68 | ### ThemeMode 69 | 70 | Theme mode, can be `dark`, `light`, or `auto`. 71 | -------------------------------------------------------------------------------- /docs/api/use-theme-mode.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useThemeMode 3 | order: 2 4 | group: 5 | title: Hooks 6 | order: 3 7 | --- 8 | 9 | ## 简介 10 | 11 | 可以获取到 `ThemeProvider` 下的主题外观模式。 12 | 13 | ## 用法 14 | 15 | ```tsx 16 | /** 17 | * inherit: true 18 | * defaultShowCode: true 19 | */ 20 | import { Divider, Typography } from 'antd'; 21 | import { useThemeMode } from 'antd-style'; 22 | import { Flexbox } from 'react-layout-kit'; 23 | const { Text } = Typography; 24 | 25 | export default () => { 26 | const { themeMode, appearance, browserPrefers } = useThemeMode(); 27 | 28 | return ( 29 | 30 | 主题模式: 31 | {themeMode} 32 | 33 | 外观模式: 34 | {appearance} 35 | 36 | 浏览器外观: 37 | {browserPrefers} 38 | 39 | ); 40 | }; 41 | ``` 42 | 43 | ## API 44 | 45 | ### Typescript 46 | 47 | ```ts 48 | useThemeMode: () => ThemeContextState; 49 | ``` 50 | 51 | ### ThemeContextState 52 | 53 | | 参数 | 类型 | 默认值 | 说明 | 54 | | -------------- | ------------------------------------- | ------- | -------------- | 55 | | browserPrefers | [`BrowserPrefers`](#themeappearance) | `light` | 浏览器外观 | 56 | | themeMode | [`ThemeMode`](#thememode) | `light` | 主题模式 | 57 | | appearance | [`ThemeAppearance`](#themeappearance) | `light` | 显示外观 | 58 | | isDarkMode | `boolean` | `false` | 是否为暗色模式 | 59 | 60 | ### BrowserPrefers 61 | 62 | 浏览器外观,仅为 `dark` 或者 `light`。 63 | 64 | ### ThemeAppearance 65 | 66 | 外观模式,为 `dark` 或者 `light` 或自定义的字符串。 67 | 68 | ### ThemeMode 69 | 70 | 主题模式,可以是 `dark`、`light` 或者 `auto`。 71 | -------------------------------------------------------------------------------- /docs/api/use-theme.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useTheme 3 | order: 1 4 | group: Hooks 5 | --- 6 | 7 | ## Introduction 8 | 9 | When used in conjunction with container components (`ThemeProvider`), it can obtain the theme information under the container. If `ThemeProvider` is not added, the default value is obtained. 10 | 11 | When `useTheme` is used under the `ThemeProvider` component, the theme value in the ThemeProvider can be obtained. 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```ts 18 | import { useTheme } from 'antd-style'; 19 | 20 | function Theme() { 21 | const theme = useTheme(); 22 | 23 | useEffect(() => { 24 | console.log(theme); 25 | }, [theme]); 26 | 27 | return null; 28 | } 29 | ``` 30 | 31 | ## Typescript 32 | 33 | ```ts 34 | useTheme = () => Theme; 35 | ``` 36 | 37 | ### Return Value 38 | 39 | | Parameter | Description | Type | Default | 40 | | ---------- | ----------- | ---------------------- | ------- | 41 | | themeMode | Theme mode | `dark / light / auto` | `light` | 42 | | appearance | Display | `dark / light` | `light` | 43 | | isDarkMode | Dark mode | `boolean` | `false` | 44 | -------------------------------------------------------------------------------- /docs/api/use-theme.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useTheme 3 | order: 1 4 | group: Hooks 5 | --- 6 | 7 | ## 简介 8 | 9 | 配合容器组件进行使用(`ThemeProvider`),可以获取到容器下的主题信息。如果不添加 `ThemeProvider`,默认获取到的值为默认值。 10 | 11 | 当 `useTheme` 放在 `ThemeProvider` 组件下使用,可以获得 ThemeProvider 中的主题值。 12 | 13 | 14 | 15 | ## 用法 16 | 17 | ```ts 18 | import { useTheme } from 'antd-style'; 19 | 20 | function Theme() { 21 | const theme = useTheme(); 22 | 23 | useEffect(() => { 24 | console.log(theme); 25 | }, [theme]); 26 | 27 | return null; 28 | } 29 | ``` 30 | 31 | ## Typescript 32 | 33 | ```ts 34 | useTheme = () => Theme; 35 | ``` 36 | 37 | ### 返回值 38 | 39 | | 参数 | 说明 | 类型 | 默认值 | 40 | | ---------- | -------------- | ---------------------- | ------- | 41 | | themeMode | 主题模式 | `dark / light / auto` | `light` | 42 | | appearance | 显示外观 | `dark / light` | `light` | 43 | | isDarkMode | 是否为暗色模式 | `boolean` | `false` | 44 | -------------------------------------------------------------------------------- /docs/best-practice/antd-based-components.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 Styling Best Practices for Customizing Components Based on antd v5 3 | group: 4 | title: UI Library Development 5 | order: 3 6 | --- 7 | 8 | # How to Write Styles Elegantly for a Component Library Based on antd v5? 9 | -------------------------------------------------------------------------------- /docs/best-practice/antd-based-components.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 基于 antd v5 二次封装组件库 3 | group: 4 | title: 组件库研发 5 | order: 3 6 | --- 7 | 8 | # 基于 antd v5 二开的组件库,应该如何优雅书写样式? 9 | -------------------------------------------------------------------------------- /docs/best-practice/antd-override.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 自定义 antd 组件样式 3 | group: 主题定制 4 | --- 5 | 6 | # 如何更加优雅地覆写 antd 组件样式? 7 | 8 | ## 基于 ConfigProvider 自定义 9 | 10 | antd 在 V5 提供了全新的 theme 属性用于自定义,因此如果需要自定义组件样式,建议优先采用 CP 上的 theme 字段。 11 | 12 | 示例 demo 如下: 13 | 14 | 15 | 16 | :::info 17 | 更多基于 ConfigProvider 的主题定制能力,详见 [聊聊 Ant Design V5 的主题(上):CSSinJS 动态主题的花活](https://www.yuque.com/antfe/featured/durxuu94nvgvgmzq#vFlnd)。 18 | ::: 19 | 20 | antd-style 的 ThemeProvider 是基于 ConfigProvider 的业务层封装,提供业务友好的定制能力,查看:[自定义主题](/zh-CN/guide/custom-theme) 21 | 22 | ## 基本覆写 23 | 24 | `createStyles` 方法存在一个 `prefixCls` 参数,使用该参数可以传入组件的前缀,这样一来,任何的样式覆写都可以随着 prefixCls 的变化而自动变化。 25 | 26 | 27 | 28 | ## 抬升权重覆写 29 | 30 | 在某些组件中,直接添加类名可能因为权重不够高,导致无法覆盖样式,此时可以通过 `&` 符号来抬升相应的权重。 31 | 32 | 33 | 34 | ## 多 classNames 场景覆写 35 | 36 | classNames 是 antd V5 的一个重头戏: [[RFC] Semantic DOM Structure for all Components](https://github.com/ant-design/ant-design/discussions/40221)。 37 | 在过去,我们要做样式定义,需要找很多 dom 节点进行大量的样式覆写,而 antd 版本升级的过程中,有时候会对 dom 结构进行调整。这样一来,我们覆写的样式就会出现问题。 38 | 39 | 而 classNames 将为我们提供一个稳定的 dom 结构 API ,我们可以通过 classNames 传入的类名,将会文档指向对应的 dom 节点,进而大大降低 DOM 变化带来的 Breaking Change 风险,同时也让我们不必再 hack 式地找样式类名。 40 | 41 | 42 | 43 | ## 相关讨论 44 | 45 | - [样式权重问题](https://github.com/ant-design/antd-style/issues/24) 46 | -------------------------------------------------------------------------------- /docs/best-practice/clay.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Clay Style UI 3 | group: Style Cases 4 | --- 5 | 6 | # Clay Style 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/best-practice/clay.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 黏土风 UI 3 | group: 样式案例 4 | --- 5 | 6 | # 黏土风格 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/best-practice/custom-token-types.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Extending Custom Token Type Definition 3 | group: 4 | title: Theme Customization 5 | order: 1 6 | --- 7 | 8 | # How to extend the CustomToken object type definition for antd-style? 9 | 10 | ## Solution 11 | 12 | By extending the type definition of the `CustomToken` interface for `antd-style`, you can add corresponding token type definitions to the `useTheme` hooks. 13 | 14 | At the same time, by adding generics to the `ThemeProvider` object, you can constrain the input definition of `customToken`. 15 | 16 | ```tsx | pure 17 | import { ThemeProvider, useTheme } from 'antd-style'; 18 | 19 | interface NewToken { 20 | customBrandColor: string; 21 | } 22 | 23 | // By extending the type definition of the `CustomToken` interface for `antd-style`, you can add corresponding token type definitions to the `useTheme` hooks 24 | declare module 'antd-style' { 25 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 26 | export interface CustomToken extends NewToken {} 27 | } 28 | 29 | const App = () => { 30 | const token = useTheme(); 31 | return
{token.customBrandColor}
; 32 | }; 33 | 34 | export default () => ( 35 | // By adding generics to the `ThemeProvider` object, you can constrain the input definition of the `customToken` interface 36 | customToken={{ customBrandColor: '#c956df' }}> 37 | 38 | 39 | ); 40 | ``` 41 | 42 | :::info 43 | Since `CustomToken` is likely an empty interface, if the project has configured the `@typescript-eslint/no-empty-interface` rule, the interface definition may be corrected to a type during code formatting, and types cannot be extended, resulting in loss of prompts (related issue: [#16](https://github.com/ant-design/antd-style/issues/16)). Therefore, the solution is to add a rule disabling as shown in the example code above. 44 | ::: 45 | 46 | ## Reference Code 47 | 48 | - [dumi-theme-antd-style](https://github.com/arvinxx/dumi-theme-antd-style/blob/master/src/styles/customToken.ts) 49 | - [Ant Design Official Website](https://github.com/ant-design/ant-design/blob/master/.dumi/theme/SiteThemeProvider.tsx) 50 | 51 | ## Related Discussions 52 | 53 | - [🧐\[Question\] How to extend the CustomToken object type definition for antd-style](https://github.com/ant-design/antd-style/issues/16) 54 | -------------------------------------------------------------------------------- /docs/best-practice/custom-token-types.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 扩展自定义 Token 类型定义 3 | group: 4 | title: 主题定制 5 | order: 1 6 | --- 7 | 8 | # 如何给 antd-style 扩展 CustomToken 对象类型定义? 9 | 10 | ## 解决思路 11 | 12 | 通过给 `antd-style` 扩展 `CustomToken` 接口的类型定义,可以为 `useTheme` hooks 中增加相应的 token 类型定义。 13 | 14 | 同时,给 `ThemeProvider` 对象添加泛型,可以约束 `customToken` 的入参定义。 15 | 16 | ```tsx | pure 17 | import { ThemeProvider, useTheme } from 'antd-style'; 18 | 19 | interface NewToken { 20 | customBrandColor: string; 21 | } 22 | 23 | // 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象 24 | declare module 'antd-style' { 25 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 26 | export interface CustomToken extends NewToken {} 27 | } 28 | 29 | const App = () => { 30 | const token = useTheme(); 31 | return
{token.customBrandColor}
; 32 | }; 33 | 34 | export default () => ( 35 | // 给 ThemeProvider 对象添加泛型后可以约束 customToken 接口的入参定义 36 | customToken={{ customBrandColor: '#c956df' }}> 37 | 38 | 39 | ); 40 | ``` 41 | 42 | :::info 43 | 由于 CustomToken 大概率是一个空 interface,如果在项目中有配置 ` @typescript-eslint/no-empty-interface` 的规则,就在代码格式化时导致接口定义被订正改为 type,而 type 是无法扩展的,会导致提示丢失(相关 issue: [#16](https://github.com/ant-design/antd-style/issues/16))。因此解决方案为如上述示例代码一样,添加禁用规则。 44 | ::: 45 | 46 | ## 参考代码 47 | 48 | - [dumi-theme-antd-style](https://github.com/arvinxx/dumi-theme-antd-style/blob/master/src/styles/customToken.ts) 49 | - [Ant Design 官网](https://github.com/ant-design/ant-design/blob/master/.dumi/theme/SiteThemeProvider.tsx) 50 | 51 | ## 相关讨论 52 | 53 | - [🧐[问题] 请问一下如何给 antd-style 扩展 CustomToken 对象类型定义](https://github.com/ant-design/antd-style/issues/16) 54 | -------------------------------------------------------------------------------- /docs/best-practice/demos/ConfigProviderOverride.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: true 3 | */ 4 | 5 | import { Button, Checkbox, ConfigProvider, Popover, theme } from 'antd'; 6 | import { Flexbox } from 'react-layout-kit'; 7 | 8 | export default () => { 9 | const { token } = theme.useToken(); 10 | 11 | return ( 12 | 24 |
25 | 29 |
antd V5 的 Popup ,结合 结合 组件级 Token,可以非常简单地实现自定义样式
30 | 31 | 32 | 不再显示 33 | 36 | 37 |
38 | } 39 | color={'blue'} 40 | arrow={{ pointAtCenter: true }} 41 | trigger="hover" 42 | > 43 | antd v5 的组件级自定义样式,轻松又便捷 44 | 45 | 46 |
47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /docs/best-practice/demos/DefaultOverride.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * defaultShowCode: true 3 | */ 4 | import { Button, Space } from 'antd'; 5 | import { ThemeProvider, createStyles } from 'antd-style'; 6 | 7 | const useStyles = createStyles(({ token, css, prefixCls }) => ({ 8 | override: css` 9 | &.${prefixCls}-btn { 10 | background-color: ${token.colorWarning}; 11 | } 12 | `, 13 | })); 14 | 15 | const Demo = ({ text }: { text?: string }) => { 16 | const { styles } = useStyles(); 17 | 18 | return ; 19 | }; 20 | 21 | export default () => { 22 | return ( 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /docs/best-practice/demos/InputclassNames.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * defaultShowCode: true 3 | */ 4 | import { Input } from 'antd'; 5 | import { createStyles } from 'antd-style'; 6 | 7 | const useStyles = createStyles(({ token, css, prefixCls }) => ({ 8 | bg: css` 9 | background: ${token.colorBgLayout}; 10 | padding: 24px; 11 | `, 12 | input: css` 13 | background: transparent; 14 | `, 15 | wrapper: css` 16 | background: transparent; 17 | border: 2px solid ${token.colorBorder}; 18 | `, 19 | suffix: css` 20 | color: ${token.colorTextQuaternary}; 21 | `, 22 | })); 23 | 24 | export default () => { 25 | const { styles } = useStyles(); 26 | 27 | return ( 28 |
29 | 34 |
35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /docs/best-practice/demos/NestElements.tsx: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ css, cx }) => { 4 | // 使用 cx 包裹 css 5 | const child = cx(css` 6 | background: red; 7 | width: 100px; 8 | height: 100px; 9 | `); 10 | 11 | return { 12 | parent: css` 13 | cursor: pointer; 14 | 15 | &:hover { 16 | .${child} { 17 | background: blue; 18 | } 19 | } 20 | `, 21 | child, 22 | }; 23 | }); 24 | 25 | const Demo = () => { 26 | const { styles } = useStyles(); 27 | 28 | return ( 29 |
30 |
31 | hover to change color 32 |
33 | ); 34 | }; 35 | 36 | export default Demo; 37 | -------------------------------------------------------------------------------- /docs/best-practice/demos/OverrideWeight.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * defaultShowCode: true 3 | */ 4 | import { App, Layout } from 'antd'; 5 | import { createStyles } from 'antd-style'; 6 | 7 | const useStyles = createStyles(({ token, css, prefixCls }) => ({ 8 | default: css` 9 | .${prefixCls}-layout-header { 10 | background-color: ${token.colorPrimary}; 11 | } 12 | `, 13 | moreWeight: css` 14 | // ↓ 15 | &.${prefixCls}-layout-header { 16 | background-color: ${token.colorPrimary}; 17 | } 18 | `, 19 | })); 20 | 21 | export default () => { 22 | const { styles } = useStyles(); 23 | 24 | return ( 25 | 26 | 27 | 无法覆盖 28 | 可正常覆盖 29 | 30 | 31 | ); 32 | }; 33 | -------------------------------------------------------------------------------- /docs/best-practice/demos/StaticMethod/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 240 3 | */ 4 | import { Button, Space } from 'antd'; 5 | import Layout from './layout'; 6 | import { showMessage, showModal, showNotification } from './request'; 7 | 8 | const App = () => ( 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | ); 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /docs/best-practice/demos/StaticMethod/layout.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 240 3 | */ 4 | import { ThemeProvider } from 'antd-style'; 5 | import { MessageInstance } from 'antd/es/message/interface'; 6 | import { ModalStaticFunctions } from 'antd/es/modal/confirm'; 7 | import { NotificationInstance } from 'antd/es/notification/interface'; 8 | import { PropsWithChildren } from 'react'; 9 | import { Center } from 'react-layout-kit'; 10 | 11 | export let message: MessageInstance, 12 | modal: Omit, 13 | notification: NotificationInstance; 14 | 15 | export default ({ children }: PropsWithChildren) => { 16 | return ( 17 |
18 | { 23 | message = instances.message; 24 | modal = instances.modal; 25 | notification = instances.notification; 26 | }} 27 | > 28 | {children} 29 | 30 |
31 | ); 32 | }; 33 | -------------------------------------------------------------------------------- /docs/best-practice/demos/StaticMethod/request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 240 3 | */ 4 | import { message, modal, notification } from './layout'; 5 | 6 | export const showMessage = () => { 7 | message.success('Success!'); 8 | }; 9 | 10 | export const showNotification = () => { 11 | notification.info({ 12 | message: `Notification`, 13 | description: 'Hello, Ant Design Style', 14 | }); 15 | }; 16 | 17 | export const showModal = () => { 18 | modal.warning({ 19 | title: 'This is a warning message', 20 | content: 'some messages...some messages...', 21 | centered: true, 22 | maskClosable: true, 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /docs/best-practice/demos/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.tsx", "**/*.ts"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "declaration": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "jsx": "react-jsx", 9 | "lib": ["DOM", "ESNext"], 10 | "baseUrl": ".", 11 | "paths": { 12 | "antd-style": ["../../../es"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/best-practice/fix-switch-theme-fouc.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 暗色模式下首屏会 “闪” 一下 3 | group: 4 | title: 主题切换 5 | order: 2 6 | --- 7 | 8 | ## 暗色模式下首屏会 “闪” 一下 9 | 10 | 在使用 antd-style 时,首屏一般是亮色的。这就会导致暗色模式下,用户的界面先显示亮色主题,再切换到暗色主题。用户感受上就是会 “闪” 一下,体验很差。这一类问题有一个专业术语叫做 FOUC 。 11 | 12 | 如何解决? 13 | 14 | 本文预设你已经了解了 antd-style 在 SSG、SSR 下的解决方案。 15 | 16 | 原理分析: 17 | 18 | 1. SSG 产出亮色 HTML; 19 | 2. JS 水合后 cssinjs 运行,重新生成暗色类名与样式; 20 | 21 | FOUC 的根本原因是,服务端不知道客户端此时的主题状态。 22 | 23 | 因此解决思路有两种: 24 | 25 | 1. SSR:将用户客户端的主题状态让服务端可以感知,例如使用 query url、cookie 等机制; 26 | 2. 颜色变量抽取为 CSS 变量; 27 | 28 | ### SSR 解决方案 29 | 30 | 以 next.js App Router 为例: 31 | 32 | ```tsx | pure 33 | const RootLayout = ({ children }: PropsWithChildren) => { 34 | // 从 cookie 中获取 主题变化情况 35 | const cookieStore = cookies(); 36 | const appearance = cookieStore.get('theme'); 37 | 38 | return ( 39 | 40 | 41 | 42 | {children} 43 | 44 | 45 | 46 | 47 | ); 48 | }; 49 | 50 | export default RootLayout; 51 | ``` 52 | 53 | ```tsx | pure 54 | export interface AppThemeProps { 55 | children?: ReactNode; 56 | defaultAppearance?: ThemeAppearance; 57 | } 58 | 59 | const Layout = memo(({ children, defaultAppearance }) => { 60 | console.log('server:appearance', defaultAppearance); 61 | 62 | return ( 63 | { 66 | document.cookie = `theme=${appearance};`; 67 | }} 68 | themeMode={themeMode} 69 | > 70 | {children} 71 | 72 | ); 73 | }); 74 | 75 | export default Layout; 76 | ``` 77 | -------------------------------------------------------------------------------- /docs/best-practice/index.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Best Practices and Case Studies 3 | nav: 4 | title: Best Practices 5 | order: 3 6 | --- 7 | 8 | # Best Practices and Case Studies 9 | 10 | As more and more users adopt antd-style, it has been observed that users still encounter some edge cases in practical applications. 11 | 12 | Therefore, this section has been adjusted to focus on "Best Practices" and "Case Studies", detailing the best practices for using antd-style based on common scenarios encountered by users. 13 | 14 | In addition to best practices, this section also includes some practical case studies, with the hope of providing assistance to you. 15 | -------------------------------------------------------------------------------- /docs/best-practice/index.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 最佳实践与案例集 3 | nav: 4 | title: 最佳实践 5 | order: 3 6 | --- 7 | 8 | # 最佳实践与案例集 9 | 10 | 随着 antd-style 被更多用户使用,发现大家在实际应用中还是会遇到一些边角问题。 11 | 12 | 因此这一趴调整为「最佳实践」与「案例集」,按照大家常遇到的场景,来详细阐述 antd-style 使用的最佳实践。 13 | 14 | 当然,除了最佳实践之外,这部分也包含了一些实践案例,希望能够帮助到你。 15 | -------------------------------------------------------------------------------- /docs/best-practice/mac-select.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Component —— macOS Selector 3 | group: 4 | title: Style Cases 5 | order: 10 6 | --- 7 | 8 | # MacOS Selector 9 | 10 | This is a macOS-style interactive selector that combines [floating-ui](https://floating-ui.com/) with the `antd-style`. If you are tired of the default selector in antd but still want to maintain the visual style of antd, you can use antd-style to create your own interactive components. 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/best-practice/mac-select.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 自定义组件: MacOS 选择器 3 | group: 4 | title: 样式案例 5 | order: 10 6 | --- 7 | 8 | # MacOS 选择器 9 | 10 | 这是一个结合 [floating-ui](https://floating-ui.com/) 与 `antd-style` 实现的 macOS 交互风格的选择器。如果用腻了 antd 默认的选择器,但又希望有 antd 的视觉风格,可以使用 antd-style 来实现自己的交互组件。 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/best-practice/mirgration-less-global-style.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Modules Global Style Override Migration 3 | group: 4 | title: Writing Style 5 | order: 0 6 | --- 7 | 8 | # CSS Modules Global Style Override Migration 9 | 10 | How to handle the usage of `:global` in CSS Modules syntax during migration? 11 | 12 | In CSS Modules, there are scenarios where the `:global` is used to override component styles. How should this part of the code be handled during migration? 13 | 14 | ## Solution 15 | 16 | Preferably, use [codemod](/guide/migrate-less-codemod) for one-click migration. This Codemod will automatically convert the `:global` in CSS Modules syntax to the syntax in antd-style. 17 | 18 | If manual adjustment is needed, simply remove the `:global` syntax. 19 | 20 | Before migration: 21 | 22 | ```less 23 | .container { 24 | :global(.ant-btn-link) { 25 | padding: 0; 26 | font-size: 12px; 27 | } 28 | } 29 | ``` 30 | 31 | After migration: 32 | 33 | ```ts 34 | const useStyles = createStyles(({ css }) => ({ 35 | container: css` 36 | .ant-btn-link { 37 | padding: 0; 38 | font-size: 12px; 39 | } 40 | `, 41 | })); 42 | ``` 43 | 44 | ## Principle Analysis 45 | 46 | Elements in CSS modules are by default given a hash. The `:global` syntax is used to avoid adding a hash to the style name. However, antd-style uses `emotion/css` as the underlying style library, where combined styles do not automatically add a hash. Therefore, simply removing `:global` is sufficient. 47 | 48 | ## Related Discussions 49 | 50 | - [🧐\[Issue\] How to handle the usage of :global in less syntax during migration](https://github.com/ant-design/antd-style/issues/72) 51 | -------------------------------------------------------------------------------- /docs/best-practice/mirgration-less-global-style.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Modules 全局样式覆写迁移 3 | group: 4 | title: 样式书写 5 | order: 0 6 | --- 7 | 8 | # CSS Modules 全局样式覆写迁移 9 | 10 | 迁移过程中 CSS Modules 语法中使用到的 `:global` 怎么处理? 11 | 12 | 在 CSS Modules 中有部分场景需要通过 :global 去覆盖组件样式,迁移过程中这部分代码如何处理? 13 | 14 | ## 解决方案 15 | 16 | 优先使用 [codemod](/zh-CN/guide/migrate-less-codemod) 一键迁移,该 Codemod 会自动将 Css Modules 语法中的 :global 转换为 antd-style 中的语法。 17 | 18 | 如需手动调整,那么直接移除 :global 语法既可。 19 | 20 | 迁移前: 21 | 22 | ```less 23 | .container { 24 | :global(.ant-btn-link) { 25 | padding: 0; 26 | font-size: 12px; 27 | } 28 | } 29 | ``` 30 | 31 | 迁移后: 32 | 33 | ```ts 34 | const useStyles = createStyles(({ css }) => ({ 35 | container: css` 36 | .ant-btn-link { 37 | padding: 0; 38 | font-size: 12px; 39 | } 40 | `, 41 | })); 42 | ``` 43 | 44 | ## 原理解析 45 | 46 | css module 中的元素默认会添加 hash,`:global` 语法是为了避免给样式名添加 hash。而 antd-style 使用了 `emotion/css` 47 | 作为底层样式库,其中联合的样式并不会自动添加 hash,因此直接去除 :global 即可。 48 | 49 | ## 相关讨论 50 | 51 | - [🧐[问题] 迁移过程中 less 语法中使用到的 :global 怎么处理](https://github.com/ant-design/antd-style/issues/72) 52 | -------------------------------------------------------------------------------- /docs/best-practice/nest-element-style.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Writing Linked Styles for Parent-Child Components 3 | group: Writing Style 4 | --- 5 | 6 | # How to Write Linked Styles 7 | 8 | Sometimes we need to modify the style of a child component when hovering over the container component. In this case, we can use `cx` to generate a className. 9 | 10 | ## Demo 11 | 12 | Core code: 13 | 14 | ```ts 15 | const useStyles = createStyles(({ css, cx }) => { 16 | // 1. Use cx to wrap css and get the className (acss-xxx) 17 | const child = cx(css` 18 | background: red; 19 | width: 100px; 20 | height: 100px; 21 | `); 22 | 23 | return { 24 | parent: css` 25 | cursor: pointer; 26 | 27 | &:hover { 28 | // 2. Implement cascading 29 | .${child} { 30 | background: blue; 31 | } 32 | } 33 | `, 34 | // 3. Export the child className 35 | child, 36 | }; 37 | }); 38 | ``` 39 | 40 | 41 | 42 | ## Principle Analysis 43 | 44 | The idea is simple because the `css` method always produces a [serialized style object](/api/create-styles#css). Wrapping the `css` object with `cx` will convert the object into a className (`acss-xxxx`). 45 | 46 | ## Related Discussions 47 | 48 | - [\[Issue\] How to nest styles](https://github.com/ant-design/antd-style/issues/54) 49 | - [\[BUG\] Inconsistency between the classNames generated by internal cx and the exported classNames after enabling the babel-plugin-antd-style plugin](https://github.com/ant-design/antd-style/issues/83) 50 | -------------------------------------------------------------------------------- /docs/best-practice/nest-element-style.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 父子联动的样式书写 3 | group: 样式书写 4 | --- 5 | 6 | # 如何书写联动样式 7 | 8 | 有时候我们需要实现在 hover 容器组件的时候,修改 child 的样式。这种情况下,我们可以使用 cx 来生成 className。 9 | 10 | ## Demo 11 | 12 | 核心代码: 13 | 14 | ```ts 15 | const useStyles = createStyles(({ css, cx }) => { 16 | // 1. 使用 cx 包裹 css,得到 (acss-xxx) 类名 17 | const child = cx(css` 18 | background: red; 19 | width: 100px; 20 | height: 100px; 21 | `); 22 | 23 | return { 24 | parent: css` 25 | cursor: pointer; 26 | 27 | &:hover { 28 | // 2. 实现级联 29 | .${child} { 30 | background: blue; 31 | } 32 | } 33 | `, 34 | // 3. 导出 child className 35 | child, 36 | }; 37 | }); 38 | ``` 39 | 40 | 41 | 42 | ## 原理解析 43 | 44 | 思路上很简单,因为 `css` 方法产出的始终是[序列化样式对象](/zh-CN/api/create-styles#css)。用 `cx` 包裹 `css` 对象,就会将该对象转成类名 (`acss-xxxx`)。 45 | 46 | ## 相关讨论 47 | 48 | - [[问题] 样式怎么嵌套呢](https://github.com/ant-design/antd-style/issues/54) 49 | - [[BUG] 开启 babel-plugin-antd-style 插件后内部 cx 生成的类名和导出的不一致](https://github.com/ant-design/antd-style/issues/83) 50 | -------------------------------------------------------------------------------- /docs/best-practice/static-message.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Failure of antd Static Methods to Respond to Themes 3 | group: Theme Customization 4 | --- 5 | 6 | # How to Resolve the Issue of antd Static Methods such as Modal and message Not Responding to Themes? 7 | 8 | In the past, in version 4, these static methods could be used in non-component environments, such as using `message.error` in axios to display error messages. 9 | 10 | Now, in version 5, it is necessary to use `const { message } = App.useApp();`. 11 | 12 | Does this mean that we can no longer use them as before? 13 | 14 | ## Solution 15 | 16 | Of course not. Refer to the demo below. By defining the corresponding instance variables in a separate file, you can still use them in non-React environments and they will still respond to themes. 17 | 18 | 19 | 20 | ## Principle Analysis 21 | 22 | antd-style provides a [`getStaticInstance`](api/theme-provider#consume-static-instance-method) interface in the `ThemeProvider`, from which users can obtain the integrated instance. 23 | 24 | The implementation principle of this method is also simple. Taking message as an example: 25 | 26 | ```tsx | pure 27 | import { message } from 'antd'; 28 | 29 | const Provider = ({ getStaticInstance, children, theme }) => { 30 | // 1. Use useMessage to obtain the instance 31 | const [messageInstance, messageContextHolder] = message.useMessage(staticInstanceConfig?.message); 32 | 33 | useEffect(() => { 34 | // 3. Use getStaticInstance to expose the instance 35 | getStaticInstance?.({ 36 | message: messageInstance, 37 | }); 38 | }, []); 39 | 40 | return ( 41 | 42 | {/* 2. Insert the context of message */} 43 | {messageContextHolder} 44 | {children} 45 | 46 | ); 47 | }; 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/best-practice/static-message.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: antd 静态方法的主题失效 3 | group: 主题定制 4 | --- 5 | 6 | # Modal 、message 等 antd 的静态方法不响应主题,如何解决? 7 | 8 | 原先在 v4 中可以在非组件环境下使用这些静态方法,比如放在 axios 里面用 `message.error` 做一些报错的提示。 9 | 10 | 现在 V5 版本里,需要用 `const { message } = App.useApp();` 11 | 12 | 是不是意味着无法再像以前那样用了? 13 | 14 | ## 解决方案 15 | 16 | 当然不是,参考下方 Demo,通过在独立文件中定义相应的实例变量,即可在非 React 环境下使用,并且仍然响应主题。 17 | 18 | 19 | 20 | ## 原理解析 21 | 22 | antd-style 在 `ThemeProvider` 中提供了一个 [`getStaticInstance`](/zh-CN/api/theme-provider#消费静态实例方法) 接口,用户可以从中获取集成后的实例。 23 | 24 | 该方法的实现原理也很简单,以 message 为例: 25 | 26 | ```tsx | pure 27 | import { message } from 'antd'; 28 | 29 | const Provider = ({ getStaticInstance, children, theme }) => { 30 | // 1. 使用 useMessage 获取实例 31 | const [messageInstance, messageContextHolder] = message.useMessage(staticInstanceConfig?.message); 32 | 33 | useEffect(() => { 34 | // 3. 将实例用 getStaticInstance 抛出 35 | getStaticInstance?.({ 36 | message: messageInstance, 37 | }); 38 | }, []); 39 | 40 | return ( 41 | 42 | {/* 2. 插入 message 的上下文 */} 43 | {messageContextHolder} 44 | {children} 45 | 46 | ); 47 | }; 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/best-practice/styled.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Style Components 3 | group: Style Cases 4 | --- 5 | 6 | # Building Stylish Components Using Styled 7 | 8 | ## Stylish Title Components 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/best-practice/styled.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 样式组件 3 | group: 样式案例 4 | --- 5 | 6 | # 使用 Styled 构建风格样式组件 7 | 8 | ## 风格化标题组件 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/changelog.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Release Notes 3 | nav: 4 | title: Release Notes 5 | order: 999 6 | --- 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/changelog.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 更新日志 3 | nav: 4 | title: 更新日志 5 | order: 999 6 | --- 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/demos/StyleProvider/customContainer.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 100 3 | */ 4 | import { Button } from 'antd'; 5 | import { createStyles, css, StyleProvider } from 'antd-style'; 6 | 7 | const useStyles = createStyles({ 8 | text: css` 9 | color: blue; 10 | `, 11 | }); 12 | 13 | const Text = () => { 14 | const { styles } = useStyles(); 15 | return
样式将插入在 body 节点
; 16 | }; 17 | 18 | export default () => { 19 | return ( 20 | 21 | 22 | 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /docs/demos/StyleProvider/insertpoint.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 50 3 | */ 4 | import { createStyles, css, StyleProvider } from 'antd-style'; 5 | 6 | const useStyles = createStyles({ 7 | text: css` 8 | color: hotpink; 9 | `, 10 | }); 11 | 12 | const Text = () => { 13 | const { styles } = useStyles(); 14 | return
插入的 style 节点在第一个 meta 标签之后
; 15 | }; 16 | 17 | export default () => { 18 | const firstMeta = document.getElementsByTagName('meta')[0]; 19 | 20 | return ( 21 | 22 | 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /docs/demos/StyleProvider/speedy.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 50 3 | */ 4 | import { createStyles, css, StyleProvider } from 'antd-style'; 5 | 6 | const useStyles = createStyles({ 7 | text: css` 8 | color: blue; 9 | `, 10 | }); 11 | 12 | const Text = () => { 13 | const { styles } = useStyles(); 14 | return
开启 speedy 模式后,style 标签中将不存在具体样式
; 15 | }; 16 | 17 | export default () => { 18 | return ( 19 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/AppGlobalStyle.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 180 3 | */ 4 | import { css } from '@emotion/css'; 5 | import { App, Divider } from 'antd'; 6 | import { ThemeProvider } from 'antd-style'; 7 | import { Flexbox } from 'react-layout-kit'; 8 | 9 | const appScopeStyle = css` 10 | @font-face { 11 | font-family: 'Rocher'; 12 | // refs: https://www.matuzo.at/blog/2023/100daysof-day75/ 13 | src: url('/fonts/RocherColorGX.woff2'); 14 | } 15 | 16 | .custom-button { 17 | font-family: 'Rocher'; 18 | padding: 24px; 19 | font-size: 24px; 20 | } 21 | `; 22 | 23 | export default () => { 24 | return ( 25 | 26 |
Out App Container Custom Button
27 | 28 | 29 | 30 |
in App Container Custom Button
31 |
32 |
33 |
34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/SwitchTheme.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 460 3 | */ 4 | import { ThemeProvider } from 'antd-style'; 5 | import { Flexbox } from 'react-layout-kit'; 6 | import App from '../common/demo'; 7 | 8 | export default () => { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/TSSupport.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | */ 4 | import { ThemeProvider, useTheme } from 'antd-style'; 5 | 6 | interface NewToken { 7 | customBrandColor: string; 8 | } 9 | 10 | // 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象 11 | declare module 'antd-style' { 12 | export interface CustomToken extends NewToken {} 13 | } 14 | 15 | const App = () => { 16 | const token = useTheme(); 17 | return
{token.customBrandColor}
; 18 | }; 19 | 20 | export default () => ( 21 | // 给 `ThemeProvider` 对象添加泛型,可以约束 `customToken` 的入参定义。 22 | customToken={{ customBrandColor: '#c956df' }}> 23 | 24 | 25 | ); 26 | 27 | /** 28 | * In some instances, if you are using a previous version of React and/or Typescript, 29 | * you may get an error like this: 30 | * 31 | * 'ThemeProvider' cannot be used as a JSX component. 32 | * Its return type 'ReactNode' is not a valid JSX element. 33 | * Type 'undefined' is not assignable to type 'Element | null'. 34 | * 35 | * You can fix this by either upgrading React and/or Typescript, or by overriding the 36 | * ThemeProvider type definition like this: 37 | * 38 | * import { ThemeProvider, ThemeProviderProps } from 'antd-style' 39 | * ... 40 | * const ThemeProviderComponent = ThemeProvider as ( 41 | * props: ThemeProviderProps 42 | * ) => JSX.Element 43 | * 44 | * and then use ThemeProviderComponent instead of ThemeProvider. 45 | */ 46 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/WithApp.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * title: ThemeProvider + App 3 | * description: 由于 App 有 DOM 节点,能限制作用域来修改 DOM 原生样式,因此可以重置原生节点样式 4 | * iframe: 80 5 | */ 6 | import { App } from 'antd'; 7 | import { ThemeProvider } from 'antd-style'; 8 | 9 | import Demo from './demo'; 10 | 11 | export default () => { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/WithProvider.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * title: ThemeProvider 3 | * description: 由于 ThemeProvider 没有有根 DOM 节点,因此无法修改原生节点样式(除非搭配 GlobalStyle,而搭配 GlobalStyle 则会污染全局样式) 4 | * iframe: 80 5 | */ 6 | import { ThemeProvider } from 'antd-style'; 7 | import App from './demo'; 8 | 9 | export default () => { 10 | return ( 11 | <> 12 | 13 | 14 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/_app.tsx: -------------------------------------------------------------------------------- 1 | import { Space } from 'antd'; 2 | import { useTheme } from 'antd-style'; 3 | import { FC } from 'react'; 4 | 5 | interface AppProps { 6 | title: string; 7 | tokenName?: string; 8 | } 9 | 10 | const App: FC = ({ title, tokenName }) => { 11 | const token = useTheme(); 12 | 13 | // @ts-ignore 14 | const tokenColor = tokenName ? token[tokenName] : token.colorPrimary; 15 | 16 | return ( 17 | 18 |
{title}
19 | 27 |
35 | {tokenColor || 'None'} 36 | 37 |
38 | {tokenName || '-'} 39 |
40 | 41 | ); 42 | }; 43 | 44 | export default App; 45 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/customToken.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | * defaultShowCode: true 4 | * codePlacement: left 5 | */ 6 | import { ThemeProvider, useTheme } from 'antd-style'; 7 | import { Flexbox } from 'react-layout-kit'; 8 | import App from './_app'; 9 | 10 | export default () => { 11 | const theme = useTheme(); 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/default.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * defaultShowCode: true 3 | * codePlacement: left 4 | */ 5 | import { Divider } from 'antd'; 6 | import { ThemeProvider } from 'antd-style'; 7 | import { Container } from './style'; 8 | import App from './_app'; 9 | 10 | export default () => ( 11 | } size={24}> 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/demo.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 80 3 | */ 4 | const App = () => { 5 | return ( 6 |
7 | 节点样式 8 |
9 | ); 10 | }; 11 | export default App; 12 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/nested-prefixCls.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * debug: true 3 | * iframe: true 4 | */ 5 | import { Button } from 'antd'; 6 | import { ThemeProvider, createStyles } from 'antd-style'; 7 | 8 | const useStyles = createStyles(({ css, prefixCls }) => ({ 9 | button: css` 10 | .${prefixCls}-btn { 11 | background: pink; 12 | } 13 | `, 14 | })); 15 | 16 | const Demo = () => { 17 | const { styles } = useStyles(); 18 | return ( 19 |
20 | 21 |
22 | ); 23 | }; 24 | 25 | const App = () => { 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | }; 34 | export default App; 35 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/staticMethod.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 240 3 | */ 4 | import { Button, Space } from 'antd'; 5 | import { ThemeProvider } from 'antd-style'; 6 | import { MessageInstance } from 'antd/es/message/interface'; 7 | import { ModalStaticFunctions } from 'antd/es/modal/confirm'; 8 | import { NotificationInstance } from 'antd/es/notification/interface'; 9 | import { Center } from 'react-layout-kit'; 10 | 11 | let message: MessageInstance, 12 | modal: Omit, 13 | notification: NotificationInstance; 14 | 15 | const App = () => { 16 | const showMessage = () => { 17 | message.success('Success!'); 18 | }; 19 | 20 | const showModal = () => { 21 | modal.warning({ 22 | title: 'This is a warning message', 23 | content: 'some messages...some messages...', 24 | centered: true, 25 | maskClosable: true, 26 | }); 27 | }; 28 | 29 | const showNotification = () => { 30 | notification.info({ 31 | message: `Notification`, 32 | description: 'Hello, Ant Design Style', 33 | }); 34 | }; 35 | 36 | return ( 37 | 38 | 41 | 42 | 43 | 44 | ); 45 | }; 46 | 47 | export default () => { 48 | return ( 49 |
50 | { 55 | message = instances.message; 56 | modal = instances.modal; 57 | notification = instances.notification; 58 | }} 59 | > 60 | 61 | 62 |
63 | ); 64 | }; 65 | -------------------------------------------------------------------------------- /docs/demos/ThemeProvider/style.ts: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | import { Space } from 'antd'; 3 | 4 | export const Container = styled(Space)` 5 | padding: 40px; 6 | background: ${(p) => p.theme.colorBgLayout}; 7 | `; 8 | -------------------------------------------------------------------------------- /docs/demos/api/createInstance/withContainer.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 100 3 | */ 4 | import { Button } from 'antd'; 5 | import { createInstance } from 'antd-style'; 6 | 7 | const { css, StyleProvider, createStyles } = createInstance({ 8 | key: 'test', 9 | container: document.body, 10 | }); 11 | 12 | const useStyles = createStyles({ 13 | text: css` 14 | color: blue; 15 | `, 16 | }); 17 | 18 | const Text = () => { 19 | const { styles } = useStyles(); 20 | return
我是文本
; 21 | }; 22 | 23 | export default () => { 24 | return ( 25 | 26 | 27 | 28 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /docs/demos/api/createInstance/withStyleProviderContainer.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 150 3 | */ 4 | 5 | import { Button, Divider } from 'antd'; 6 | import { createInstance } from 'antd-style'; 7 | 8 | const { css, StyleProvider, createStyles } = createInstance({ 9 | key: 'test', 10 | }); 11 | 12 | const useStyles = createStyles({ 13 | text: css` 14 | color: red; 15 | `, 16 | }); 17 | 18 | const Text = () => { 19 | const { styles } = useStyles(); 20 | return
我是文本
; 21 | }; 22 | 23 | export default () => { 24 | return ( 25 | <> 26 | 27 | 28 | 29 | 30 | 下方 style 插入在 head 31 | 32 | 33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /docs/demos/api/createStyles/Responsive.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | * title: 响应式断点 4 | * description: 不同断点下,背景色和文本内容不同 5 | */ 6 | import { createStyles, useResponsive } from 'antd-style'; 7 | 8 | const useStyles = createStyles(({ css, responsive }) => ({ 9 | container: css` 10 | height: 100px; 11 | display: flex; 12 | font-size: 24px; 13 | align-items: center; 14 | justify-content: center; 15 | 16 | background-color: lightskyblue; 17 | color: darkblue; 18 | 19 | ${responsive.tablet} { 20 | background: darkseagreen; 21 | color: darkgreen; 22 | } 23 | 24 | ${responsive.desktop} { 25 | background: darksalmon; 26 | color: saddlebrown; 27 | } 28 | 29 | ${responsive.mobile} { 30 | background: pink; 31 | color: deeppink; 32 | } 33 | `, 34 | })); 35 | 36 | const App = () => { 37 | const { styles } = useStyles(); 38 | 39 | const { laptop, desktop, mobile } = useResponsive(); 40 | return ( 41 |
42 | {mobile ? 'mobile' : desktop ? 'desktop' : laptop ? 'laptop' : 'tablet'} 43 |
44 | ); 45 | }; 46 | 47 | export default App; 48 | -------------------------------------------------------------------------------- /docs/demos/api/createStyles/default.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * inherit: true 3 | * defaultShowCode: true 4 | */ 5 | import { SmileOutlined } from '@ant-design/icons'; 6 | import { Button, Space } from 'antd'; 7 | import { createStyles } from 'antd-style'; 8 | 9 | const useStyles = createStyles(({ token, css, cx }) => { 10 | const commonCard = css` 11 | border-radius: ${token.borderRadiusLG}px; 12 | padding: ${token.paddingLG}px; 13 | `; 14 | 15 | return { 16 | container: css` 17 | background-color: ${token.colorBgLayout}; 18 | padding: 24px; 19 | `, 20 | 21 | defaultCard: css` 22 | ${commonCard}; 23 | background: ${token.colorBgContainer}; 24 | color: ${token.colorText}; 25 | `, 26 | 27 | primaryCard: cx( 28 | commonCard, 29 | css` 30 | background: ${token.colorPrimary}; 31 | color: ${token.colorTextLightSolid}; 32 | `, 33 | ), 34 | }; 35 | }); 36 | 37 | const App = () => { 38 | const { styles } = useStyles(); 39 | 40 | return ( 41 |
42 | 43 | 44 |
51 | ); 52 | }; 53 | 54 | export default App; 55 | -------------------------------------------------------------------------------- /docs/demos/api/createStyles/label.tsx: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles( 4 | ({ css }) => ({ 5 | text: css` 6 | color: blue; 7 | `, 8 | }), 9 | { label: 'with-label' }, 10 | ); 11 | 12 | export default () => { 13 | const { styles } = useStyles(); 14 | return
赋予 with-label 标签
; 15 | }; 16 | -------------------------------------------------------------------------------- /docs/demos/api/createStyles/with-antd-cp.tsx: -------------------------------------------------------------------------------- 1 | import { SmileOutlined } from '@ant-design/icons'; 2 | import { Button, ConfigProvider } from 'antd'; 3 | import { createStyles } from 'antd-style'; 4 | 5 | const useStyles = createStyles(({ css, prefixCls, iconPrefixCls }) => ({ 6 | button: css` 7 | &.${prefixCls}-btn { 8 | background: lightsteelblue; 9 | border: none; 10 | color: royalblue; 11 | } 12 | 13 | .${iconPrefixCls} { 14 | color: darkblue; 15 | } 16 | `, 17 | })); 18 | 19 | const App = () => { 20 | const { styles } = useStyles(); 21 | 22 | return ( 23 | 26 | ); 27 | }; 28 | export default () => ( 29 | 30 | 31 | 32 | ); 33 | -------------------------------------------------------------------------------- /docs/demos/api/useResponsive/Demo/DisplayTag.tsx: -------------------------------------------------------------------------------- 1 | import { Tag } from 'antd'; 2 | import { FC } from 'react'; 3 | 4 | interface DisplayTagProps { 5 | active?: boolean; 6 | color: 'blue' | 'green'; 7 | title: string; 8 | value: string; 9 | } 10 | 11 | export const DisplayTag: FC = ({ active, color, title, value, ...props }) => { 12 | return ( 13 | 14 | {title}: {value} 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /docs/demos/api/useResponsive/custom.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | */ 4 | 5 | import { ThemeProvider } from 'antd-style'; 6 | import Demo from './Demo'; 7 | import { Container } from './style'; 8 | 9 | export default () => { 10 | return ( 11 | 12 | 21 | 22 | 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /docs/demos/api/useResponsive/default.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | */ 4 | 5 | import Demo from './Demo'; 6 | import { Container } from './style'; 7 | 8 | export default () => { 9 | return ( 10 | 11 | 12 | {/**/} 13 | {/**/} 14 | {/* */} 15 | {/**/} 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /docs/demos/api/useResponsive/style.ts: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | 3 | export const Container = styled.div` 4 | background: ${({ theme }) => theme.colorBgLayout}; 5 | padding: 24px; 6 | `; 7 | export const Label = styled.div` 8 | color: ${(p) => p.theme.colorTextPlaceholder}; 9 | `; 10 | -------------------------------------------------------------------------------- /docs/demos/api/useTheme.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 500 3 | */ 4 | import { App, Divider, Space } from 'antd'; 5 | import { ThemeProvider, useTheme } from 'antd-style'; 6 | 7 | const Demo = () => { 8 | const token = useTheme(); 9 | 10 | return ( 11 | 12 |
colorPrimary
13 | 21 |
29 | {token.colorPrimary} 30 | 31 |
colorPrimary
32 | 33 | ); 34 | }; 35 | 36 | export default () => { 37 | const token = useTheme(); 38 | return ( 39 |
40 | 41 | 42 |
43 | ThemeProvider & 暗色模式 44 |
45 | 46 |
47 |
48 |
49 |
50 | 51 |
ThemeProvider & token 值
52 | 53 | 54 | 55 | 56 |
未包裹,使用默认值
57 | 58 |
59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /docs/demos/cases/HeroButton/settings.ts: -------------------------------------------------------------------------------- 1 | export const transition = { 2 | type: 'spring', 3 | duration: 0.7, 4 | bounce: 0.2, 5 | }; 6 | -------------------------------------------------------------------------------- /docs/demos/cases/HeroButton/style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | export const useStyles = createStyles(({ css, token }) => { 4 | const blush = css` 5 | position: absolute; 6 | bottom: -15px; 7 | width: 100px; 8 | height: 30px; 9 | filter: blur(20px); 10 | `; 11 | 12 | return { 13 | container: css` 14 | position: relative; 15 | `, 16 | button: css` 17 | border: none; 18 | //background: #1677FF; 19 | //background: #f2056f; 20 | //background: ${token.purple}; 21 | &:hover { 22 | background: linear-gradient( 23 | 90deg, 24 | ${token.blue} 0%, 25 | ${token.geekblue} 30%, 26 | ${token.cyan} 70% 27 | ); 28 | } 29 | 30 | canvas { 31 | position: absolute; 32 | width: 100%; 33 | height: 100%; 34 | } 35 | `, 36 | pink: css` 37 | ${blush}; 38 | right: 20px; 39 | z-index: 10; 40 | background: ${token.cyan}; 41 | `, 42 | blue: css` 43 | ${blush}; 44 | right: 20px; 45 | z-index: 10; 46 | background: ${token.purple}; 47 | `, 48 | 49 | canvas: css` 50 | z-index: 20; 51 | position: absolute; 52 | top: -100px; 53 | bottom: -100px; 54 | left: -100px; 55 | right: -100px; 56 | width: calc(100% + 200px); 57 | pointer-events: none; 58 | `, 59 | }; 60 | }); 61 | -------------------------------------------------------------------------------- /docs/demos/cases/MacSelect/ScrollArrow/style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles, css } from 'antd-style'; 2 | 3 | export const useStyles = createStyles(({ token, cx }, prefixCls: string) => ({ 4 | container: cx( 5 | prefixCls, 6 | css` 7 | color: ${token.colorTextPlaceholder}; 8 | border-radius: 0; 9 | cursor: default; 10 | font-size: 12px; 11 | line-height: 1; 12 | height: 25px; 13 | user-select: none; 14 | position: absolute; 15 | z-index: 1; 16 | width: 100%; 17 | 18 | &::before { 19 | content: ''; 20 | display: block; 21 | width: 100%; 22 | height: 35px; 23 | position: absolute; 24 | left: 0; 25 | z-index: -1; 26 | pointer-events: none; 27 | } 28 | 29 | &[data-dir='up'] { 30 | top: 0; 31 | 32 | &::before { 33 | background: linear-gradient(to bottom, ${token.colorBgElevated} 50%, transparent); 34 | border-radius: 8px 8px 0 0; 35 | top: 1px; 36 | left: 1px; 37 | right: 1px; 38 | width: auto; 39 | } 40 | } 41 | 42 | &[data-dir='down'] { 43 | bottom: 0; 44 | 45 | &::before { 46 | background: linear-gradient(to top, ${token.colorBgElevated} 50%, transparent); 47 | border-radius: 0 0 8px 8px; 48 | top: -10px; 49 | left: 1px; 50 | right: 1px; 51 | width: auto; 52 | } 53 | } 54 | `, 55 | ), 56 | })); 57 | -------------------------------------------------------------------------------- /docs/demos/cases/MacSelect/Select/style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | export const useStyles = createStyles(({ css, cx, token }, prefixCls: string) => ({ 4 | container: cx( 5 | prefixCls, 6 | css` 7 | background: ${token.colorBgElevated}; 8 | font-size: ${token.fontSize}; 9 | border: 1px solid ${token.colorBorder}; 10 | box-shadow: ${token.boxShadowSecondary}; 11 | border-radius: 8px; 12 | box-sizing: border-box; 13 | overflow-y: auto; 14 | overscroll-behavior: contain; 15 | scrollbar-width: none; 16 | padding: 5px; 17 | outline: 0; 18 | user-select: none; 19 | width: 160px; 20 | 21 | &::-webkit-scrollbar { 22 | display: none; 23 | } 24 | `, 25 | ), 26 | button: cx( 27 | `${prefixCls}-button`, 28 | css` 29 | all: unset; 30 | font-size: ${token.fontSize}px; 31 | padding: 12px 10px; 32 | line-height: 1; 33 | background: ${token.colorBgContainer}; 34 | color: ${token.colorText}; 35 | border-radius: ${token.borderRadius}px; 36 | cursor: default; 37 | user-select: none; 38 | border: 1px solid ${token.colorBorder}; 39 | -webkit-tap-highlight-color: transparent; 40 | 41 | &:hover { 42 | background: ${token.colorPrimaryBg}; 43 | border-color: transparent; 44 | } 45 | 46 | &:focus-visible { 47 | border-color: ${token.colorPrimary}; 48 | box-shadow: 0 0 0 2px ${token.colorPrimaryBg}; 49 | } 50 | `, 51 | ), 52 | })); 53 | -------------------------------------------------------------------------------- /docs/demos/cases/MacSelect/SelectItem/index.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ForwardedRef, forwardRef } from 'react'; 2 | 3 | import { useStyles } from './style'; 4 | 5 | interface SelectItemProps { 6 | value: any; 7 | label: any; 8 | prefixCls?: string; 9 | isSelected?: boolean; 10 | isActive?: boolean; 11 | ref?: ForwardedRef; 12 | disabled?: boolean; 13 | } 14 | 15 | const SelectItem: FC = forwardRef( 16 | ({ value, label, prefixCls, isSelected, isActive, disabled, ...props }, ref) => { 17 | const { styles, cx } = useStyles({ prefixCls, selected: isSelected }); 18 | 19 | return ( 20 | 35 | ); 36 | }, 37 | ); 38 | 39 | export default SelectItem; 40 | -------------------------------------------------------------------------------- /docs/demos/cases/MacSelect/SelectItem/style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | export const useStyles = createStyles(({ css, cx, token }, prefixCls) => ({ 4 | item: cx( 5 | `${prefixCls}-item`, 6 | 7 | css` 8 | display: block; 9 | all: unset; 10 | width: 100%; 11 | padding: 12px 10px; 12 | border-radius: 5px; 13 | box-sizing: inherit; 14 | user-select: none; 15 | line-height: 1; 16 | scroll-margin: 50px; 17 | 18 | font-weight: normal; 19 | color: ${token.colorText}; 20 | background: transparent; 21 | &:hover { 22 | background: ${token.colorFillTertiary}; 23 | } 24 | `, 25 | ), 26 | selected: cx( 27 | `${prefixCls}-item-selected`, 28 | css` 29 | background: ${token.colorPrimaryBg}; 30 | font-weight: bold; 31 | &:hover { 32 | background: ${token.colorPrimaryBgHover}; 33 | } 34 | `, 35 | ), 36 | active: cx( 37 | `${prefixCls}-item-active`, 38 | css` 39 | background: ${token.colorFillTertiary}; 40 | `, 41 | ), 42 | })); 43 | -------------------------------------------------------------------------------- /docs/demos/cases/MacSelect/data.ts: -------------------------------------------------------------------------------- 1 | import { SelectProps } from 'antd'; 2 | 3 | export const fruits: SelectProps['options'] = [ 4 | { 5 | label: '🍒 樱桃', 6 | value: 'Cherry', 7 | }, 8 | { label: '🍓 草莓', value: 'Strawberry' }, 9 | { label: '🍇 葡萄', value: 'Grape' }, 10 | { label: '🍎 苹果', value: 'Apple' }, 11 | { label: '🍉 西瓜', value: 'Watermelon' }, 12 | { label: '🍑 桃子', value: 'Peach' }, 13 | { label: '🍊 橘子', value: 'Orange' }, 14 | { label: '🍋 柠檬', value: 'Lemon' }, 15 | { label: '🍍 菠萝', value: 'Pineapple' }, 16 | { label: '🍌 香蕉', value: 'Banana' }, 17 | { label: '🥑 鳄梨', value: 'Avocado' }, 18 | { label: '🍏 青苹果', value: 'Green Apple' }, 19 | { label: '🍈 甜瓜', value: 'Melon' }, 20 | { label: '🍐 梨', value: 'Pear' }, 21 | { label: '🥝 猕猴桃', value: 'Kiwifruit' }, 22 | { label: '🥭 芒果', value: 'Mango' }, 23 | { label: '🥥 椰子', value: 'Coconut' }, 24 | { label: '🍅 西红柿', value: 'Tomato' }, 25 | { label: '🫐 蓝莓', value: 'Blueberry' }, 26 | ]; 27 | -------------------------------------------------------------------------------- /docs/demos/cases/MacSelect/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | * title: MacOS 选择器 4 | * description: 演示使用 antd-style 如何实现一个适配 antd 主题风格的组件 5 | */ 6 | import { App, Divider, Select } from 'antd'; 7 | import { ThemeMode, ThemeProvider, useTheme } from 'antd-style'; 8 | import { Center, Flexbox } from 'react-layout-kit'; 9 | import { create } from 'zustand'; 10 | 11 | import MacSelect from './Select'; 12 | 13 | import { ThemeController } from '../../common/ThemeController'; 14 | 15 | import { fruits } from './data'; 16 | 17 | const useStore = create(() => 'auto'); 18 | const Demo = () => { 19 | const theme = useTheme(); 20 | return ( 21 |
22 | 28 | macOS: 29 | 30 | 31 | antd: 32 | { 40 | setSearchMode(false); 41 | }} 42 | /> 43 | 44 |
45 |
46 | ); 47 | }; 48 | 49 | export default HeaderSearch; 50 | -------------------------------------------------------------------------------- /docs/demos/migration/CSSinJSMode/style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | export default createStyles(({ token }) => ({ 4 | container: { 5 | background: token.colorBgLayout, 6 | height: 200, 7 | display: 'flex', 8 | alignItems: 'center', 9 | justifyContent: 'center', 10 | }, 11 | headerSearch: { 12 | display: 'inline-flex', 13 | alignItems: 'center', 14 | }, 15 | input: { 16 | width: '0', 17 | minWidth: '0', 18 | overflow: 'hidden', 19 | background: 'transparent', 20 | borderRadius: '0', 21 | transition: 'width 0.3s, margin-left 0.3s', 22 | input: { boxShadow: 'none !important' }, 23 | }, 24 | show: { width: '210px', marginLeft: '8px' }, 25 | })); 26 | -------------------------------------------------------------------------------- /docs/demos/migration/LessMode/index.module.less: -------------------------------------------------------------------------------- 1 | .container { 2 | background: #f5f5f5; 3 | height: 200px; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | } 8 | 9 | .headerSearch { 10 | display: inline-flex; 11 | align-items: center; 12 | 13 | .input { 14 | width: 0; 15 | min-width: 0; 16 | overflow: hidden; 17 | background: transparent; 18 | border-radius: 0; 19 | transition: width 0.3s, margin-left 0.3s; 20 | 21 | input { 22 | box-shadow: none !important; 23 | } 24 | 25 | &.show { 26 | width: 210px; 27 | margin-left: 8px; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/demos/migration/LessMode/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 200 3 | */ 4 | import { SearchOutlined } from '@ant-design/icons'; 5 | import { AutoComplete, Input, InputRef } from 'antd'; 6 | import classNames from 'classnames'; 7 | import { FC, useRef, useState } from 'react'; 8 | 9 | // @ts-ignore 10 | import styles from './index.module.less'; 11 | 12 | const HeaderSearch: FC = () => { 13 | const [searchMode, setSearchMode] = useState(false); 14 | 15 | const inputRef = useRef(null); 16 | 17 | const inputClass = classNames(styles.input, searchMode ? styles.show : ''); 18 | 19 | return ( 20 |
21 |
{ 24 | setSearchMode(true); 25 | inputRef.current?.focus(); 26 | }} 27 | > 28 | 34 | 35 | { 39 | setSearchMode(false); 40 | }} 41 | /> 42 | 43 |
44 |
45 | ); 46 | }; 47 | 48 | export default HeaderSearch; 49 | -------------------------------------------------------------------------------- /docs/demos/migration/ProComponentsStatic/CSSinJS.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | */ 4 | import styled from '@emotion/styled'; 5 | import { App } from 'antd'; 6 | import { ThemeProvider } from 'antd-style'; 7 | import { Flexbox } from 'react-layout-kit'; 8 | 9 | import Statistic from './CSSinJSComponent'; 10 | 11 | const Container = styled(Flexbox)` 12 | background: ${(p) => p.theme.colorBgLayout}; 13 | `; 14 | export default () => { 15 | return ( 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /docs/demos/migration/ProComponentsStatic/less.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * compact: true 3 | */ 4 | import { App, ConfigProvider, theme } from 'antd'; 5 | import { Flexbox } from 'react-layout-kit'; 6 | import Statistic from './LessComponent'; 7 | 8 | export default () => { 9 | return ( 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /docs/demos/styled/basic.tsx: -------------------------------------------------------------------------------- 1 | import DsAvatar from '../common/Typography/Avatar'; 2 | 3 | export default () => ( 4 |
5 | 6 |
7 | ); 8 | -------------------------------------------------------------------------------- /docs/demos/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.tsx", "**/*.ts"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "declaration": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "jsx": "react-jsx", 9 | "lib": ["DOM", "ESNext"], 10 | "baseUrl": ".", 11 | "paths": { 12 | "antd-style": ["../../es"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/demos/typings.d.ts: -------------------------------------------------------------------------------- 1 | import { Theme as AntdStyleTheme } from 'antd-style'; 2 | 3 | // 为 emotion 的 styled 注入 antd-style 的主题类型 4 | declare module '@emotion/react' { 5 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 6 | export interface Theme extends AntdStyleTheme {} 7 | } 8 | -------------------------------------------------------------------------------- /docs/guide/babel-plugin.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Babel Plugin 3 | order: 1 4 | group: Advanced Usage 5 | --- 6 | 7 | # Babel Plugin 8 | 9 | We provide a Babel plugin for antd-style to enhance the development experience. 10 | 11 | ```bash 12 | pnpm i -D babel-plugin-antd-style 13 | ``` 14 | 15 | ## Configuration 16 | 17 | `.babelrc` configuration: 18 | 19 | ```json 20 | { 21 | "plugins": ["antd-style"] 22 | } 23 | ``` 24 | 25 | umi/dumi configuration: 26 | 27 | ```js 28 | export default defineConfig({ 29 | extraBabelPlugins: [require.resolve('babel-plugin-antd-style')], 30 | }); 31 | ``` 32 | 33 | ## Features 34 | 35 | ### Support for className resolution 36 | 37 | After installing the Babel plugin, className will be resolved to the corresponding style file directory, effective only in development. 38 | 39 | ![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/243569986-46274fce-8568-4ae1-a309-2972cb926611.png) 40 | -------------------------------------------------------------------------------- /docs/guide/babel-plugin.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Babel 插件 3 | order: 1 4 | group: 进阶使用 5 | --- 6 | 7 | # Babel 插件 8 | 9 | 我们提供了 antd-style 的 Babel 插件,以提升研发体验。 10 | 11 | ```bash 12 | pnpm i -D babel-plugin-antd-style 13 | ``` 14 | 15 | ## 配置 16 | 17 | `.babelrc` 配置: 18 | 19 | ```json 20 | { 21 | "plugins": ["antd-style"] 22 | } 23 | ``` 24 | 25 | umi/dumi 配置: 26 | 27 | ```js 28 | export default defineConfig({ 29 | extraBabelPlugins: [require.resolve('babel-plugin-antd-style')], 30 | }); 31 | ``` 32 | 33 | ## 功能 34 | 35 | ### 支持 className 定位 36 | 37 | 安装 Babel 插件后,className 将会定位到对应的样式文件目录,仅 dev 生效。 38 | 39 | ![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/243569986-46274fce-8568-4ae1-a309-2972cb926611.png) 40 | -------------------------------------------------------------------------------- /docs/guide/cssinjs-compiler-difference.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 Compilation Differences Between CSS-in-JS and Less 3 | order: 10 4 | group: 5 | title: Migrating from Less 6 | order: 4 7 | --- 8 | 9 | # Compilation Differences Between CSS-in-JS and Less 10 | 11 | TODO: This document is still being written. Pull requests are welcome. 12 | -------------------------------------------------------------------------------- /docs/guide/cssinjs-compiler-difference.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 🚧 CSSinJS 与 Less 的编译差异 3 | order: 10 4 | group: 5 | title: 从 Less 迁移 6 | order: 4 7 | --- 8 | 9 | # CSSinJS 与 Less 编译差异 10 | 11 | TODO: 本文档还在编写中,欢迎 PR。 12 | -------------------------------------------------------------------------------- /docs/guide/demos/benchmark/dynamic-value.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * iframe: 600 3 | */ 4 | export default () => ( 5 |