Skip to content

Commit

Permalink
feat: ClampedText component (#28664)
Browse files Browse the repository at this point in the history
  • Loading branch information
daibhin authored Feb 13, 2025
1 parent 2c54ab9 commit b3e3c02
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 72 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions frontend/src/lib/lemon-ui/ClampedText/ClampedText.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Meta, StoryFn, StoryObj } from '@storybook/react'

import { ClampedText, ClampedTextProps } from './ClampedText'

type Story = StoryObj<typeof ClampedText>
const meta: Meta<typeof ClampedText> = {
title: 'Lemon UI/ClampedText',
component: ClampedText,
parameters: {
testOptions: {
waitForLoadersToDisappear: false,
},
},
tags: ['autodocs'],
}
export default meta

const Template: StoryFn<typeof ClampedText> = (props: ClampedTextProps) => {
return <ClampedText {...props} />
}

export const SingleLine: Story = Template.bind({})
SingleLine.args = { lines: 2, text: 'One line of text' }

export const MultiLine: Story = Template.bind({})
MultiLine.args = {
lines: 2,
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
}
78 changes: 78 additions & 0 deletions frontend/src/lib/lemon-ui/ClampedText/ClampedText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useEffect, useState } from 'react'

import { Link } from '../Link'

export interface ClampedTextProps {
lines: number
text: string
}

const isCssEllipsisApplied = (elem: HTMLDivElement): boolean => elem.scrollHeight > elem.clientHeight

export const ClampedText = React.forwardRef<HTMLDivElement, ClampedTextProps>(function ClampedText(
{ lines, text },
ref
) {
const [localLines, setLocalLines] = useState<number | undefined>(lines)
const [isExpanded, setIsExpanded] = useState<boolean>(false)
const [showMore, setShowMore] = useState<boolean>(false)

const handleToggleShowMore = (show: boolean): void => {
setShowMore(!showMore)
setIsExpanded(!isExpanded)
setLocalLines(show ? undefined : lines)
}

const handleConfigElement = (elem: HTMLDivElement): void => {
if (!elem) {
return
}

if (isCssEllipsisApplied(elem)) {
if (!showMore || !isExpanded) {
setShowMore(true)
}
} else {
setShowMore(false)
}
}

useEffect(() => setLocalLines(lines), [lines])

return (
<div ref={ref}>
<TruncatedElement lines={localLines} ref={handleConfigElement} text={text} />
<div>
{isExpanded || showMore ? (
<Link onClick={() => handleToggleShowMore(!isExpanded)}>
{isExpanded ? 'Show less' : 'Show more'}
</Link>
) : null}
</div>
</div>
)
})

const TruncatedElement = React.forwardRef<HTMLDivElement, { lines?: number; text: string }>(function TruncatedElement(
{ text, lines },
ref
) {
return (
<span
// eslint-disable-next-line react/forbid-dom-props
style={
lines
? {
overflow: 'hidden',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: lines,
}
: {}
}
ref={ref}
>
{text}
</span>
)
})
1 change: 1 addition & 0 deletions frontend/src/lib/lemon-ui/ClampedText/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ClampedText } from './ClampedText'
3 changes: 2 additions & 1 deletion frontend/src/scenes/error-tracking/issue/Metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IconInfo } from '@posthog/icons'
import { LemonSkeleton, Tooltip } from '@posthog/lemon-ui'
import { useValues } from 'kea'
import { TZLabel } from 'lib/components/TZLabel'
import { ClampedText } from 'lib/lemon-ui/ClampedText'
import { humanFriendlyLargeNumber } from 'lib/utils'
import { errorTrackingIssueSceneLogic } from 'scenes/error-tracking/errorTrackingIssueSceneLogic'

Expand Down Expand Up @@ -32,7 +33,7 @@ export const Metadata = (): JSX.Element => {

return (
<div className="space-y-1">
{issue ? <div className="italic line-clamp-3">{issue.description}</div> : <LemonSkeleton />}
{issue && issue.description ? <ClampedText text={issue.description} lines={2} /> : <LemonSkeleton />}
<div className="flex flex-1 justify-between">
<div className="flex items-end space-x-6">
<div>
Expand Down
71 changes: 0 additions & 71 deletions frontend/src/scenes/error-tracking/issue/panels/MetaPanel.tsx

This file was deleted.

0 comments on commit b3e3c02

Please sign in to comment.