Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(LineClamp): 表示されている行数が最大行数以下のときにTooltipを表示しないように修正 #4710

Merged
merged 19 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e6f9333
fix(LineClamp): 表示されている行数が最大行数以下のときにTooltipを表示しないように修正
Qs-F Jun 10, 2024
abe5845
fix: propsを渡す要素を修正
Qs-F Jun 10, 2024
b5a1e3e
Merge branch 'master' into fix/lineclamp/unexpected-tooltip-shown@970
Qs-F Jun 11, 2024
02faffa
Merge branch 'master' into fix/lineclamp/unexpected-tooltip-shown@970
Qs-F Jun 13, 2024
9a85b0b
fix(LineClamp): Fix to remove unexpected scroll area expansion
Qs-F Jul 11, 2024
ad09867
Merge remote-tracking branch 'origin' into fix/lineclamp/unexpected-t…
Qs-F Jul 11, 2024
f2dc910
fix(LineClamp): fix to use tailwind-variants slots option
Qs-F Jul 11, 2024
99c6ef4
Merge remote-tracking branch 'origin' into fix/lineclamp/unexpected-t…
Qs-F Jul 11, 2024
2d7879a
fix(LineClamp): add comment why comparing el and shadowEl size
Qs-F Jul 11, 2024
f94fc10
test(LineClamp): add VRT for LineClamp in Button
Qs-F Jul 16, 2024
99701df
test(LineClamp): fix VRT story
Qs-F Jul 17, 2024
68e280a
fix(LineClamp): fix when lines are more than 2
Qs-F Jul 18, 2024
3c31b3a
fix(LineClamp): fix to clamp
Qs-F Jul 18, 2024
6ebd7bd
test(LineClamp): fix section name
Qs-F Jul 18, 2024
31dbb0b
Merge remote-tracking branch 'origin' into fix/lineclamp/unexpected-t…
Qs-F Jul 18, 2024
8035730
Merge remote-tracking branch 'origin' into fix/lineclamp/unexpected-t…
Qs-F Jul 22, 2024
4b64566
refactor(LineClamp): use compoundVariants and add comment for workaround
Qs-F Jul 22, 2024
654ab12
test(LineClamp): remove special font usage and reorganize VRT story
Qs-F Jul 22, 2024
6587fbb
Merge remote-tracking branch 'origin' into fix/lineclamp/unexpected-t…
Qs-F Jul 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 69 additions & 16 deletions packages/smarthr-ui/src/components/LineClamp/LineClamp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,45 @@ type Props = PropsWithChildren<VariantProps<typeof lineClamp>>
type ElementProps = Omit<ComponentPropsWithRef<'span'>, keyof Props>

const lineClamp = tv({
base: 'smarthr-ui-LineClamp',
slots: {
base: 'smarthr-ui-LineClamp shr-relative',
clampedLine: 'shr-w-full',
shadowElementWrapper:
'shr-absolute shr-overflow-hidden shr-w-full shr-h-full shr-opacity-0 shr-invisible shr-left-0 shr-top-0 shr-whitespace-normal',
shadowElement: 'shr-absolute shr-w-full shr-top-0 shr-left-0',
},
variants: {
maxLines: {
1: 'shr-inline-block shr-w-full shr-overflow-hidden shr-overflow-ellipsis shr-whitespace-nowrap shr-align-middle',
2: 'shr-line-clamp-[2]',
3: 'shr-line-clamp-[3]',
4: 'shr-line-clamp-[4]',
5: 'shr-line-clamp-[5]',
6: 'shr-line-clamp-[6]',
1: {
clampedLine:
'shr-inline-block shr-w-full shr-overflow-hidden shr-overflow-ellipsis shr-whitespace-nowrap shr-align-middle',
},
2: {
clampedLine: 'shr-line-clamp-[2]',
},
3: {
clampedLine: 'shr-line-clamp-[3]',
},
4: {
clampedLine: 'shr-line-clamp-[4]',
},
5: {
clampedLine: 'shr-line-clamp-[5]',
},
6: {
clampedLine: 'shr-line-clamp-[6]',
},
},
},
compoundVariants: [
{
maxLines: [2, 3, 4, 5, 6],
className: {
// baseがdisplay:-webkit-boxでないと高さ取得用の要素が表示部分と同じ大きさで表示されないバグを回避するため
base: '[display:-webkit-box]',
},
},
],
})

export const LineClamp: FC<Props & ElementProps> = ({
Expand All @@ -34,30 +62,55 @@ export const LineClamp: FC<Props & ElementProps> = ({
className,
...props
}) => {
if (maxLines < 1) {
throw new Error('"maxLines" cannot be less than 0.')
}

const [isTooltipVisible, setTooltipVisible] = useState(false)
const ref = useRef<HTMLSpanElement>(null)
const shadowRef = useRef<HTMLSpanElement>(null)

const isMultiLineOverflow = () => {
const el = ref.current
return el ? el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight : false
const shadowEl = shadowRef.current

// -webkit-line-clamp を使った要素ではel.scrollHeightとel.clientHeightの比較だと
// フォントの高さの計算が期待と異なり適切な高さが取得できないためshadowElと比較している
// 参考: https://github.com/kufu/smarthr-ui/pull/4710
return el && shadowEl
? shadowEl.clientWidth > el.clientWidth || shadowEl.clientHeight > el.clientHeight
Qs-F marked this conversation as resolved.
Show resolved Hide resolved
: false
}

useEffect(() => {
setTooltipVisible(isMultiLineOverflow())
}, [maxLines, children])

if (maxLines < 1) {
throw new Error('"maxLines" cannot be less than 0.')
}

const { baseStyle, clampedLineStyle, shadowElementWrapperStyle, shadowElementStyle } =
useMemo(() => {
const { base, clampedLine, shadowElementWrapper, shadowElement } = lineClamp({ maxLines })
return {
baseStyle: base({ className }),
clampedLineStyle: clampedLine(),
shadowElementWrapperStyle: shadowElementWrapper(),
shadowElementStyle: shadowElement(),
}
}, [maxLines, className])

const ActualLineClamp = () => (
<span {...props} className={styles} ref={ref}>
{children}
<span {...props} className={baseStyle}>
<span className={clampedLineStyle} ref={ref}>
{children}
</span>
{/* 切り取られていないテキストの高さを取得するための要素 */}
<span aria-hidden className={shadowElementWrapperStyle}>
<span className={shadowElementStyle} ref={shadowRef}>
{children}
</span>
</span>
</span>
)

const styles = useMemo(() => lineClamp({ maxLines, className }), [className, maxLines])

return isTooltipVisible ? (
<Tooltip message={children} multiLine vertical="auto">
<ActualLineClamp />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { userEvent, within } from '@storybook/test'
import React from 'react'
import styled from 'styled-components'

import { Button } from '../Button'
import { InformationPanel } from '../InformationPanel'

import { LineClamp } from './LineClamp'
Expand Down Expand Up @@ -106,6 +107,47 @@ VRTForcedColors.parameters = {
chromatic: { forcedColors: 'active' },
}

export const VRTLineClampInButton: StoryFn = () => (
<>
<VRTInformationPanel title="VRT 用の Story です">
フォントのタイプサイズがline-heightより大きいときにツールチップが表示されないことを確認します
</VRTInformationPanel>
<Wrapper>
<List>
<dt>LineClampが1行でされるボタン</dt>
<dd>
<Button style={{ width: 100 }}>
<LineClamp data-testid="user-focus" maxLines={1}>
LineClampされるボタン
</LineClamp>
</Button>
</dd>
<dt>LineClampが2行でされるボタン</dt>
<dd>
<Button style={{ textWrap: 'wrap', width: 100 }}>
<LineClamp data-testid="user-focus" maxLines={2}>
LineClampされるボタン
</LineClamp>
</Button>
</dd>
<dt>LineClampされないボタン</dt>
<dd>
<Button>
<LineClamp data-testid="user-focus" maxLines={1}>
LineClampされないボタン
</LineClamp>
</Button>
</dd>
</List>
</Wrapper>
</>
)
VRTLineClampInButton.play = async ({ canvasElement }) => {
await new Promise((resolve) => setTimeout(resolve, 500)) // スナップショット時にツールチップを確実に表示させるため
const tooltips = canvasElement.querySelectorAll('.smarthr-ui-Tooltip')
tooltips.forEach((tooltip) => userEvent.hover(tooltip))
}

const VRTInformationPanel = styled(InformationPanel)`
margin-bottom: 24px;
`
Expand Down