diff --git a/components/common/OverflowText.js b/components/common/OverflowText.js new file mode 100644 index 00000000..d67c4923 --- /dev/null +++ b/components/common/OverflowText.js @@ -0,0 +1,66 @@ +import PropTypes from 'prop-types'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import ReactTooltip from 'react-tooltip'; + +import styles from './OverflowText.module.css'; + +const OverflowText = ({ children, tooltipId }) => { + const measureEl = useRef(); + const [isOverflown, setIsOverflown] = useState(false); + + const measure = useCallback( + el => { + if (!el) return; + setIsOverflown(el.scrollWidth > el.clientWidth); + }, + [setIsOverflown], + ); + + // Do one measure on mount + useEffect(() => { + measure(measureEl.current); + }, [measure]); + + // Set up resize listener for subsequent measures + useEffect(() => { + if (!measureEl.current) return; + + // Destructure ref in case it changes out from under us + const el = measureEl.current; + + if ('ResizeObserver' in global) { + // Ideally, we have access to ResizeObservers + const observer = new ResizeObserver(() => { + measure(el); + }); + observer.observe(el); + return () => observer.unobserve(el); + } else { + // Otherwise, fall back to measuring on window resizes + const handler = () => measure(el); + + window.addEventListener('resize', handler, { passive: true }); + return () => window.removeEventListener('resize', handler, { passive: true }); + } + }); + + return ( + + {children} + {isOverflown && {children}} + + ); +}; + +OverflowText.propTypes = { + children: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + tooltipId: PropTypes.string.isRequired, +}; + +export default OverflowText; diff --git a/components/common/OverflowText.module.css b/components/common/OverflowText.module.css new file mode 100644 index 00000000..c2066631 --- /dev/null +++ b/components/common/OverflowText.module.css @@ -0,0 +1,6 @@ +.root { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/components/metrics/WebsiteHeader.js b/components/metrics/WebsiteHeader.js index db68cd54..a4fb7df0 100644 --- a/components/metrics/WebsiteHeader.js +++ b/components/metrics/WebsiteHeader.js @@ -1,6 +1,7 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import Link from 'components/common/Link'; +import OverflowText from 'components/common/OverflowText'; import PageHeader from 'components/layout/PageHeader'; import RefreshButton from 'components/common/RefreshButton'; import ButtonLayout from 'components/layout/ButtonLayout'; @@ -13,15 +14,19 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal const header = showLink ? ( <> - - {title} + + {title} ) : ( -
+ <> - {title} -
+ {title} + ); return ( diff --git a/components/metrics/WebsiteHeader.module.css b/components/metrics/WebsiteHeader.module.css index 5b5876c6..4c9670fa 100644 --- a/components/metrics/WebsiteHeader.module.css +++ b/components/metrics/WebsiteHeader.module.css @@ -2,6 +2,14 @@ color: var(--gray900); font-size: var(--font-size-large); line-height: var(--font-size-large); + align-items: center; + display: flex; + max-width: 100%; + overflow: hidden; +} + +.titleLink { + max-width: 100%; } .link { diff --git a/components/settings/WebsiteSettings.js b/components/settings/WebsiteSettings.js index 998df40e..8d61f8ae 100644 --- a/components/settings/WebsiteSettings.js +++ b/components/settings/WebsiteSettings.js @@ -5,6 +5,7 @@ import classNames from 'classnames'; import Link from 'components/common/Link'; import Table from 'components/common/Table'; import Button from 'components/common/Button'; +import OverflowText from 'components/common/OverflowText'; import PageHeader from 'components/layout/PageHeader'; import Modal from 'components/common/Modal'; import WebsiteEditForm from 'components/forms/WebsiteEditForm'; @@ -84,12 +85,20 @@ export default function WebsiteSettings() { ); const DetailsLink = ({ website_id, name, domain }) => ( - + - {name} + {name} ); + const Domain = ({ domain, website_id }) => ( + {domain} + ); + const adminColumns = [ { key: 'name', @@ -101,6 +110,7 @@ export default function WebsiteSettings() { key: 'domain', label: , className: 'col-4 col-xl-3', + render: Domain, }, { key: 'account', @@ -125,6 +135,7 @@ export default function WebsiteSettings() { key: 'domain', label: , className: 'col-6 col-xl-4', + render: Domain, }, { key: 'action', diff --git a/components/settings/WebsiteSettings.module.css b/components/settings/WebsiteSettings.module.css index 444235b3..6ecb34c7 100644 --- a/components/settings/WebsiteSettings.module.css +++ b/components/settings/WebsiteSettings.module.css @@ -5,3 +5,7 @@ .buttons { justify-content: flex-end; } + +.detailLink { + width: 100%; +}