Skip to content
Open
  •  
  •  
  •  
4 changes: 3 additions & 1 deletion .dumi/theme/slots/ContentTabs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import type { FC, ReactNode } from 'react';
import React from 'react';
import { CodeOutlined, SkinOutlined } from '@oceanbase/icons';
import { CodeOutlined, LinkOutlined, SkinOutlined } from '@oceanbase/icons';
import { Tabs } from '@oceanbase/design';
import { useRouteMeta } from 'dumi';
import type { IContentTabsProps } from 'dumi/theme-default/slots/ContentTabs';
import type { TabsProps } from 'rc-tabs';

const titleMap: Record<string, ReactNode> = {
design: '设计',
playground: 'Figma Code Connect',
};

const iconMap: Record<string, ReactNode> = {
design: <SkinOutlined />,
playground: <LinkOutlined />,
};

const ContentTabs: FC<IContentTabsProps> = ({ tabs, tabKey, onChange }) => {
Expand Down
170 changes: 170 additions & 0 deletions packages/design/src/alert/demo/index.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { Alert, Button, Col, Row, Select, Space, Switch, Typography } from '@oceanbase/design';
import type { CSSProperties } from 'react';
import React, { useMemo, useState } from 'react';

/**
* Playground:与 `../index.figma.tsx` 中 `figma.connect` 的 props / example 一一对应,
* 便于在文档里用控件复现 Figma Component playground 中的 type / size / button / closable。
*/

const STYLE_BY_SIZE: Record<'default' | 'large' | 'mini', CSSProperties> = {
default: {
paddingTop: 8,
paddingBottom: 8,
paddingLeft: 16,
paddingRight: 16,
},
large: {
paddingTop: 12,
paddingBottom: 12,
paddingLeft: 16,
paddingRight: 16,
},
mini: {
paddingTop: 4,
paddingBottom: 4,
paddingLeft: 8,
paddingRight: 8,
},
};

type FigmaAlertType = 'info' | 'warning' | 'success' | 'error';

/** 与 `../index.figma.tsx` 的 props/example 一致;default/large 与 mini 的稿面间距差仅在此用 STYLE_BY_SIZE 预览(§3.4a)。 */
function FigmaAlertExample(props: {
closable: boolean;
type: FigmaAlertType;
size: 'default' | 'large' | 'mini';
style: CSSProperties;
action?: React.ReactNode;
message: React.ReactNode;
}) {
const { closable, type, size, style, action, message } = props;
return (
<Alert
closable={closable}
type={type}
mini={size === 'mini'}
style={style}
action={action}
message={message}
/>
);
}

const MESSAGE_DEMO = (
<span>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.{' '}
<Typography.Link href="#" onClick={e => e.preventDefault()}>
help
</Typography.Link>
</span>
);

const App: React.FC = () => {
const [type, setType] = useState<FigmaAlertType>('info');
const [size, setSize] = useState<'default' | 'large' | 'mini'>('default');
/** 对应 Figma `button`:false / ture(设计稿拼写) */
const [withButton, setWithButton] = useState(true);
const [closable, setClosable] = useState(true);

const style = STYLE_BY_SIZE[size];
const action = useMemo(
() => (withButton ? <Button type="default">Button</Button> : undefined),
[withButton]
);

return (
<Row
wrap={false}
gutter={0}
style={{
minHeight: 360,
border: '1px solid var(--ant-color-border-secondary, #f0f0f0)',
borderRadius: 8,
overflow: 'hidden',
background: 'var(--ant-color-bg-container, #fff)',
}}
>
<Col
flex="1 1 auto"
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
minHeight: 280,
padding: 24,
background: 'var(--ant-color-fill-quaternary, #fafafa)',
}}
>
<FigmaAlertExample
closable={closable}
type={type}
size={size}
style={style}
action={action}
message={MESSAGE_DEMO}
/>
</Col>
<Col
flex="0 0 280px"
style={{
borderLeft: '1px solid var(--ant-color-border-secondary, #f0f0f0)',
padding: '16px 20px',
}}
>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
Alert
</Typography.Text>
<Space direction="vertical" size={16} style={{ width: '100%', marginTop: 12 }}>
<div>
<div style={{ marginBottom: 6, fontSize: 12 }}>type</div>
<Select
style={{ width: '100%' }}
value={type}
onChange={v => setType(v as FigmaAlertType)}
options={[
{ value: 'info', label: 'info' },
{ value: 'warning', label: 'warning' },
{ value: 'success', label: 'success' },
{ value: 'error', label: 'error' },
]}
/>
</div>
<div>
<div style={{ marginBottom: 6, fontSize: 12 }}>size</div>
<Select
style={{ width: '100%' }}
value={size}
onChange={v => setSize(v as 'default' | 'large' | 'mini')}
options={[
{ value: 'default', label: 'default' },
{ value: 'large', label: 'large' },
{ value: 'mini', label: 'mini' },
]}
/>
</div>
<div>
<div style={{ marginBottom: 6, fontSize: 12 }}>button</div>
<Select
style={{ width: '100%' }}
value={withButton ? 'true' : 'false'}
onChange={v => setWithButton(v === 'true')}
options={[
{ value: 'false', label: 'false' },
{ value: 'true', label: 'true' },
]}
/>
</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<span style={{ fontSize: 12 }}>closable</span>
<Switch checked={closable} onChange={setClosable} />
</div>
</Space>
</Col>
</Row>
);
};

