From 755f354b52cbf0cdf448c6183b2ce432b62ef465 Mon Sep 17 00:00:00 2001 From: afc163 Date: Fri, 26 Jun 2026 17:05:47 +0800 Subject: [PATCH 01/23] chore: standardize repository config --- .dumirc.ts | 16 +- .github/FUNDING.yml | 17 +- .github/dependabot.yml | 49 +---- .github/workflows/codeql.yml | 43 ++++ .github/workflows/main.yml | 6 - .github/workflows/react-component-ci.yml | 12 ++ .github/workflows/react-doctor.yml | 27 +++ .github/workflows/surge-preview.yml | 39 ++++ .gitignore | 12 +- README.md | 243 ++++++++--------------- docs/examples/animated.tsx | 2 +- docs/examples/basic.tsx | 2 +- docs/examples/dynamic-extra.tsx | 26 ++- docs/examples/editable.tsx | 2 +- docs/examples/extra.tsx | 4 +- docs/examples/indicator.tsx | 4 +- docs/examples/mix.tsx | 4 +- docs/examples/overflow.tsx | 4 +- docs/examples/position.tsx | 2 +- docs/examples/renderTabBar-dragable.tsx | 4 +- docs/examples/renderTabBar-sticky.tsx | 2 +- docs/index.md | 4 +- package.json | 32 +-- tsconfig.json | 32 +-- vercel.json | 6 + 25 files changed, 300 insertions(+), 294 deletions(-) create mode 100644 .github/workflows/codeql.yml delete mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/react-component-ci.yml create mode 100644 .github/workflows/react-doctor.yml create mode 100644 .github/workflows/surge-preview.yml create mode 100644 vercel.json diff --git a/.dumirc.ts b/.dumirc.ts index d31eaee7..40f97753 100644 --- a/.dumirc.ts +++ b/.dumirc.ts @@ -1,8 +1,22 @@ import { defineConfig } from 'dumi'; +import path from 'path'; + +const basePath = process.env.GH_PAGES ? '/tabs/' : '/'; +const publicPath = process.env.GH_PAGES ? '/tabs/' : '/'; export default defineConfig({ + alias: { + '@rc-component/tabs$': path.resolve('src'), + '@rc-component/tabs/es': path.resolve('src'), + '@rc-component/tabs/assets': path.resolve('assets'), + }, + mfsu: false, + favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'], themeConfig: { name: 'Tabs', + logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', }, - mfsu: false, + outputPath: 'docs-dist', + base: basePath, + publicPath, }); diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 33b1999c..758659af 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,15 +1,2 @@ -# These are supported funding model platforms - -github: ant-design # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: ant-design # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -polar: # Replace with a single Polar username -buy_me_a_coffee: # Replace with a single Buy Me a Coffee username -thanks_dev: # Replace with a single thanks.dev username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +github: ant-design +open_collective: ant-design diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 94da832d..07575c02 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,45 +1,8 @@ version: 2 updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - time: "21:00" - open-pull-requests-limit: 10 - ignore: - - dependency-name: np - versions: - - 7.2.0 - - 7.3.0 - - 7.4.0 - - dependency-name: "@types/jest" - versions: - - 26.0.20 - - 26.0.21 - - 26.0.22 - - dependency-name: react-dnd - versions: - - 11.1.3 - - 13.0.0 - - 13.1.0 - - 13.1.1 - - 14.0.1 - - dependency-name: "@types/react-dom" - versions: - - 17.0.0 - - 17.0.1 - - 17.0.2 - - dependency-name: "@types/react" - versions: - - 17.0.0 - - 17.0.1 - - 17.0.2 - - 17.0.3 - - dependency-name: react-dnd-html5-backend - versions: - - 11.1.3 - - 12.1.0 - - 12.1.1 - - dependency-name: less - versions: - - 4.1.0 + - package-ecosystem: npm + directory: '/' + schedule: + interval: daily + time: '21:00' + open-pull-requests-limit: 10 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..23f424a8 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,43 @@ +name: 'CodeQL' + +on: + push: + branches: ['master'] + pull_request: + branches: ['master'] + schedule: + - cron: '17 10 * * 1' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [javascript] + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e + with: + category: '/language:${{ matrix.language }}' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 5735e2d2..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: ✅ test -on: [push, pull_request] -jobs: - test: - uses: react-component/rc-test/.github/workflows/test.yml@main - secrets: inherit \ No newline at end of file diff --git a/.github/workflows/react-component-ci.yml b/.github/workflows/react-component-ci.yml new file mode 100644 index 00000000..1ed64209 --- /dev/null +++ b/.github/workflows/react-component-ci.yml @@ -0,0 +1,12 @@ +name: ✅ test +on: + push: + branches: [master] + pull_request: + branches: [master] +permissions: + contents: read +jobs: + test: + uses: react-component/rc-test/.github/workflows/test-utoo.yml@main + secrets: inherit diff --git a/.github/workflows/react-doctor.yml b/.github/workflows/react-doctor.yml new file mode 100644 index 00000000..f68281c8 --- /dev/null +++ b/.github/workflows/react-doctor.yml @@ -0,0 +1,27 @@ +name: React Doctor + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + push: + branches: [master] + +permissions: + contents: read + pull-requests: write + issues: write + statuses: write + +concurrency: + group: react-doctor-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + react-doctor: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + with: + fetch-depth: 0 + persist-credentials: false + - uses: millionco/react-doctor@0b4f4f4bd248a154e64eb508a48347f71154b3f3 diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml new file mode 100644 index 00000000..1b29a17b --- /dev/null +++ b/.github/workflows/surge-preview.yml @@ -0,0 +1,39 @@ +name: Surge Preview + +on: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + checks: write + statuses: write + +jobs: + preview: + runs-on: ubuntu-latest + env: + SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} + PREVIEW: true + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + with: + persist-credentials: false + - uses: afc163/surge-preview@bf90a5a86111f6311ca42f0a5a0f80fb0fb03cec + if: ${{ env.SURGE_TOKEN != '' }} + with: + surge_token: ${{ env.SURGE_TOKEN }} + github_token: ${{ secrets.GITHUB_TOKEN }} + dist: docs-dist + failOnError: true + setCommitStatus: true + build: | + npm install + npm run build + - name: Skip Surge preview + if: ${{ env.SURGE_TOKEN == '' }} + run: echo "SURGE_TOKEN is not configured; skip Surge preview." diff --git a/.gitignore b/.gitignore index 0d12566f..bcd4e0c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,7 @@ -.storybook *.iml *.log *.log.* .idea/ -.vscode .ipr .iws *~ @@ -28,17 +26,21 @@ assets/**/*.css build lib es -coverage +/coverage yarn.lock package-lock.json pnpm-lock.yaml +.doc +docs-dist +.vercel +.storybook # umi .umi .umi-production .umi-test .env.local -.dumi +.dumi/ bun.lockb -bun.lock \ No newline at end of file +bun.lock diff --git a/README.md b/README.md index 76ab4366..53919f5a 100644 --- a/README.md +++ b/README.md @@ -1,185 +1,116 @@ -# rc-tabs - ---- - -React Tabs component. - -[![NPM version][npm-image]][npm-url] [![dumi](https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square)](https://github.com/umijs/dumi) [![build status][github-actions-image]][github-actions-url] [![Test coverage][codecov-image]][codecov-url] [![npm download][download-image]][download-url] [![bundle size][bundlephobia-image]][bundlephobia-url] - -[npm-image]: http://img.shields.io/npm/v/rc-tabs.svg?style=flat-square -[npm-url]: http://npmjs.org/package/rc-tabs -[github-actions-image]: https://github.com/react-component/tabs/workflows/CI/badge.svg -[github-actions-url]: https://github.com/react-component/tabs/actions -[codecov-image]: https://img.shields.io/codecov/c/github/react-component/tabs/master.svg?style=flat-square -[codecov-url]: https://codecov.io/gh/react-component/tabs/branch/master -[download-image]: https://img.shields.io/npm/dm/rc-tabs.svg?style=flat-square -[download-url]: https://npmjs.org/package/rc-tabs -[bundlephobia-url]: https://bundlephobia.com/result?p=rc-tabs -[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/rc-tabs - -## Screenshot - - - -## Example - -http://localhost:8000/examples - -online example: https://tabs.react-component.now.sh/ - -## install - -[![rc-tabs](https://nodei.co/npm/rc-tabs.png)](https://npmjs.org/package/rc-tabs) - -## Feature - -### Keyboard - -- left and up: tabs to previous tab -- right and down: tabs to next tab +
+

