Commit 9cd8753c authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Update use of `Link`

* Convert `LinkBase` to `Link` and use styling API as needed
* Add `underline` prop to `Link` usages as the default value of that
  prop may change in future
* Move styling, where possible, off of `Link` onto another element
parent 53e96479
import { import {
Link, Link,
LinkBase,
CaretLeftIcon, CaretLeftIcon,
CaretRightIcon, CaretRightIcon,
} from '@hypothesis/frontend-shared'; } from '@hypothesis/frontend-shared';
...@@ -37,7 +36,12 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) { ...@@ -37,7 +36,12 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) {
> >
<div data-testid="content-logo"> <div data-testid="content-logo">
{info.logo && ( {info.logo && (
<Link href={info.logo.link} target="_blank" data-testid="logo-link"> <Link
href={info.logo.link}
target="_blank"
data-testid="logo-link"
underline="none"
>
<img <img
alt={info.logo.title} alt={info.logo.title}
src={info.logo.logo} src={info.logo.logo}
...@@ -78,15 +82,16 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) { ...@@ -78,15 +82,16 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) {
{info.links.previousItem && ( {info.links.previousItem && (
<> <>
<Link <Link
classes="flex gap-x-1 items-center text-annotator-sm whitespace-nowrap"
title="Open previous item" title="Open previous item"
href={info.links.previousItem} href={info.links.previousItem}
underline="always" underline="always"
target="_blank" target="_blank"
data-testid="content-previous-link" data-testid="content-previous-link"
> >
<div className="flex gap-x-1 items-center text-annotator-sm whitespace-nowrap">
<CaretLeftIcon className="w-em h-em" /> <CaretLeftIcon className="w-em h-em" />
<span>Previous</span> <span>Previous</span>
</div>
</Link> </Link>
<div className="text-annotator-sm">|</div> <div className="text-annotator-sm">|</div>
</> </>
...@@ -99,7 +104,7 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) { ...@@ -99,7 +104,7 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) {
'min-w-0 whitespace-nowrap overflow-hidden text-ellipsis shrink font-medium' 'min-w-0 whitespace-nowrap overflow-hidden text-ellipsis shrink font-medium'
)} )}
> >
<LinkBase <Link
title={itemTitle} title={itemTitle}
href={info.links.currentItem} href={info.links.currentItem}
data-testid="content-item-link" data-testid="content-item-link"
...@@ -107,7 +112,7 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) { ...@@ -107,7 +112,7 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) {
unstyled unstyled
> >
{itemTitle} {itemTitle}
</LinkBase> </Link>
</div> </div>
{info.links.nextItem && ( {info.links.nextItem && (
...@@ -115,14 +120,15 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) { ...@@ -115,14 +120,15 @@ export default function ContentInfoBanner({ info }: ContentInfoBannerProps) {
<div className="text-annotator-sm">|</div> <div className="text-annotator-sm">|</div>
<Link <Link
title="Open next item" title="Open next item"
classes="flex gap-x-1 items-center text-annotator-sm whitespace-nowrap"
href={info.links.nextItem} href={info.links.nextItem}
underline="always" underline="always"
target="_blank" target="_blank"
data-testid="content-next-link" data-testid="content-next-link"
> >
<div className="flex gap gap-x-1 items-center text-annotator-sm whitespace-nowrap">
<span>Next</span> <span>Next</span>
<CaretRightIcon className="w-em h-em" /> <CaretRightIcon className="w-em h-em" />
</div>
</Link> </Link>
</> </>
)} )}
......
...@@ -46,7 +46,7 @@ describe('ContentInfoBanner', () => { ...@@ -46,7 +46,7 @@ describe('ContentInfoBanner', () => {
it('shows item title', () => { it('shows item title', () => {
const wrapper = createComponent(); const wrapper = createComponent();
const link = wrapper.find('LinkBase[data-testid="content-item-link"]'); const link = wrapper.find('Link[data-testid="content-item-link"]');
assert.equal(link.text(), 'Chapter 2: Some book chapter'); assert.equal(link.text(), 'Chapter 2: Some book chapter');
assert.equal(link.prop('target'), '_blank'); assert.equal(link.prop('target'), '_blank');
}); });
...@@ -56,7 +56,7 @@ describe('ContentInfoBanner', () => { ...@@ -56,7 +56,7 @@ describe('ContentInfoBanner', () => {
const wrapper = createComponent(); const wrapper = createComponent();
const link = wrapper.find('LinkBase[data-testid="content-item-link"]'); const link = wrapper.find('Link[data-testid="content-item-link"]');
assert.equal(link.text(), 'Chapter 2'); assert.equal(link.text(), 'Chapter 2');
}); });
...@@ -70,7 +70,7 @@ describe('ContentInfoBanner', () => { ...@@ -70,7 +70,7 @@ describe('ContentInfoBanner', () => {
'Expansive Book' 'Expansive Book'
); );
assert.equal( assert.equal(
wrapper.find('LinkBase[data-testid="content-item-link"]').prop('title'), wrapper.find('Link[data-testid="content-item-link"]').prop('title'),
'Chapter 2: Some book chapter' 'Chapter 2: Some book chapter'
); );
}); });
......
...@@ -92,6 +92,7 @@ function ToastMessageItem({ message, onDismiss }: ToastMessageItemProps) { ...@@ -92,6 +92,7 @@ function ToastMessageItem({ message, onDismiss }: ToastMessageItemProps) {
event.stopPropagation() /* consume the event so that it does not dismiss the message */ event.stopPropagation() /* consume the event so that it does not dismiss the message */
} }
target="_new" target="_new"
underline="none"
> >
More info More info
</Link> </Link>
......
...@@ -23,7 +23,7 @@ export default function AnnotationDocumentInfo({ ...@@ -23,7 +23,7 @@ export default function AnnotationDocumentInfo({
<div className="text-color-text-light"> <div className="text-color-text-light">
on &quot; on &quot;
{link ? ( {link ? (
<Link href={link} target="_blank"> <Link href={link} target="_blank" underline="none">
{title} {title}
</Link> </Link>
) : ( ) : (
......
...@@ -7,17 +7,19 @@ export default function AnnotationLicense() { ...@@ -7,17 +7,19 @@ export default function AnnotationLicense() {
return ( return (
<div className="pt-2 border-t text-xs leading-none"> <div className="pt-2 border-t text-xs leading-none">
<Link <Link
classes="flex items-center"
color="text-light"
href="http://creativecommons.org/publicdomain/zero/1.0/" href="http://creativecommons.org/publicdomain/zero/1.0/"
target="_blank" target="_blank"
title="View more information about the Creative Commons Public Domain dedication" title="View more information about the Creative Commons Public Domain dedication"
underline="none"
variant="text-light"
> >
<div className="flex items-center">
<CcStdIcon className="w-[10px] h-[10px]" /> <CcStdIcon className="w-[10px] h-[10px]" />
<CcZeroIcon className="w-[10px] h-[10px] ml-px" /> <CcZeroIcon className="w-[10px] h-[10px] ml-px" />
<div className="ml-1"> <div className="ml-1">
Annotations can be freely reused by anyone for any purpose. Annotations can be freely reused by anyone for any purpose.
</div> </div>
</div>
</Link> </Link>
</div> </div>
); );
......
import { LinkBase, GlobeIcon, GroupsIcon } from '@hypothesis/frontend-shared'; import { Link, GlobeIcon, GroupsIcon } from '@hypothesis/frontend-shared';
import classnames from 'classnames'; import classnames from 'classnames';
import type { Group } from '../../../types/api'; import type { Group } from '../../../types/api';
...@@ -23,23 +23,26 @@ function AnnotationShareInfo({ group, isPrivate }: AnnotationShareInfoProps) { ...@@ -23,23 +23,26 @@ function AnnotationShareInfo({ group, isPrivate }: AnnotationShareInfoProps) {
return ( return (
<> <>
{group && linkToGroup && ( {group && linkToGroup && (
<LinkBase <Link
// The light-text hover color is not a standard color for a Link, so // The light-text hover color is not a standard color for a Link, so
// LinkBase is used here // a custom variant is used
classes={classnames( classes={classnames(
'flex items-baseline gap-x-1', 'text-color-text-light hover:text-color-text-light'
'text-color-text-light hover:text-color-text-light hover:underline'
)} )}
href={group.links.html} href={group.links.html}
target="_blank" target="_blank"
underline="hover"
variant="custom"
> >
<div className="flex items-baseline gap-x-1">
{group.type === 'open' ? ( {group.type === 'open' ? (
<GlobeIcon className="w-2.5 h-2.5" /> <GlobeIcon className="w-2.5 h-2.5" />
) : ( ) : (
<GroupsIcon className="w-2.5 h-2.5" /> <GroupsIcon className="w-2.5 h-2.5" />
)} )}
<span>{group.name}</span> <span>{group.name}</span>
</LinkBase> </div>
</Link>
)} )}
{isPrivate && !linkToGroup && ( {isPrivate && !linkToGroup && (
<div className="text-color-text-light" data-testid="private-info"> <div className="text-color-text-light" data-testid="private-info">
......
import { LinkBase } from '@hypothesis/frontend-shared'; import { Link } from '@hypothesis/frontend-shared';
import { useEffect, useMemo, useState } from 'preact/hooks'; import { useEffect, useMemo, useState } from 'preact/hooks';
import { import {
...@@ -88,16 +88,18 @@ export default function AnnotationTimestamps({ ...@@ -88,16 +88,18 @@ export default function AnnotationTimestamps({
</span> </span>
)} )}
{annotationURL ? ( {annotationURL ? (
<LinkBase <Link
// The light-text hover color is not a standard color for a Link, so // The light-text hover color is not a standard color for a Link, so
// LinkBase is used here // LinkBase is used here
classes="text-color-text-light hover:text-color-text-light hover:underline" classes="text-color-text-light hover:text-color-text-light"
target="_blank" target="_blank"
title={created.absolute} title={created.absolute}
href={annotationURL} href={annotationURL}
underline="hover"
variant="custom"
> >
{created.relative} {created.relative}
</LinkBase> </Link>
) : ( ) : (
<span <span
className="color-text-color-light" className="color-text-color-light"
......
import { LinkBase } from '@hypothesis/frontend-shared'; import { Link } from '@hypothesis/frontend-shared';
type AnnotationUserProps = { type AnnotationUserProps = {
authorLink?: string; authorLink?: string;
...@@ -14,9 +14,9 @@ function AnnotationUser({ authorLink, displayName }: AnnotationUserProps) { ...@@ -14,9 +14,9 @@ function AnnotationUser({ authorLink, displayName }: AnnotationUserProps) {
if (authorLink) { if (authorLink) {
return ( return (
<LinkBase href={authorLink} target="_blank"> <Link href={authorLink} target="_blank" underline="none" variant="custom">
{user} {user}
</LinkBase> </Link>
); );
} }
......
...@@ -51,7 +51,7 @@ function HelpPanelTab({ linkText, url }: HelpPanelTabProps) { ...@@ -51,7 +51,7 @@ function HelpPanelTab({ linkText, url }: HelpPanelTabProps) {
// a flex container (centered on both axes) // a flex container (centered on both axes)
className="flex-1 flex items-center justify-center border-r last-of-type:border-r-0 text-md font-medium" className="flex-1 flex items-center justify-center border-r last-of-type:border-r-0 text-md font-medium"
> >
<Link color="text-light" href={url} target="_blank"> <Link variant="text-light" href={url} target="_blank" underline="none">
<div className="flex items-center gap-x-2"> <div className="flex items-center gap-x-2">
<span>{linkText}</span> <ExternalIcon className="w-3 h-3" /> <span>{linkText}</span> <ExternalIcon className="w-3 h-3" />
</div> </div>
......
import { import { Link, LinkButton, LogoIcon } from '@hypothesis/frontend-shared';
Link,
LinkBase,
LinkButton,
LogoIcon,
} from '@hypothesis/frontend-shared';
import { useSidebarStore } from '../store'; import { useSidebarStore } from '../store';
...@@ -25,7 +20,7 @@ function LoggedOutMessage({ onLogin }: LoggedOutMessageProps) { ...@@ -25,7 +20,7 @@ function LoggedOutMessage({ onLogin }: LoggedOutMessageProps) {
This is a public annotation created with Hypothesis. <br /> This is a public annotation created with Hypothesis. <br />
To reply or make your own annotations on this document,{' '} To reply or make your own annotations on this document,{' '}
<Link <Link
color="text" variant="text"
href={store.getLink('signup')} href={store.getLink('signup')}
target="_blank" target="_blank"
underline="always" underline="always"
...@@ -39,14 +34,16 @@ function LoggedOutMessage({ onLogin }: LoggedOutMessageProps) { ...@@ -39,14 +34,16 @@ function LoggedOutMessage({ onLogin }: LoggedOutMessageProps) {
. .
</span> </span>
<div> <div>
<LinkBase <Link
href="https://hypothes.is" href="https://hypothes.is"
aria-label="Hypothesis homepage" aria-label="Hypothesis homepage"
target="_blank" target="_blank"
title="Hypothesis homepage" title="Hypothesis homepage"
underline="none"
variant="custom"
> >
<LogoIcon className="w-16 h-16 text-grey-7" /> <LogoIcon className="w-16 h-16 text-grey-7" />
</LinkBase> </Link>
</div> </div>
</div> </div>
); );
......
import { ButtonBase, IconButton, LinkBase } from '@hypothesis/frontend-shared'; import { ButtonBase, IconButton, Link } from '@hypothesis/frontend-shared';
import { import {
EditorLatexIcon, EditorLatexIcon,
EditorQuoteIcon, EditorQuoteIcon,
...@@ -292,20 +292,25 @@ function Toolbar({ isPreviewing, onCommand, onTogglePreview }: ToolbarProps) { ...@@ -292,20 +292,25 @@ function Toolbar({ isPreviewing, onCommand, onTogglePreview }: ToolbarProps) {
title="Bulleted list" title="Bulleted list"
/> />
<div className="grow flex justify-end"> <div className="grow flex justify-end">
<LinkBase <Link
classes={classnames( classes="text-grey-7 hover:!text-grey-7"
'flex justify-center items-center',
'text-grey-7 hover:!text-grey-7',
'touch:h-touch-minimum touch:w-touch-minimum',
'px-2 py-2.5'
)}
href="https://web.hypothes.is/help/formatting-annotations-with-markdown/" href="https://web.hypothes.is/help/formatting-annotations-with-markdown/"
target="_blank" target="_blank"
title="Formatting help" title="Formatting help"
aria-label="Formatting help" aria-label="Formatting help"
underline="none"
variant="custom"
>
<div
className={classnames(
'flex justify-center items-center',
'touch:h-touch-minimum touch:w-touch-minimum',
'px-2 py-2.5 touch:p-0'
)}
> >
<HelpIcon className="w-2.5 h-2.5" /> <HelpIcon className="w-2.5 h-2.5" />
</LinkBase> </div>
</Link>
<ToolbarButton <ToolbarButton
label={isPreviewing ? 'Write' : 'Preview'} label={isPreviewing ? 'Write' : 'Preview'}
......
import { import {
LinkBase, Link,
EmailIcon, EmailIcon,
SocialFacebookIcon, SocialFacebookIcon,
SocialTwitterIcon, SocialTwitterIcon,
...@@ -23,19 +23,21 @@ type ShareLinkProps = { ...@@ -23,19 +23,21 @@ type ShareLinkProps = {
function ShareLink({ label, icon: Icon, uri }: ShareLinkProps) { function ShareLink({ label, icon: Icon, uri }: ShareLinkProps) {
return ( return (
<li> <li>
<LinkBase <Link
aria-label={label} aria-label={label}
classes="text-grey-6 hover:text-color-text block" classes="text-grey-6 hover:text-color-text"
href={uri} href={uri}
title={label} title={label}
target="_blank" target="_blank"
variant="custom"
underline="none"
> >
<Icon <Icon
// Make the icons sized to the current text size to allow for // Make the icons sized to the current text size to allow for
// differently-sized sharing icon links // differently-sized sharing icon links
className="w-em h-em" className="w-em h-em"
/> />
</LinkBase> </Link>
</li> </li>
); );
} }
......
...@@ -26,12 +26,13 @@ export default function TagListItem({ ...@@ -26,12 +26,13 @@ export default function TagListItem({
<div className="grow px-1.5 py-1 touch:p-2"> <div className="grow px-1.5 py-1 touch:p-2">
{href ? ( {href ? (
<Link <Link
color="text-light" variant="text-light"
href={href} href={href}
lang="" lang=""
target="_blank" target="_blank"
aria-label={`Tag: ${tag}`} aria-label={`Tag: ${tag}`}
title={`View annotations with tag: ${tag}`} title={`View annotations with tag: ${tag}`}
underline="none"
> >
{tag} {tag}
</Link> </Link>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment