diff --git a/packages/design/package.json b/packages/design/package.json index 9b22b749b5..f5d2299163 100644 --- a/packages/design/package.json +++ b/packages/design/package.json @@ -79,6 +79,7 @@ "rc-input-number": "^9.0.0", "rc-menu": "^9.13.0", "rc-picker": "^4.3.0", + "rc-segmented": "^2.3.0", "rc-select": "^14.13.0", "rc-tooltip": "^6.2.0", "rc-util": "^5.39.1", diff --git a/packages/design/src/components/segmented/Segmented.stories.tsx b/packages/design/src/components/segmented/Segmented.stories.tsx new file mode 100644 index 0000000000..7e1ff2af27 --- /dev/null +++ b/packages/design/src/components/segmented/Segmented.stories.tsx @@ -0,0 +1,44 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import type { Meta } from '@storybook/react'; +import { Segmented } from './Segmented'; + +const meta: Meta = { + title: 'Components / Segmented', + component: Segmented, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +}; + +export default meta; + +export const SegmentedBasic = { + render() { + return ( +
+ +
+ ); + }, +}; diff --git a/packages/design/src/components/segmented/Segmented.tsx b/packages/design/src/components/segmented/Segmented.tsx new file mode 100644 index 0000000000..6990a6bb09 --- /dev/null +++ b/packages/design/src/components/segmented/Segmented.tsx @@ -0,0 +1,27 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { forwardRef } from 'react'; +import type { SegmentedProps } from 'rc-segmented'; +import RcSegmented from 'rc-segmented'; + +import styles from './index.module.less'; + +export interface ISegmentedProps extends Omit {} + +export const Segmented = forwardRef(function InnerSegmented(props, ref) { + return ; +}); diff --git a/packages/design/src/components/segmented/index.module.less b/packages/design/src/components/segmented/index.module.less new file mode 100644 index 0000000000..c6ebe63819 --- /dev/null +++ b/packages/design/src/components/segmented/index.module.less @@ -0,0 +1,114 @@ +@segmented-prefix-cls: segmented; + +.segmented-disabled-item() { + &, + &:hover, + &:focus { + color: fade(#000, 25%); + cursor: not-allowed; + } +} + +.segmented-item-selected() { + background-color: white; + box-shadow: 0px 4px 16px 0px rgba(var(--color-black), 0.08); +} + +.@{segmented-prefix-cls} { + display: inline-flex; + padding: 2px; + height: 32px; + width: 100%; + border-radius: 6px; + background-color: rgb(var(--grey-50)); + + &-group { + position: relative; + display: flex; + align-items: stretch; + justify-items: flex-start; + + width: 100%; + border-radius: 2px; + } + + &-item { + position: relative; + min-height: 28px; + padding: 4px 10px; + border-radius: 4px; + height: 100%; + flex: 1; + flex-grow: 1; + flex-shrink: 1; + box-sizing: border-box; + + color: rgba(var(--color-black)); + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + cursor: pointer; + font-size: 13px; + + &-selected { + .segmented-item-selected(); + color: rgba(var(--color-black)); + } + + &:hover, + &:focus { + color: rgba(var(--color-black)); + } + + &-disabled { + .segmented-disabled-item(); + } + + &-label { + z-index: 2; + line-height: 24px; + } + + &-input { + position: absolute; + top: 0; + left: 0; + + width: 0; + height: 0; + opacity: 0; + pointer-events: none; + } + } + + // disabled styles + &-disabled &-item, + &-disabled &-item:hover, + &-disabled &-item:focus { + .segmented-disabled-item(); + } + + &-thumb { + .segmented-item-selected(); + + position: absolute; + box-sizing: border-box; + width: 0; + height: 100%; + border-radius: 4px; + padding: 4px 0; + } + + // transition effect when `enter-active` + &-thumb-motion-appear-active, + &-thumb-motion-enter-active { + transition: + transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), + width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + will-change: transform, width; + } + + &-rtl { + direction: rtl; + } +} diff --git a/packages/design/src/components/segmented/index.ts b/packages/design/src/components/segmented/index.ts new file mode 100644 index 0000000000..f7007e2011 --- /dev/null +++ b/packages/design/src/components/segmented/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { Segmented, type ISegmentedProps } from './Segmented'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb74ca94d5..a1d76be264 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -371,6 +371,9 @@ importers: rc-picker: specifier: ^4.3.0 version: 4.3.0(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + rc-segmented: + specifier: ^2.3.0 + version: 2.3.0(react-dom@18.2.0)(react@18.2.0) rc-select: specifier: ^14.13.0 version: 14.13.0(react-dom@18.2.0)(react@18.2.0) @@ -12139,6 +12142,20 @@ packages: resize-observer-polyfill: 1.5.1 dev: false + /rc-segmented@2.3.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.23.9 + classnames: 2.5.1 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.39.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /rc-select@14.13.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-ew34FsaqHokK4dxVrcIxSYrgWJ2XJYlkk32eiOIiEo3GkHUExdCzmozMYaUc2P67c5QJRUvvY0uqCs3QG67h5A==} engines: {node: '>=8.x'}