From 6567e31742995182c12f70ee95bd9a05dabf407a Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" Date: Thu, 29 Jun 2023 14:51:49 +0800 Subject: [PATCH 01/11] feat: add new component `Skeleton` --- packages/arcodesign/components/index.ts | 1 + .../components/skeleton/README.en-US.md | 60 ++ .../arcodesign/components/skeleton/README.md | 60 ++ .../skeleton/__ast__/index.ast.json | 477 ++++++++++++++++ .../__test__/__snapshots__/index.spec.js.snap | 513 ++++++++++++++++++ .../skeleton/__test__/index.spec.js | 82 +++ .../components/skeleton/demo/animation.md | 34 ++ .../components/skeleton/demo/avatar.md | 11 + .../components/skeleton/demo/custom.md | 46 ++ .../components/skeleton/demo/grid.md | 11 + .../components/skeleton/demo/index.md | 11 + .../skeleton/demo/style/mobile.less | 16 + .../components/skeleton/elements.tsx | 286 ++++++++++ .../arcodesign/components/skeleton/index.tsx | 91 ++++ .../components/skeleton/skeleton-context.tsx | 6 + .../components/skeleton/style/index.less | 141 +++++ .../components/skeleton/style/index.ts | 3 + .../arcodesign/components/skeleton/type.ts | 105 ++++ packages/arcodesign/components/style.ts | 1 + .../app/arcodesign/default/css-variables.less | 11 + .../tokens/app/arcodesign/default/index.d.ts | 11 + .../tokens/app/arcodesign/default/index.js | 13 +- .../tokens/app/arcodesign/default/index.json | 130 +++++ .../tokens/app/arcodesign/default/index.less | 11 + .../tokens/src/arcodesign/default/index.js | 53 ++ 25 files changed, 2183 insertions(+), 1 deletion(-) create mode 100644 packages/arcodesign/components/skeleton/README.en-US.md create mode 100644 packages/arcodesign/components/skeleton/README.md create mode 100644 packages/arcodesign/components/skeleton/__ast__/index.ast.json create mode 100644 packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap create mode 100644 packages/arcodesign/components/skeleton/__test__/index.spec.js create mode 100644 packages/arcodesign/components/skeleton/demo/animation.md create mode 100644 packages/arcodesign/components/skeleton/demo/avatar.md create mode 100644 packages/arcodesign/components/skeleton/demo/custom.md create mode 100644 packages/arcodesign/components/skeleton/demo/grid.md create mode 100644 packages/arcodesign/components/skeleton/demo/index.md create mode 100644 packages/arcodesign/components/skeleton/demo/style/mobile.less create mode 100644 packages/arcodesign/components/skeleton/elements.tsx create mode 100644 packages/arcodesign/components/skeleton/index.tsx create mode 100644 packages/arcodesign/components/skeleton/skeleton-context.tsx create mode 100644 packages/arcodesign/components/skeleton/style/index.less create mode 100644 packages/arcodesign/components/skeleton/style/index.ts create mode 100644 packages/arcodesign/components/skeleton/type.ts diff --git a/packages/arcodesign/components/index.ts b/packages/arcodesign/components/index.ts index ea9ecc74..8df12bd0 100644 --- a/packages/arcodesign/components/index.ts +++ b/packages/arcodesign/components/index.ts @@ -44,6 +44,7 @@ export { default as Portal } from './portal'; export { default as Progress } from './progress'; export { default as PullRefresh } from './pull-refresh'; export { default as SearchBar } from './search-bar'; +export { default as Skeleton } from './skeleton'; export { default as Stepper } from './stepper'; export { default as Steps } from './steps'; export { default as Sticky } from './sticky'; diff --git a/packages/arcodesign/components/skeleton/README.en-US.md b/packages/arcodesign/components/skeleton/README.en-US.md new file mode 100644 index 00000000..f1b0c0d0 --- /dev/null +++ b/packages/arcodesign/components/skeleton/README.en-US.md @@ -0,0 +1,60 @@ +### Data Display + +# Skeleton + +Display a set of placeholder graphics during content loading + +====== + +> Props + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|animation|Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed|"gradient" \| "breath"|-| +|title|Show title placeholder|boolean \| SkeletonTitleProps|true| +|paragraph|Show paragraph placeholder|boolean \| SkeletonParagraphProps|true| +|avatar|Show Avatar placeholder|boolean \| SkeletonAvatarProps|false| +|grid|Show Grid placeholder\. When it's value is present, the paragraph, avatar or title placeholder will not be displayed|boolean \| SkeletonGridProps|false| +|children|Children element|ReactNode|null| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Refs + +|Property|Description|Type| +|----------|-------------|------| +|dom|The outer DOM element of the component|HTMLDivElement| + +> SkeletonTitleProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|width|The width of title|ReactText|'38%'| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonParagraphProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|rows|Number of lines for paragraph|number|3| +|width|The width of paragraph\. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line|string \| number \| ReactText\[\]|'58%'| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonAvatarProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|shape|Shape of avatar|"circle" \| "square"|'circle'| +|size|Size of avatar|"medium" \| "large" \| "small" \| "smaller" \| "ultra\-small"|'smaller'| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> SkeletonGridProps + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|columns|columns of grid|number|4| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| diff --git a/packages/arcodesign/components/skeleton/README.md b/packages/arcodesign/components/skeleton/README.md new file mode 100644 index 00000000..7169bc3d --- /dev/null +++ b/packages/arcodesign/components/skeleton/README.md @@ -0,0 +1,60 @@ +### 信息展示 + +# 骨架屏 Skeleton + +在内容加载过程中展示一组占位图形。 + +====== + +> 属性/Props + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|animation|加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果|"gradient" \| "breath"|-| +|title|是否显示标题占位图|boolean \| SkeletonTitleProps|true| +|paragraph|是否显示段落占位图|boolean \| SkeletonParagraphProps|true| +|avatar|是否显示头像占位图|boolean \| SkeletonAvatarProps|false| +|grid|是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符)|boolean \| SkeletonGridProps|false| +|children|子元素|ReactNode|null| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> 引用/Refs + +|参数|描述|类型| +|----------|-------------|------| +|dom|最外层 DOM 元素|HTMLDivElement| + +> SkeletonTitleProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|width|标题占位图宽度|ReactText|'38%'| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonParagraphProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|rows|段落占位图的行数|number|3| +|width|段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度|string \| number \| ReactText\[\]|'58%'| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonAvatarProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|shape|头像形状|"circle" \| "square"|'circle'| +|size|头像尺寸|"medium" \| "large" \| "small" \| "smaller" \| "ultra\-small"|'smaller'| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> SkeletonGridProps + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|columns|金刚位列数|number|4| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| diff --git a/packages/arcodesign/components/skeleton/__ast__/index.ast.json b/packages/arcodesign/components/skeleton/__ast__/index.ast.json new file mode 100644 index 00000000..c202bf2d --- /dev/null +++ b/packages/arcodesign/components/skeleton/__ast__/index.ast.json @@ -0,0 +1,477 @@ +{ + "description": "在内容加载过程中展示一组占位图形。", + "descriptionTags": { + "en": "Display a set of placeholder graphics during content loading", + "type": "信息展示", + "type_en": "Data Display", + "name": "骨架屏", + "name_en": "Skeleton" + }, + "displayName": "Skeleton", + "methods": [], + "props": { + "animation": { + "defaultValue": null, + "description": "加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果\n@en Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed", + "name": "animation", + "tags": { + "en": "Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed" + }, + "descWithTags": "加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "enum", + "raw": "\"gradient\" | \"breath\"", + "value": [ + { + "value": "\"gradient\"" + }, + { + "value": "\"breath\"" + } + ] + } + }, + "title": { + "defaultValue": { + "value": "true" + }, + "description": "是否显示标题占位图\n@en Show title placeholder", + "name": "title", + "tags": { + "en": "Show title placeholder", + "default": "true" + }, + "descWithTags": "是否显示标题占位图", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonTitleProps" + } + }, + "paragraph": { + "defaultValue": { + "value": "true" + }, + "description": "是否显示段落占位图\n@en Show paragraph placeholder", + "name": "paragraph", + "tags": { + "en": "Show paragraph placeholder", + "default": "true" + }, + "descWithTags": "是否显示段落占位图", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonParagraphProps" + } + }, + "avatar": { + "defaultValue": { + "value": "false" + }, + "description": "是否显示头像占位图\n@en Show Avatar placeholder", + "name": "avatar", + "tags": { + "en": "Show Avatar placeholder", + "default": "false" + }, + "descWithTags": "是否显示头像占位图", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonAvatarProps" + } + }, + "grid": { + "defaultValue": { + "value": "false" + }, + "description": "是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符)\n@en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed", + "name": "grid", + "tags": { + "en": "Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed", + "default": "false" + }, + "descWithTags": "是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符)", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean | SkeletonGridProps" + } + }, + "children": { + "defaultValue": { + "value": "null" + }, + "description": "子元素\n@en Children element", + "name": "children", + "tags": { + "en": "Children element", + "default": "null" + }, + "descWithTags": "子元素", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonTitleProps": { + "width": { + "name": "width", + "required": false, + "description": "标题占位图宽度\n@en The width of title", + "defaultValue": { + "value": "'38%'" + }, + "type": { + "name": "ReactText" + }, + "tags": { + "en": "The width of title", + "default": "'38%'" + }, + "descWithTags": "标题占位图宽度" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonParagraphProps": { + "rows": { + "name": "rows", + "required": false, + "description": "段落占位图的行数\n@en Number of lines for paragraph", + "defaultValue": { + "value": "3" + }, + "type": { + "name": "number" + }, + "tags": { + "en": "Number of lines for paragraph", + "default": "3" + }, + "descWithTags": "段落占位图的行数" + }, + "width": { + "name": "width", + "required": false, + "description": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度\n@en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "defaultValue": { + "value": "'58%'" + }, + "type": { + "name": "string | number | ReactText[]" + }, + "tags": { + "en": "The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "default": "'58%'" + }, + "descWithTags": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonAvatarProps": { + "shape": { + "name": "shape", + "required": false, + "description": "头像形状\n@en Shape of avatar", + "defaultValue": { + "value": "'circle'" + }, + "type": { + "name": "enum", + "raw": "\"circle\" | \"square\"", + "value": [ + { + "value": "\"circle\"" + }, + { + "value": "\"square\"" + } + ] + }, + "tags": { + "en": "Shape of avatar", + "default": "'circle'" + }, + "descWithTags": "头像形状" + }, + "size": { + "name": "size", + "required": false, + "description": "头像尺寸\n@en Size of avatar", + "defaultValue": { + "value": "'smaller'" + }, + "type": { + "name": "enum", + "raw": "\"medium\" | \"large\" | \"small\" | \"smaller\" | \"ultra-small\"", + "value": [ + { + "value": "\"medium\"" + }, + { + "value": "\"large\"" + }, + { + "value": "\"small\"" + }, + { + "value": "\"smaller\"" + }, + { + "value": "\"ultra-small\"" + } + ] + }, + "tags": { + "en": "Size of avatar", + "default": "'smaller'" + }, + "descWithTags": "头像尺寸" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonGridProps": { + "columns": { + "name": "columns", + "required": false, + "description": "金刚位列数\n@en columns of grid", + "defaultValue": { + "value": "4" + }, + "type": { + "name": "number" + }, + "tags": { + "en": "columns of grid", + "default": "4" + }, + "descWithTags": "金刚位列数" + }, + "className": { + "name": "className", + "required": false, + "description": "自定义类名\n@en Custom classname", + "defaultValue": { + "value": "\"\"" + }, + "type": { + "name": "string" + }, + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名" + }, + "style": { + "name": "style", + "required": false, + "description": "自定义样式\n@en Custom stylesheet", + "defaultValue": { + "value": "{}" + }, + "type": { + "name": "CSSProperties" + }, + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式" + } + }, + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonProps", + "ref": "SkeletonRef" + }, + "isDefaultExport": true +} \ No newline at end of file diff --git a/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap b/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap new file mode 100644 index 00000000..73ef363d --- /dev/null +++ b/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap @@ -0,0 +1,513 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`skeleton demo test skeleton demo: animation.md renders correctly 1`] = ` +
+
+ + +
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: avatar.md renders correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: custom.md renders correctly 1`] = ` +
+
+
+
+
+
+
+ loading +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: grid.md renders correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`skeleton demo test skeleton demo: index.md renders correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+`; diff --git a/packages/arcodesign/components/skeleton/__test__/index.spec.js b/packages/arcodesign/components/skeleton/__test__/index.spec.js new file mode 100644 index 00000000..fe84a528 --- /dev/null +++ b/packages/arcodesign/components/skeleton/__test__/index.spec.js @@ -0,0 +1,82 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import demoTest from '../../../tests/demoTest'; +import mountTest from '../../../tests/mountTest'; +import { defaultContext } from '../../context-provider'; +import Skeleton from '..'; + +demoTest('skeleton'); + +mountTest(Skeleton, 'Skeleton'); + +const prefix = `${defaultContext.prefixCls}-skeleton`; + +describe('Skeleton', () => { + it('should render correctly when set ref', () => { + const ref = React.createRef(); + const titleRef = React.createRef(); + const paragraphRef = React.createRef(); + const avatarRef = React.createRef(); + const nodeRef = React.createRef(); + mount( + + + + + +
+ + , + ); + expect(ref.current.dom).not.toBeUndefined(); + expect(titleRef.current.dom).not.toBeUndefined(); + expect(paragraphRef.current.dom).not.toBeUndefined(); + expect(avatarRef.current.dom).not.toBeUndefined(); + expect(nodeRef.current.dom).not.toBeUndefined(); + }); + it('should render correctly when set avatar', () => { + const comp = mount(); + expect(comp.find(`.${prefix}-avatar`).length).toBe(1); + comp.setProps({ + avatar: { shape: 'square' }, + }); + expect(comp.find(`.${defaultContext.prefixCls}-avatar-shape-square`).length).toBe(1); + }); + it('should render correctly when set grid', () => { + const comp = mount(); + expect(comp.find(`.${prefix}-grid-item`).length).toBe(5); + }); + it('should render correctly when set children', () => { + const comp = mount( + + +
+ + , + ); + expect(comp.find(`.${prefix}-node`).length).toBe(1); + expect(comp.find(`.${prefix}-title`).length).toBe(1); + expect(comp.find(`.${prefix}-paragraph`).length).toBe(1); + }); + it('should render correctly when set animation', () => { + const comp = mount( + + +
+ + , + ); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); + comp.setProps({ + animation: 'gradient', + }); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(5); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); + comp.setProps({ + animation: 'breath', + }); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(5); + }); +}); diff --git a/packages/arcodesign/components/skeleton/demo/animation.md b/packages/arcodesign/components/skeleton/demo/animation.md new file mode 100644 index 00000000..f64077bb --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/animation.md @@ -0,0 +1,34 @@ +## 动效 @en{Animation} + +#### 5 + +```js +import { Cell, Checkbox, Radio, Skeleton, Switch } from '@arco-design/mobile-react'; + +const options = [ + { label: 'gradient', value: 'gradient' }, + { label: 'breath', value: 'breath' }, +]; + +const themes = [ + { label: 'light', value: 'light' }, + { label: 'dark', value: 'dark' }, +]; + +export default function SkeletonDemo() { + const [type, setType] = React.useState('gradient'); + const [theme, setTheme] = React.useState('light'); + return ( +
+ + + +
+ ); +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/avatar.md b/packages/arcodesign/components/skeleton/demo/avatar.md new file mode 100644 index 00000000..05165490 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/avatar.md @@ -0,0 +1,11 @@ +## 含头像 @en{With avatar} + +#### 2 + +```js +import { Skeleton } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + return ; +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/custom.md b/packages/arcodesign/components/skeleton/demo/custom.md new file mode 100644 index 00000000..7bd20242 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/custom.md @@ -0,0 +1,46 @@ +## 独立节点自由组合 @en{Custom} + +#### 5 + +```js +import { Cell, Skeleton, Switch } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + const [loading, setLoading] = React.useState(true); + return ( +
+ + + + + + {loading ? ( + + +
+ + +
+ +
+ + + + ) : ( +
actual content
+ )} +
+ ); +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/grid.md b/packages/arcodesign/components/skeleton/demo/grid.md new file mode 100644 index 00000000..450df531 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/grid.md @@ -0,0 +1,11 @@ +## 金刚区 @en{Grid} + +#### 3 + +```js +import { Skeleton } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + return +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/index.md b/packages/arcodesign/components/skeleton/demo/index.md new file mode 100644 index 00000000..00aeff23 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/index.md @@ -0,0 +1,11 @@ +## 基础用法 @en{Basic} + +#### 1 + +```js +import { Skeleton } from '@arco-design/mobile-react'; + +export default function SkeletonDemo() { + return +} +``` diff --git a/packages/arcodesign/components/skeleton/demo/style/mobile.less b/packages/arcodesign/components/skeleton/demo/style/mobile.less new file mode 100644 index 00000000..f6e46152 --- /dev/null +++ b/packages/arcodesign/components/skeleton/demo/style/mobile.less @@ -0,0 +1,16 @@ +@import '../../../../style/mixin.less'; + +#demo-skeleton { + .arcodesign-mobile-demo-content { + .dark { + background-color: #0e0e0e; + color: white; + .arco-skeleton-item { + background-color: rgba(255, 255, 255, 0.2); + } + .arco-radio .radio-text { + color: white; + } + } + } +} diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx new file mode 100644 index 00000000..8f5ed589 --- /dev/null +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -0,0 +1,286 @@ +import React, { + Ref, + forwardRef, + useContext, + useEffect, + useImperativeHandle, + useRef, + useState, +} from 'react'; +import { cls, isArray } from '@arco-design/mobile-utils'; +import { useListenResize } from '../_helpers'; +import { ContextLayout } from '../context-provider'; +import Avatar from '../avatar'; +import { + SkeletonAvatarProps, + SkeletonGridProps, + SkeletonNodeProps, + SkeletonParagraphProps, + SkeletonRef, + SkeletonTitleProps, +} from './type'; +import { SkeletonContext } from './skeleton-context'; + +const calcOffset = (dom?: HTMLElement | null) => { + if (!dom) { + return 0; + } + return dom.offsetTop + dom.offsetLeft + 0.5 * dom.offsetHeight; +}; + +function useOffset | T[]>( + dom?: K, +) { + const [offset, setOffset] = useState(0); + const calcLayout = () => { + const isList = Array.isArray(dom); + if ( + !(isList ? (dom as T[]).length > 0 : (dom as React.MutableRefObject)?.current) + ) { + return; + } + setOffset( + isList + ? (dom as T[]).map(calcOffset) + : calcOffset((dom as React.MutableRefObject).current), + ); + }; + + useEffect(() => { + calcLayout(); + }, []); + + useListenResize(calcLayout); + return offset as K extends T[] ? number[] : number; +} + +export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref) => { + const { className = '', style, children } = props; + const { animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const isGradientAnimation = animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( + + {({ prefixCls }) => ( +
+ {children} + {isGradientAnimation && ( +
+ )} +
+ )} + + ); +}); + +export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref) => { + const { className = '', style, width = '38%' } = props; + const { animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const isGradientAnimation = animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( + + {({ prefixCls }) => ( +
+ {isGradientAnimation && ( +
+ )} +
+ )} + + ); +}); + +export const SkeletonParagraph = forwardRef( + (props: SkeletonParagraphProps, ref: Ref) => { + const { className = '', style, rows = 3, width } = props; + const { animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const lineDomRefs = useRef([]); + const isGradientAnimation = animation === 'gradient'; + const offsets = useOffset(isGradientAnimation ? lineDomRefs.current : undefined); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + const getWidth = (idx: number) => { + if (isArray(width)) { + return width[idx]; + } + if (rows - 1 === idx) { + return width; + } + return undefined; + }; + + return ( + + {({ prefixCls }) => ( +
+ {Array.from(new Array(rows)).map((_, idx) => ( +
el && (lineDomRefs.current[idx] = el)} + > + {isGradientAnimation && ( +
+ )} +
+ ))} +
+ )} + + ); + }, +); + +export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref) => { + const { className = '', style, shape = 'circle', size = 'smaller' } = props; + const { animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const isGradientAnimation = animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( + + {({ prefixCls }) => ( +
+ +
+ {isGradientAnimation && ( +
+ )} +
+ +
+ )} + + ); +}); + +export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref) => { + const { className = '', style, columns = 4 } = props; + const { animation } = useContext(SkeletonContext); + const domRef = useRef(null); + const iconDomRefs = useRef([]); + const textDomRefs = useRef([]); + const isGradientAnimation = animation === 'gradient'; + const iconOffsets = useOffset(isGradientAnimation ? iconDomRefs.current : undefined); + const textOffsets = useOffset(isGradientAnimation ? textDomRefs.current : undefined); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + return ( + + {({ prefixCls }) => ( +
+ {Array.from(new Array(columns)).map((_, idx) => ( +
+
el && (iconDomRefs.current[idx] = el)} + > + {isGradientAnimation && ( +
+ )} +
+
el && (textDomRefs.current[idx] = el)} + > + {isGradientAnimation && ( +
+ )} +
+
+ ))} +
+ )} + + ); +}); diff --git a/packages/arcodesign/components/skeleton/index.tsx b/packages/arcodesign/components/skeleton/index.tsx new file mode 100644 index 00000000..0473a09b --- /dev/null +++ b/packages/arcodesign/components/skeleton/index.tsx @@ -0,0 +1,91 @@ +import React, { useRef, forwardRef, Ref, useImperativeHandle, useContext } from 'react'; +import { cls, componentWrapper } from '@arco-design/mobile-utils'; +import { GlobalContext } from '../context-provider'; +import { SkeletonProps, SkeletonRef } from './type'; +import { + SkeletonAvatar, + SkeletonGrid, + SkeletonNode, + SkeletonParagraph, + SkeletonTitle, +} from './elements'; +import { SkeletonContext } from './skeleton-context'; + +function getComponentProps(prop?: T | boolean): T | {} { + if (prop && typeof prop === 'object') { + return prop; + } + return {}; +} + +const Skeleton = forwardRef((props: SkeletonProps, ref: Ref) => { + const { + className = '', + style, + children, + animation, + title = true, + paragraph = true, + avatar = false, + grid, + } = props; + const domRef = useRef(null); + const { prefixCls } = useContext(GlobalContext); + + useImperativeHandle(ref, () => ({ + dom: domRef.current, + })); + + const isGrid = !!grid; + const hasTitle = !!title; + const hasParagraph = !!paragraph; + const hasAvatar = !!avatar; + const content = isGrid ? ( + + ) : ( + <> + {hasAvatar && } + {(hasTitle || hasParagraph) && ( +
+ {hasTitle && } + {hasParagraph && } +
+ )} + + ); + + return ( +
+ + {content} + {children} + +
+ ); +}); + +/** + * 在内容加载过程中展示一组占位图形。 + * @en Display a set of placeholder graphics during content loading + * @type 信息展示 + * @type_en Data Display + * @name 骨架屏 + * @name_en Skeleton + */ +export default componentWrapper(Skeleton, { + Node: SkeletonNode, + Title: SkeletonTitle, + Paragraph: SkeletonParagraph, + Avatar: SkeletonAvatar, + Grid: SkeletonGrid, +}); diff --git a/packages/arcodesign/components/skeleton/skeleton-context.tsx b/packages/arcodesign/components/skeleton/skeleton-context.tsx new file mode 100644 index 00000000..0b2dc361 --- /dev/null +++ b/packages/arcodesign/components/skeleton/skeleton-context.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { SkeletonContextParams } from './type'; + +export const SkeletonContext = React.createContext({ + animation: undefined, +}); diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less new file mode 100644 index 00000000..56230ca3 --- /dev/null +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -0,0 +1,141 @@ +@import '../../../style/mixin.less'; + +.@{prefix}-skeleton { + position: relative; +} + +.@{prefix}-skeleton-title { + .use-var(height, 'skeleton-title-height'); +} + +.@{prefix}-skeleton-paragraph { + &-line { + width: 100%; + .use-var(height, 'skeleton-paragraph-height'); + + &:last-child:not(:first-child):not(:nth-child(2)) { + width: 58%; + } + } + + &-line + &-line { + .use-var(margin-top, 'skeleton-paragraph-margin-top'); + } +} + +.@{prefix}-skeleton-avatar { + .@{prefix}-avatar { + background-color: transparent; + overflow: hidden; + } + .@{prefix}-skeleton-item { + width: 100%; + height: 100%; + } +} + +.@{prefix}-skeleton-content { + width: 100%; + + .@{prefix}-skeleton-title + .@{prefix}-skeleton-paragraph { + .use-var(margin-top, 'skeleton-gutter-large'); + } +} + +.@{prefix}-skeleton-with-avatar { + display: flex; + align-items: flex-start; + + .@{prefix}-skeleton-content { + .@{prefix}-skeleton-title { + .use-var(margin-top, 'skeleton-gutter-medium'); + } + } + + .@{prefix}-skeleton-avatar + .@{prefix}-skeleton-content { + .use-var(margin-left, 'skeleton-gutter-medium'); + } +} + +.@{prefix}-skeleton-grid { + display: flex; + justify-content: space-between; + width: 100%; + + &-item { + display: flex; + flex-direction: column; + align-items: center; + } + &-icon { + .use-var(width, 'skeleton-grid-icon-width'); + .use-var(height, 'skeleton-grid-icon-width'); + } + &-text { + .use-var(margin-top, 'skeleton-gutter-medium'); + .use-var(width, 'skeleton-grid-text-width'); + .use-var(height, 'skeleton-grid-text-height'); + } +} + +.@{prefix}-skeleton-node { + display: inline-block; + width: auto; +} + +.@{prefix}-skeleton-item { + position: relative; + overflow: hidden; + .use-var(border-radius, 'skeleton-border-radius'); + .use-var(background-color, 'skeleton-background-color'); +} + +.@{prefix}-skeleton-animation-item { + position: absolute; + width: 200vw; + height: 100%; + top: 0; + left: 0; + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 25%, + @skeleton-gradient-animation-color 40%, + rgba(255, 255, 255, 0) 55% + ); + & when (@use-css-vars = 1) { + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 25%, + var(--skeleton-gradient-animation-color) 40%, + rgba(255, 255, 255, 0) 55% + ); + } + animation: gradient 2s linear infinite; +} +.@{prefix}-skeleton-animation-breath { + animation: breath 2s linear infinite; +} + +@keyframes gradient { + 0% { + transform: translateX(-200%) skewX(-45deg); + } + + 100% { + transform: translateX(200%) skewX(-45deg); + } +} + +@keyframes breath { + 0% { + opacity: 1; + } + + 50% { + opacity: 0.3; + } + + 100% { + opacity: 1; + } +} diff --git a/packages/arcodesign/components/skeleton/style/index.ts b/packages/arcodesign/components/skeleton/style/index.ts new file mode 100644 index 00000000..d33b50ec --- /dev/null +++ b/packages/arcodesign/components/skeleton/style/index.ts @@ -0,0 +1,3 @@ +import '../../../style/public.less'; +import '../../avatar/style'; +import './index.less'; diff --git a/packages/arcodesign/components/skeleton/type.ts b/packages/arcodesign/components/skeleton/type.ts new file mode 100644 index 00000000..fec85f57 --- /dev/null +++ b/packages/arcodesign/components/skeleton/type.ts @@ -0,0 +1,105 @@ +import { BaseProps, SimpleBaseProps } from '../_helpers'; +import { AvatarProps } from '../avatar'; + +export interface SkeletonProps extends SimpleBaseProps { + /** + * 加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果 + * @en Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed + */ + animation?: 'gradient' | 'breath'; + /** + * 是否显示标题占位图 + * @en Show title placeholder + * @default true + */ + title?: boolean | SkeletonTitleProps; + /** + * 是否显示段落占位图 + * @en Show paragraph placeholder + * @default true + */ + paragraph?: boolean | SkeletonParagraphProps; + /** + * 是否显示头像占位图 + * @en Show Avatar placeholder + * @default false + */ + avatar?: boolean | SkeletonAvatarProps; + /** + * 是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符) + * @en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed + * @default false + */ + grid?: boolean | SkeletonGridProps; + /** + * 子元素 + * @en Children element + * @default null + */ + children?: React.ReactNode; +} + +export interface SkeletonTitleProps extends SimpleBaseProps { + /** + * 标题占位图宽度 + * @en The width of title + * @default '38%' + */ + width?: number | string; +} + +export interface SkeletonParagraphProps extends SimpleBaseProps { + /** + * 段落占位图的行数 + * @en Number of lines for paragraph + * @default 3 + */ + rows?: number; + /** + * 段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度 + * @en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line + * @default '58%' + */ + width?: number | string | Array; +} + +export interface SkeletonAvatarProps extends SimpleBaseProps { + /** + * 头像形状 + * @en Shape of avatar + * @default 'circle' + */ + shape?: AvatarProps['shape']; + /** + * 头像尺寸 + * @en Size of avatar + * @default 'smaller' + */ + size?: AvatarProps['size']; +} + +export interface SkeletonGridProps extends SimpleBaseProps { + /** + * 金刚位列数 + * @en columns of grid + * @default 4 + */ + columns?: number; +} + +export interface SkeletonNodeProps extends BaseProps {} + +export interface SkeletonRef { + /** + * 最外层 DOM 元素 + * @en The outer DOM element of the component + */ + dom: HTMLDivElement | null; +} + +export interface SkeletonContextParams { + /** + * 是否开启动效 + */ + animation?: SkeletonProps['animation']; +} diff --git a/packages/arcodesign/components/style.ts b/packages/arcodesign/components/style.ts index b486c534..6b49a734 100644 --- a/packages/arcodesign/components/style.ts +++ b/packages/arcodesign/components/style.ts @@ -45,6 +45,7 @@ import './portal/style'; import './progress/style'; import './pull-refresh/style'; import './search-bar/style'; +import './skeleton/style'; import './stepper/style'; import './steps/style'; import './sticky/style'; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less index 9f16beae..e313102d 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less @@ -793,4 +793,15 @@ --divider-right-width: ~`pxtorem(28)`; --divider-content-padding: ~`pxtorem(12)`; --divider-padding: ~`pxtorem(16)`; + --skeleton-border-radius: ~`pxtorem(0)`; + --skeleton-background-color: #F2F3F5; + --skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); + --skeleton-title-height: ~`pxtorem(16)`; + --skeleton-paragraph-height: ~`pxtorem(16)`; + --skeleton-paragraph-margin-top: ~`pxtorem(12)`; + --skeleton-grid-icon-width: ~`pxtorem(32)`; + --skeleton-grid-text-width: ~`pxtorem(64)`; + --skeleton-grid-text-height: ~`pxtorem(16)`; + --skeleton-gutter-medium: ~`pxtorem(8)`; + --skeleton-gutter-large: ~`pxtorem(20)`; } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts index 69b0c649..fc5567fe 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts @@ -792,6 +792,17 @@ export interface ArcodesignToken extends Record { 'divider-right-width': string; 'divider-content-padding': string; 'divider-padding': string; + 'skeleton-border-radius': string; + 'skeleton-background-color': string; + 'skeleton-gradient-animation-color': string; + 'skeleton-title-height': string; + 'skeleton-paragraph-height': string; + 'skeleton-paragraph-margin-top': string; + 'skeleton-grid-icon-width': string; + 'skeleton-grid-text-width': string; + 'skeleton-grid-text-height': string; + 'skeleton-gutter-medium': string; + 'skeleton-gutter-large': string; } declare const tokens: ArcodesignToken; export default tokens; \ No newline at end of file diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index f48a7f69..a41f6b5d 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -803,7 +803,18 @@ var tokens = { "divider-left-width": "0.56rem", "divider-right-width": "0.56rem", "divider-content-padding": "0.24rem", - "divider-padding": "0.32rem" + "divider-padding": "0.32rem", + "skeleton-border-radius": "0", + "skeleton-background-color": "#F2F3F5", + "skeleton-gradient-animation-color": "rgba(255, 255, 255, 0.6)", + "skeleton-title-height": "0.32rem", + "skeleton-paragraph-height": "0.32rem", + "skeleton-paragraph-margin-top": "0.24rem", + "skeleton-grid-icon-width": "0.64rem", + "skeleton-grid-text-width": "1.28rem", + "skeleton-grid-text-height": "0.32rem", + "skeleton-gutter-medium": "0.16rem", + "skeleton-gutter-large": "0.4rem" }; var _default = tokens; exports["default"] = _default; \ No newline at end of file diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.json b/packages/arcodesign/tokens/app/arcodesign/default/index.json index 43a012d4..c9315dd7 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.json +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.json @@ -6629,6 +6629,136 @@ "en": "Size of the rounded corners of the square SearchBar" } }, + "skeletonBackgroundColor": { + "cssKey": "skeleton-background-color", + "desc": "骨架屏元素背景色", + "override": "", + "value": "#F2F3F5", + "jsValue": "#F2F3F5", + "staticValue": "#F2F3F5", + "localeDesc": { + "ch": "骨架屏元素背景色", + "en": "Skeleton element background color" + } + }, + "skeletonBorderRadius": { + "cssKey": "skeleton-border-radius", + "desc": "骨架屏元素圆角", + "override": "", + "value": "~`pxtorem(0)`", + "jsValue": "@getRem@0", + "staticValue": "0", + "localeDesc": { + "ch": "骨架屏元素圆角", + "en": "Skeleton element border radius" + } + }, + "skeletonGradientAnimationColor": { + "cssKey": "skeleton-gradient-animation-color", + "desc": "骨架屏扫光高亮色", + "override": "", + "value": "rgba(255, 255, 255, 0.6)", + "jsValue": "rgba(255, 255, 255, 0.6)", + "staticValue": "rgba(255, 255, 255, 0.6)", + "localeDesc": { + "ch": "骨架屏扫光高亮色", + "en": "Skeleton element gradient animation highlight color" + } + }, + "skeletonGridIconWidth": { + "cssKey": "skeleton-grid-icon-width", + "desc": "骨架屏金刚位图标区宽度", + "override": "", + "value": "~`pxtorem(32)`", + "jsValue": "@getRem@32", + "staticValue": "0.64rem", + "localeDesc": { + "ch": "骨架屏金刚位图标区宽度", + "en": "Skeleton grid item icon width" + } + }, + "skeletonGridTextHeight": { + "cssKey": "skeleton-grid-text-height", + "desc": "骨架屏金刚位文字区高度", + "override": "", + "value": "~`pxtorem(16)`", + "jsValue": "@getRem@16", + "staticValue": "0.32rem", + "localeDesc": { + "ch": "骨架屏金刚位文字区高度", + "en": "Skeleton grid item text height" + } + }, + "skeletonGridTextWidth": { + "cssKey": "skeleton-grid-text-width", + "desc": "骨架屏金刚位文字区宽度", + "override": "", + "value": "~`pxtorem(64)`", + "jsValue": "@getRem@64", + "staticValue": "1.28rem", + "localeDesc": { + "ch": "骨架屏金刚位文字区宽度", + "en": "Skeleton grid item text width" + } + }, + "skeletonGutterLarge": { + "cssKey": "skeleton-gutter-large", + "desc": "骨架屏元素外边距,大尺寸", + "override": "", + "value": "~`pxtorem(20)`", + "jsValue": "@getRem@20", + "staticValue": "0.4rem", + "localeDesc": { + "ch": "骨架屏元素外边距,大尺寸" + } + }, + "skeletonGutterMedium": { + "cssKey": "skeleton-gutter-medium", + "desc": "骨架屏元素外边距,中尺寸", + "override": "", + "value": "~`pxtorem(8)`", + "jsValue": "@getRem@8", + "staticValue": "0.16rem", + "localeDesc": { + "ch": "骨架屏元素外边距,中尺寸" + } + }, + "skeletonParagraphHeight": { + "cssKey": "skeleton-paragraph-height", + "desc": "骨架屏段落行高度", + "override": "", + "value": "~`pxtorem(16)`", + "jsValue": "@getRem@16", + "staticValue": "0.32rem", + "localeDesc": { + "ch": "骨架屏段落行高度", + "en": "Skeleton paragraph line height" + } + }, + "skeletonParagraphMarginTop": { + "cssKey": "skeleton-paragraph-margin-top", + "desc": "骨架屏各段落行间距", + "override": "", + "value": "~`pxtorem(12)`", + "jsValue": "@getRem@12", + "staticValue": "0.24rem", + "localeDesc": { + "ch": "骨架屏各段落行间距", + "en": "Margin top between skeleton paragraph lines" + } + }, + "skeletonTitleHeight": { + "cssKey": "skeleton-title-height", + "desc": "骨架屏标题高度", + "override": "", + "value": "~`pxtorem(16)`", + "jsValue": "@getRem@16", + "staticValue": "0.32rem", + "localeDesc": { + "ch": "骨架屏标题高度", + "en": "Skeleton title height" + } + }, "sliderHasMarkPaddingBottom": { "cssKey": "slider-has-mark-padding-bottom", "desc": "slider 有标记时的底部内边距", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.less b/packages/arcodesign/tokens/app/arcodesign/default/index.less index 9c3860b9..830321b7 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.less @@ -792,4 +792,15 @@ @divider-right-width: ~`pxtorem(28)`; @divider-content-padding: ~`pxtorem(12)`; @divider-padding: ~`pxtorem(16)`; +@skeleton-border-radius: ~`pxtorem(0)`; +@skeleton-background-color: #F2F3F5; +@skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); +@skeleton-title-height: ~`pxtorem(16)`; +@skeleton-paragraph-height: ~`pxtorem(16)`; +@skeleton-paragraph-margin-top: ~`pxtorem(12)`; +@skeleton-grid-icon-width: ~`pxtorem(32)`; +@skeleton-grid-text-width: ~`pxtorem(64)`; +@skeleton-grid-text-height: ~`pxtorem(16)`; +@skeleton-gutter-medium: ~`pxtorem(8)`; +@skeleton-gutter-large: ~`pxtorem(20)`; diff --git a/packages/arcodesign/tokens/src/arcodesign/default/index.js b/packages/arcodesign/tokens/src/arcodesign/default/index.js index 1fcd953f..a5cc7159 100644 --- a/packages/arcodesign/tokens/src/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/src/arcodesign/default/index.js @@ -4018,6 +4018,59 @@ function getCompTokens() { * @en Top and Bottom padding of divider */ dividerPadding: getRem(16), + /** + * 骨架屏元素圆角 + * @en Skeleton element border radius + */ + skeletonBorderRadius: getRem(0), + /** + * 骨架屏元素背景色 + * @en Skeleton element background color + */ + skeletonBackgroundColor: '#F2F3F5', + /** + * 骨架屏扫光高亮色 + * @en Skeleton element gradient animation highlight color + */ + skeletonGradientAnimationColor: 'rgba(255, 255, 255, 0.6)', + /** + * 骨架屏标题高度 + * @en Skeleton title height + */ + skeletonTitleHeight: getRem(16), + /** + * 骨架屏段落行高度 + * @en Skeleton paragraph line height + */ + skeletonParagraphHeight: getRem(16), + /** + * 骨架屏各段落行间距 + * @en Margin top between skeleton paragraph lines + */ + skeletonParagraphMarginTop: getRem(12), + /** + * 骨架屏金刚位图标区宽度 + * @en Skeleton grid item icon width + */ + skeletonGridIconWidth: getRem(32), + /** + * 骨架屏金刚位文字区宽度 + * @en Skeleton grid item text width + */ + skeletonGridTextWidth: getRem(64), + /** + * 骨架屏金刚位文字区高度 + * @en Skeleton grid item text height + */ + skeletonGridTextHeight: getRem(16), + /** + * 骨架屏元素外边距,中尺寸 + */ + skeletonGutterMedium: getRem(8), + /** + * 骨架屏元素外边距,大尺寸 + */ + skeletonGutterLarge: getRem(20), }; } From 0d8c3f01b68d9b1964b9a8bd6fa8498fe5617e06 Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" Date: Sun, 2 Jul 2023 16:09:20 +0800 Subject: [PATCH 02/11] feat: support rtl --- .../components/skeleton/elements.tsx | 239 ++++++++---------- .../components/skeleton/style/index.less | 18 +- 2 files changed, 127 insertions(+), 130 deletions(-) diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx index 8f5ed589..4a334ce3 100644 --- a/packages/arcodesign/components/skeleton/elements.tsx +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -9,7 +9,7 @@ import React, { } from 'react'; import { cls, isArray } from '@arco-design/mobile-utils'; import { useListenResize } from '../_helpers'; -import { ContextLayout } from '../context-provider'; +import { GlobalContext } from '../context-provider'; import Avatar from '../avatar'; import { SkeletonAvatarProps, @@ -56,6 +56,7 @@ function useOffset) => { const { className = '', style, children } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); const { animation } = useContext(SkeletonContext); const domRef = useRef(null); const isGradientAnimation = animation === 'gradient'; @@ -66,33 +67,30 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref - {({ prefixCls }) => ( +
+ {children} + {isGradientAnimation && (
- {children} - {isGradientAnimation && ( -
- )} -
+ className={`${prefixCls}-skeleton-animation-item`} + style={{ [useRtl ? 'right' : 'left']: 0 - offset }} + /> )} - +
); }); export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref) => { const { className = '', style, width = '38%' } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); const { animation } = useContext(SkeletonContext); const domRef = useRef(null); const isGradientAnimation = animation === 'gradient'; @@ -103,33 +101,30 @@ export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref - {({ prefixCls }) => ( +
+ {isGradientAnimation && (
- {isGradientAnimation && ( -
- )} -
+ className={`${prefixCls}-skeleton-animation-item`} + style={{ [useRtl ? 'right' : 'left']: 0 - offset }} + /> )} - +
); }); export const SkeletonParagraph = forwardRef( (props: SkeletonParagraphProps, ref: Ref) => { const { className = '', style, rows = 3, width } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); const { animation } = useContext(SkeletonContext); const domRef = useRef(null); const lineDomRefs = useRef([]); @@ -151,43 +146,40 @@ export const SkeletonParagraph = forwardRef( }; return ( - - {({ prefixCls }) => ( +
+ {Array.from(new Array(rows)).map((_, idx) => (
el && (lineDomRefs.current[idx] = el)} > - {Array.from(new Array(rows)).map((_, idx) => ( + {isGradientAnimation && (
el && (lineDomRefs.current[idx] = el)} - > - {isGradientAnimation && ( -
- )} -
- ))} + className={`${prefixCls}-skeleton-animation-item`} + style={{ [useRtl ? 'right' : 'left']: 0 - (offsets[idx] || 0) }} + /> + )}
- )} - + ))} +
); }, ); export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref) => { const { className = '', style, shape = 'circle', size = 'smaller' } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); const { animation } = useContext(SkeletonContext); const domRef = useRef(null); const isGradientAnimation = animation === 'gradient'; @@ -198,33 +190,30 @@ export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref - {({ prefixCls }) => ( -
- +
+ +
+ {isGradientAnimation && (
- {isGradientAnimation && ( -
- )} -
- + className={`${prefixCls}-skeleton-animation-item`} + style={{ [useRtl ? 'right' : 'left']: 0 - offset }} + /> + )}
- )} - + +
); }); export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref) => { const { className = '', style, columns = 4 } = props; + const { useRtl, prefixCls } = useContext(GlobalContext); const { animation } = useContext(SkeletonContext); const domRef = useRef(null); const iconDomRefs = useRef([]); @@ -238,49 +227,43 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref - {({ prefixCls }) => ( -
- {Array.from(new Array(columns)).map((_, idx) => ( -
+
+ {Array.from(new Array(columns)).map((_, idx) => ( +
+
el && (iconDomRefs.current[idx] = el)} + > + {isGradientAnimation && (
el && (iconDomRefs.current[idx] = el)} - > - {isGradientAnimation && ( -
- )} -
+ className={`${prefixCls}-skeleton-animation-item`} + style={{ + [useRtl ? 'right' : 'left']: 0 - (iconOffsets?.[idx] || 0), + }} + /> + )} +
+
el && (textDomRefs.current[idx] = el)} + > + {isGradientAnimation && (
el && (textDomRefs.current[idx] = el)} - > - {isGradientAnimation && ( -
- )} -
-
- ))} + className={`${prefixCls}-skeleton-animation-item`} + style={{ right: 0 - (textOffsets?.[idx] || 0) }} + /> + )} +
- )} - + ))} +
); }); diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index 56230ca3..4d0b4df9 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -53,7 +53,7 @@ } .@{prefix}-skeleton-avatar + .@{prefix}-skeleton-content { - .use-var(margin-left, 'skeleton-gutter-medium'); + .use-var-with-rtl(margin-left, 'skeleton-gutter-medium'); } } @@ -95,7 +95,8 @@ width: 200vw; height: 100%; top: 0; - left: 0; + .set-prop-with-rtl(left, 0); + background-image: linear-gradient( 90deg, rgba(255, 255, 255, 0) 25%, @@ -111,6 +112,9 @@ ); } animation: gradient 2s linear infinite; + [dir='rtl'] & { + animation-name: gradient-reverse; + } } .@{prefix}-skeleton-animation-breath { animation: breath 2s linear infinite; @@ -126,6 +130,16 @@ } } +@keyframes gradient-reverse { + 0% { + transform: translateX(200%) skewX(45deg); + } + + 100% { + transform: translateX(-200%) skewX(45deg); + } +} + @keyframes breath { 0% { opacity: 1; From 6a369698a0a72f55f0d92baef273aea3b6b3e9e1 Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" Date: Tue, 4 Jul 2023 15:40:44 +0800 Subject: [PATCH 03/11] fix: offset calculation --- packages/arcodesign/components/skeleton/elements.tsx | 6 ++++-- packages/arcodesign/components/skeleton/style/index.less | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx index 4a334ce3..60c3e5f1 100644 --- a/packages/arcodesign/components/skeleton/elements.tsx +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -25,7 +25,7 @@ const calcOffset = (dom?: HTMLElement | null) => { if (!dom) { return 0; } - return dom.offsetTop + dom.offsetLeft + 0.5 * dom.offsetHeight; + return dom.offsetTop + dom.offsetLeft; }; function useOffset | T[]>( @@ -258,7 +258,9 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref )}
diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index 4d0b4df9..fa8968f2 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -111,6 +111,7 @@ rgba(255, 255, 255, 0) 55% ); } + transform-origin: top left; animation: gradient 2s linear infinite; [dir='rtl'] & { animation-name: gradient-reverse; From 689231a0dacc868bd16bdd922bb95d3f173697a9 Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" Date: Wed, 5 Jul 2023 16:30:15 +0800 Subject: [PATCH 04/11] feat: optimize --- .../components/skeleton/README.en-US.md | 53 +- .../arcodesign/components/skeleton/README.md | 53 +- .../skeleton/__ast__/index.ast.json | 716 +++++++++++++++--- .../components/skeleton/demo/animation.md | 31 +- .../components/skeleton/demo/custom.md | 4 +- .../components/skeleton/demo/grid.md | 2 +- .../components/skeleton/demo/index.md | 2 +- .../skeleton/demo/style/mobile.less | 15 +- .../components/skeleton/elements.tsx | 117 +-- .../arcodesign/components/skeleton/index.tsx | 37 +- .../components/skeleton/skeleton-context.tsx | 5 +- .../components/skeleton/style/index.less | 38 +- .../arcodesign/components/skeleton/type.ts | 60 +- .../app/arcodesign/default/css-variables.less | 4 +- .../tokens/app/arcodesign/default/index.d.ts | 2 + .../tokens/app/arcodesign/default/index.js | 4 +- .../tokens/app/arcodesign/default/index.json | 34 +- .../tokens/app/arcodesign/default/index.less | 4 +- .../tokens/src/arcodesign/default/index.js | 14 +- 19 files changed, 926 insertions(+), 269 deletions(-) diff --git a/packages/arcodesign/components/skeleton/README.en-US.md b/packages/arcodesign/components/skeleton/README.en-US.md index f1b0c0d0..eb0527ba 100644 --- a/packages/arcodesign/components/skeleton/README.en-US.md +++ b/packages/arcodesign/components/skeleton/README.en-US.md @@ -10,11 +10,14 @@ Display a set of placeholder graphics during content loading |Property|Description|Type|DefaultValue| |----------|-------------|------|------| -|animation|Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed|"gradient" \| "breath"|-| |title|Show title placeholder|boolean \| SkeletonTitleProps|true| |paragraph|Show paragraph placeholder|boolean \| SkeletonParagraphProps|true| |avatar|Show Avatar placeholder|boolean \| SkeletonAvatarProps|false| -|grid|Show Grid placeholder\. When it's value is present, the paragraph, avatar or title placeholder will not be displayed|boolean \| SkeletonGridProps|false| +|grid|Show Grid placeholder\. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default|boolean \| SkeletonGridProps|false| +|showAnimation|Show loading effect|boolean|true| +|animation|Animation of loading effect, 'gradient' and 'breath' effects are optional|"gradient" \| "breath"|"gradient"| +|animationGradientColor|Highlight color of gradient animation|string|"rgba(0, 0, 0, 0.04)"| +|backgroundColor|Background color of skeleton item|string|"#F7F8FA"| |children|Children element|ReactNode|null| |className|Custom classname|string|""| |style|Custom stylesheet|CSSProperties|{}| @@ -25,11 +28,51 @@ Display a set of placeholder graphics during content loading |----------|-------------|------| |dom|The outer DOM element of the component|HTMLDivElement| +> Skeleton.Node + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|children|Custom component content|ReactNode|null| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Title + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|width|The width of title|ReactText|"40%"| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Paragraph + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|rows|Number of lines for paragraph|number|3| +|width|The width of paragraph\. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line|string \| number \| ReactText\[\]|"60%"| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Avatar + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + +> Skeleton.Grid + +|Property|Description|Type|DefaultValue| +|----------|-------------|------|------| +|columns|columns of grid|number|4| +|className|Custom classname|string|""| +|style|Custom stylesheet|CSSProperties|{}| + > SkeletonTitleProps |Property|Description|Type|DefaultValue| |----------|-------------|------|------| -|width|The width of title|ReactText|'38%'| +|width|The width of title|ReactText|"40%"| |className|Custom classname|string|""| |style|Custom stylesheet|CSSProperties|{}| @@ -38,7 +81,7 @@ Display a set of placeholder graphics during content loading |Property|Description|Type|DefaultValue| |----------|-------------|------|------| |rows|Number of lines for paragraph|number|3| -|width|The width of paragraph\. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line|string \| number \| ReactText\[\]|'58%'| +|width|The width of paragraph\. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line|string \| number \| ReactText\[\]|"60%"| |className|Custom classname|string|""| |style|Custom stylesheet|CSSProperties|{}| @@ -46,8 +89,6 @@ Display a set of placeholder graphics during content loading |Property|Description|Type|DefaultValue| |----------|-------------|------|------| -|shape|Shape of avatar|"circle" \| "square"|'circle'| -|size|Size of avatar|"medium" \| "large" \| "small" \| "smaller" \| "ultra\-small"|'smaller'| |className|Custom classname|string|""| |style|Custom stylesheet|CSSProperties|{}| diff --git a/packages/arcodesign/components/skeleton/README.md b/packages/arcodesign/components/skeleton/README.md index 7169bc3d..0a4852aa 100644 --- a/packages/arcodesign/components/skeleton/README.md +++ b/packages/arcodesign/components/skeleton/README.md @@ -10,11 +10,14 @@ |参数|描述|类型|默认值| |----------|-------------|------|------| -|animation|加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果|"gradient" \| "breath"|-| |title|是否显示标题占位图|boolean \| SkeletonTitleProps|true| |paragraph|是否显示段落占位图|boolean \| SkeletonParagraphProps|true| |avatar|是否显示头像占位图|boolean \| SkeletonAvatarProps|false| -|grid|是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符)|boolean \| SkeletonGridProps|false| +|grid|是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符)|boolean \| SkeletonGridProps|false| +|showAnimation|是否展示动画效果|boolean|true| +|animation|加载动画效果,可选“扫光”、“呼吸”两种效果|"gradient" \| "breath"|"gradient"| +|animationGradientColor|扫光动效高光颜色|string|"rgba(0, 0, 0, 0.04)"| +|backgroundColor|占位块背景色|string|"#F7F8FA"| |children|子元素|ReactNode|null| |className|自定义类名|string|""| |style|自定义样式|CSSProperties|{}| @@ -25,11 +28,51 @@ |----------|-------------|------| |dom|最外层 DOM 元素|HTMLDivElement| +> Skeleton.Node + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|children|自定义组件内容|ReactNode|null| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Title + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|width|标题占位图宽度|ReactText|"40%"| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Paragraph + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|rows|段落占位图的行数|number|3| +|width|段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度|string \| number \| ReactText\[\]|"60%"| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Avatar + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + +> Skeleton.Grid + +|参数|描述|类型|默认值| +|----------|-------------|------|------| +|columns|金刚位列数|number|4| +|className|自定义类名|string|""| +|style|自定义样式|CSSProperties|{}| + > SkeletonTitleProps |参数|描述|类型|默认值| |----------|-------------|------|------| -|width|标题占位图宽度|ReactText|'38%'| +|width|标题占位图宽度|ReactText|"40%"| |className|自定义类名|string|""| |style|自定义样式|CSSProperties|{}| @@ -38,7 +81,7 @@ |参数|描述|类型|默认值| |----------|-------------|------|------| |rows|段落占位图的行数|number|3| -|width|段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度|string \| number \| ReactText\[\]|'58%'| +|width|段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度|string \| number \| ReactText\[\]|"60%"| |className|自定义类名|string|""| |style|自定义样式|CSSProperties|{}| @@ -46,8 +89,6 @@ |参数|描述|类型|默认值| |----------|-------------|------|------| -|shape|头像形状|"circle" \| "square"|'circle'| -|size|头像尺寸|"medium" \| "large" \| "small" \| "smaller" \| "ultra\-small"|'smaller'| |className|自定义类名|string|""| |style|自定义样式|CSSProperties|{}| diff --git a/packages/arcodesign/components/skeleton/__ast__/index.ast.json b/packages/arcodesign/components/skeleton/__ast__/index.ast.json index c202bf2d..2a021601 100644 --- a/packages/arcodesign/components/skeleton/__ast__/index.ast.json +++ b/packages/arcodesign/components/skeleton/__ast__/index.ast.json @@ -10,32 +10,6 @@ "displayName": "Skeleton", "methods": [], "props": { - "animation": { - "defaultValue": null, - "description": "加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果\n@en Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed", - "name": "animation", - "tags": { - "en": "Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed" - }, - "descWithTags": "加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果", - "parent": { - "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", - "name": "SkeletonProps" - }, - "required": false, - "type": { - "name": "enum", - "raw": "\"gradient\" | \"breath\"", - "value": [ - { - "value": "\"gradient\"" - }, - { - "value": "\"breath\"" - } - ] - } - }, "title": { "defaultValue": { "value": "true" @@ -100,13 +74,13 @@ "defaultValue": { "value": "false" }, - "description": "是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符)\n@en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed", + "description": "是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符)\n@en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default", "name": "grid", "tags": { - "en": "Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed", + "en": "Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default", "default": "false" }, - "descWithTags": "是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符)", + "descWithTags": "是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符)", "parent": { "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", "name": "SkeletonProps" @@ -116,6 +90,95 @@ "name": "boolean | SkeletonGridProps" } }, + "showAnimation": { + "defaultValue": { + "value": "true" + }, + "description": "是否展示动画效果\n@en Show loading effect", + "name": "showAnimation", + "tags": { + "en": "Show loading effect", + "default": "true" + }, + "descWithTags": "是否展示动画效果", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "animation": { + "defaultValue": { + "value": "\"gradient\"" + }, + "description": "加载动画效果,可选“扫光”、“呼吸”两种效果\n@en Animation of loading effect, 'gradient' and 'breath' effects are optional", + "name": "animation", + "tags": { + "en": "Animation of loading effect, 'gradient' and 'breath' effects are optional", + "default": "\"gradient\"" + }, + "descWithTags": "加载动画效果,可选“扫光”、“呼吸”两种效果", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "enum", + "raw": "\"gradient\" | \"breath\"", + "value": [ + { + "value": "\"gradient\"" + }, + { + "value": "\"breath\"" + } + ] + } + }, + "animationGradientColor": { + "defaultValue": { + "value": "\"rgba(0, 0, 0, 0.04)\"" + }, + "description": "扫光动效高光颜色\n@en Highlight color of gradient animation", + "name": "animationGradientColor", + "tags": { + "en": "Highlight color of gradient animation", + "default": "\"rgba(0, 0, 0, 0.04)\"" + }, + "descWithTags": "扫光动效高光颜色", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "backgroundColor": { + "defaultValue": { + "value": "\"#F7F8FA\"" + }, + "description": "占位块背景色\n@en Background color of skeleton item", + "name": "backgroundColor", + "tags": { + "en": "Background color of skeleton item", + "default": "\"#F7F8FA\"" + }, + "descWithTags": "占位块背景色", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonProps" + }, + "required": false, + "type": { + "name": "string" + } + }, "children": { "defaultValue": { "value": "null" @@ -199,14 +262,14 @@ "required": false, "description": "标题占位图宽度\n@en The width of title", "defaultValue": { - "value": "'38%'" + "value": "\"40%\"" }, "type": { "name": "ReactText" }, "tags": { "en": "The width of title", - "default": "'38%'" + "default": "\"40%\"" }, "descWithTags": "标题占位图宽度" }, @@ -265,14 +328,14 @@ "required": false, "description": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度\n@en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", "defaultValue": { - "value": "'58%'" + "value": "\"60%\"" }, "type": { "name": "string | number | ReactText[]" }, "tags": { "en": "The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", - "default": "'58%'" + "default": "\"60%\"" }, "descWithTags": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度" }, @@ -310,65 +373,6 @@ } }, "SkeletonAvatarProps": { - "shape": { - "name": "shape", - "required": false, - "description": "头像形状\n@en Shape of avatar", - "defaultValue": { - "value": "'circle'" - }, - "type": { - "name": "enum", - "raw": "\"circle\" | \"square\"", - "value": [ - { - "value": "\"circle\"" - }, - { - "value": "\"square\"" - } - ] - }, - "tags": { - "en": "Shape of avatar", - "default": "'circle'" - }, - "descWithTags": "头像形状" - }, - "size": { - "name": "size", - "required": false, - "description": "头像尺寸\n@en Size of avatar", - "defaultValue": { - "value": "'smaller'" - }, - "type": { - "name": "enum", - "raw": "\"medium\" | \"large\" | \"small\" | \"smaller\" | \"ultra-small\"", - "value": [ - { - "value": "\"medium\"" - }, - { - "value": "\"large\"" - }, - { - "value": "\"small\"" - }, - { - "value": "\"smaller\"" - }, - { - "value": "\"ultra-small\"" - } - ] - }, - "tags": { - "en": "Size of avatar", - "default": "'smaller'" - }, - "descWithTags": "头像尺寸" - }, "className": { "name": "className", "required": false, @@ -468,7 +472,533 @@ } } }, - "depComps": {}, + "depComps": { + "Node": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonNode", + "methods": [], + "props": { + "children": { + "defaultValue": { + "value": "null" + }, + "description": "自定义组件内容\n@en Custom component content", + "name": "children", + "tags": { + "en": "Custom component content", + "default": "null" + }, + "descWithTags": "自定义组件内容", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "BaseProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "BaseProps", + "ref": "SkeletonRef" + } + }, + "Title": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonTitle", + "methods": [], + "props": { + "width": { + "defaultValue": { + "value": "\"40%\"" + }, + "description": "标题占位图宽度\n@en The width of title", + "name": "width", + "tags": { + "en": "The width of title", + "default": "\"40%\"" + }, + "descWithTags": "标题占位图宽度", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonTitleProps" + }, + "required": false, + "type": { + "name": "ReactText" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonTitleProps", + "ref": "SkeletonRef" + } + }, + "Paragraph": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonParagraph", + "methods": [], + "props": { + "rows": { + "defaultValue": { + "value": "3" + }, + "description": "段落占位图的行数\n@en Number of lines for paragraph", + "name": "rows", + "tags": { + "en": "Number of lines for paragraph", + "default": "3" + }, + "descWithTags": "段落占位图的行数", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonParagraphProps" + }, + "required": false, + "type": { + "name": "number" + } + }, + "width": { + "defaultValue": { + "value": "\"60%\"" + }, + "description": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度\n@en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "name": "width", + "tags": { + "en": "The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line", + "default": "\"60%\"" + }, + "descWithTags": "段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonParagraphProps" + }, + "required": false, + "type": { + "name": "string | number | ReactText[]" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonParagraphProps", + "ref": "SkeletonRef" + } + }, + "Avatar": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonAvatar", + "methods": [], + "props": { + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SimpleBaseProps", + "ref": "SkeletonRef" + } + }, + "Grid": { + "description": "", + "descriptionTags": {}, + "displayName": "SkeletonGrid", + "methods": [], + "props": { + "columns": { + "defaultValue": { + "value": "4" + }, + "description": "金刚位列数\n@en columns of grid", + "name": "columns", + "tags": { + "en": "columns of grid", + "default": "4" + }, + "descWithTags": "金刚位列数", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/skeleton/type.ts", + "name": "SkeletonGridProps" + }, + "required": false, + "type": { + "name": "number" + } + }, + "className": { + "defaultValue": { + "value": "\"\"" + }, + "description": "自定义类名\n@en Custom classname", + "name": "className", + "tags": { + "en": "Custom classname", + "default": "\"\"" + }, + "descWithTags": "自定义类名", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "style": { + "defaultValue": { + "value": "{}" + }, + "description": "自定义样式\n@en Custom stylesheet", + "name": "style", + "tags": { + "en": "Custom stylesheet", + "default": "{}" + }, + "descWithTags": "自定义样式", + "parent": { + "fileName": "arcom-github/packages/arcodesign/components/_helpers/type.ts", + "name": "SimpleBaseProps" + }, + "required": false, + "type": { + "name": "CSSProperties" + } + }, + "ref": { + "defaultValue": null, + "description": "", + "name": "ref", + "tags": {}, + "descWithTags": "", + "parent": { + "fileName": "arcom-github/node_modules/@types/react/index.d.ts", + "name": "RefAttributes" + }, + "required": false, + "type": { + "name": "Ref" + } + } + }, + "deps": { + "SkeletonRef": { + "dom": { + "name": "dom", + "required": true, + "description": "最外层 DOM 元素\n@en The outer DOM element of the component", + "defaultValue": null, + "type": { + "name": "HTMLDivElement" + }, + "tags": { + "en": "The outer DOM element of the component" + }, + "descWithTags": "最外层 DOM 元素" + } + } + }, + "depComps": {}, + "typeNameInfo": { + "props": "SkeletonGridProps", + "ref": "SkeletonRef" + } + } + }, "typeNameInfo": { "props": "SkeletonProps", "ref": "SkeletonRef" diff --git a/packages/arcodesign/components/skeleton/demo/animation.md b/packages/arcodesign/components/skeleton/demo/animation.md index f64077bb..3a62e51a 100644 --- a/packages/arcodesign/components/skeleton/demo/animation.md +++ b/packages/arcodesign/components/skeleton/demo/animation.md @@ -10,24 +10,29 @@ const options = [ { label: 'breath', value: 'breath' }, ]; -const themes = [ - { label: 'light', value: 'light' }, - { label: 'dark', value: 'dark' }, -]; +const color = 'rgba(148, 191, 255, 20%)'; export default function SkeletonDemo() { const [type, setType] = React.useState('gradient'); - const [theme, setTheme] = React.useState('light'); + const [checked, setChecked] = React.useState(true); return ( -
- - + + + + + {checked && ( + + + + )} + + -
); } diff --git a/packages/arcodesign/components/skeleton/demo/custom.md b/packages/arcodesign/components/skeleton/demo/custom.md index 7bd20242..404ebbc8 100644 --- a/packages/arcodesign/components/skeleton/demo/custom.md +++ b/packages/arcodesign/components/skeleton/demo/custom.md @@ -9,7 +9,7 @@ export default function SkeletonDemo() { const [loading, setLoading] = React.useState(true); return (
- + @@ -38,7 +38,7 @@ export default function SkeletonDemo() { /> ) : ( -
actual content
+
actual content
)}
); diff --git a/packages/arcodesign/components/skeleton/demo/grid.md b/packages/arcodesign/components/skeleton/demo/grid.md index 450df531..7bbb9fe8 100644 --- a/packages/arcodesign/components/skeleton/demo/grid.md +++ b/packages/arcodesign/components/skeleton/demo/grid.md @@ -6,6 +6,6 @@ import { Skeleton } from '@arco-design/mobile-react'; export default function SkeletonDemo() { - return + return ; } ``` diff --git a/packages/arcodesign/components/skeleton/demo/index.md b/packages/arcodesign/components/skeleton/demo/index.md index 00aeff23..3d033861 100644 --- a/packages/arcodesign/components/skeleton/demo/index.md +++ b/packages/arcodesign/components/skeleton/demo/index.md @@ -6,6 +6,6 @@ import { Skeleton } from '@arco-design/mobile-react'; export default function SkeletonDemo() { - return + return ; } ``` diff --git a/packages/arcodesign/components/skeleton/demo/style/mobile.less b/packages/arcodesign/components/skeleton/demo/style/mobile.less index f6e46152..366ec254 100644 --- a/packages/arcodesign/components/skeleton/demo/style/mobile.less +++ b/packages/arcodesign/components/skeleton/demo/style/mobile.less @@ -2,15 +2,12 @@ #demo-skeleton { .arcodesign-mobile-demo-content { - .dark { - background-color: #0e0e0e; - color: white; - .arco-skeleton-item { - background-color: rgba(255, 255, 255, 0.2); - } - .arco-radio .radio-text { - color: white; - } + .arco-cell-group { + margin-bottom: 0.32rem; + } + .arco-cell { + margin-left: 0; + padding-right: 0; } } } diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx index 60c3e5f1..4afc4dfb 100644 --- a/packages/arcodesign/components/skeleton/elements.tsx +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -7,10 +7,9 @@ import React, { useRef, useState, } from 'react'; -import { cls, isArray } from '@arco-design/mobile-utils'; +import { cls, isArray, nextTick } from '@arco-design/mobile-utils'; import { useListenResize } from '../_helpers'; import { GlobalContext } from '../context-provider'; -import Avatar from '../avatar'; import { SkeletonAvatarProps, SkeletonGridProps, @@ -21,15 +20,19 @@ import { } from './type'; import { SkeletonContext } from './skeleton-context'; -const calcOffset = (dom?: HTMLElement | null) => { +const calcOffset = (dom?: HTMLElement | null, useRtl?: boolean) => { if (!dom) { return 0; } - return dom.offsetTop + dom.offsetLeft; + if (useRtl) { + return dom.offsetLeft - dom.offsetTop; + } + return dom.offsetLeft + dom.offsetTop; }; function useOffset | T[]>( dom?: K, + useRtl?: boolean, ) { const [offset, setOffset] = useState(0); const calcLayout = () => { @@ -41,14 +44,16 @@ function useOffset).current), + ? (dom as T[]).map(item => calcOffset(item, useRtl)) + : calcOffset((dom as React.MutableRefObject).current, useRtl), ); }; useEffect(() => { - calcLayout(); - }, []); + nextTick(() => { + calcLayout(); + }); + }, [dom, useRtl]); useListenResize(calcLayout); return offset as K extends T[] ? number[] : number; @@ -57,10 +62,10 @@ function useOffset) => { const { className = '', style, children } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef(null); - const isGradientAnimation = animation === 'gradient'; - const offset = useOffset(isGradientAnimation ? domRef : undefined); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -71,17 +76,17 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref {children} {isGradientAnimation && (
)}
@@ -89,12 +94,12 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref) => { - const { className = '', style, width = '38%' } = props; + const { className = '', style, width = '40%' } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef(null); - const isGradientAnimation = animation === 'gradient'; - const offset = useOffset(isGradientAnimation ? domRef : undefined); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -105,16 +110,16 @@ export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref {isGradientAnimation && (
)}
@@ -123,13 +128,13 @@ export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref) => { - const { className = '', style, rows = 3, width } = props; + const { className = '', style, rows = 3, width = '60%' } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef(null); const lineDomRefs = useRef([]); - const isGradientAnimation = animation === 'gradient'; - const offsets = useOffset(isGradientAnimation ? lineDomRefs.current : undefined); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offsets = useOffset(isGradientAnimation ? lineDomRefs.current : undefined, useRtl); useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -157,17 +162,18 @@ export const SkeletonParagraph = forwardRef( className={cls( `${prefixCls}-skeleton-item`, `${prefixCls}-skeleton-paragraph-line`, - animation && `${prefixCls}-skeleton-animation-${animation}`, + showAnimation && `${prefixCls}-skeleton-animation-${animation}`, )} style={{ width: getWidth(idx), + backgroundColor, }} ref={el => el && (lineDomRefs.current[idx] = el)} > {isGradientAnimation && (
)}
@@ -178,35 +184,34 @@ export const SkeletonParagraph = forwardRef( ); export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref) => { - const { className = '', style, shape = 'circle', size = 'smaller' } = props; + const { className = '', style } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef(null); - const isGradientAnimation = animation === 'gradient'; - const offset = useOffset(isGradientAnimation ? domRef : undefined); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); useImperativeHandle(ref, () => ({ dom: domRef.current, })); return ( -
- +
+ {isGradientAnimation && (
- {isGradientAnimation && ( -
- )} -
- + className={`${prefixCls}-skeleton-animation-item`} + style={{ left: 0 - offset }} + /> + )}
); }); @@ -214,13 +219,13 @@ export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref) => { const { className = '', style, columns = 4 } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef(null); const iconDomRefs = useRef([]); const textDomRefs = useRef([]); - const isGradientAnimation = animation === 'gradient'; - const iconOffsets = useOffset(isGradientAnimation ? iconDomRefs.current : undefined); - const textOffsets = useOffset(isGradientAnimation ? textDomRefs.current : undefined); + const isGradientAnimation = showAnimation && animation === 'gradient'; + const iconOffsets = useOffset(isGradientAnimation ? iconDomRefs.current : undefined, useRtl); + const textOffsets = useOffset(isGradientAnimation ? textDomRefs.current : undefined, useRtl); useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -234,15 +239,16 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref el && (iconDomRefs.current[idx] = el)} > {isGradientAnimation && (
)} @@ -251,15 +257,16 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref el && (textDomRefs.current[idx] = el)} > {isGradientAnimation && (
)} diff --git a/packages/arcodesign/components/skeleton/index.tsx b/packages/arcodesign/components/skeleton/index.tsx index 0473a09b..a1f3e683 100644 --- a/packages/arcodesign/components/skeleton/index.tsx +++ b/packages/arcodesign/components/skeleton/index.tsx @@ -3,11 +3,11 @@ import { cls, componentWrapper } from '@arco-design/mobile-utils'; import { GlobalContext } from '../context-provider'; import { SkeletonProps, SkeletonRef } from './type'; import { - SkeletonAvatar, - SkeletonGrid, - SkeletonNode, - SkeletonParagraph, - SkeletonTitle, + SkeletonAvatar as Avatar, + SkeletonGrid as Grid, + SkeletonNode as Node, + SkeletonParagraph as Paragraph, + SkeletonTitle as Title, } from './elements'; import { SkeletonContext } from './skeleton-context'; @@ -23,11 +23,14 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref) => { className = '', style, children, - animation, title = true, paragraph = true, avatar = false, grid, + showAnimation = true, + animation = 'gradient', + animationGradientColor, + backgroundColor, } = props; const domRef = useRef(null); const { prefixCls } = useContext(GlobalContext); @@ -41,14 +44,14 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref) => { const hasParagraph = !!paragraph; const hasAvatar = !!avatar; const content = isGrid ? ( - + ) : ( <> - {hasAvatar && } + {hasAvatar && } {(hasTitle || hasParagraph) && (
- {hasTitle && } - {hasParagraph && } + {hasTitle && } + {hasParagraph && <Paragraph {...getComponentProps(paragraph)} />} </div> )} </> @@ -63,10 +66,10 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { }, className, )} - style={style} + style={{ color: animationGradientColor, ...style }} ref={domRef} > - <SkeletonContext.Provider value={{ animation }}> + <SkeletonContext.Provider value={{ showAnimation, animation, backgroundColor }}> {content} {children} </SkeletonContext.Provider> @@ -83,9 +86,9 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { * @name_en Skeleton */ export default componentWrapper(Skeleton, { - Node: SkeletonNode, - Title: SkeletonTitle, - Paragraph: SkeletonParagraph, - Avatar: SkeletonAvatar, - Grid: SkeletonGrid, + Node, + Title, + Paragraph, + Avatar, + Grid, }); diff --git a/packages/arcodesign/components/skeleton/skeleton-context.tsx b/packages/arcodesign/components/skeleton/skeleton-context.tsx index 0b2dc361..81cb0107 100644 --- a/packages/arcodesign/components/skeleton/skeleton-context.tsx +++ b/packages/arcodesign/components/skeleton/skeleton-context.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { SkeletonContextParams } from './type'; +import { SkeletonContextParams, SkeletonProps } from './type'; export const SkeletonContext = React.createContext<SkeletonContextParams>({ - animation: undefined, + showAnimation: true, + animation: 'gradient' as SkeletonProps['animation'], }); diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index fa8968f2..2da10423 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -2,6 +2,7 @@ .@{prefix}-skeleton { position: relative; + .use-var(color, skeleton-gradient-animation-color); } .@{prefix}-skeleton-title { @@ -12,10 +13,6 @@ &-line { width: 100%; .use-var(height, 'skeleton-paragraph-height'); - - &:last-child:not(:first-child):not(:nth-child(2)) { - width: 58%; - } } &-line + &-line { @@ -23,15 +20,10 @@ } } -.@{prefix}-skeleton-avatar { - .@{prefix}-avatar { - background-color: transparent; - overflow: hidden; - } - .@{prefix}-skeleton-item { - width: 100%; - height: 100%; - } +.@{prefix}-skeleton-avatar.@{prefix}-skeleton-item { + .use-var(width, 'skeleton-avatar-size'); + .use-var(height, 'skeleton-avatar-size'); + border-radius: 100%; } .@{prefix}-skeleton-content { @@ -46,6 +38,10 @@ display: flex; align-items: flex-start; + .@{prefix}-skeleton-avatar { + flex: none; + } + .@{prefix}-skeleton-content { .@{prefix}-skeleton-title { .use-var(margin-top, 'skeleton-gutter-medium'); @@ -80,7 +76,6 @@ .@{prefix}-skeleton-node { display: inline-block; - width: auto; } .@{prefix}-skeleton-item { @@ -95,22 +90,13 @@ width: 200vw; height: 100%; top: 0; - .set-prop-with-rtl(left, 0); - + left: 0; background-image: linear-gradient( 90deg, rgba(255, 255, 255, 0) 25%, - @skeleton-gradient-animation-color 40%, + currentColor 40%, rgba(255, 255, 255, 0) 55% ); - & when (@use-css-vars = 1) { - background-image: linear-gradient( - 90deg, - rgba(255, 255, 255, 0) 25%, - var(--skeleton-gradient-animation-color) 40%, - rgba(255, 255, 255, 0) 55% - ); - } transform-origin: top left; animation: gradient 2s linear infinite; [dir='rtl'] & { @@ -147,7 +133,7 @@ } 50% { - opacity: 0.3; + .use-var(opacity, skeleton-breath-opacity); } 100% { diff --git a/packages/arcodesign/components/skeleton/type.ts b/packages/arcodesign/components/skeleton/type.ts index fec85f57..ad6bad5b 100644 --- a/packages/arcodesign/components/skeleton/type.ts +++ b/packages/arcodesign/components/skeleton/type.ts @@ -1,12 +1,6 @@ import { BaseProps, SimpleBaseProps } from '../_helpers'; -import { AvatarProps } from '../avatar'; export interface SkeletonProps extends SimpleBaseProps { - /** - * 加载动画效果,可选“扫光”、“呼吸”两种效果,不传入表示不展示动画效果 - * @en Animation of loading effect, 'gradient' and 'breath' effects are optional, default is no animation effect if not passed - */ - animation?: 'gradient' | 'breath'; /** * 是否显示标题占位图 * @en Show title placeholder @@ -26,11 +20,35 @@ export interface SkeletonProps extends SimpleBaseProps { */ avatar?: boolean | SkeletonAvatarProps; /** - * 是否显示金刚位占位图(该参数非空时,不展示标题/段落/头像占位符) - * @en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed + * 是否显示金刚位占位图(如该参数非空时,默认展示四列金刚位,且不展示标题/段落/头像占位符) + * @en Show Grid placeholder. When it's value is present, the paragraph, avatar or title placeholder will not be displayed, and four columns will be displayed by default * @default false */ grid?: boolean | SkeletonGridProps; + /** + * 是否展示动画效果 + * @en Show loading effect + * @default true + */ + showAnimation?: boolean; + /** + * 加载动画效果,可选“扫光”、“呼吸”两种效果 + * @en Animation of loading effect, 'gradient' and 'breath' effects are optional + * @default "gradient" + */ + animation?: 'gradient' | 'breath'; + /** + * 扫光动效高光颜色 + * @en Highlight color of gradient animation + * @default "rgba(0, 0, 0, 0.04)" + */ + animationGradientColor?: string; + /** + * 占位块背景色 + * @en Background color of skeleton item + * @default "#F7F8FA" + */ + backgroundColor?: string; /** * 子元素 * @en Children element @@ -43,7 +61,7 @@ export interface SkeletonTitleProps extends SimpleBaseProps { /** * 标题占位图宽度 * @en The width of title - * @default '38%' + * @default "40%" */ width?: number | string; } @@ -58,25 +76,12 @@ export interface SkeletonParagraphProps extends SimpleBaseProps { /** * 段落占位图宽度,若为数组格式对应每行宽度,否则表示最后一行的宽度 * @en The width of paragraph. If width is an Array, it corresponds to the width of each line, otherwise it indicates the width of the last line - * @default '58%' + * @default "60%" */ width?: number | string | Array<number | string>; } -export interface SkeletonAvatarProps extends SimpleBaseProps { - /** - * 头像形状 - * @en Shape of avatar - * @default 'circle' - */ - shape?: AvatarProps['shape']; - /** - * 头像尺寸 - * @en Size of avatar - * @default 'smaller' - */ - size?: AvatarProps['size']; -} +export interface SkeletonAvatarProps extends SimpleBaseProps {} export interface SkeletonGridProps extends SimpleBaseProps { /** @@ -98,8 +103,7 @@ export interface SkeletonRef { } export interface SkeletonContextParams { - /** - * 是否开启动效 - */ - animation?: SkeletonProps['animation']; + backgroundColor?: string; + showAnimation: boolean; + animation: SkeletonProps['animation']; } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less index e313102d..f79c19ab 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less @@ -795,10 +795,12 @@ --divider-padding: ~`pxtorem(16)`; --skeleton-border-radius: ~`pxtorem(0)`; --skeleton-background-color: #F2F3F5; - --skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); + --skeleton-gradient-animation-color: rgba(0, 0, 0, 0.04); + --skeleton-breath-opacity: 0.3; --skeleton-title-height: ~`pxtorem(16)`; --skeleton-paragraph-height: ~`pxtorem(16)`; --skeleton-paragraph-margin-top: ~`pxtorem(12)`; + --skeleton-avatar-size: ~`pxtorem(32)`; --skeleton-grid-icon-width: ~`pxtorem(32)`; --skeleton-grid-text-width: ~`pxtorem(64)`; --skeleton-grid-text-height: ~`pxtorem(16)`; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts index fc5567fe..24c1b54d 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts @@ -795,9 +795,11 @@ export interface ArcodesignToken extends Record<string, string> { 'skeleton-border-radius': string; 'skeleton-background-color': string; 'skeleton-gradient-animation-color': string; + 'skeleton-breath-opacity': string; 'skeleton-title-height': string; 'skeleton-paragraph-height': string; 'skeleton-paragraph-margin-top': string; + 'skeleton-avatar-size': string; 'skeleton-grid-icon-width': string; 'skeleton-grid-text-width': string; 'skeleton-grid-text-height': string; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index a41f6b5d..c027d68d 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -806,10 +806,12 @@ var tokens = { "divider-padding": "0.32rem", "skeleton-border-radius": "0", "skeleton-background-color": "#F2F3F5", - "skeleton-gradient-animation-color": "rgba(255, 255, 255, 0.6)", + "skeleton-gradient-animation-color": "rgba(0, 0, 0, 0.04)", + "skeleton-breath-opacity": "0.3", "skeleton-title-height": "0.32rem", "skeleton-paragraph-height": "0.32rem", "skeleton-paragraph-margin-top": "0.24rem", + "skeleton-avatar-size": "0.64rem", "skeleton-grid-icon-width": "0.64rem", "skeleton-grid-text-width": "1.28rem", "skeleton-grid-text-height": "0.32rem", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.json b/packages/arcodesign/tokens/app/arcodesign/default/index.json index c9315dd7..c84362b6 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.json +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.json @@ -6629,6 +6629,18 @@ "en": "Size of the rounded corners of the square SearchBar" } }, + "skeletonAvatarSize": { + "cssKey": "skeleton-avatar-size", + "desc": "骨架屏头像大小", + "override": "", + "value": "~`pxtorem(32)`", + "jsValue": "@getRem@32", + "staticValue": "0.64rem", + "localeDesc": { + "ch": "骨架屏头像大小", + "en": "Skeleton avatar size" + } + }, "skeletonBackgroundColor": { "cssKey": "skeleton-background-color", "desc": "骨架屏元素背景色", @@ -6653,15 +6665,27 @@ "en": "Skeleton element border radius" } }, + "skeletonBreathOpacity": { + "cssKey": "skeleton-breath-opacity", + "desc": "骨架屏呼吸动效透明度", + "override": "", + "value": "0.3", + "jsValue": "0.3", + "staticValue": "0.3", + "localeDesc": { + "ch": "骨架屏呼吸动效透明度", + "en": "Skeleton element breath animation opacity" + } + }, "skeletonGradientAnimationColor": { "cssKey": "skeleton-gradient-animation-color", - "desc": "骨架屏扫光高亮色", + "desc": "骨架屏扫光动效高亮色", "override": "", - "value": "rgba(255, 255, 255, 0.6)", - "jsValue": "rgba(255, 255, 255, 0.6)", - "staticValue": "rgba(255, 255, 255, 0.6)", + "value": "rgba(0, 0, 0, 0.04)", + "jsValue": "rgba(0, 0, 0, 0.04)", + "staticValue": "rgba(0, 0, 0, 0.04)", "localeDesc": { - "ch": "骨架屏扫光高亮色", + "ch": "骨架屏扫光动效高亮色", "en": "Skeleton element gradient animation highlight color" } }, diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.less b/packages/arcodesign/tokens/app/arcodesign/default/index.less index 830321b7..2b1598fb 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.less @@ -794,10 +794,12 @@ @divider-padding: ~`pxtorem(16)`; @skeleton-border-radius: ~`pxtorem(0)`; @skeleton-background-color: #F2F3F5; -@skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); +@skeleton-gradient-animation-color: rgba(0, 0, 0, 0.04); +@skeleton-breath-opacity: 0.3; @skeleton-title-height: ~`pxtorem(16)`; @skeleton-paragraph-height: ~`pxtorem(16)`; @skeleton-paragraph-margin-top: ~`pxtorem(12)`; +@skeleton-avatar-size: ~`pxtorem(32)`; @skeleton-grid-icon-width: ~`pxtorem(32)`; @skeleton-grid-text-width: ~`pxtorem(64)`; @skeleton-grid-text-height: ~`pxtorem(16)`; diff --git a/packages/arcodesign/tokens/src/arcodesign/default/index.js b/packages/arcodesign/tokens/src/arcodesign/default/index.js index a5cc7159..103ae791 100644 --- a/packages/arcodesign/tokens/src/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/src/arcodesign/default/index.js @@ -4029,10 +4029,15 @@ function getCompTokens() { */ skeletonBackgroundColor: '#F2F3F5', /** - * 骨架屏扫光高亮色 + * 骨架屏扫光动效高亮色 * @en Skeleton element gradient animation highlight color */ - skeletonGradientAnimationColor: 'rgba(255, 255, 255, 0.6)', + skeletonGradientAnimationColor: 'rgba(0, 0, 0, 0.04)', + /** + * 骨架屏呼吸动效透明度 + * @en Skeleton element breath animation opacity + */ + skeletonBreathOpacity: '0.3', /** * 骨架屏标题高度 * @en Skeleton title height @@ -4048,6 +4053,11 @@ function getCompTokens() { * @en Margin top between skeleton paragraph lines */ skeletonParagraphMarginTop: getRem(12), + /** + * 骨架屏头像大小 + * @en Skeleton avatar size + */ + skeletonAvatarSize: getRem(32), /** * 骨架屏金刚位图标区宽度 * @en Skeleton grid item icon width From 0ec4bc5018988b65708906d010d1d0f460a5708c Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" <xiaziqi.sia@bytedance.com> Date: Thu, 6 Jul 2023 15:21:41 +0800 Subject: [PATCH 05/11] chore: update test --- .../__test__/__snapshots__/index.spec.js.snap | 425 ++++++++++-------- .../skeleton/__test__/index.spec.js | 14 +- 2 files changed, 248 insertions(+), 191 deletions(-) diff --git a/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap b/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap index 73ef363d..149464ba 100644 --- a/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap +++ b/packages/arcodesign/components/skeleton/__test__/__snapshots__/index.spec.js.snap @@ -1,147 +1,142 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`skeleton demo test skeleton demo: animation.md renders correctly 1`] = ` -<div - class="light" -> - <div - class="arco-radio-group" - > - <div - aria-checked="true" - aria-disabled="false" - class="arco-radio shape-circle inline" - role="checkbox" - tabindex="0" - > - <div - class="radio-icon checked" - > - <svg - class="arco-icon arco-icon-circle-checked " - height="1em" - viewBox="0 0 20 20" - width="1em" - xmlns="http://www.w3.org/2000/svg" - > - <path - clip-rule="evenodd" - d="M10 1c-5 0-9 4-9 9s4 9 9 9 9-4 9-9-4-9-9-9zm4.9 6.3L10 13.2s0 .1-.1.1l-.6.7c-.1.1-.2.1-.3.2-.1 0-.3 0-.4-.1l-.6-.7-.1-.1-2.8-2.4c-.2-.2-.2-.5-.1-.7l.6-.7c.2-.2.5-.2.7-.1l2.5 2.1L13.5 6c.2-.2.5-.2.7-.1l.7.6c.1.3.2.6 0 .8z" - fill="currentColor" - fill-rule="evenodd" - /> - </svg> - </div> - <div - class="radio-text" - > - gradient - </div> - </div> - <div - aria-checked="false" - aria-disabled="false" - class="arco-radio shape-circle inline" - role="checkbox" - tabindex="0" - > - <div - class="radio-icon" - > - <svg - class="arco-icon arco-icon-circle-unchecked " - height="1em" - viewBox="0 0 20 20" - width="1em" - xmlns="http://www.w3.org/2000/svg" - > - <path - d="M10 19c-5 0-9-4-9-9s4-9 9-9 9 4 9 9-4 9-9 9zm0-17c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z" - fill="currentColor" - /> - </svg> - </div> - <div - class="radio-text" - > - breath - </div> - </div> - </div> +<div> <div - class="arco-radio-group" - style="margin-bottom:20px" + class="arco-cell-group all-border-box" > <div - aria-checked="true" - aria-disabled="false" - class="arco-radio shape-circle inline" - role="checkbox" - tabindex="0" + class="cell-group-body bordered" > <div - class="radio-icon checked" + class="arco-cell all-border-box bordered" > - <svg - class="arco-icon arco-icon-circle-checked " - height="1em" - viewBox="0 0 20 20" - width="1em" - xmlns="http://www.w3.org/2000/svg" + <div + class="arco-cell-inner" > - <path - clip-rule="evenodd" - d="M10 1c-5 0-9 4-9 9s4 9 9 9 9-4 9-9-4-9-9-9zm4.9 6.3L10 13.2s0 .1-.1.1l-.6.7c-.1.1-.2.1-.3.2-.1 0-.3 0-.4-.1l-.6-.7-.1-.1-2.8-2.4c-.2-.2-.2-.5-.1-.7l.6-.7c.2-.2.5-.2.7-.1l2.5 2.1L13.5 6c.2-.2.5-.2.7-.1l.7.6c.1.3.2.6 0 .8z" - fill="currentColor" - fill-rule="evenodd" - /> - </svg> - </div> - <div - class="radio-text" - > - light + <div + class="cell-label" + > + <div + class="cell-title" + > + show animation + </div> + </div> + <div + class="cell-content has-label" + > + <div + aria-checked="true" + aria-disabled="false" + class="arco-switch all-border-box type-pc system-pc fully checked" + role="switch" + tabindex="0" + > + <div + class="arco-switch-inner" + /> + </div> + </div> + </div> </div> - </div> - <div - aria-checked="false" - aria-disabled="false" - class="arco-radio shape-circle inline" - role="checkbox" - tabindex="0" - > <div - class="radio-icon" + class="arco-cell all-border-box bordered" > - <svg - class="arco-icon arco-icon-circle-unchecked " - height="1em" - viewBox="0 0 20 20" - width="1em" - xmlns="http://www.w3.org/2000/svg" + <div + class="arco-cell-inner" > - <path - d="M10 19c-5 0-9-4-9-9s4-9 9-9 9 4 9 9-4 9-9 9zm0-17c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z" - fill="currentColor" - /> - </svg> - </div> - <div - class="radio-text" - > - dark + <div + class="cell-label" + > + <div + class="cell-title" + > + type + </div> + </div> + <div + class="cell-content has-label" + > + <div + class="arco-radio-group" + > + <div + aria-checked="true" + aria-disabled="false" + class="arco-radio shape-circle inline" + role="checkbox" + tabindex="0" + > + <div + class="radio-icon checked" + > + <svg + class="arco-icon arco-icon-circle-checked " + height="1em" + viewBox="0 0 20 20" + width="1em" + xmlns="http://www.w3.org/2000/svg" + > + <path + clip-rule="evenodd" + d="M10 1c-5 0-9 4-9 9s4 9 9 9 9-4 9-9-4-9-9-9zm4.9 6.3L10 13.2s0 .1-.1.1l-.6.7c-.1.1-.2.1-.3.2-.1 0-.3 0-.4-.1l-.6-.7-.1-.1-2.8-2.4c-.2-.2-.2-.5-.1-.7l.6-.7c.2-.2.5-.2.7-.1l2.5 2.1L13.5 6c.2-.2.5-.2.7-.1l.7.6c.1.3.2.6 0 .8z" + fill="currentColor" + fill-rule="evenodd" + /> + </svg> + </div> + <div + class="radio-text" + > + gradient + </div> + </div> + <div + aria-checked="false" + aria-disabled="false" + class="arco-radio shape-circle inline" + role="checkbox" + tabindex="0" + > + <div + class="radio-icon" + > + <svg + class="arco-icon arco-icon-circle-unchecked " + height="1em" + viewBox="0 0 20 20" + width="1em" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M10 19c-5 0-9-4-9-9s4-9 9-9 9 4 9 9-4 9-9 9zm0-17c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z" + fill="currentColor" + /> + </svg> + </div> + <div + class="radio-text" + > + breath + </div> + </div> + </div> + </div> + </div> </div> </div> </div> <div class="arco-skeleton" + style="color:rgba(148, 191, 255, 20%)" > <div class="arco-skeleton-content" > <div class="arco-skeleton-item arco-skeleton-title arco-skeleton-animation-gradient" - style="width:38%" + style="width:40%;background-color:" > <div class="arco-skeleton-animation-item" @@ -153,6 +148,7 @@ exports[`skeleton demo test skeleton demo: animation.md renders correctly 1`] = > <div class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + style="background-color:" > <div class="arco-skeleton-animation-item" @@ -161,6 +157,7 @@ exports[`skeleton demo test skeleton demo: animation.md renders correctly 1`] = </div> <div class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + style="background-color:" > <div class="arco-skeleton-animation-item" @@ -169,6 +166,7 @@ exports[`skeleton demo test skeleton demo: animation.md renders correctly 1`] = </div> <div class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + style="width:60%;background-color:" > <div class="arco-skeleton-animation-item" @@ -186,39 +184,53 @@ exports[`skeleton demo test skeleton demo: avatar.md renders correctly 1`] = ` class="arco-skeleton arco-skeleton-with-avatar" > <div - class="arco-skeleton-avatar" + class="arco-skeleton-item arco-skeleton-avatar arco-skeleton-animation-gradient" > <div - class="arco-avatar-wrapper smaller circle arco-avatar-wrapper-shape-circle" - > - <div - class="arco-avatar arco-avatar-size-smaller smaller arco-avatar-shape-circle circle" - > - <div - class="arco-skeleton-item" - /> - </div> - </div> + class="arco-skeleton-animation-item" + style="left:0" + /> </div> <div class="arco-skeleton-content" > <div - class="arco-skeleton-item arco-skeleton-title" - style="width:38%" - /> + class="arco-skeleton-item arco-skeleton-title arco-skeleton-animation-gradient" + style="width:40%" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div class="arco-skeleton-paragraph" > <div - class="arco-skeleton-item arco-skeleton-paragraph-line" - /> + class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-paragraph-line" - /> + class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-paragraph-line" - /> + class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + style="width:60%" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> </div> </div> </div> @@ -230,7 +242,7 @@ exports[`skeleton demo test skeleton demo: custom.md renders correctly 1`] = ` class="arco-cell-group all-border-box" > <div - class="cell-group-body" + class="cell-group-body bordered" > <div class="arco-cell all-border-box bordered" @@ -338,24 +350,12 @@ exports[`skeleton demo test skeleton demo: custom.md renders correctly 1`] = ` style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:20px" > <div - class="arco-skeleton-avatar" + class="arco-skeleton-item arco-skeleton-avatar arco-skeleton-animation-gradient" > <div - class="arco-avatar-wrapper smaller square arco-avatar-wrapper-shape-square" - > - <div - class="arco-avatar arco-avatar-size-smaller smaller arco-avatar-shape-square square" - > - <div - class="arco-skeleton-item arco-skeleton-animation-gradient" - > - <div - class="arco-skeleton-animation-item" - style="left:0" - /> - </div> - </div> - </div> + class="arco-skeleton-animation-item" + style="left:0" + /> </div> <div class="arco-skeleton-item arco-skeleton-node arco-skeleton-animation-gradient" @@ -372,7 +372,7 @@ exports[`skeleton demo test skeleton demo: custom.md renders correctly 1`] = ` </div> <div class="arco-skeleton-item arco-skeleton-title arco-skeleton-animation-gradient" - style="width:38%;margin-bottom:20px" + style="width:40%;margin-bottom:20px" > <div class="arco-skeleton-animation-item" @@ -444,41 +444,81 @@ exports[`skeleton demo test skeleton demo: grid.md renders correctly 1`] = ` class="arco-skeleton-grid-item" > <div - class="arco-skeleton-item arco-skeleton-grid-icon" - /> + class="arco-skeleton-item arco-skeleton-grid-icon arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-grid-text" - /> + class="arco-skeleton-item arco-skeleton-grid-text arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> </div> <div class="arco-skeleton-grid-item" > <div - class="arco-skeleton-item arco-skeleton-grid-icon" - /> + class="arco-skeleton-item arco-skeleton-grid-icon arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-grid-text" - /> + class="arco-skeleton-item arco-skeleton-grid-text arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> </div> <div class="arco-skeleton-grid-item" > <div - class="arco-skeleton-item arco-skeleton-grid-icon" - /> + class="arco-skeleton-item arco-skeleton-grid-icon arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-grid-text" - /> + class="arco-skeleton-item arco-skeleton-grid-text arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> </div> <div class="arco-skeleton-grid-item" > <div - class="arco-skeleton-item arco-skeleton-grid-icon" - /> + class="arco-skeleton-item arco-skeleton-grid-icon arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-grid-text" - /> + class="arco-skeleton-item arco-skeleton-grid-text arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> </div> </div> </div> @@ -492,21 +532,42 @@ exports[`skeleton demo test skeleton demo: index.md renders correctly 1`] = ` class="arco-skeleton-content" > <div - class="arco-skeleton-item arco-skeleton-title" - style="width:38%" - /> + class="arco-skeleton-item arco-skeleton-title arco-skeleton-animation-gradient" + style="width:40%" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div class="arco-skeleton-paragraph" > <div - class="arco-skeleton-item arco-skeleton-paragraph-line" - /> + class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-paragraph-line" - /> + class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> <div - class="arco-skeleton-item arco-skeleton-paragraph-line" - /> + class="arco-skeleton-item arco-skeleton-paragraph-line arco-skeleton-animation-gradient" + style="width:60%" + > + <div + class="arco-skeleton-animation-item" + style="left:0" + /> + </div> </div> </div> </div> diff --git a/packages/arcodesign/components/skeleton/__test__/index.spec.js b/packages/arcodesign/components/skeleton/__test__/index.spec.js index fe84a528..c47d753d 100644 --- a/packages/arcodesign/components/skeleton/__test__/index.spec.js +++ b/packages/arcodesign/components/skeleton/__test__/index.spec.js @@ -37,10 +37,6 @@ describe('Skeleton', () => { it('should render correctly when set avatar', () => { const comp = mount(<Skeleton avatar />); expect(comp.find(`.${prefix}-avatar`).length).toBe(1); - comp.setProps({ - avatar: { shape: 'square' }, - }); - expect(comp.find(`.${defaultContext.prefixCls}-avatar-shape-square`).length).toBe(1); }); it('should render correctly when set grid', () => { const comp = mount(<Skeleton grid={{ columns: 5 }} />); @@ -66,11 +62,6 @@ describe('Skeleton', () => { </Skeleton.Node> </Skeleton>, ); - expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); - expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); - comp.setProps({ - animation: 'gradient', - }); expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(5); expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); comp.setProps({ @@ -78,5 +69,10 @@ describe('Skeleton', () => { }); expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); expect(comp.find(`.${prefix}-animation-breath`).length).toBe(5); + comp.setProps({ + showAnimation: false, + }); + expect(comp.find(`.${prefix}-animation-gradient`).length).toBe(0); + expect(comp.find(`.${prefix}-animation-breath`).length).toBe(0); }); }); From e50e30d041ed6de5b1654371f7c318f42825b0fb Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" <xiaziqi.sia@bytedance.com> Date: Sun, 9 Jul 2023 14:13:56 +0800 Subject: [PATCH 06/11] feat: optimize --- .../components/skeleton/demo/custom.md | 2 +- .../components/skeleton/elements.tsx | 39 +++++++++++-------- .../arcodesign/components/skeleton/index.tsx | 22 ++++++++++- .../components/skeleton/style/index.less | 22 ++++++----- .../arcodesign/components/skeleton/type.ts | 1 + 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/packages/arcodesign/components/skeleton/demo/custom.md b/packages/arcodesign/components/skeleton/demo/custom.md index 404ebbc8..a79d378f 100644 --- a/packages/arcodesign/components/skeleton/demo/custom.md +++ b/packages/arcodesign/components/skeleton/demo/custom.md @@ -25,7 +25,7 @@ export default function SkeletonDemo() { marginBottom: 20, }} > - <Skeleton.Avatar shape="square" /> + <Skeleton.Avatar /> <Skeleton.Node style={{ borderRadius: 10 }}> <div style={{ width: 250, height: 50 }} /> </Skeleton.Node> diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx index 4afc4dfb..56300cd9 100644 --- a/packages/arcodesign/components/skeleton/elements.tsx +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -34,7 +34,7 @@ function useOffset<T extends HTMLElement, K extends React.MutableRefObject<T | n dom?: K, useRtl?: boolean, ) { - const [offset, setOffset] = useState<number | number[]>(0); + const [offset, setOffset] = useState<number | number[]>(); const calcLayout = () => { const isList = Array.isArray(dom); if ( @@ -62,7 +62,8 @@ function useOffset<T extends HTMLElement, K extends React.MutableRefObject<T | n export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref<SkeletonRef>) => { const { className = '', style, children } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation, gradientWidth } = + useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const isGradientAnimation = showAnimation && animation === 'gradient'; const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); @@ -83,10 +84,10 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref<Skele ref={domRef} > {children} - {isGradientAnimation && ( + {isGradientAnimation && offset !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - offset }} + style={{ left: 0 - offset, width: gradientWidth }} /> )} </div> @@ -96,7 +97,8 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref<Skele export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref<SkeletonRef>) => { const { className = '', style, width = '40%' } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation, gradientWidth } = + useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const isGradientAnimation = showAnimation && animation === 'gradient'; const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); @@ -116,10 +118,10 @@ export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref<Ske style={{ width, backgroundColor, ...style }} ref={domRef} > - {isGradientAnimation && ( + {isGradientAnimation && offset !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - offset }} + style={{ left: 0 - offset, width: gradientWidth }} /> )} </div> @@ -130,7 +132,8 @@ export const SkeletonParagraph = forwardRef( (props: SkeletonParagraphProps, ref: Ref<SkeletonRef>) => { const { className = '', style, rows = 3, width = '60%' } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation, gradientWidth } = + useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const lineDomRefs = useRef<HTMLDivElement[]>([]); const isGradientAnimation = showAnimation && animation === 'gradient'; @@ -170,10 +173,10 @@ export const SkeletonParagraph = forwardRef( }} ref={el => el && (lineDomRefs.current[idx] = el)} > - {isGradientAnimation && ( + {isGradientAnimation && offsets !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - (offsets[idx] || 0) }} + style={{ left: 0 - (offsets[idx] || 0), width: gradientWidth }} /> )} </div> @@ -186,7 +189,8 @@ export const SkeletonParagraph = forwardRef( export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref<SkeletonRef>) => { const { className = '', style } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation, gradientWidth } = + useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const isGradientAnimation = showAnimation && animation === 'gradient'; const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); @@ -206,10 +210,10 @@ export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref<S style={{ backgroundColor, ...style }} ref={domRef} > - {isGradientAnimation && ( + {isGradientAnimation && offset !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - offset }} + style={{ left: 0 - offset, width: gradientWidth }} /> )} </div> @@ -219,7 +223,8 @@ export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref<S export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref<SkeletonRef>) => { const { className = '', style, columns = 4 } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation, gradientWidth } = + useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const iconDomRefs = useRef<HTMLDivElement[]>([]); const textDomRefs = useRef<HTMLDivElement[]>([]); @@ -244,11 +249,12 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref<Skele style={{ backgroundColor }} ref={el => el && (iconDomRefs.current[idx] = el)} > - {isGradientAnimation && ( + {isGradientAnimation && iconOffsets !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} style={{ left: 0 - (iconOffsets?.[idx] || 0), + width: gradientWidth, }} /> )} @@ -262,11 +268,12 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref<Skele style={{ backgroundColor }} ref={el => el && (textDomRefs.current[idx] = el)} > - {isGradientAnimation && ( + {isGradientAnimation && textOffsets !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} style={{ left: 0 - (textOffsets?.[idx] || 0), + width: gradientWidth, }} /> )} diff --git a/packages/arcodesign/components/skeleton/index.tsx b/packages/arcodesign/components/skeleton/index.tsx index a1f3e683..c977e6d4 100644 --- a/packages/arcodesign/components/skeleton/index.tsx +++ b/packages/arcodesign/components/skeleton/index.tsx @@ -1,4 +1,12 @@ -import React, { useRef, forwardRef, Ref, useImperativeHandle, useContext } from 'react'; +import React, { + useRef, + forwardRef, + Ref, + useImperativeHandle, + useContext, + useEffect, + useState, +} from 'react'; import { cls, componentWrapper } from '@arco-design/mobile-utils'; import { GlobalContext } from '../context-provider'; import { SkeletonProps, SkeletonRef } from './type'; @@ -34,6 +42,7 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { } = props; const domRef = useRef<HTMLDivElement | null>(null); const { prefixCls } = useContext(GlobalContext); + const [gradientWidth, setGradientWidth] = useState<number>(); useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -57,6 +66,13 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { </> ); + useEffect(() => { + if (showAnimation && animation === 'gradient') { + const width = domRef.current?.clientHeight || 0; + width > window.innerWidth && setGradientWidth(width); + } + }, []); + return ( <div className={cls( @@ -69,7 +85,9 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { style={{ color: animationGradientColor, ...style }} ref={domRef} > - <SkeletonContext.Provider value={{ showAnimation, animation, backgroundColor }}> + <SkeletonContext.Provider + value={{ showAnimation, animation, backgroundColor, gradientWidth }} + > {content} {children} </SkeletonContext.Provider> diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index 2da10423..2a7d1c6a 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -24,6 +24,7 @@ .use-var(width, 'skeleton-avatar-size'); .use-var(height, 'skeleton-avatar-size'); border-radius: 100%; + transform: translateZ(0); } .@{prefix}-skeleton-content { @@ -87,18 +88,21 @@ .@{prefix}-skeleton-animation-item { position: absolute; - width: 200vw; + width: 100vw; height: 100%; top: 0; left: 0; background-image: linear-gradient( 90deg, - rgba(255, 255, 255, 0) 25%, - currentColor 40%, - rgba(255, 255, 255, 0) 55% + rgba(255, 255, 255, 0) 35%, + currentColor 50%, + rgba(255, 255, 255, 0) 65% ); transform-origin: top left; - animation: gradient 2s linear infinite; + animation-name: gradient; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-duration: 1.5s; [dir='rtl'] & { animation-name: gradient-reverse; } @@ -109,21 +113,21 @@ @keyframes gradient { 0% { - transform: translateX(-200%) skewX(-45deg); + transform: translateX(-65%) skewX(-45deg); } 100% { - transform: translateX(200%) skewX(-45deg); + transform: translateX(135%) skewX(-45deg); } } @keyframes gradient-reverse { 0% { - transform: translateX(200%) skewX(45deg); + transform: translateX(65%) skewX(45deg); } 100% { - transform: translateX(-200%) skewX(45deg); + transform: translateX(-135%) skewX(45deg); } } diff --git a/packages/arcodesign/components/skeleton/type.ts b/packages/arcodesign/components/skeleton/type.ts index ad6bad5b..e216cb7f 100644 --- a/packages/arcodesign/components/skeleton/type.ts +++ b/packages/arcodesign/components/skeleton/type.ts @@ -106,4 +106,5 @@ export interface SkeletonContextParams { backgroundColor?: string; showAnimation: boolean; animation: SkeletonProps['animation']; + gradientWidth?: number; } From 25d594c4e81026536715af0989a65cb954e79001 Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" <xiaziqi.sia@bytedance.com> Date: Sun, 16 Jul 2023 15:23:36 +0800 Subject: [PATCH 07/11] feat: fixed gradient width --- .../components/skeleton/elements.tsx | 25 +++++++------------ .../arcodesign/components/skeleton/index.tsx | 22 ++-------------- .../arcodesign/components/skeleton/type.ts | 1 - 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/packages/arcodesign/components/skeleton/elements.tsx b/packages/arcodesign/components/skeleton/elements.tsx index 56300cd9..48dfa65d 100644 --- a/packages/arcodesign/components/skeleton/elements.tsx +++ b/packages/arcodesign/components/skeleton/elements.tsx @@ -62,8 +62,7 @@ function useOffset<T extends HTMLElement, K extends React.MutableRefObject<T | n export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref<SkeletonRef>) => { const { className = '', style, children } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation, gradientWidth } = - useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const isGradientAnimation = showAnimation && animation === 'gradient'; const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); @@ -87,7 +86,7 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref<Skele {isGradientAnimation && offset !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - offset, width: gradientWidth }} + style={{ left: 0 - offset }} /> )} </div> @@ -97,8 +96,7 @@ export const SkeletonNode = forwardRef((props: SkeletonNodeProps, ref: Ref<Skele export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref<SkeletonRef>) => { const { className = '', style, width = '40%' } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation, gradientWidth } = - useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const isGradientAnimation = showAnimation && animation === 'gradient'; const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); @@ -121,7 +119,7 @@ export const SkeletonTitle = forwardRef((props: SkeletonTitleProps, ref: Ref<Ske {isGradientAnimation && offset !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - offset, width: gradientWidth }} + style={{ left: 0 - offset }} /> )} </div> @@ -132,8 +130,7 @@ export const SkeletonParagraph = forwardRef( (props: SkeletonParagraphProps, ref: Ref<SkeletonRef>) => { const { className = '', style, rows = 3, width = '60%' } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation, gradientWidth } = - useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const lineDomRefs = useRef<HTMLDivElement[]>([]); const isGradientAnimation = showAnimation && animation === 'gradient'; @@ -176,7 +173,7 @@ export const SkeletonParagraph = forwardRef( {isGradientAnimation && offsets !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - (offsets[idx] || 0), width: gradientWidth }} + style={{ left: 0 - (offsets[idx] || 0) }} /> )} </div> @@ -189,8 +186,7 @@ export const SkeletonParagraph = forwardRef( export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref<SkeletonRef>) => { const { className = '', style } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation, gradientWidth } = - useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const isGradientAnimation = showAnimation && animation === 'gradient'; const offset = useOffset(isGradientAnimation ? domRef : undefined, useRtl); @@ -213,7 +209,7 @@ export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref<S {isGradientAnimation && offset !== undefined && ( <div className={`${prefixCls}-skeleton-animation-item`} - style={{ left: 0 - offset, width: gradientWidth }} + style={{ left: 0 - offset }} /> )} </div> @@ -223,8 +219,7 @@ export const SkeletonAvatar = forwardRef((props: SkeletonAvatarProps, ref: Ref<S export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref<SkeletonRef>) => { const { className = '', style, columns = 4 } = props; const { useRtl, prefixCls } = useContext(GlobalContext); - const { backgroundColor, showAnimation, animation, gradientWidth } = - useContext(SkeletonContext); + const { backgroundColor, showAnimation, animation } = useContext(SkeletonContext); const domRef = useRef<HTMLDivElement | null>(null); const iconDomRefs = useRef<HTMLDivElement[]>([]); const textDomRefs = useRef<HTMLDivElement[]>([]); @@ -254,7 +249,6 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref<Skele className={`${prefixCls}-skeleton-animation-item`} style={{ left: 0 - (iconOffsets?.[idx] || 0), - width: gradientWidth, }} /> )} @@ -273,7 +267,6 @@ export const SkeletonGrid = forwardRef((props: SkeletonGridProps, ref: Ref<Skele className={`${prefixCls}-skeleton-animation-item`} style={{ left: 0 - (textOffsets?.[idx] || 0), - width: gradientWidth, }} /> )} diff --git a/packages/arcodesign/components/skeleton/index.tsx b/packages/arcodesign/components/skeleton/index.tsx index c977e6d4..a1f3e683 100644 --- a/packages/arcodesign/components/skeleton/index.tsx +++ b/packages/arcodesign/components/skeleton/index.tsx @@ -1,12 +1,4 @@ -import React, { - useRef, - forwardRef, - Ref, - useImperativeHandle, - useContext, - useEffect, - useState, -} from 'react'; +import React, { useRef, forwardRef, Ref, useImperativeHandle, useContext } from 'react'; import { cls, componentWrapper } from '@arco-design/mobile-utils'; import { GlobalContext } from '../context-provider'; import { SkeletonProps, SkeletonRef } from './type'; @@ -42,7 +34,6 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { } = props; const domRef = useRef<HTMLDivElement | null>(null); const { prefixCls } = useContext(GlobalContext); - const [gradientWidth, setGradientWidth] = useState<number>(); useImperativeHandle(ref, () => ({ dom: domRef.current, @@ -66,13 +57,6 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { </> ); - useEffect(() => { - if (showAnimation && animation === 'gradient') { - const width = domRef.current?.clientHeight || 0; - width > window.innerWidth && setGradientWidth(width); - } - }, []); - return ( <div className={cls( @@ -85,9 +69,7 @@ const Skeleton = forwardRef((props: SkeletonProps, ref: Ref<SkeletonRef>) => { style={{ color: animationGradientColor, ...style }} ref={domRef} > - <SkeletonContext.Provider - value={{ showAnimation, animation, backgroundColor, gradientWidth }} - > + <SkeletonContext.Provider value={{ showAnimation, animation, backgroundColor }}> {content} {children} </SkeletonContext.Provider> diff --git a/packages/arcodesign/components/skeleton/type.ts b/packages/arcodesign/components/skeleton/type.ts index e216cb7f..ad6bad5b 100644 --- a/packages/arcodesign/components/skeleton/type.ts +++ b/packages/arcodesign/components/skeleton/type.ts @@ -106,5 +106,4 @@ export interface SkeletonContextParams { backgroundColor?: string; showAnimation: boolean; animation: SkeletonProps['animation']; - gradientWidth?: number; } From b15183a19a048c0bde9834fbc08cc2a2503ebd84 Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" <xiaziqi.sia@bytedance.com> Date: Sun, 16 Jul 2023 15:24:10 +0800 Subject: [PATCH 08/11] feat: animation duration token --- .../components/skeleton/style/index.less | 4 +++- .../app/arcodesign/default/css-variables.less | 2 ++ .../tokens/app/arcodesign/default/index.d.ts | 2 ++ .../tokens/app/arcodesign/default/index.js | 2 ++ .../tokens/app/arcodesign/default/index.json | 24 +++++++++++++++++++ .../tokens/app/arcodesign/default/index.less | 2 ++ .../tokens/src/arcodesign/default/index.js | 10 ++++++++ 7 files changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index 2a7d1c6a..c177ccee 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -103,12 +103,14 @@ animation-timing-function: linear; animation-iteration-count: infinite; animation-duration: 1.5s; + .use-var(animation-duration, 'skeleton-gradient-animation-duration'); [dir='rtl'] & { animation-name: gradient-reverse; } } .@{prefix}-skeleton-animation-breath { - animation: breath 2s linear infinite; + animation: breath linear infinite; + .use-var(animation-duration, 'skeleton-breath-animation-duration'); } @keyframes gradient { diff --git a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less index f79c19ab..7ea41ed7 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less @@ -797,6 +797,8 @@ --skeleton-background-color: #F2F3F5; --skeleton-gradient-animation-color: rgba(0, 0, 0, 0.04); --skeleton-breath-opacity: 0.3; + --skeleton-gradient-animation-duration: 1.5s; + --skeleton-breath-animation-duration: 2s; --skeleton-title-height: ~`pxtorem(16)`; --skeleton-paragraph-height: ~`pxtorem(16)`; --skeleton-paragraph-margin-top: ~`pxtorem(12)`; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts index 24c1b54d..f7b06281 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts @@ -796,6 +796,8 @@ export interface ArcodesignToken extends Record<string, string> { 'skeleton-background-color': string; 'skeleton-gradient-animation-color': string; 'skeleton-breath-opacity': string; + 'skeleton-gradient-animation-duration': string; + 'skeleton-breath-animation-duration': string; 'skeleton-title-height': string; 'skeleton-paragraph-height': string; 'skeleton-paragraph-margin-top': string; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index c027d68d..dc374d01 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -808,6 +808,8 @@ var tokens = { "skeleton-background-color": "#F2F3F5", "skeleton-gradient-animation-color": "rgba(0, 0, 0, 0.04)", "skeleton-breath-opacity": "0.3", + "skeleton-gradient-animation-duration": "1.5s", + "skeleton-breath-animation-duration": "2s", "skeleton-title-height": "0.32rem", "skeleton-paragraph-height": "0.32rem", "skeleton-paragraph-margin-top": "0.24rem", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.json b/packages/arcodesign/tokens/app/arcodesign/default/index.json index c84362b6..6725b901 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.json +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.json @@ -6665,6 +6665,18 @@ "en": "Skeleton element border radius" } }, + "skeletonBreathAnimationDuration": { + "cssKey": "skeleton-breath-animation-duration", + "desc": "骨架屏呼吸动效时间", + "override": "", + "value": "2s", + "jsValue": "2s", + "staticValue": "2s", + "localeDesc": { + "ch": "骨架屏呼吸动效时间", + "en": "Skeleton element breath animation duration" + } + }, "skeletonBreathOpacity": { "cssKey": "skeleton-breath-opacity", "desc": "骨架屏呼吸动效透明度", @@ -6689,6 +6701,18 @@ "en": "Skeleton element gradient animation highlight color" } }, + "skeletonGradientAnimationDuration": { + "cssKey": "skeleton-gradient-animation-duration", + "desc": "骨架屏扫光动效时间", + "override": "", + "value": "1.5s", + "jsValue": "1.5s", + "staticValue": "1.5s", + "localeDesc": { + "ch": "骨架屏扫光动效时间", + "en": "Skeleton element gradient animation duration" + } + }, "skeletonGridIconWidth": { "cssKey": "skeleton-grid-icon-width", "desc": "骨架屏金刚位图标区宽度", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.less b/packages/arcodesign/tokens/app/arcodesign/default/index.less index 2b1598fb..9e113dfd 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.less @@ -796,6 +796,8 @@ @skeleton-background-color: #F2F3F5; @skeleton-gradient-animation-color: rgba(0, 0, 0, 0.04); @skeleton-breath-opacity: 0.3; +@skeleton-gradient-animation-duration: 1.5s; +@skeleton-breath-animation-duration: 2s; @skeleton-title-height: ~`pxtorem(16)`; @skeleton-paragraph-height: ~`pxtorem(16)`; @skeleton-paragraph-margin-top: ~`pxtorem(12)`; diff --git a/packages/arcodesign/tokens/src/arcodesign/default/index.js b/packages/arcodesign/tokens/src/arcodesign/default/index.js index 103ae791..e6052336 100644 --- a/packages/arcodesign/tokens/src/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/src/arcodesign/default/index.js @@ -4038,6 +4038,16 @@ function getCompTokens() { * @en Skeleton element breath animation opacity */ skeletonBreathOpacity: '0.3', + /** + * 骨架屏扫光动效时间 + * @en Skeleton element gradient animation duration + */ + skeletonGradientAnimationDuration: '1.5s', + /** + * 骨架屏呼吸动效时间 + * @en Skeleton element breath animation duration + */ + skeletonBreathAnimationDuration: '2s', /** * 骨架屏标题高度 * @en Skeleton title height From 45df05ca5bb93ef2174791dffcead886f7a117e0 Mon Sep 17 00:00:00 2001 From: "xiaziqi.sia" <xiaziqi.sia@bytedance.com> Date: Mon, 17 Jul 2023 19:45:37 +0800 Subject: [PATCH 09/11] feat: update token --- packages/arcodesign/components/skeleton/style/index.less | 8 ++++---- .../tokens/app/arcodesign/default/css-variables.less | 4 ++-- .../arcodesign/tokens/app/arcodesign/default/index.d.ts | 4 ++-- .../arcodesign/tokens/app/arcodesign/default/index.js | 4 ++-- .../arcodesign/tokens/app/arcodesign/default/index.json | 8 ++++---- .../arcodesign/tokens/app/arcodesign/default/index.less | 4 ++-- .../arcodesign/tokens/src/arcodesign/default/index.js | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index c177ccee..9ec65a44 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -31,7 +31,7 @@ width: 100%; .@{prefix}-skeleton-title + .@{prefix}-skeleton-paragraph { - .use-var(margin-top, 'skeleton-gutter-large'); + .use-var(margin-top, 'skeleton-large-gutter'); } } @@ -45,12 +45,12 @@ .@{prefix}-skeleton-content { .@{prefix}-skeleton-title { - .use-var(margin-top, 'skeleton-gutter-medium'); + .use-var(margin-top, 'skeleton-medium-gutter'); } } .@{prefix}-skeleton-avatar + .@{prefix}-skeleton-content { - .use-var-with-rtl(margin-left, 'skeleton-gutter-medium'); + .use-var-with-rtl(margin-left, 'skeleton-medium-gutter'); } } @@ -69,7 +69,7 @@ .use-var(height, 'skeleton-grid-icon-width'); } &-text { - .use-var(margin-top, 'skeleton-gutter-medium'); + .use-var(margin-top, 'skeleton-medium-gutter'); .use-var(width, 'skeleton-grid-text-width'); .use-var(height, 'skeleton-grid-text-height'); } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less index 7ea41ed7..e10e08b2 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less @@ -806,6 +806,6 @@ --skeleton-grid-icon-width: ~`pxtorem(32)`; --skeleton-grid-text-width: ~`pxtorem(64)`; --skeleton-grid-text-height: ~`pxtorem(16)`; - --skeleton-gutter-medium: ~`pxtorem(8)`; - --skeleton-gutter-large: ~`pxtorem(20)`; + --skeleton-medium-gutter: ~`pxtorem(8)`; + --skeleton-large-gutter: ~`pxtorem(20)`; } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts index f7b06281..152240be 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts @@ -805,8 +805,8 @@ export interface ArcodesignToken extends Record<string, string> { 'skeleton-grid-icon-width': string; 'skeleton-grid-text-width': string; 'skeleton-grid-text-height': string; - 'skeleton-gutter-medium': string; - 'skeleton-gutter-large': string; + 'skeleton-medium-gutter': string; + 'skeleton-large-gutter': string; } declare const tokens: ArcodesignToken; export default tokens; \ No newline at end of file diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index dc374d01..0628ccac 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -817,8 +817,8 @@ var tokens = { "skeleton-grid-icon-width": "0.64rem", "skeleton-grid-text-width": "1.28rem", "skeleton-grid-text-height": "0.32rem", - "skeleton-gutter-medium": "0.16rem", - "skeleton-gutter-large": "0.4rem" + "skeleton-medium-gutter": "0.16rem", + "skeleton-large-gutter": "0.4rem" }; var _default = tokens; exports["default"] = _default; \ No newline at end of file diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.json b/packages/arcodesign/tokens/app/arcodesign/default/index.json index 6725b901..21a8da5b 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.json +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.json @@ -6749,8 +6749,8 @@ "en": "Skeleton grid item text width" } }, - "skeletonGutterLarge": { - "cssKey": "skeleton-gutter-large", + "skeletonLargeGutter": { + "cssKey": "skeleton-large-gutter", "desc": "骨架屏元素外边距,大尺寸", "override": "", "value": "~`pxtorem(20)`", @@ -6760,8 +6760,8 @@ "ch": "骨架屏元素外边距,大尺寸" } }, - "skeletonGutterMedium": { - "cssKey": "skeleton-gutter-medium", + "skeletonMediumGutter": { + "cssKey": "skeleton-medium-gutter", "desc": "骨架屏元素外边距,中尺寸", "override": "", "value": "~`pxtorem(8)`", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.less b/packages/arcodesign/tokens/app/arcodesign/default/index.less index 9e113dfd..389d8596 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.less @@ -805,6 +805,6 @@ @skeleton-grid-icon-width: ~`pxtorem(32)`; @skeleton-grid-text-width: ~`pxtorem(64)`; @skeleton-grid-text-height: ~`pxtorem(16)`; -@skeleton-gutter-medium: ~`pxtorem(8)`; -@skeleton-gutter-large: ~`pxtorem(20)`; +@skeleton-medium-gutter: ~`pxtorem(8)`; +@skeleton-large-gutter: ~`pxtorem(20)`; diff --git a/packages/arcodesign/tokens/src/arcodesign/default/index.js b/packages/arcodesign/tokens/src/arcodesign/default/index.js index e6052336..34f95ace 100644 --- a/packages/arcodesign/tokens/src/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/src/arcodesign/default/index.js @@ -4086,11 +4086,11 @@ function getCompTokens() { /** * 骨架屏元素外边距,中尺寸 */ - skeletonGutterMedium: getRem(8), + skeletonMediumGutter: getRem(8), /** * 骨架屏元素外边距,大尺寸 */ - skeletonGutterLarge: getRem(20), + skeletonLargeGutter: getRem(20), }; } From 960a9935a278d5cfff4cadcf51635259cee1a474 Mon Sep 17 00:00:00 2001 From: taoyiyue <taoyiyue@bytedance.com> Date: Wed, 2 Aug 2023 10:26:33 +0800 Subject: [PATCH 10/11] chore: demo update --- packages/arcodesign/components/skeleton/demo/animation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/arcodesign/components/skeleton/demo/animation.md b/packages/arcodesign/components/skeleton/demo/animation.md index 3a62e51a..12abd610 100644 --- a/packages/arcodesign/components/skeleton/demo/animation.md +++ b/packages/arcodesign/components/skeleton/demo/animation.md @@ -10,7 +10,7 @@ const options = [ { label: 'breath', value: 'breath' }, ]; -const color = 'rgba(148, 191, 255, 20%)'; +const color = 'rgba(0, 0, 0, 4%)'; export default function SkeletonDemo() { const [type, setType] = React.useState('gradient'); From 505017ac2e72ac611dfb9b39d30a53e2edaefe08 Mon Sep 17 00:00:00 2001 From: taoyiyue <taoyiyue@bytedance.com> Date: Tue, 8 Aug 2023 21:33:33 +0800 Subject: [PATCH 11/11] fix: tokens adjust --- .../components/skeleton/style/index.less | 51 +++++++++---------- .../app/arcodesign/default/css-variables.less | 9 ++-- .../tokens/app/arcodesign/default/index.d.ts | 3 +- .../tokens/app/arcodesign/default/index.js | 9 ++-- .../tokens/app/arcodesign/default/index.json | 34 +++++++++---- .../tokens/app/arcodesign/default/index.less | 9 ++-- .../tokens/src/arcodesign/default/index.js | 13 +++-- 7 files changed, 74 insertions(+), 54 deletions(-) diff --git a/packages/arcodesign/components/skeleton/style/index.less b/packages/arcodesign/components/skeleton/style/index.less index 9ec65a44..1a6788fc 100644 --- a/packages/arcodesign/components/skeleton/style/index.less +++ b/packages/arcodesign/components/skeleton/style/index.less @@ -6,23 +6,23 @@ } .@{prefix}-skeleton-title { - .use-var(height, 'skeleton-title-height'); + .use-var(height, skeleton-title-height); } .@{prefix}-skeleton-paragraph { &-line { width: 100%; - .use-var(height, 'skeleton-paragraph-height'); + .use-var(height, skeleton-paragraph-height); } &-line + &-line { - .use-var(margin-top, 'skeleton-paragraph-margin-top'); + .use-var(margin-top, skeleton-paragraph-margin-top); } } .@{prefix}-skeleton-avatar.@{prefix}-skeleton-item { - .use-var(width, 'skeleton-avatar-size'); - .use-var(height, 'skeleton-avatar-size'); + .use-var(width, skeleton-avatar-size); + .use-var(height, skeleton-avatar-size); border-radius: 100%; transform: translateZ(0); } @@ -31,7 +31,7 @@ width: 100%; .@{prefix}-skeleton-title + .@{prefix}-skeleton-paragraph { - .use-var(margin-top, 'skeleton-large-gutter'); + .use-var(margin-top, skeleton-large-gutter); } } @@ -45,12 +45,12 @@ .@{prefix}-skeleton-content { .@{prefix}-skeleton-title { - .use-var(margin-top, 'skeleton-medium-gutter'); + .use-var(margin-top, skeleton-medium-gutter); } } .@{prefix}-skeleton-avatar + .@{prefix}-skeleton-content { - .use-var-with-rtl(margin-left, 'skeleton-medium-gutter'); + .use-var-with-rtl(margin-left, skeleton-medium-gutter); } } @@ -65,13 +65,13 @@ align-items: center; } &-icon { - .use-var(width, 'skeleton-grid-icon-width'); - .use-var(height, 'skeleton-grid-icon-width'); + .use-var(width, skeleton-grid-icon-size); + .use-var(height, skeleton-grid-icon-size); } &-text { - .use-var(margin-top, 'skeleton-medium-gutter'); - .use-var(width, 'skeleton-grid-text-width'); - .use-var(height, 'skeleton-grid-text-height'); + .use-var(margin-top, skeleton-medium-gutter); + .use-var(width, skeleton-grid-text-width); + .use-var(height, skeleton-grid-text-height); } } @@ -82,8 +82,8 @@ .@{prefix}-skeleton-item { position: relative; overflow: hidden; - .use-var(border-radius, 'skeleton-border-radius'); - .use-var(background-color, 'skeleton-background-color'); + .use-var(border-radius, skeleton-border-radius); + .use-var(background-color, skeleton-background-color); } .@{prefix}-skeleton-animation-item { @@ -99,21 +99,20 @@ rgba(255, 255, 255, 0) 65% ); transform-origin: top left; - animation-name: gradient; - animation-timing-function: linear; + animation-name: skeleton-gradient; animation-iteration-count: infinite; - animation-duration: 1.5s; - .use-var(animation-duration, 'skeleton-gradient-animation-duration'); - [dir='rtl'] & { - animation-name: gradient-reverse; + .use-var(animation-timing-function, skeleton-gradient-animation-timing-function); + .use-var(animation-duration, skeleton-gradient-animation-duration); + [dir="rtl"] & { + animation-name: skeleton-gradient-reverse; } } .@{prefix}-skeleton-animation-breath { - animation: breath linear infinite; - .use-var(animation-duration, 'skeleton-breath-animation-duration'); + animation: skeleton-breath linear infinite; + .use-var(animation-duration, skeleton-breath-animation-duration); } -@keyframes gradient { +@keyframes skeleton-gradient { 0% { transform: translateX(-65%) skewX(-45deg); } @@ -123,7 +122,7 @@ } } -@keyframes gradient-reverse { +@keyframes skeleton-gradient-reverse { 0% { transform: translateX(65%) skewX(45deg); } @@ -133,7 +132,7 @@ } } -@keyframes breath { +@keyframes skeleton-breath { 0% { opacity: 1; } diff --git a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less index e10e08b2..4b1ea3e3 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/css-variables.less @@ -795,15 +795,16 @@ --divider-padding: ~`pxtorem(16)`; --skeleton-border-radius: ~`pxtorem(0)`; --skeleton-background-color: #F2F3F5; - --skeleton-gradient-animation-color: rgba(0, 0, 0, 0.04); - --skeleton-breath-opacity: 0.3; + --skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); + --skeleton-breath-opacity: 0.4; + --skeleton-gradient-animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1); --skeleton-gradient-animation-duration: 1.5s; - --skeleton-breath-animation-duration: 2s; + --skeleton-breath-animation-duration: 1.5s; --skeleton-title-height: ~`pxtorem(16)`; --skeleton-paragraph-height: ~`pxtorem(16)`; --skeleton-paragraph-margin-top: ~`pxtorem(12)`; --skeleton-avatar-size: ~`pxtorem(32)`; - --skeleton-grid-icon-width: ~`pxtorem(32)`; + --skeleton-grid-icon-size: ~`pxtorem(32)`; --skeleton-grid-text-width: ~`pxtorem(64)`; --skeleton-grid-text-height: ~`pxtorem(16)`; --skeleton-medium-gutter: ~`pxtorem(8)`; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts index 152240be..5f111f56 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.d.ts @@ -796,13 +796,14 @@ export interface ArcodesignToken extends Record<string, string> { 'skeleton-background-color': string; 'skeleton-gradient-animation-color': string; 'skeleton-breath-opacity': string; + 'skeleton-gradient-animation-timing-function': string; 'skeleton-gradient-animation-duration': string; 'skeleton-breath-animation-duration': string; 'skeleton-title-height': string; 'skeleton-paragraph-height': string; 'skeleton-paragraph-margin-top': string; 'skeleton-avatar-size': string; - 'skeleton-grid-icon-width': string; + 'skeleton-grid-icon-size': string; 'skeleton-grid-text-width': string; 'skeleton-grid-text-height': string; 'skeleton-medium-gutter': string; diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.js b/packages/arcodesign/tokens/app/arcodesign/default/index.js index 0628ccac..bdbb81a6 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.js @@ -806,15 +806,16 @@ var tokens = { "divider-padding": "0.32rem", "skeleton-border-radius": "0", "skeleton-background-color": "#F2F3F5", - "skeleton-gradient-animation-color": "rgba(0, 0, 0, 0.04)", - "skeleton-breath-opacity": "0.3", + "skeleton-gradient-animation-color": "rgba(255, 255, 255, 0.6)", + "skeleton-breath-opacity": "0.4", + "skeleton-gradient-animation-timing-function": "cubic-bezier(0.42, 0, 0.58, 1)", "skeleton-gradient-animation-duration": "1.5s", - "skeleton-breath-animation-duration": "2s", + "skeleton-breath-animation-duration": "1.5s", "skeleton-title-height": "0.32rem", "skeleton-paragraph-height": "0.32rem", "skeleton-paragraph-margin-top": "0.24rem", "skeleton-avatar-size": "0.64rem", - "skeleton-grid-icon-width": "0.64rem", + "skeleton-grid-icon-size": "0.64rem", "skeleton-grid-text-width": "1.28rem", "skeleton-grid-text-height": "0.32rem", "skeleton-medium-gutter": "0.16rem", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.json b/packages/arcodesign/tokens/app/arcodesign/default/index.json index 21a8da5b..a1f18333 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.json +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.json @@ -6669,9 +6669,9 @@ "cssKey": "skeleton-breath-animation-duration", "desc": "骨架屏呼吸动效时间", "override": "", - "value": "2s", - "jsValue": "2s", - "staticValue": "2s", + "value": "1.5s", + "jsValue": "1.5s", + "staticValue": "1.5s", "localeDesc": { "ch": "骨架屏呼吸动效时间", "en": "Skeleton element breath animation duration" @@ -6681,9 +6681,9 @@ "cssKey": "skeleton-breath-opacity", "desc": "骨架屏呼吸动效透明度", "override": "", - "value": "0.3", - "jsValue": "0.3", - "staticValue": "0.3", + "value": "0.4", + "jsValue": "0.4", + "staticValue": "0.4", "localeDesc": { "ch": "骨架屏呼吸动效透明度", "en": "Skeleton element breath animation opacity" @@ -6693,9 +6693,9 @@ "cssKey": "skeleton-gradient-animation-color", "desc": "骨架屏扫光动效高亮色", "override": "", - "value": "rgba(0, 0, 0, 0.04)", - "jsValue": "rgba(0, 0, 0, 0.04)", - "staticValue": "rgba(0, 0, 0, 0.04)", + "value": "rgba(255, 255, 255, 0.6)", + "jsValue": "rgba(255, 255, 255, 0.6)", + "staticValue": "rgba(255, 255, 255, 0.6)", "localeDesc": { "ch": "骨架屏扫光动效高亮色", "en": "Skeleton element gradient animation highlight color" @@ -6713,8 +6713,20 @@ "en": "Skeleton element gradient animation duration" } }, - "skeletonGridIconWidth": { - "cssKey": "skeleton-grid-icon-width", + "skeletonGradientAnimationTimingFunction": { + "cssKey": "skeleton-gradient-animation-timing-function", + "desc": "骨架屏扫光动效曲线", + "override": "", + "value": "cubic-bezier(0.42, 0, 0.58, 1)", + "jsValue": "cubic-bezier(0.42, 0, 0.58, 1)", + "staticValue": "cubic-bezier(0.42, 0, 0.58, 1)", + "localeDesc": { + "ch": "骨架屏扫光动效曲线", + "en": "Skeleton element gradient animation timing function" + } + }, + "skeletonGridIconSize": { + "cssKey": "skeleton-grid-icon-size", "desc": "骨架屏金刚位图标区宽度", "override": "", "value": "~`pxtorem(32)`", diff --git a/packages/arcodesign/tokens/app/arcodesign/default/index.less b/packages/arcodesign/tokens/app/arcodesign/default/index.less index 389d8596..dc2ab27c 100644 --- a/packages/arcodesign/tokens/app/arcodesign/default/index.less +++ b/packages/arcodesign/tokens/app/arcodesign/default/index.less @@ -794,15 +794,16 @@ @divider-padding: ~`pxtorem(16)`; @skeleton-border-radius: ~`pxtorem(0)`; @skeleton-background-color: #F2F3F5; -@skeleton-gradient-animation-color: rgba(0, 0, 0, 0.04); -@skeleton-breath-opacity: 0.3; +@skeleton-gradient-animation-color: rgba(255, 255, 255, 0.6); +@skeleton-breath-opacity: 0.4; +@skeleton-gradient-animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1); @skeleton-gradient-animation-duration: 1.5s; -@skeleton-breath-animation-duration: 2s; +@skeleton-breath-animation-duration: 1.5s; @skeleton-title-height: ~`pxtorem(16)`; @skeleton-paragraph-height: ~`pxtorem(16)`; @skeleton-paragraph-margin-top: ~`pxtorem(12)`; @skeleton-avatar-size: ~`pxtorem(32)`; -@skeleton-grid-icon-width: ~`pxtorem(32)`; +@skeleton-grid-icon-size: ~`pxtorem(32)`; @skeleton-grid-text-width: ~`pxtorem(64)`; @skeleton-grid-text-height: ~`pxtorem(16)`; @skeleton-medium-gutter: ~`pxtorem(8)`; diff --git a/packages/arcodesign/tokens/src/arcodesign/default/index.js b/packages/arcodesign/tokens/src/arcodesign/default/index.js index 34f95ace..1a4d7d2d 100644 --- a/packages/arcodesign/tokens/src/arcodesign/default/index.js +++ b/packages/arcodesign/tokens/src/arcodesign/default/index.js @@ -4032,12 +4032,17 @@ function getCompTokens() { * 骨架屏扫光动效高亮色 * @en Skeleton element gradient animation highlight color */ - skeletonGradientAnimationColor: 'rgba(0, 0, 0, 0.04)', + skeletonGradientAnimationColor: 'rgba(255, 255, 255, 0.6)', /** * 骨架屏呼吸动效透明度 * @en Skeleton element breath animation opacity */ - skeletonBreathOpacity: '0.3', + skeletonBreathOpacity: '0.4', + /** + * 骨架屏扫光动效曲线 + * @en Skeleton element gradient animation timing function + */ + skeletonGradientAnimationTimingFunction: 'cubic-bezier(0.42, 0, 0.58, 1)', /** * 骨架屏扫光动效时间 * @en Skeleton element gradient animation duration @@ -4047,7 +4052,7 @@ function getCompTokens() { * 骨架屏呼吸动效时间 * @en Skeleton element breath animation duration */ - skeletonBreathAnimationDuration: '2s', + skeletonBreathAnimationDuration: '1.5s', /** * 骨架屏标题高度 * @en Skeleton title height @@ -4072,7 +4077,7 @@ function getCompTokens() { * 骨架屏金刚位图标区宽度 * @en Skeleton grid item icon width */ - skeletonGridIconWidth: getRem(32), + skeletonGridIconSize: getRem(32), /** * 骨架屏金刚位文字区宽度 * @en Skeleton grid item text width