Skip to content

Commit

Permalink
feat: implement stories for EllipsisMiddle and AddressText
Browse files Browse the repository at this point in the history
  • Loading branch information
WhiteMinds committed Nov 10, 2023
1 parent bee589e commit 6b8457f
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import 'antd/dist/antd.css'
// This should be after all third-party library styles so that it can override them.
import '../src/index.css'
import '../src/utils/i18n'
import type { Preview } from '@storybook/react'
import { MINIMAL_VIEWPORTS, INITIAL_VIEWPORTS } from '@storybook/addon-viewport'

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
"eject": "react-app-rewired eject",
"husky:init": "husky install",
"prepare": "husky install",
"storybook": "storybook dev -p 6006",
"storybook": "storybook dev -p 3000",
"build-storybook": "storybook build"
},
"jest": {
Expand Down
4 changes: 4 additions & 0 deletions src/components/AddressText/index.stories.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.border {
border: 1px solid #000;
box-sizing: content-box;
}
63 changes: 63 additions & 0 deletions src/components/AddressText/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { Meta, StoryObj } from '@storybook/react'

import AddressText from '.'
import styles from './index.stories.module.scss'
import { useForkedState } from '../../utils/hook'

const meta = {
component: AddressText,
argTypes: {
children: {
// In React 17, `FC<P>` is wrapped in `PropsWithChildren<P>`, causing the type of `children` to be unrecognizable by Storybook.
description: 'This item will be used as text when text is empty.',
type: 'string',
},
},
} satisfies Meta<typeof AddressText>

export default meta
type Story = StoryObj<typeof meta>

const addressHash = 'ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqflz4emgssc6nqj4yv3nfv2sca7g9dzhscgmg28x'

export const Primary: Story = {
parameters: {
viewport: {
defaultViewport: 'mobile2',
},
},
args: {
children: addressHash,
},
}

export const UseTextWidthForPlaceholderWidth: Story = {
parameters: {
viewport: {
defaultViewport: 'tablet',
},
},
args: {
children: addressHash,
useTextWidthForPlaceholderWidth: true,
className: styles.border,
},
render: function Render(args) {
const [useTextWidthForPlaceholderWidth, setUseTextWidthForPlaceholderWidth] = useForkedState(
args.useTextWidthForPlaceholderWidth,
)

return (
<div>
<AddressText {...args} useTextWidthForPlaceholderWidth={useTextWidthForPlaceholderWidth} />
<button
type="button"
onClick={() => setUseTextWidthForPlaceholderWidth(value => !value)}
style={{ marginTop: 16 }}
>
toggle useTextWidthForPlaceholderWidth
</button>
</div>
)
},
}
80 changes: 80 additions & 0 deletions src/components/EllipsisMiddle/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { Meta, StoryObj } from '@storybook/react'

import EllipsisMiddle from '.'
import { useForkedState } from '../../utils/hook'

const meta = {
component: EllipsisMiddle,
parameters: {
viewport: {
defaultViewport: 'tablet',
},
},
argTypes: {
children: {
// In React 17, `FC<P>` is wrapped in `PropsWithChildren<P>`, causing the type of `children` to be unrecognizable by Storybook.
description: 'This item will be used as text when text is empty.',
type: 'string',
},
},
} satisfies Meta<typeof EllipsisMiddle>

export default meta
type Story = StoryObj<typeof meta>

function getSentence(count: number) {
return new Array(count)
.fill(null)
.map((_, idx) => `This is a sentence ${idx}.`)
.join(' ')
}

export const ShortSentence: Story = {
args: {
children: getSentence(1),
},
}

export const LongSentence: Story = {
args: {
children: getSentence(10),
},
}

export const MinStartLen: Story = {
parameters: {
viewport: {
defaultViewport: 'mobile1',
},
},
args: {
minStartLen: 40,
children: getSentence(10),
},
}

export const UseTextWidthForPlaceholderWidth: Story = {
args: {
children: getSentence(1),
useTextWidthForPlaceholderWidth: true,
style: { border: '1px solid #000', boxSizing: 'content-box' },
},
render: function Render(args) {
const [useTextWidthForPlaceholderWidth, setUseTextWidthForPlaceholderWidth] = useForkedState(
args.useTextWidthForPlaceholderWidth,
)

return (
<div>
<EllipsisMiddle {...args} useTextWidthForPlaceholderWidth={useTextWidthForPlaceholderWidth} />
<button
type="button"
onClick={() => setUseTextWidthForPlaceholderWidth(value => !value)}
style={{ marginTop: 16 }}
>
toggle useTextWidthForPlaceholderWidth
</button>
</div>
)
},
}
4 changes: 3 additions & 1 deletion src/components/EllipsisMiddle/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { createTextWidthMeasurer } from '../../utils/string'

const EllipsisMiddle: FC<
HTMLAttributes<HTMLDivElement> & {
/** This item will be used as text when text is empty. */
children?: string
/** When this item is not empty, ignore the value of `children`. */
text?: string
// Any key that represents the use of a different font
/** Any key that represents the use of a different font. */
fontKey?: string | number | boolean
minStartLen?: number
minEndLen?: number
Expand Down
10 changes: 8 additions & 2 deletions src/utils/hook.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState, useRef, useMemo, useCallback, RefObject } from 'react'
import { useEffect, useState, useRef, useMemo, useCallback, RefObject, Dispatch, SetStateAction } from 'react'
import {
AddressPrefix,
addressToScript,
Expand All @@ -14,8 +14,8 @@ import { deprecatedAddrToNewAddr } from './util'
import { startEndEllipsis } from './string'
import { ListPageParams, PageParams, THEORETICAL_EPOCH_TIME, EPOCHS_PER_HALVING } from '../constants/common'
import { omit } from './object'
// TODO: This file depends on higher-level abstractions, so it should not be in the utils folder. It should be moved to `src/hooks/index.ts`.
import { useParseDate } from './date'
// TODO: This file depends on higher-level abstractions, so it should not be in the utils folder. It should be moved to `src/hooks/index.ts`.
import { useStatistics } from '../services/ExplorerService'
import { cacheService } from '../services/CacheService'

Expand All @@ -35,6 +35,12 @@ export function usePrevious<T>(value: T): T | undefined {
return ref.current
}

export function useForkedState<S>(basedState: S): [S, Dispatch<SetStateAction<S>>] {
const [state, setState] = useState<S>(basedState)
useEffect(() => setState(basedState), [basedState])
return [state, setState]
}

export const useInterval = (callback: () => void, delay: number, deps: any[] = []) => {
const savedCallback = useRef(() => {})
useEffect(() => {
Expand Down
1 change: 1 addition & 0 deletions src/utils/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import i18n from 'i18next'
import { initReactI18next, useTranslation } from 'react-i18next'
import en from '../locales/en.json'
import zh from '../locales/zh.json'
// TODO: This file depends on higher-level abstractions, so it should not be in the utils folder.
import { appSettings } from '../services/AppSettings'
import { includes } from './array'

Expand Down

0 comments on commit 6b8457f

Please sign in to comment.