diff --git a/packages/vant/src/block/Block.tsx b/packages/vant/src/block/Block.tsx new file mode 100644 index 00000000000..095e9b48f1d --- /dev/null +++ b/packages/vant/src/block/Block.tsx @@ -0,0 +1,40 @@ +import { ExtractPropTypes, defineComponent } from 'vue'; +import { createNamespace } from '../utils'; + +const [name, bem] = createNamespace('block'); + +export const blockProps = { + card: { + type: Boolean, + default: false, + }, + title: { + type: String, + default: '', + }, + id: { + type: String, + default: '', + }, +}; + +export type BlockProps = ExtractPropTypes; + +export default defineComponent({ + name, + + props: blockProps, + + setup(props, { slots }) { + return () => ( +
+ {props.title ?

{props.title}

: null} + {props.card ? ( +
{slots.default?.()}
+ ) : ( + slots.default?.() + )} +
+ ); + }, +}); diff --git a/packages/vant/src/block/README.md b/packages/vant/src/block/README.md new file mode 100644 index 00000000000..52c6216e555 --- /dev/null +++ b/packages/vant/src/block/README.md @@ -0,0 +1,58 @@ +# Button + +### Intro + +block components provide container like functionality. + +### Install + +Register component globally via `app.use`, refer to [Component Registration](#/en-US/advanced-usage#zu-jian-zhu-ce) for more registration ways. + +```js +import { createApp } from 'vue'; +import { Block } from 'vant'; + +const app = createApp(); +app.use(Block); +``` + +## Usage + +### Base + +use as a container, passing in the 'title' attribute as the title. + +```html + + default + primary + success + +``` + +### Card + +set the container to card mode through the 'card' attribute. + +```html + + default + primary + success + +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +| --------- | ----------- | --------- | ------- | +| title | Title | _string_ | `-` | +| card | Card mode | _boolean_ | `-` | + +### Slots + +| Name | Description | +| ------- | ------------ | +| default | Default slot | diff --git a/packages/vant/src/block/README.zh-CN.md b/packages/vant/src/block/README.zh-CN.md new file mode 100644 index 00000000000..b9098525c7f --- /dev/null +++ b/packages/vant/src/block/README.zh-CN.md @@ -0,0 +1,58 @@ +# Block 块级组件 + +### 介绍 + +块级组件提供类似容器的功能 + +### 引入 + +通过以下方式来全局注册组件,更多注册方式请参考[组件注册](#/zh-CN/advanced-usage#zu-jian-zhu-ce)。 + +```js +import { createApp } from 'vue'; +import { Block } from 'vant'; + +const app = createApp(); +app.use(Block); +``` + +## 代码演示 + +### 基础用法 + +当作一个容器来使用,传入 `title` 属性作为标题。 + +```html + + default + primary + success + +``` + +### 卡片模式 + +通过 `card` 属性将容器设置为卡片模式。 + +```html + + default + primary + success + +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| ----- | -------- | --------- | ------ | +| title | 标题 | _string_ | `-` | +| card | 卡片模式 | _boolean_ | `-` | + +### Slots + +| 名称 | 说明 | +| ------- | -------- | +| default | 默认插槽 | diff --git a/packages/vant/src/block/demo/index.vue b/packages/vant/src/block/demo/index.vue new file mode 100644 index 00000000000..19b5581aec2 --- /dev/null +++ b/packages/vant/src/block/demo/index.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/packages/vant/src/block/index.less b/packages/vant/src/block/index.less new file mode 100644 index 00000000000..4532a52743b --- /dev/null +++ b/packages/vant/src/block/index.less @@ -0,0 +1,36 @@ +:root { + --van-block-title-padding: var(--van-padding-xl) var(--van-padding-md) + var(--van-padding-md); + --van-block-title-color: var(--van-doc-text-color-4); + --van-block-title-fint-size: var(--van-font-size-md); + --van-block-title-line-height: 16px; + --van-block-card-margin: var(--van-padding-md) var(--van-padding-md) 0; + --van-block-card-border-radius: var(--van-radius-lg); +} + +.van-block { + &__title { + margin: 0; + padding: var(--van-block-title-padding); + color: var(--van-block-title-color); + font-weight: normal; + font-size: var(--van-block-title-fint-size); + line-height: var(--van-block-title-line-height); + } + + &__card { + margin: var(--van-block-card-margin); + overflow: hidden; + border-radius: var(--van-block-card-border-radius); + } + + &__title + &__card { + margin-top: 0; + } + + &:first-of-type { + .van-block__title { + padding-top: 20px; + } + } +} diff --git a/packages/vant/src/block/index.ts b/packages/vant/src/block/index.ts new file mode 100644 index 00000000000..231cf8ea922 --- /dev/null +++ b/packages/vant/src/block/index.ts @@ -0,0 +1,14 @@ +import { withInstall } from '../utils'; +import _Block from './Block'; + +export const Block = withInstall(_Block); +export default Block; +export { blockProps } from './Block'; +export type { BlockProps } from './Block'; +export type { BlockThemeVars } from './types'; + +declare module 'vue' { + export interface GlobalComponents { + VanBlock: typeof Block; + } +} diff --git a/packages/vant/src/block/test/__snapshots__/demo-ssr.spec.ts.snap b/packages/vant/src/block/test/__snapshots__/demo-ssr.spec.ts.snap new file mode 100644 index 00000000000..c9d5f61e323 --- /dev/null +++ b/packages/vant/src/block/test/__snapshots__/demo-ssr.spec.ts.snap @@ -0,0 +1,96 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`should render demo and match snapshot 1`] = ` + +
+