export default App;
5 changes: 5 additions & 0 deletions packages/design/src/alert/index.$tab-playground.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
本页对应 `packages/design/src/alert/index.figma.tsx` 的 Figma Code Connect 映射。[Figma](https://www.figma.com/design/dqhv73np0wsgrmzIZYRDf2/codeconnect%E6%B5%8B%E8%AF%95%E7%BB%84%E4%BB%B6%E5%BA%93?node-id=5025-6647&m=dev)。

## 代码演示

<code src="./demo/index.figma.tsx" title="预览" description="与 index.figma.tsx 中 Code Connect 示例一致。"></code>
40 changes: 40 additions & 0 deletions packages/design/src/alert/index.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// @ts-nocheck

import { figma } from '@figma/code-connect';
import { Alert, Button } from '@oceanbase/design';

/**
* Code Connect — Alert
* Page: "↵Alert"
* Figma `size` default/large 在组件 API 中无独立 prop,与 `mini` 的像素差在 `demo/index.figma.tsx` 用容器样式呈现(§3.4a / §3.4c)。
*/

// Figma: "Alert" · 5025:6647
// https://www.figma.com/design/dqhv73np0wsgrmzIZYRDf2/codeconnect%E6%B5%8B%E8%AF%95%E7%BB%84%E4%BB%B6%E5%BA%93?node-id=5025-6647&m=dev
figma.connect(Alert, '<FIGMA_OCEANBASE_ALERT>', {
props: {
closable: figma.boolean('closable', {
true: true,
false: false,
}),
type: figma.enum('type', {
info: 'info',
warning: 'warning',
success: 'success',
error: 'error',
}),
mini: figma.enum('size', {
default: false,
large: false,
mini: true,
}),
action: figma.enum('button', {
false: undefined,
ture: <Button type="default">Button</Button>,
}),
message: figma.textContent('Text'),
},
example: ({ closable, type, mini, action, message }) => (
<Alert closable={closable} type={type} mini={mini} action={action} message={message} />
),
});
113 changes: 113 additions & 0 deletions packages/design/src/badge/demo/index.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Badge, Col, Row, Select, Space, Typography } from '@oceanbase/design';
import React, { useMemo, useState } from 'react';

/**
* Playground:与 `../index.figma.tsx` 中第三条 `figma.connect`(`<FIGMA_OCEANBASE_BADGE>`)的
* `props` / `example` 一致。前两条仅静态 `row` 的 connect 不在此交互复现。
*/

/** Figma `size`:medium → antd Badge `default`,small → `small` */
type FigmaSizeKey = 'medium' | 'small';

function FigmaBadgeExample(props: {
dot: boolean;
size: 'default' | 'small';
count?: number;
color: string;
}) {
const { dot, size, count, color } = props;
return <Badge dot={dot} count={count} size={size} color={color} />;
}

/** 与 `index.figma.tsx` 中 `count` / `color` 的嵌套 `figma.enum` 分支一致 */
function deriveCountAndColor(
dot: boolean,
figmaSize: FigmaSizeKey
): { count: number | undefined; color: string } {
if (dot) {
return { count: undefined, color: '#ff4d4f' };
}
if (figmaSize === 'small') {
return { count: 5, color: '#eb4242' };
}
return { count: 99, color: '#ebeff7' };
}

const App: React.FC = () => {
const [dotStr, setDotStr] = useState<'false' | 'true'>('false');
const [figmaSize, setFigmaSize] = useState<FigmaSizeKey>('medium');

const dot = dotStr === 'true';
const size: 'default' | 'small' = figmaSize === 'medium' ? 'default' : 'small';

const { count, color } = useMemo(() => deriveCountAndColor(dot, figmaSize), [dot, figmaSize]);

return (
<Row
wrap={false}
gutter={0}
style={{
minHeight: 360,
border: '1px solid var(--ant-color-border-secondary, #f0f0f0)',
borderRadius: 8,
overflow: 'hidden',
background: 'var(--ant-color-bg-container, #fff)',
}}
>
<Col
flex="1 1 auto"
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
minHeight: 280,
padding: 24,
background: 'var(--ant-color-fill-quaternary, #fafafa)',
}}
>
<FigmaBadgeExample dot={dot} size={size} count={count} color={color} />
</Col>
<Col
flex="0 0 280px"
style={{
borderLeft: '1px solid var(--ant-color-border-secondary, #f0f0f0)',
padding: '16px 20px',
}}
>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
Badge
</Typography.Text>
<Space direction="vertical" size={16} style={{ width: '100%', marginTop: 12 }}>
<div>
<div style={{ marginBottom: 6, fontSize: 12 }}>dot</div>
<Select
style={{ width: '100%' }}
value={dotStr}
onChange={v => setDotStr(v as 'false' | 'true')}
options={[
{ value: 'false', label: 'false' },
/** 设计稿枚举键拼写为 ture */
{ value: 'true', label: 'ture' },
]}
/>
</div>
<div>
<div style={{ marginBottom: 6, fontSize: 12 }}>size</div>
<Select
style={{ width: '100%' }}
value={figmaSize}
onChange={v => setFigmaSize(v as FigmaSizeKey)}
options={[
{ value: 'medium', label: 'medium' },
{ value: 'small', label: 'small' },
]}
/>
</div>
</Space>
</Col>
</Row>
);
};

export default App;
5 changes: 5 additions & 0 deletions packages/design/src/badge/index.$tab-playground.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
本页对应 `packages/design/src/badge/index.figma.tsx` 的 Figma Code Connect 映射。[Figma](https://www.figma.com/design/dqhv73np0wsgrmzIZYRDf2/codeconnect%E6%B5%8B%E8%AF%95%E7%BB%84%E4%BB%B6%E5%BA%93?node-id=5025-2361&m=dev)。

## 代码演示

<code src="./demo/index.figma.tsx" title="预览" description="与第三条 figma.connect(主 Badge 实例)的 props / example 一致。"></code>
Loading
Loading