diff --git a/apps/governance/src/routes/proposals/components/proposal-description/proposal-description.tsx b/apps/governance/src/routes/proposals/components/proposal-description/proposal-description.tsx index 85901433d..babffb0b9 100644 --- a/apps/governance/src/routes/proposals/components/proposal-description/proposal-description.tsx +++ b/apps/governance/src/routes/proposals/components/proposal-description/proposal-description.tsx @@ -1,44 +1,27 @@ import ReactMarkdown from 'react-markdown'; -import { useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { RoundedWrapper } from '@vegaprotocol/ui-toolkit'; -import { SubHeading } from '../../../../components/heading'; -import { CollapsibleToggle } from '../../../../components/collapsible-toggle'; +import { RoundedWrapper, ShowMore } from '@vegaprotocol/ui-toolkit'; export const ProposalDescription = ({ description, }: { description: string; -}) => { - const { t } = useTranslation(); - const [showDescription, setShowDescription] = useState(false); - - return ( -
- - - - - {showDescription && ( - -
- - {description} - -
-
- )} -
- ); -}; +}) => ( +
+ +
+ + + {description} + + +
+
+
+); diff --git a/libs/ui-toolkit/src/components/index.ts b/libs/ui-toolkit/src/components/index.ts index 2b76f30bd..d173012d0 100644 --- a/libs/ui-toolkit/src/components/index.ts +++ b/libs/ui-toolkit/src/components/index.ts @@ -34,6 +34,7 @@ export * from './progress-bar'; export * from './radio-group'; export * from './rounded-wrapper'; export * from './select'; +export * from './show-more'; export * from './simple-grid'; export * from './slider'; export * from './sparkline'; diff --git a/libs/ui-toolkit/src/components/show-more/index.ts b/libs/ui-toolkit/src/components/show-more/index.ts new file mode 100644 index 000000000..29487baa3 --- /dev/null +++ b/libs/ui-toolkit/src/components/show-more/index.ts @@ -0,0 +1 @@ +export * from './show-more'; diff --git a/libs/ui-toolkit/src/components/show-more/show-more.spec.tsx b/libs/ui-toolkit/src/components/show-more/show-more.spec.tsx new file mode 100644 index 000000000..cc65507ea --- /dev/null +++ b/libs/ui-toolkit/src/components/show-more/show-more.spec.tsx @@ -0,0 +1,9 @@ +import { render } from '@testing-library/react'; +import { ShowMore } from './show-more'; + +describe('Button', () => { + it('should render successfully', () => { + const { baseElement } = render(test); + expect(baseElement).toBeTruthy(); + }); +}); diff --git a/libs/ui-toolkit/src/components/show-more/show-more.stories.tsx b/libs/ui-toolkit/src/components/show-more/show-more.stories.tsx new file mode 100644 index 000000000..cfdcd6dff --- /dev/null +++ b/libs/ui-toolkit/src/components/show-more/show-more.stories.tsx @@ -0,0 +1,50 @@ +import type { Story, Meta } from '@storybook/react'; +import { ShowMore } from './show-more'; + +export default { + component: ShowMore, + title: 'ShowMore', +} as Meta; + +const Template: Story = (args) => ( + +

+ Spaceflight will never tolerate carelessness, incapacity, and neglect. + Somewhere, somehow, we screwed up. It could have been in design, build, or + test. Whatever it was, we should have caught it. We were too gung ho about + the schedule and we locked out all of the problems we saw each day in our + work. “Every element of the program was in trouble and so were we. The + simulators were not working, Mission Control was behind in virtually every + area, and the flight and test procedures changed daily. Nothing we did had + any shelf life. Not one of us stood up and said, ‘Dammit, stop!’ I don’t + know what Thompson’s committee will find as the cause, but I know what I + find. We are the cause! We were not ready! We did not do our job. We were + rolling the dice, hoping that things would come together by launch day, + when in our hearts we knew it would take a miracle. We were pushing the + schedule and betting that the Cape would slip before we did. “From this + day forward, Flight Control will be known by two words: ‘Tough’ and + ‘Competent.’ Tough means we are forever accountable for what we do or what + we fail to do. We will never again compromise our responsibilities. Every + time we walk into Mission Control we will know what we stand for. + Competent means we will never take anything for granted. We will never be + found short in our knowledge and in our skills. Mission Control will be + perfect. When you leave this meeting today you will go to your office and + the first thing you will do there is to write ‘Tough and Competent’ on + your blackboards. It will never be erased. Each day when you enter the + room these words will remind you of the price paid by Grissom, White, and + Chaffee. These words are the price of admission to the ranks of Mission + Control. +

+
+); + +export const Default = Template.bind({}); +export const CustomMaxHeight = Template.bind({}); +CustomMaxHeight.args = { + closedMaxHeightPx: 50, +}; + +export const CustomOverlayColour = Template.bind({}); +CustomOverlayColour.args = { + overlayColourOverrides: 'to-yellow-400', +}; diff --git a/libs/ui-toolkit/src/components/show-more/show-more.tsx b/libs/ui-toolkit/src/components/show-more/show-more.tsx new file mode 100644 index 000000000..64748d1a8 --- /dev/null +++ b/libs/ui-toolkit/src/components/show-more/show-more.tsx @@ -0,0 +1,78 @@ +import classNames from 'classnames'; +import { useRef, useState, useEffect } from 'react'; +import { t } from '@vegaprotocol/i18n'; +import { Button } from '../button'; +import type { ReactNode } from 'react'; + +type ShowMoreProps = { + children: ReactNode; + closedMaxHeightPx?: number; + overlayColourOverrides?: string; +}; + +export const ShowMore = ({ + children, + closedMaxHeightPx = 125, + overlayColourOverrides, +}: ShowMoreProps) => { + const containerRef = useRef(null); + const [expanded, setExpanded] = useState(false); + + useEffect(() => { + const checkHeight = () => { + const container = containerRef.current; + if (container) { + container.scrollHeight < closedMaxHeightPx + ? setExpanded(true) + : setExpanded(false); + } + }; + + checkHeight(); + + window.addEventListener('resize', checkHeight); + + return () => { + window.removeEventListener('resize', checkHeight); + }; + }, [closedMaxHeightPx]); + + const containerClasses = classNames( + 'overflow-hidden transition-all ease-in-out duration-300', + { + 'max-h-none': expanded, + } + ); + + const overlayClasses = classNames( + `absolute w-full h-16 bottom-0 left-0 transition-opacity duration-300 bg-gradient-to-b from-transparent ${ + overlayColourOverrides ? overlayColourOverrides : 'to-white dark:to-black' + }`, + { + hidden: expanded, + } + ); + + return ( + <> +
+
+ {children} +
+
+
+ + {!expanded && ( +
+ +
+ )} + + ); +};