+ base +

+ + + + +
+
+

+ card +

+
+ + + + +
+
+`; diff --git a/packages/vant/src/block/test/__snapshots__/demo.spec.ts.snap b/packages/vant/src/block/test/__snapshots__/demo.spec.ts.snap new file mode 100644 index 00000000000..09d279bced1 --- /dev/null +++ b/packages/vant/src/block/test/__snapshots__/demo.spec.ts.snap @@ -0,0 +1,81 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`should render demo and match snapshot 1`] = ` +
+

+ base +

+ + + +
+
+

+ card +

+
+ + + +
+
+`; diff --git a/packages/vant/src/block/test/demo-ssr.spec.ts b/packages/vant/src/block/test/demo-ssr.spec.ts new file mode 100644 index 00000000000..e00f7b09342 --- /dev/null +++ b/packages/vant/src/block/test/demo-ssr.spec.ts @@ -0,0 +1,7 @@ +/** + * @vitest-environment node + */ +import Demo from '../demo/index.vue'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo, { ssr: true }); diff --git a/packages/vant/src/block/test/demo.spec.ts b/packages/vant/src/block/test/demo.spec.ts new file mode 100644 index 00000000000..c0e0c95b9a2 --- /dev/null +++ b/packages/vant/src/block/test/demo.spec.ts @@ -0,0 +1,4 @@ +import Demo from '../demo/index.vue'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo); diff --git a/packages/vant/src/block/test/index.spec.ts b/packages/vant/src/block/test/index.spec.ts new file mode 100644 index 00000000000..20beced8774 --- /dev/null +++ b/packages/vant/src/block/test/index.spec.ts @@ -0,0 +1,40 @@ +import { mount } from '../../../test'; +import { Block } from '..'; + +test('should render default slot correctly', () => { + const wrapper = mount(Block, { + slots: { + default: () => 'text', + }, + }); + + const block = wrapper.find('.van-block'); + expect(block).exist.toBeTruthy(); + expect(block.text()).toBe('text'); +}); + +test('should render title correctly', () => { + const wrapper = mount(Block, { + props: { + title: 'title', + }, + }); + + const block = wrapper.find('.van-block'); + const title = block.find('.van-block__title'); + expect(title).exist.toBeTruthy(); + expect(title.text()).toBe('title'); +}); + +test('should render card mode correctly', () => { + const wrapper = mount(Block, { + props: { + title: 'title', + card: true, + }, + }); + + const block = wrapper.find('.van-block'); + const card = block.find('.van-block__card'); + expect(card).exist.toBeTruthy(); +}); diff --git a/packages/vant/src/block/types.ts b/packages/vant/src/block/types.ts new file mode 100644 index 00000000000..c3490efd548 --- /dev/null +++ b/packages/vant/src/block/types.ts @@ -0,0 +1,8 @@ +export type BlockThemeVars = { + blockTitlePading?: string; + blockTitleTextColor?: string; + blockTitleFontSize?: string; + blockTitleLineHeight?: string; + blockCardMargin?: string; + blockCardBorderRadius?: string; +}; diff --git a/packages/vant/src/config-provider/types.ts b/packages/vant/src/config-provider/types.ts index 896bdc79af0..31845269ca7 100644 --- a/packages/vant/src/config-provider/types.ts +++ b/packages/vant/src/config-provider/types.ts @@ -73,79 +73,80 @@ type BaseThemeVars = { export type ConfigProviderThemeVars = BaseThemeVars & import('../action-bar').ActionBarThemeVars & - import('../action-bar-button').ActionBarButtonThemeVars & - import('../action-bar-icon').ActionBarIconThemeVars & - import('../action-sheet').ActionSheetThemeVars & - import('../address-edit').AddressEditThemeVars & - import('../address-list').AddressListThemeVars & - import('../badge').BadgeThemeVars & - import('../barrage').BarrageThemeVars & - import('../button').ButtonThemeVars & - import('../calendar').CalendarThemeVars & - import('../card').CardThemeVars & - import('../cascader').CascaderThemeVars & - import('../cell').CellThemeVars & - import('../cell-group').CellGroupThemeVars & - import('../checkbox').CheckboxThemeVars & - import('../circle').CircleThemeVars & - import('../collapse-item').CollapseItemThemeVars & - import('../contact-card').ContactCardThemeVars & - import('../contact-edit').ContactEditThemeVars & - import('../contact-list').ContactListThemeVars & - import('../count-down').CountDownThemeVars & - import('../coupon').CouponThemeVars & - import('../coupon-cell').CouponCellThemeVars & - import('../coupon-list').CouponListThemeVars & - import('../dialog').DialogThemeVars & - import('../divider').DividerThemeVars & - import('../dropdown-item').DropdownItemThemeVars & - import('../dropdown-menu').DropdownMenuThemeVars & - import('../empty').EmptyThemeVars & - import('../field').FieldThemeVars & - import('../floating-bubble').FloatingBubbleThemeVars & - import('../floating-panel').FloatingPanelThemeVars & - import('../grid-item').GridItemThemeVars & - import('../image').ImageThemeVars & - import('../image-preview').ImagePreviewThemeVars & - import('../index-anchor').IndexAnchorThemeVars & - import('../index-bar').IndexBarThemeVars & - import('../list').ListThemeVars & - import('../loading').LoadingThemeVars & - import('../nav-bar').NavBarThemeVars & - import('../notice-bar').NoticeBarThemeVars & - import('../notify').NotifyThemeVars & - import('../number-keyboard').NumberKeyboardThemeVars & - import('../overlay').OverlayThemeVars & - import('../pagination').PaginationThemeVars & - import('../password-input').PasswordInputThemeVars & - import('../picker').PickerThemeVars & - import('../picker-group').PickerGroupThemeVars & - import('../popover').PopoverThemeVars & - import('../popup').PopupThemeVars & - import('../progress').ProgressThemeVars & - import('../pull-refresh').PullRefreshThemeVars & - import('../radio').RadioThemeVars & - import('../rate').RateThemeVars & - import('../rolling-text').RollingTextThemeVars & - import('../search').SearchThemeVars & - import('../share-sheet').ShareSheetThemeVars & - import('../sidebar').SidebarThemeVars & - import('../sidebar-item').SidebarItemThemeVars & - import('../signature').SignatureThemeVars & - import('../skeleton').SkeletonThemeVars & - import('../slider').SliderThemeVars & - import('../step').StepThemeVars & - import('../stepper').StepperThemeVars & - import('../steps').StepsThemeVars & - import('../sticky').StickyThemeVars & - import('../submit-bar').SubmitBarThemeVars & - import('../swipe').SwipeThemeVars & - import('../switch').SwitchThemeVars & - import('../tabbar').TabbarThemeVars & - import('../tabbar-item').TabbarItemThemeVars & - import('../tabs').TabsThemeVars & - import('../tag').TagThemeVars & - import('../toast').ToastThemeVars & - import('../tree-select').TreeSelectThemeVars & - import('../uploader').UploaderThemeVars & - import('../watermark').WatermarkThemeVars; + import('../action-bar-button').ActionBarButtonThemeVars & + import('../action-bar-icon').ActionBarIconThemeVars & + import('../action-sheet').ActionSheetThemeVars & + import('../address-edit').AddressEditThemeVars & + import('../address-list').AddressListThemeVars & + import('../badge').BadgeThemeVars & + import('../barrage').BarrageThemeVars & + import('../block').BlockThemeVars & + import('../button').ButtonThemeVars & + import('../calendar').CalendarThemeVars & + import('../card').CardThemeVars & + import('../cascader').CascaderThemeVars & + import('../cell').CellThemeVars & + import('../cell-group').CellGroupThemeVars & + import('../checkbox').CheckboxThemeVars & + import('../circle').CircleThemeVars & + import('../collapse-item').CollapseItemThemeVars & + import('../contact-card').ContactCardThemeVars & + import('../contact-edit').ContactEditThemeVars & + import('../contact-list').ContactListThemeVars & + import('../count-down').CountDownThemeVars & + import('../coupon').CouponThemeVars & + import('../coupon-cell').CouponCellThemeVars & + import('../coupon-list').CouponListThemeVars & + import('../dialog').DialogThemeVars & + import('../divider').DividerThemeVars & + import('../dropdown-item').DropdownItemThemeVars & + import('../dropdown-menu').DropdownMenuThemeVars & + import('../empty').EmptyThemeVars & + import('../field').FieldThemeVars & + import('../floating-bubble').FloatingBubbleThemeVars & + import('../floating-panel').FloatingPanelThemeVars & + import('../grid-item').GridItemThemeVars & + import('../image').ImageThemeVars & + import('../image-preview').ImagePreviewThemeVars & + import('../index-anchor').IndexAnchorThemeVars & + import('../index-bar').IndexBarThemeVars & + import('../list').ListThemeVars & + import('../loading').LoadingThemeVars & + import('../nav-bar').NavBarThemeVars & + import('../notice-bar').NoticeBarThemeVars & + import('../notify').NotifyThemeVars & + import('../number-keyboard').NumberKeyboardThemeVars & + import('../overlay').OverlayThemeVars & + import('../pagination').PaginationThemeVars & + import('../password-input').PasswordInputThemeVars & + import('../picker').PickerThemeVars & + import('../picker-group').PickerGroupThemeVars & + import('../popover').PopoverThemeVars & + import('../popup').PopupThemeVars & + import('../progress').ProgressThemeVars & + import('../pull-refresh').PullRefreshThemeVars & + import('../radio').RadioThemeVars & + import('../rate').RateThemeVars & + import('../rolling-text').RollingTextThemeVars & + import('../search').SearchThemeVars & + import('../share-sheet').ShareSheetThemeVars & + import('../sidebar').SidebarThemeVars & + import('../sidebar-item').SidebarItemThemeVars & + import('../signature').SignatureThemeVars & + import('../skeleton').SkeletonThemeVars & + import('../slider').SliderThemeVars & + import('../step').StepThemeVars & + import('../stepper').StepperThemeVars & + import('../steps').StepsThemeVars & + import('../sticky').StickyThemeVars & + import('../submit-bar').SubmitBarThemeVars & + import('../swipe').SwipeThemeVars & + import('../switch').SwitchThemeVars & + import('../tabbar').TabbarThemeVars & + import('../tabbar-item').TabbarItemThemeVars & + import('../tabs').TabsThemeVars & + import('../tag').TagThemeVars & + import('../toast').ToastThemeVars & + import('../tree-select').TreeSelectThemeVars & + import('../uploader').UploaderThemeVars & + import('../watermark').WatermarkThemeVars; diff --git a/packages/vant/vant.config.mjs b/packages/vant/vant.config.mjs index 78640b77bce..70bd2022bc9 100644 --- a/packages/vant/vant.config.mjs +++ b/packages/vant/vant.config.mjs @@ -149,6 +149,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io'); path: 'toast', title: 'Toast 轻提示', }, + { + path: 'block', + title: 'Block 块级组件', + }, ], }, { @@ -617,6 +621,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io'); path: 'toast', title: 'Toast', }, + { + path: 'block', + title: 'Block', + }, ], }, {