@rc-component/tabs

+

📑 Flexible React tabs with overflow, editable items, custom tab bars, and accessible panels.

+

+ Ant Design +

+

Part of the Ant Design ecosystem.

+ +

+ npm version + npm downloads + CI + Codecov + bundle size + dumi +

+
+ +## Highlights + +- Supports top, bottom, left, and right tab positions with RTL layouts. +- Handles overflow with a dropdown operation menu. +- Supports editable tabs, extra tab bar content, indicators, and custom tab bars. +- Provides semantic `classNames` and `styles` slots for panel and navigation customization. + +## Install + +```bash +npm install @rc-component/tabs +``` ## Usage -```tsx | pure -import Tabs from 'rc-tabs'; -import ReactDom from 'react-dom'; - -const callback = key => { - console.log(key); -}; +```tsx pure +import Tabs from '@rc-component/tabs'; +import '@rc-component/tabs/assets/index.css'; const items = [ - { - key: '1', - label: 'Google', - children: ( -
-

Lorem Ipsum is simply dummy text of the printing and typesetting

-
- ), - }, - { - key: '2', - label:

Amazon

, - children: - 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...', - disabled: true, - }, - { - key: '3', - label:

Twitter

, - children: ( -
- "There is no one who loves pain itself, who seeks after it and wants to have it, simply - because it is pain..." -
- ), - }, + { key: 'overview', label: 'Overview', children: 'Overview content' }, + { key: 'settings', label: 'Settings', children: 'Settings content' }, ]; -ReactDom.render( - , - root, -); +export default () => ; ``` +Online preview: https://tabs.react-component.vercel.app/ + ## API ### Tabs -| name | type | default | description | -| --- | --- | --- | --- | -| prefixCls | string | `'rc-tabs'` | prefix class name, use to custom style | -| className | string | - | to define a class name for an element | -| style | CSS properties | - | object with css properties for styling | -| items | TabItem[] | [] | configure tab content | -| id | string | - | unique identifier | -| defaultActiveKey | string | - | initial active tabPanel's key if activeKey is absent | -| activeKey | string | - | current active tabPanel's key | -| direction | `'ltr' or 'rtl'` | `'ltr'` | Layout direction of tabs component | -| animated | boolean \| { inkBar: boolean, tabPane: boolean } | `{ inkBar: true, tabPane: false }` | config animation | -| renderTabBar | (props, TabBarComponent) => ReactElement | - | How to render tab bar | -| tabBarExtraContent | ReactNode \| `{ left: ReactNode, right: ReactNode }` | - | config extra content | -| tabBarGutter | number | 0 | config tab bar gutter | -| tabBarPosition | `'left' \| 'right' \| 'top' \| 'bottom'` | `'top'` | tab nav 's position | -| tabBarStyle | style | - | tab nav style | -| tabPosition | `'left' or 'right' or 'top' or 'bottom'` | `'top'` | tab nav 's position | -| destroyOnHidden | boolean | false | whether destroy inactive TabPane when change tab | -| onChange | (key) => void | - | called when tabPanel is changed | -| onTabClick | (key) => void | - | called when tab click | -| onTabScroll | ({ direction }) => void | - | called when tab scroll | -| editable | { onEdit(type: 'add' \| 'remove', info: { key, event }), showAdd: boolean, removeIcon: ReactNode, addIcon: ReactNode } | - | config tab editable | -| locale | { dropdownAriaLabel: string, removeAriaLabel: string, addAriaLabel: string } | - | Accessibility locale help text | -| moreIcon | ReactNode | - | collapse icon | - -### TabItem - -| name | type | default | description | +| Name | Type | Default | Description | | --- | --- | --- | --- | -| key | string | - | corresponding to activeKey, should be unique | -| label | string | - | TabPane's head display text | -| tab | ReactNode | - | current tab's title corresponding to current tabPane | -| className | string | - | to define a class name for an element | -| style | CSS properties | - | object with css properties for styling | -| disabled | boolean | false | set TabPane disabled | -| children | ReactNode | - | TabPane's head display content | -| forceRender | boolean | false | forced render of content in tabs, not lazy render after clicking on tabs | -| closable | boolean | false | closable feature of tab item | -| closeIcon | ReactNode | - | Config close icon | -| prefixCls | string | `'rc-tabs-tab'` | prefix class name, use to custom style | -| id | string | - | unique identifier | -| animated | boolean \| { inkBar: boolean, tabPane: boolean } | `{ inkBar: true, tabPane: false }` | config animation | -| destroyOnHidden | boolean | false | whether destroy inactive TabPane when change tab | -| active | boolean | false | active feature of tab item | -| tabKey | string | - | key linked to tab | - -### TabPane(support in older versions) - -| name | type | default | description | +| `activeKey` | string | - | Controlled active tab key. | +| `animated` | boolean \| AnimatedConfig | `{ inkBar: true, tabPane: false }` | Animation config. | +| `className` | string | - | Additional class name. | +| `classNames` | `Partial>` | - | Semantic class names. | +| `defaultActiveKey` | string | - | Initial active tab key. | +| `destroyOnHidden` | boolean | false | Destroy inactive tab panels. | +| `direction` | `'ltr' \| 'rtl'` | `'ltr'` | Layout direction. | +| `editable` | EditableConfig | - | Editable tab configuration. | +| `getPopupContainer` | `(node: HTMLElement) => HTMLElement` | - | Popup container resolver. | +| `id` | string | - | Root id. | +| `indicator` | `{ size?: GetIndicatorSize; align?: 'start' \| 'center' \| 'end' }` | - | Indicator size and alignment. | +| `items` | Tab[] | [] | Tab items. | +| `locale` | TabsLocale | - | Accessibility locale text. | +| `more` | MoreProps | - | Overflow dropdown config. | +| `onChange` | `(activeKey: string) => void` | - | Triggered when active tab changes. | +| `onTabClick` | `(activeKey, event) => void` | - | Triggered when a tab is clicked. | +| `onTabScroll` | `({ direction }) => void` | - | Triggered when tab navigation scrolls. | +| `prefixCls` | string | `'rc-tabs'` | Prefix class name. | +| `renderTabBar` | RenderTabBar | - | Custom tab bar renderer. | +| `style` | React.CSSProperties | - | Root style. | +| `styles` | `Partial>` | - | Semantic styles. | +| `tabBarExtraContent` | React.ReactNode \| TabBarExtraMap | - | Extra content beside the tab bar. | +| `tabBarGutter` | number | 0 | Gap between tabs. | +| `tabBarStyle` | React.CSSProperties | - | Tab bar style. | +| `tabPosition` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'top'` | Tab position. | + +### Tab + +| Name | Type | Default | Description | | --- | --- | --- | --- | -| destroyOnHidden | boolean | false | whether destroy inactive TabPane when change tab | -| key | string | - | corresponding to activeKey, should be unique | -| forceRender | boolean | false | forced render of content in tabs, not lazy render after clicking on tabs | -| tab | ReactNode | - | current tab's title corresponding to current tabPane | -| closeIcon | ReactNode | - | Config close icon | +| `children` | React.ReactNode | - | Tab panel content. | +| `className` | string | - | Panel class name. | +| `closable` | boolean | - | Whether the tab can be closed in editable mode. | +| `closeIcon` | React.ReactNode | - | Custom close icon. | +| `destroyOnHidden` | boolean | false | Destroy inactive panel. | +| `disabled` | boolean | false | Disable the tab. | +| `forceRender` | boolean | false | Render panel before it becomes active. | +| `key` | string | - | Required unique tab key. | +| `label` | React.ReactNode | - | Tab label. | +| `style` | React.CSSProperties | - | Panel style. | ## Development -``` +```bash npm install npm start -``` - -## Test Case - -``` npm test -npm run chrome-test +npm run tsc +npm run compile +npm run build ``` -## Coverage +## Release -``` -npm run coverage +```bash +npm run prepublishOnly ``` -open coverage/ dir +`prepublishOnly` builds the package with Father and publishes through `rc-np`. Run `npm run gh-pages` to deploy the dumi site. ## License -rc-tabs is released under the MIT license. - -## FAQ - -### Responsive Tabs - -There are 3 cases when handling responsive tabs: ![image](https://user-images.githubusercontent.com/27722486/156315099-7e6eda9d-ab77-4b16-9b49-1727c5ec8b26.png) - -We get hidden tabs through [useVisibleRange.ts](https://github.com/react-component/tabs/blob/master/src/hooks/useVisibleRange.ts). If enconter the third case, in order to make tabs responsive, some tabs should be hidden. So we minus `addSize` when calculating `basicSize` manully, even though there's no addNode in container. In this way, case 3 turns to case 2, tabs become stable again. +@rc-component/tabs is released under the MIT license. diff --git a/docs/examples/animated.tsx b/docs/examples/animated.tsx index f6118acb..be380713 100644 --- a/docs/examples/animated.tsx +++ b/docs/examples/animated.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import Tabs from '../../src'; +import Tabs from '@rc-component/tabs'; import type { CSSMotionProps } from '@rc-component/motion'; import '../../assets/index.less'; import './animated.less'; diff --git a/docs/examples/basic.tsx b/docs/examples/basic.tsx index 80546a2c..12328d58 100644 --- a/docs/examples/basic.tsx +++ b/docs/examples/basic.tsx @@ -1,6 +1,6 @@ import React from 'react'; import '../../assets/index.less'; -import Tabs from '../../src'; +import Tabs from '@rc-component/tabs'; export default () => { const [destroy, setDestroy] = React.useState(false); diff --git a/docs/examples/dynamic-extra.tsx b/docs/examples/dynamic-extra.tsx index 9db9721d..abc8c13b 100644 --- a/docs/examples/dynamic-extra.tsx +++ b/docs/examples/dynamic-extra.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Tabs from '../../src'; -import type { TabsProps } from '../../src'; +import Tabs from '@rc-component/tabs'; +import type { TabsProps } from '@rc-component/tabs'; import '../../assets/index.less'; const items: TabsProps['items'] = []; @@ -16,22 +16,20 @@ export default () => { const extra = React.useMemo(() => { if (key === '0') { - return ( -
额外内容
- ) - } - return null - }, [key]) + return
额外内容
; + } + return null; + }, [key]); return (
- setKey(curKey)} - tabBarExtraContent={extra} - defaultActiveKey="8" - items={items} + onChange={curKey => setKey(curKey)} + tabBarExtraContent={extra} + defaultActiveKey="8" + items={items} />
); -}; \ No newline at end of file +}; diff --git a/docs/examples/editable.tsx b/docs/examples/editable.tsx index 409e0130..63efb3cf 100644 --- a/docs/examples/editable.tsx +++ b/docs/examples/editable.tsx @@ -1,5 +1,5 @@ import React, { useRef } from 'react'; -import Tabs from '../../src'; +import Tabs from '@rc-component/tabs'; import '../../assets/index.less'; export default () => { diff --git a/docs/examples/extra.tsx b/docs/examples/extra.tsx index 143fe53a..77890baa 100644 --- a/docs/examples/extra.tsx +++ b/docs/examples/extra.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Tabs from '../../src'; -import type { TabsProps } from '../../src'; +import Tabs from '@rc-component/tabs'; +import type { TabsProps } from '@rc-component/tabs'; import '../../assets/index.less'; const items: TabsProps['items'] = []; diff --git a/docs/examples/indicator.tsx b/docs/examples/indicator.tsx index 90642451..d4d95131 100644 --- a/docs/examples/indicator.tsx +++ b/docs/examples/indicator.tsx @@ -1,7 +1,7 @@ import React from 'react'; import '../../assets/index.less'; -import type { TabsProps } from '../../src'; -import Tabs from '../../src'; +import type { TabsProps } from '@rc-component/tabs'; +import Tabs from '@rc-component/tabs'; const items: TabsProps['items'] = [ { diff --git a/docs/examples/mix.tsx b/docs/examples/mix.tsx index 1621db20..d066d781 100644 --- a/docs/examples/mix.tsx +++ b/docs/examples/mix.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Tabs from '../../src'; -import type { TabsProps } from '../../src'; +import Tabs from '@rc-component/tabs'; +import type { TabsProps } from '@rc-component/tabs'; import '../../assets/index.less'; function getTabPanes(count = 50) { diff --git a/docs/examples/overflow.tsx b/docs/examples/overflow.tsx index b1b271f2..4ed9e71f 100644 --- a/docs/examples/overflow.tsx +++ b/docs/examples/overflow.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Tabs from '../../src'; -import type { TabsProps } from '../../src'; +import Tabs from '@rc-component/tabs'; +import type { TabsProps } from '@rc-component/tabs'; import '../../assets/index.less'; const items: TabsProps['items'] = []; diff --git a/docs/examples/position.tsx b/docs/examples/position.tsx index f49d7b50..d1d070ad 100644 --- a/docs/examples/position.tsx +++ b/docs/examples/position.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import Tabs from '../../src'; +import Tabs from '@rc-component/tabs'; import '../../assets/index.less'; export default () => { diff --git a/docs/examples/renderTabBar-dragable.tsx b/docs/examples/renderTabBar-dragable.tsx index 9d4a38f5..5f526b8b 100644 --- a/docs/examples/renderTabBar-dragable.tsx +++ b/docs/examples/renderTabBar-dragable.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { DndProvider, DragSource, DropTarget } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; -import Tabs from '../../src'; -import type { TabsProps } from '../../src'; +import Tabs from '@rc-component/tabs'; +import type { TabsProps } from '@rc-component/tabs'; import '../../assets/index.less'; // Drag & Drop node diff --git a/docs/examples/renderTabBar-sticky.tsx b/docs/examples/renderTabBar-sticky.tsx index bd70e7a0..9a9da6f5 100644 --- a/docs/examples/renderTabBar-sticky.tsx +++ b/docs/examples/renderTabBar-sticky.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { StickyContainer, Sticky } from 'react-sticky'; -import Tabs from '../../src'; +import Tabs from '@rc-component/tabs'; import '../../assets/index.less'; const renderTabBar = (props, DefaultTabBar) => ( diff --git a/docs/index.md b/docs/index.md index eea4076d..ee9df64b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,5 @@ --- -title: rc-tabs +title: '@rc-component/tabs' --- - \ No newline at end of file + diff --git a/package.json b/package.json index 346b949c..345820cf 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "@rc-component/tabs", "version": "1.11.0", - "description": "tabs ui component for react", + "description": "Tabs UI component for React", "keywords": [ "react", "react-component", "react-tabs" ], - "homepage": "http://github.com/react-component/tabs", + "homepage": "https://react-component.github.io/tabs", "bugs": { "url": "http://github.com/react-component/tabs/issues" }, @@ -20,22 +20,24 @@ "main": "./lib/index", "module": "./es/index", "files": [ + "assets/*.css", "lib", - "es", - "assets/index.css" + "es" ], "scripts": { - "build": "dumi build", + "build": "npm run compile && npm run docs:build", "compile": "father build && npm run compile:style", "compile:style": "lessc --js assets/index.less assets/index.css", - "coverage": "father test --coverage", - "docs:deploy": "gh-pages -d dist", + "coverage": "rc-test --coverage", + "docs:build": "dumi build", + "docs:deploy": "gh-pages -d docs-dist", + "gh-pages": "cross-env GH_PAGES=1 npm run compile && npm run docs:build && npm run docs:deploy", "lint": "eslint src/ docs/examples/ --ext .tsx,.ts,.jsx,.js", - "now-build": "npm run build", - "prepublishOnly": "npm run lint && npm run test && npm run compile && rc-np", + "prepublishOnly": "npm run compile && rc-np", + "prettier": "prettier --write --ignore-unknown .", "start": "dumi dev", "test": "rc-test", - "prepare": "husky && dumi setup" + "tsc": "tsc --noEmit" }, "dependencies": { "@rc-component/dropdown": "~1.0.0", @@ -73,16 +75,16 @@ "react-dnd-html5-backend": "^10.0.0", "react-dom": "^18.0.0", "react-sticky": "^6.0.3", - "typescript": "^5.3.2" + "typescript": "^5.3.2", + "cross-env": "^7.0.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" }, - "lint-staged": { - "*": "prettier --write --ignore-unknown" - }, "engines": { "node": ">=8.x" - } + }, + "types": "./lib/index.d.ts", + "style": "./assets/index.css" } diff --git a/tsconfig.json b/tsconfig.json index 7a55add9..cb5d1b5d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,32 +3,20 @@ "target": "esnext", "moduleResolution": "node", "baseUrl": "./", - "lib": [ - "dom", - "es2017" - ], + "lib": ["dom", "es2017"], "jsx": "react", "declaration": true, "skipLibCheck": true, "esModuleInterop": true, "paths": { - "@/*": [ - "src/*" - ], - "@@/*": [ - ".dumi/tmp/*" - ], - "rc-tabs": [ - "src/" - ], - "@rc-component/tabs": [ - "src/" - ] + "@/*": ["src/*"], + "@@/*": [".dumi/tmp/*"], + "@rc-component/tabs": ["src/index.ts"], + "@rc-component/tabs/es": ["src"], + "@rc-component/tabs/es/*": ["src/*"], + "@rc-component/tabs/assets/*": ["assets/*"] } }, - "include": [ - ".dumirc.ts", - "**/*.ts", - "**/*.tsx" - ] -} \ No newline at end of file + "include": [".dumirc.ts", "src", "tests", "docs/examples"], + "exclude": ["docs-dist", "lib", "es"] +} diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..5f9139ef --- /dev/null +++ b/vercel.json @@ -0,0 +1,6 @@ +{ + "framework": "umijs", + "installCommand": "npm install", + "buildCommand": "npm run build", + "outputDirectory": "docs-dist" +} From 73933f7d0ee1cf26c559915bb0c0651c952fd197 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 01:27:33 +0800 Subject: [PATCH 02/23] chore: address AI review feedback --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 345820cf..cd8187b5 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "coverage": "rc-test --coverage", "docs:build": "dumi build", "docs:deploy": "gh-pages -d docs-dist", - "gh-pages": "cross-env GH_PAGES=1 npm run compile && npm run docs:build && npm run docs:deploy", + "gh-pages": "npm run compile && cross-env GH_PAGES=1 npm run docs:build && npm run docs:deploy", "lint": "eslint src/ docs/examples/ --ext .tsx,.ts,.jsx,.js", "prepublishOnly": "npm run compile && rc-np", "prettier": "prettier --write --ignore-unknown .", From 342574037684f57548a5488d5aa4e9637119217f Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 01:56:50 +0800 Subject: [PATCH 03/23] docs: standardize README release details --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 53919f5a..acd7763f 100644 --- a/README.md +++ b/README.md @@ -109,8 +109,8 @@ npm run build npm run prepublishOnly ``` -`prepublishOnly` builds the package with Father and publishes through `rc-np`. Run `npm run gh-pages` to deploy the dumi site. +The release flow is handled by `@rc-component/np` through the `rc-np` command after the package build. ## License -@rc-component/tabs is released under the MIT license. +@rc-component/tabs is released under the [MIT](./LICENSE.md) license. From 021e219423370f7e23802bda70dbd6ffbffc47bd Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 02:13:59 +0800 Subject: [PATCH 04/23] ci: make surge preview non-blocking --- .github/workflows/surge-preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml index 1b29a17b..ad8683da 100644 --- a/.github/workflows/surge-preview.yml +++ b/.github/workflows/surge-preview.yml @@ -29,7 +29,7 @@ jobs: surge_token: ${{ env.SURGE_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} dist: docs-dist - failOnError: true + failOnError: false setCommitStatus: true build: | npm install From 5498027377354a0f448b10603a24dbd39d474741 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 02:25:43 +0800 Subject: [PATCH 05/23] ci: keep surge preview as fallback --- .github/workflows/surge-preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml index ad8683da..70768bf2 100644 --- a/.github/workflows/surge-preview.yml +++ b/.github/workflows/surge-preview.yml @@ -30,7 +30,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} dist: docs-dist failOnError: false - setCommitStatus: true + setCommitStatus: false build: | npm install npm run build From 5ddff1935d770b7e9a0e584dd803e863f7f12d17 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 13:04:04 +0800 Subject: [PATCH 06/23] docs: refine README usage and ecosystem note --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index acd7763f..825c590b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,7 @@

@rc-component/tabs

+

Part of the Ant Design ecosystem.

📑 Flexible React tabs with overflow, editable items, custom tab bars, and accessible panels.

-

- Ant Design -

-

Part of the Ant Design ecosystem.

npm version @@ -16,6 +13,7 @@

+ ## Highlights - Supports top, bottom, left, and right tab positions with RTL layouts. From 8db82aba16d5b4d1e495cc3c05620990e6190096 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 13:22:19 +0800 Subject: [PATCH 07/23] ci: isolate surge preview token --- .github/workflows/surge-preview.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml index 70768bf2..faf6b8bd 100644 --- a/.github/workflows/surge-preview.yml +++ b/.github/workflows/surge-preview.yml @@ -17,23 +17,26 @@ jobs: preview: runs-on: ubuntu-latest env: - SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} PREVIEW: true steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with: persist-credentials: false + - name: Build preview + if: ${{ secrets.SURGE_TOKEN != '' }} + run: | + npm install + npm run build - uses: afc163/surge-preview@bf90a5a86111f6311ca42f0a5a0f80fb0fb03cec - if: ${{ env.SURGE_TOKEN != '' }} + if: ${{ secrets.SURGE_TOKEN != '' }} + env: + SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} with: surge_token: ${{ env.SURGE_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} dist: docs-dist failOnError: false setCommitStatus: false - build: | - npm install - npm run build - name: Skip Surge preview - if: ${{ env.SURGE_TOKEN == '' }} + if: ${{ secrets.SURGE_TOKEN == '' }} run: echo "SURGE_TOKEN is not configured; skip Surge preview." From 07727149fea5f937a6e88930be2517cf423afc82 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 22:20:21 +0800 Subject: [PATCH 08/23] docs: add Chinese README --- README.md | 2 + README.zh-CN.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 README.zh-CN.md diff --git a/README.md b/README.md index 825c590b..b2ce58e0 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@

+

English | 简体中文

+ ## Highlights diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 00000000..2c653445 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,116 @@ +
+

@rc-component/tabs

+

Ant Design 生态的一部分。

+

🗂️ React 标签页组件,支持可编辑标签、溢出滚动和自定义渲染。

+ +

+ npm version + npm downloads + CI + Codecov + bundle size + dumi +

+
+ +

English | 简体中文

+ + +## 特性 + +- 支持 top, bottom, left, and right tab positions with RTL layouts. +- Handles overflow with a dropdown operation menu. +- 支持 editable tabs, extra tab bar content, indicators, and custom tab bars. +- 提供 semantic `classNames` and `styles` slots for panel and navigation customization. + +## 安装 + +```bash +npm install @rc-component/tabs +``` + +## 使用 + +```tsx pure +import Tabs from '@rc-component/tabs'; +import '@rc-component/tabs/assets/index.css'; + +const items = [ + { key: 'overview', label: 'Overview', children: 'Overview content' }, + { key: 'settings', label: 'Settings', children: 'Settings content' }, +]; + +export default () => ; +``` + +Online preview: https://tabs.react-component.vercel.app/ + +## API + +### Tabs + +| 名称 | 类型 | 默认值 | 说明 | +| --- | --- | --- | --- | +| `activeKey` | string | - | Controlled active tab key. | +| `animated` | boolean \| AnimatedConfig | `{ inkBar: true, tabPane: false }` | Animation config. | +| `className` | string | - | Additional class name. | +| `classNames` | `Partial>` | - | Semantic class names. | +| `defaultActiveKey` | string | - | Initial active tab key. | +| `destroyOnHidden` | boolean | false | Destroy inactive tab panels. | +| `direction` | `'ltr' \| 'rtl'` | `'ltr'` | Layout direction. | +| `editable` | EditableConfig | - | Editable tab configuration. | +| `getPopupContainer` | `(node: HTMLElement) => HTMLElement` | - | Popup container resolver. | +| `id` | string | - | Root id. | +| `indicator` | `{ size?: GetIndicatorSize; align?: 'start' \| 'center' \| 'end' }` | - | Indicator size and alignment. | +| `items` | Tab[] | [] | Tab items. | +| `locale` | TabsLocale | - | Accessibility locale text. | +| `more` | MoreProps | - | Overflow dropdown config. | +| `onChange` | `(activeKey: string) => void` | - | Triggered when active tab changes. | +| `onTabClick` | `(activeKey, event) => void` | - | Triggered when a tab is clicked. | +| `onTabScroll` | `({ direction }) => void` | - | Triggered when tab navigation scrolls. | +| `prefixCls` | string | `'rc-tabs'` | Prefix class name. | +| `renderTabBar` | RenderTabBar | - | Custom tab bar renderer. | +| `style` | React.CSSProperties | - | Root style. | +| `styles` | `Partial>` | - | Semantic styles. | +| `tabBarExtraContent` | React.ReactNode \| TabBarExtraMap | - | Extra content beside the tab bar. | +| `tabBarGutter` | number | 0 | Gap between tabs. | +| `tabBarStyle` | React.CSSProperties | - | Tab bar style. | +| `tabPosition` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'top'` | Tab position. | + +### Tab + +| 名称 | 类型 | 默认值 | 说明 | +| --- | --- | --- | --- | +| `children` | React.ReactNode | - | Tab panel content. | +| `className` | string | - | Panel class name. | +| `closable` | boolean | - | Whether the tab can be closed in editable mode. | +| `closeIcon` | React.ReactNode | - | Custom close icon. | +| `destroyOnHidden` | boolean | false | Destroy inactive panel. | +| `disabled` | boolean | false | Disable the tab. | +| `forceRender` | boolean | false | Render panel before it becomes active. | +| `key` | string | - | Required unique tab key. | +| `label` | React.ReactNode | - | Tab label. | +| `style` | React.CSSProperties | - | Panel style. | + +## 本地开发 + +```bash +npm install +npm start +npm test +npm run tsc +npm run compile +npm run build +``` + +## 发布 + +```bash +npm run prepublishOnly +``` + +The release flow is handled by `@rc-component/np` through the `rc-np` command after the package build. + +## 许可证 + +@rc-component/tabs is released under the [MIT](./LICENSE.md) license. From a954f7d43ab26f612b036e79f1f266147e0e2a67 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 22:35:02 +0800 Subject: [PATCH 09/23] docs: add Ant Design logo to README --- README.md | 1 + README.zh-CN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index b2ce58e0..0eaf54a1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@

@rc-component/tabs

Part of the Ant Design ecosystem.

+ Ant Design

📑 Flexible React tabs with overflow, editable items, custom tab bars, and accessible panels.

diff --git a/README.zh-CN.md b/README.zh-CN.md index 2c653445..5b5e6dc8 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,6 +1,7 @@

@rc-component/tabs

Ant Design 生态的一部分。

+ Ant Design

🗂️ React 标签页组件,支持可编辑标签、溢出滚动和自定义渲染。

From c5c61c1bfd94ddab1c72365850dfb8621a4f0b2a Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 Jun 2026 23:04:03 +0800 Subject: [PATCH 10/23] docs: refine bilingual README branding --- README.md | 3 +- README.zh-CN.md | 79 ++++++++++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 0eaf54a1..0820a37e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@

@rc-component/tabs

-

Part of the Ant Design ecosystem.

- Ant Design +

Ant Design Part of the Ant Design ecosystem.

📑 Flexible React tabs with overflow, editable items, custom tab bars, and accessible panels.

diff --git a/README.zh-CN.md b/README.zh-CN.md index 5b5e6dc8..1d283341 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,8 +1,7 @@

@rc-component/tabs

-

Ant Design 生态的一部分。

- Ant Design -

🗂️ React 标签页组件,支持可编辑标签、溢出滚动和自定义渲染。

+

Ant Design Ant Design 生态的一部分。

+

📑 React 标签页组件,支持可编辑标签、溢出滚动和自定义渲染。

npm version @@ -19,10 +18,10 @@ ## 特性 -- 支持 top, bottom, left, and right tab positions with RTL layouts. -- Handles overflow with a dropdown operation menu. -- 支持 editable tabs, extra tab bar content, indicators, and custom tab bars. -- 提供 semantic `classNames` and `styles` slots for panel and navigation customization. +- 支持 RTL 布局的顶部、底部、左侧和右侧选项卡位置。 +- 使用下拉操作菜单处理溢出。 +- 支持可编辑选项卡、额外选项卡栏内容、指示器和自定义选项卡栏。 +- 为面板和导航自定义提供语义 `classNames` 和 `styles` 插槽。 ## 安装 @@ -44,7 +43,7 @@ const items = [ export default () => ; ``` -Online preview: https://tabs.react-component.vercel.app/ +在线预览:https://tabs.react-component.vercel.app/ ## API @@ -52,46 +51,46 @@ Online preview: https://tabs.react-component.vercel.app/ | 名称 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | -| `activeKey` | string | - | Controlled active tab key. | -| `animated` | boolean \| AnimatedConfig | `{ inkBar: true, tabPane: false }` | Animation config. | -| `className` | string | - | Additional class name. | -| `classNames` | `Partial>` | - | Semantic class names. | -| `defaultActiveKey` | string | - | Initial active tab key. | +| `activeKey` | string | - | 受控的活动 Tab 键。 | +| `animated` | boolean \| AnimatedConfig | `{ inkBar: true, tabPane: false }` | 动画配置。 | +| `className` | string | - | 附加className。 | +| `classNames` | `Partial>` | - | 语义className。 | +| `defaultActiveKey` | string | - | 初始活动 Tab 键。 | | `destroyOnHidden` | boolean | false | Destroy inactive tab panels. | | `direction` | `'ltr' \| 'rtl'` | `'ltr'` | Layout direction. | -| `editable` | EditableConfig | - | Editable tab configuration. | -| `getPopupContainer` | `(node: HTMLElement) => HTMLElement` | - | Popup container resolver. | -| `id` | string | - | Root id. | +| `editable` | EditableConfig | - | 可编辑标签页配置。 | +| `getPopupContainer` | `(node: HTMLElement) => HTMLElement` | - | 弹层容器解析器。 | +| `id` | string | - | 根 ID。 | | `indicator` | `{ size?: GetIndicatorSize; align?: 'start' \| 'center' \| 'end' }` | - | Indicator size and alignment. | -| `items` | Tab[] | [] | Tab items. | -| `locale` | TabsLocale | - | Accessibility locale text. | -| `more` | MoreProps | - | Overflow dropdown config. | -| `onChange` | `(activeKey: string) => void` | - | Triggered when active tab changes. | -| `onTabClick` | `(activeKey, event) => void` | - | Triggered when a tab is clicked. | -| `onTabScroll` | `({ direction }) => void` | - | Triggered when tab navigation scrolls. | -| `prefixCls` | string | `'rc-tabs'` | Prefix class name. | -| `renderTabBar` | RenderTabBar | - | Custom tab bar renderer. | -| `style` | React.CSSProperties | - | Root style. | -| `styles` | `Partial>` | - | Semantic styles. | -| `tabBarExtraContent` | React.ReactNode \| TabBarExtraMap | - | Extra content beside the tab bar. | -| `tabBarGutter` | number | 0 | Gap between tabs. | -| `tabBarStyle` | React.CSSProperties | - | Tab bar style. | +| `items` | Tab[] | [] | 选项卡项目。 | +| `locale` | TabsLocale | - | 无障碍本地化文本。 | +| `more` | MoreProps | - | 溢出下拉菜单配置。 | +| `onChange` | `(activeKey: string) => void` | - | 当活动选项卡更改时触发。 | +| `onTabClick` | `(activeKey, event) => void` | - | 单击选项卡时触发。 | +| `onTabScroll` | `({ direction }) => void` | - | 当选项卡导航滚动时触发。 | +| `prefixCls` | string | `'rc-tabs'` | 前缀className。 | +| `renderTabBar` | RenderTabBar | - | 自定义标签栏渲染函数。 | +| `style` | React.CSSProperties | - | 根样式。 | +| `styles` | `Partial>` | - | 语义化样式。 | +| `tabBarExtraContent` | React.ReactNode \| TabBarExtraMap | - | 标签栏旁的额外内容。 | +| `tabBarGutter` | number | 0 | 选项卡之间的间隙。 | +| `tabBarStyle` | React.CSSProperties | - | 标签栏样式。 | | `tabPosition` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'top'` | Tab position. | ### Tab | 名称 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | -| `children` | React.ReactNode | - | Tab panel content. | -| `className` | string | - | Panel class name. | -| `closable` | boolean | - | Whether the tab can be closed in editable mode. | -| `closeIcon` | React.ReactNode | - | Custom close icon. | -| `destroyOnHidden` | boolean | false | Destroy inactive panel. | -| `disabled` | boolean | false | Disable the tab. | -| `forceRender` | boolean | false | Render panel before it becomes active. | -| `key` | string | - | Required unique tab key. | +| `children` | React.ReactNode | - | 选项卡面板内容。 | +| `className` | string | - | 面板className称。 | +| `closable` | boolean | - | 是否可以在可编辑模式下关闭选项卡。 | +| `closeIcon` | React.ReactNode | - | 自定义关闭图标。 | +| `destroyOnHidden` | boolean | false | 销毁非活动面板。 | +| `disabled` | boolean | false | 禁用该选项卡。 | +| `forceRender` | boolean | false | 在面板变为活动状态之前渲染面板。 | +| `key` | string | - | 需要唯一的 Tab 键。 | | `label` | React.ReactNode | - | Tab label. | -| `style` | React.CSSProperties | - | Panel style. | +| `style` | React.CSSProperties | - | 面板风格。 | ## 本地开发 @@ -110,8 +109,8 @@ npm run build npm run prepublishOnly ``` -The release flow is handled by `@rc-component/np` through the `rc-np` command after the package build. +包构建完成后,发布流程由 `@rc-component/np` 通过 `rc-np` 命令处理。 ## 许可证 -@rc-component/tabs is released under the [MIT](./LICENSE.md) license. +@rc-component/tabs 基于 [MIT](./LICENSE.md) 许可证发布。 From 8f2283d0afe48fdb96c9bb4f763019643c651b30 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 01:28:44 +0800 Subject: [PATCH 11/23] chore: standardize rc tooling and docs --- .dumirc.ts | 2 +- README.md | 11 +++++++++ README.zh-CN.md | 11 +++++++++ package.json | 42 ++++++++++++++++----------------- tests/accessibility.test.tsx | 19 ++++++++++----- tsconfig.json | 45 ++++++++++++++++++++++++++++-------- 6 files changed, 92 insertions(+), 38 deletions(-) diff --git a/.dumirc.ts b/.dumirc.ts index 40f97753..65a8e909 100644 --- a/.dumirc.ts +++ b/.dumirc.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'dumi'; import path from 'path'; const basePath = process.env.GH_PAGES ? '/tabs/' : '/'; -const publicPath = process.env.GH_PAGES ? '/tabs/' : '/'; +const publicPath = basePath; export default defineConfig({ alias: { diff --git a/README.md b/README.md index 0820a37e..2808a3ab 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,17 @@ export default () => ; Online preview: https://tabs.react-component.vercel.app/ +## Examples + +Run the local dumi site: + +```bash +npm install +npm start +``` + +Then open `http://localhost:8000`. + ## API ### Tabs diff --git a/README.zh-CN.md b/README.zh-CN.md index 1d283341..1493e01c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -45,6 +45,17 @@ export default () => ; 在线预览:https://tabs.react-component.vercel.app/ +## 示例 + +运行本地 dumi 站点: + +```bash +npm install +npm start +``` + +然后打开 `http://localhost:8000`。 + ## API ### Tabs diff --git a/package.json b/package.json index cd8187b5..547d3a9a 100644 --- a/package.json +++ b/package.json @@ -49,34 +49,34 @@ }, "devDependencies": { "@rc-component/father-plugin": "^2.2.0", - "@rc-component/np": "^1.0.3", - "@testing-library/jest-dom": "^6.1.4", - "@testing-library/react": "^16.0.1", - "@testing-library/user-event": "^14.5.2", + "@rc-component/np": "^1.0.4", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^15.0.7", + "@testing-library/user-event": "14.5.2", "@types/enzyme": "^3.10.5", - "@types/jest": "^30.0.0", - "@types/node": "^24.5.2", - "@types/react": "^18.2.42", + "@types/jest": "^29.5.14", + "@types/node": "^26.0.1", + "@types/react": "^18.3.31", "@types/react-dom": "^18.3.7", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", "@umijs/fabric": "^4.0.1", - "dumi": "^2.0.0", - "eslint": "^8.54.0", - "father": "^4.0.0", - "gh-pages": "^6.1.0", + "dumi": "^2.4.35", + "eslint": "^8.57.1", + "father": "^4.6.23", + "gh-pages": "^6.3.0", "husky": "^9.1.7", - "less": "^4.1.3", - "lint-staged": "^16.2.3", - "prettier": "^3.5.3", - "rc-test": "^7.0.14", - "react": "^18.0.0", + "less": "^4.6.7", + "lint-staged": "^16.4.0", + "prettier": "^3.9.0", + "rc-test": "^7.1.3", + "react": "^18.3.1", "react-dnd": "^10.0.0", "react-dnd-html5-backend": "^10.0.0", - "react-dom": "^18.0.0", + "react-dom": "^18.3.1", "react-sticky": "^6.0.3", - "typescript": "^5.3.2", - "cross-env": "^7.0.0" + "typescript": "^5.9.3", + "cross-env": "^10.1.0" }, "peerDependencies": { "react": ">=16.9.0", diff --git a/tests/accessibility.test.tsx b/tests/accessibility.test.tsx index fbee0fa6..c31e4679 100644 --- a/tests/accessibility.test.tsx +++ b/tests/accessibility.test.tsx @@ -139,22 +139,29 @@ describe('Tabs.Accessibility', () => { it('should distinguish between keyboard and mouse navigation', async () => { const user = userEvent.setup(); - const { getByRole } = render(createTabs()); + const { getByRole, unmount } = render(createTabs()); const secondTab = getByRole('tab', { name: /Tab2/i }); - const fourthTab = getByRole('tab', { name: /Tab4/i }); // mouse click should not add focus style - await user.click(secondTab); + fireEvent.mouseDown(secondTab); + fireEvent.click(secondTab); expect(secondTab.parentElement).not.toHaveClass('rc-tabs-tab-focus'); - // clear focus - await user.click(document.body); + unmount(); + + const { getByRole: getByRoleWithKeyboard } = render(createTabs()); + const firstTab = getByRoleWithKeyboard('tab', { name: /Tab1/i }); + const secondKeyboardTab = getByRoleWithKeyboard('tab', { name: /Tab2/i }); + const fourthTab = getByRoleWithKeyboard('tab', { name: /Tab4/i }); // keyboard navigation should add focus style await user.tab(); // default focus active tab - expect(secondTab.parentElement).toHaveClass('rc-tabs-tab-focus'); + expect(firstTab.parentElement).toHaveClass('rc-tabs-tab-focus'); + + await user.keyboard('{ArrowRight}'); + expect(secondKeyboardTab.parentElement).toHaveClass('rc-tabs-tab-focus'); await user.keyboard('{ArrowRight}'); // skip disabled tab diff --git a/tsconfig.json b/tsconfig.json index cb5d1b5d..d72095a0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,20 +3,45 @@ "target": "esnext", "moduleResolution": "node", "baseUrl": "./", - "lib": ["dom", "es2017"], + "lib": [ + "dom", + "es2017" + ], "jsx": "react", "declaration": true, "skipLibCheck": true, "esModuleInterop": true, "paths": { - "@/*": ["src/*"], - "@@/*": [".dumi/tmp/*"], - "@rc-component/tabs": ["src/index.ts"], - "@rc-component/tabs/es": ["src"], - "@rc-component/tabs/es/*": ["src/*"], - "@rc-component/tabs/assets/*": ["assets/*"] - } + "@/*": [ + "src/*" + ], + "@@/*": [ + ".dumi/tmp/*" + ], + "@rc-component/tabs": [ + "src/index.ts" + ], + "@rc-component/tabs/es": [ + "src" + ], + "@rc-component/tabs/es/*": [ + "src/*" + ], + "@rc-component/tabs/assets/*": [ + "assets/*" + ] + }, + "ignoreDeprecations": "5.0" }, - "include": [".dumirc.ts", "src", "tests", "docs/examples"], - "exclude": ["docs-dist", "lib", "es"] + "include": [ + ".dumirc.ts", + "src", + "tests", + "docs/examples" + ], + "exclude": [ + "docs-dist", + "lib", + "es" + ] } From f18c5f5ef6604d30ee4e31dd0df6d6d44b213c7c Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 02:01:08 +0800 Subject: [PATCH 12/23] chore: address standardization review comments --- .github/workflows/surge-preview.yml | 16 +++++++++++++--- README.zh-CN.md | 20 ++++++++++---------- tsconfig.json | 1 + 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml index faf6b8bd..cb6c8c4a 100644 --- a/.github/workflows/surge-preview.yml +++ b/.github/workflows/surge-preview.yml @@ -22,13 +22,23 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with: persist-credentials: false + - name: Check Surge token + id: surge-token + env: + SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} + run: | + if [ -n "$SURGE_TOKEN" ]; then + echo "enabled=true" >> "$GITHUB_OUTPUT" + else + echo "enabled=false" >> "$GITHUB_OUTPUT" + fi - name: Build preview - if: ${{ secrets.SURGE_TOKEN != '' }} + if: ${{ steps.surge-token.outputs.enabled == 'true' }} run: | npm install npm run build - uses: afc163/surge-preview@bf90a5a86111f6311ca42f0a5a0f80fb0fb03cec - if: ${{ secrets.SURGE_TOKEN != '' }} + if: ${{ steps.surge-token.outputs.enabled == 'true' }} env: SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} with: @@ -38,5 +48,5 @@ jobs: failOnError: false setCommitStatus: false - name: Skip Surge preview - if: ${{ secrets.SURGE_TOKEN == '' }} + if: ${{ steps.surge-token.outputs.enabled != 'true' }} run: echo "SURGE_TOKEN is not configured; skip Surge preview." diff --git a/README.zh-CN.md b/README.zh-CN.md index 1493e01c..3fb12bc3 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -64,44 +64,44 @@ npm start | --- | --- | --- | --- | | `activeKey` | string | - | 受控的活动 Tab 键。 | | `animated` | boolean \| AnimatedConfig | `{ inkBar: true, tabPane: false }` | 动画配置。 | -| `className` | string | - | 附加className。 | -| `classNames` | `Partial>` | - | 语义className。 | +| `className` | string | - | 附加 className。 | +| `classNames` | `Partial>` | - | 语义化类名。 | | `defaultActiveKey` | string | - | 初始活动 Tab 键。 | -| `destroyOnHidden` | boolean | false | Destroy inactive tab panels. | -| `direction` | `'ltr' \| 'rtl'` | `'ltr'` | Layout direction. | +| `destroyOnHidden` | boolean | false | 销毁非活动标签页面板。 | +| `direction` | `'ltr' \| 'rtl'` | `'ltr'` | 布局方向。 | | `editable` | EditableConfig | - | 可编辑标签页配置。 | | `getPopupContainer` | `(node: HTMLElement) => HTMLElement` | - | 弹层容器解析器。 | | `id` | string | - | 根 ID。 | -| `indicator` | `{ size?: GetIndicatorSize; align?: 'start' \| 'center' \| 'end' }` | - | Indicator size and alignment. | +| `indicator` | `{ size?: GetIndicatorSize; align?: 'start' \| 'center' \| 'end' }` | - | 指示器尺寸和对齐方式。 | | `items` | Tab[] | [] | 选项卡项目。 | | `locale` | TabsLocale | - | 无障碍本地化文本。 | | `more` | MoreProps | - | 溢出下拉菜单配置。 | | `onChange` | `(activeKey: string) => void` | - | 当活动选项卡更改时触发。 | | `onTabClick` | `(activeKey, event) => void` | - | 单击选项卡时触发。 | | `onTabScroll` | `({ direction }) => void` | - | 当选项卡导航滚动时触发。 | -| `prefixCls` | string | `'rc-tabs'` | 前缀className。 | +| `prefixCls` | string | `'rc-tabs'` | 前缀 className。 | | `renderTabBar` | RenderTabBar | - | 自定义标签栏渲染函数。 | | `style` | React.CSSProperties | - | 根样式。 | | `styles` | `Partial>` | - | 语义化样式。 | | `tabBarExtraContent` | React.ReactNode \| TabBarExtraMap | - | 标签栏旁的额外内容。 | | `tabBarGutter` | number | 0 | 选项卡之间的间隙。 | | `tabBarStyle` | React.CSSProperties | - | 标签栏样式。 | -| `tabPosition` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'top'` | Tab position. | +| `tabPosition` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'top'` | 标签页位置。 | ### Tab | 名称 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `children` | React.ReactNode | - | 选项卡面板内容。 | -| `className` | string | - | 面板className称。 | +| `className` | string | - | 面板 className。 | | `closable` | boolean | - | 是否可以在可编辑模式下关闭选项卡。 | | `closeIcon` | React.ReactNode | - | 自定义关闭图标。 | | `destroyOnHidden` | boolean | false | 销毁非活动面板。 | | `disabled` | boolean | false | 禁用该选项卡。 | | `forceRender` | boolean | false | 在面板变为活动状态之前渲染面板。 | | `key` | string | - | 需要唯一的 Tab 键。 | -| `label` | React.ReactNode | - | Tab label. | -| `style` | React.CSSProperties | - | 面板风格。 | +| `label` | React.ReactNode | - | Tab 标签内容。 | +| `style` | React.CSSProperties | - | 面板样式。 | ## 本地开发 diff --git a/tsconfig.json b/tsconfig.json index d72095a0..0dfc8d55 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,6 +35,7 @@ }, "include": [ ".dumirc.ts", + ".fatherrc.ts", "src", "tests", "docs/examples" From cd5c1a92045b77bcd18e76053e32d04baaeeff22 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 02:30:42 +0800 Subject: [PATCH 13/23] test: cover mouse focus reset --- tests/accessibility.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/accessibility.test.tsx b/tests/accessibility.test.tsx index c31e4679..385d889c 100644 --- a/tests/accessibility.test.tsx +++ b/tests/accessibility.test.tsx @@ -146,6 +146,7 @@ describe('Tabs.Accessibility', () => { // mouse click should not add focus style fireEvent.mouseDown(secondTab); fireEvent.click(secondTab); + fireEvent.mouseUp(secondTab); expect(secondTab.parentElement).not.toHaveClass('rc-tabs-tab-focus'); unmount(); From 1953df80755d80a1d5f6eface9f29815c93c9d7a Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 12:24:43 +0800 Subject: [PATCH 14/23] ci: update GitHub Actions versions --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 23f424a8..6999184b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -29,15 +29,15 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e + uses: github/codeql-action/init@a0853c24544627f65ddf259abe73b1d18a591444 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e + uses: github/codeql-action/autobuild@a0853c24544627f65ddf259abe73b1d18a591444 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e + uses: github/codeql-action/analyze@a0853c24544627f65ddf259abe73b1d18a591444 with: category: '/language:${{ matrix.language }}' From f73faab53b3fa64ffbbf44b6abc3e8f5ddf1780f Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 12:30:18 +0800 Subject: [PATCH 15/23] ci: use resolvable CodeQL action ref --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6999184b..23f424a8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -29,15 +29,15 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@a0853c24544627f65ddf259abe73b1d18a591444 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@a0853c24544627f65ddf259abe73b1d18a591444 + uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a0853c24544627f65ddf259abe73b1d18a591444 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e with: category: '/language:${{ matrix.language }}' From fe1a801a3b1a725597ec7a6bea2797938496056f Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 13:28:15 +0800 Subject: [PATCH 16/23] docs: add license file --- LICENSE | 21 +++++++++++++++++++++ README.md | 2 +- README.zh-CN.md | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..bd0a1f72 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-present react-component + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 2808a3ab..2db9c2ff 100644 --- a/README.md +++ b/README.md @@ -124,4 +124,4 @@ The release flow is handled by `@rc-component/np` through the `rc-np` command af ## License -@rc-component/tabs is released under the [MIT](./LICENSE.md) license. +@rc-component/tabs is released under the [MIT](./LICENSE) license. diff --git a/README.zh-CN.md b/README.zh-CN.md index 3fb12bc3..6fa168dd 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -124,4 +124,4 @@ npm run prepublishOnly ## 许可证 -@rc-component/tabs 基于 [MIT](./LICENSE.md) 许可证发布。 +@rc-component/tabs 基于 [MIT](./LICENSE) 许可证发布。 From 71542518ed70c108636a0a711e4c8c152aaa5a93 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 14:01:42 +0800 Subject: [PATCH 17/23] ci: use actions checkout v7 --- .github/workflows/codeql.yml | 2 +- .github/workflows/react-doctor.yml | 2 +- .github/workflows/surge-preview.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 23f424a8..82242dfd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + uses: actions/checkout@v7 with: persist-credentials: false diff --git a/.github/workflows/react-doctor.yml b/.github/workflows/react-doctor.yml index f68281c8..097eb883 100644 --- a/.github/workflows/react-doctor.yml +++ b/.github/workflows/react-doctor.yml @@ -20,7 +20,7 @@ jobs: react-doctor: runs-on: ubuntu-latest steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@v7 with: fetch-depth: 0 persist-credentials: false diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml index cb6c8c4a..ebfecd53 100644 --- a/.github/workflows/surge-preview.yml +++ b/.github/workflows/surge-preview.yml @@ -19,7 +19,7 @@ jobs: env: PREVIEW: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@v7 with: persist-credentials: false - name: Check Surge token From 881ee0b9fbf212d6109a91a195496938fb67ef6d Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 14:32:22 +0800 Subject: [PATCH 18/23] chore: standardize package metadata --- package.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 547d3a9a..03b3819d 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,11 @@ ], "homepage": "https://react-component.github.io/tabs", "bugs": { - "url": "http://github.com/react-component/tabs/issues" + "url": "https://github.com/react-component/tabs/issues" }, "repository": { "type": "git", - "url": "git@github.com:react-component/tabs.git" + "url": "https://github.com/react-component/tabs.git" }, "license": "MIT", "author": "yiminghe@gmail.com", @@ -86,5 +86,8 @@ "node": ">=8.x" }, "types": "./lib/index.d.ts", - "style": "./assets/index.css" + "style": "./assets/index.css", + "publishConfig": { + "access": "public" + } } From a9c785bbeb1fba7fd68cf0f0784058d587ccaaac Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 14:38:34 +0800 Subject: [PATCH 19/23] ci: standardize dependabot updates --- .github/dependabot.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 07575c02..3b730ef9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,6 +3,17 @@ updates: - package-ecosystem: npm directory: '/' schedule: - interval: daily + interval: weekly + day: monday time: '21:00' + timezone: Asia/Shanghai + open-pull-requests-limit: 10 + + - package-ecosystem: github-actions + directory: '/' + schedule: + interval: weekly + day: monday + time: '21:00' + timezone: Asia/Shanghai open-pull-requests-limit: 10 From 6110def4bf10d42f1f7289f4de2dcd378b1193e2 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 15:07:27 +0800 Subject: [PATCH 20/23] chore: ignore generated docs artifacts --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index bcd4e0c9..dc304eff 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ docs-dist bun.lockb bun.lock +coverage +.dumi/tmp +.dumi/tmp-production From 2cb19e978e169aeea72d3def0f3b976f08d22c7b Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 17:16:37 +0800 Subject: [PATCH 21/23] chore: refine preview workflow ignores --- .github/workflows/surge-preview.yml | 3 +++ .prettierignore | 14 ++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .prettierignore diff --git a/.github/workflows/surge-preview.yml b/.github/workflows/surge-preview.yml index ebfecd53..eaff160a 100644 --- a/.github/workflows/surge-preview.yml +++ b/.github/workflows/surge-preview.yml @@ -16,6 +16,9 @@ permissions: jobs: preview: runs-on: ubuntu-latest + concurrency: + group: surge-preview-${{ github.event.pull_request.number }} + cancel-in-progress: true env: PREVIEW: true steps: diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..c466d872 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,14 @@ +node_modules +coverage +docs-dist +dist +es +lib +.dumi/tmp +.dumi/tmp-production +.vercel +package-lock.json +pnpm-lock.yaml +yarn.lock +bun.lockb +*.log From 155b4b467e1cfbc20b082b987b02d500e158c04b Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 19:39:38 +0800 Subject: [PATCH 22/23] docs: document dumi dev server port --- README.md | 2 ++ README.zh-CN.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 2db9c2ff..4888e335 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,8 @@ npm run compile npm run build ``` +The dumi site runs at `http://localhost:8000` by default. + ## Release ```bash diff --git a/README.zh-CN.md b/README.zh-CN.md index 6fa168dd..f6307bbf 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -114,6 +114,8 @@ npm run compile npm run build ``` +dumi 站点默认运行在 `http://localhost:8000`。 + ## 发布 ```bash From dc59453fb07cb6d8c8ddcd291f037ef4b2b6fc09 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sun, 28 Jun 2026 19:59:07 +0800 Subject: [PATCH 23/23] chore: standardize husky configuration --- .husky/pre-commit | 2 +- package.json | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index d0a77842..2312dc58 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -npx lint-staged \ No newline at end of file +npx lint-staged diff --git a/package.json b/package.json index 03b3819d..295107f3 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "prettier": "prettier --write --ignore-unknown .", "start": "dumi dev", "test": "rc-test", - "tsc": "tsc --noEmit" + "tsc": "tsc --noEmit", + "prepare": "husky" }, "dependencies": { "@rc-component/dropdown": "~1.0.0", @@ -89,5 +90,8 @@ "style": "./assets/index.css", "publishConfig": { "access": "public" + }, + "lint-staged": { + "*": "prettier --write --ignore-unknown" } }