Commit ad24c557 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Convert AnnotationShareControl to TW and use shared Card component

Previously, this component was _styled_ as a "panel", via SASS mixins,
but did not have any behavioral "panel-ness."

For now, use the shared Card (presentational) component for this
 component, and remove unused SASS and mixins.
parent e9cdc38f
import {
Card,
Icon,
IconButton,
TextInput,
TextInputWithButton,
useElementShouldClose,
} from '@hypothesis/frontend-shared';
import classnames from 'classnames';
import { useEffect, useRef, useState } from 'preact/hooks';
import { isShareableURI } from '../../helpers/annotation-sharing';
......@@ -37,6 +39,23 @@ function selectionOverflowsInputElement() {
return isIOS();
}
/**
*
* @param {object} props
* @param {string} [props.classes] - Optional additional CSS classes
*/
function MenuArrowDown({ classes }) {
return (
<Icon
name="pointer"
classes={classnames(
'absolute inline z-2 text-grey-3 fill-white rotate-180',
classes
)}
/>
);
}
/**
* "Popup"-style component for sharing a single annotation.
*
......@@ -123,7 +142,7 @@ function AnnotationShareControl({
);
return (
<div className="AnnotationShareControl" ref={shareRef}>
<div className="relative" ref={shareRef}>
<IconButton
icon="share"
title="Share"
......@@ -131,14 +150,31 @@ function AnnotationShareControl({
expanded={isOpen}
/>
{isOpen && (
<div className="annotation-share-panel">
<div className="annotation-share-panel__header">
<div className="annotation-share-panel__title">
<Card
classes={classnames(
// Prefer width 96 (24rem) but ensure that component isn't wider
// than 85vw
'w-96 max-w-[85vw]',
// Position this Card above its IconButton. Account for larger
// IconButtons in touch interfaces
'absolute bottom-8 right-1 touch:bottom-touch-minimum',
'space-y-2 p-2',
// Cards do not have a border in the clean theme. Turn it back on.
'theme-clean:border'
)}
>
<div className="flex items-center pb-2 border-b">
<h2 className="text-brand text-lg font-medium">
Share this annotation
</h2>
</div>
</div>
<div className="annotation-share-panel__content">
<div className="hyp-u-layout-row annotation-share-panel__inputs">
<div
className={classnames(
// Slightly larger font size for touch devices to correspond with
// larger button and input sizes
'flex w-full text-sm touch:text-base'
)}
>
<TextInputWithButton>
<TextInput
aria-label="Use this URL to share this annotation"
......@@ -155,21 +191,20 @@ function AnnotationShareControl({
/>
</TextInputWithButton>
</div>
<div className="text-base font-normal" data-testid="share-details">
{inContextAvailable ? (
<div className="annotation-share-panel__details">
{annotationSharingInfo}
</div>
<>{annotationSharingInfo}</>
) : (
<div className="annotation-share-panel__details">
<>
This annotation cannot be shared in its original context because
it was made on a document that is not available on the web. This
link shares the annotation by itself.
</div>
</>
)}
{showShareLinks && <ShareLinks shareURI={shareUri} />}
</div>
<Icon name="pointer" classes="annotation-share-panel__arrow" />
</div>
{showShareLinks && <ShareLinks shareURI={shareUri} />}
<MenuArrowDown classes="bottom-[-12px] right-1 touch:right-[9px]" />
</Card>
)}
</div>
);
......
......@@ -106,7 +106,7 @@ describe('AnnotationShareControl', () => {
const wrapper = createComponent();
// Component is not `open` initially
assert.isFalse(wrapper.find('.annotation-share-panel').exists());
assert.isFalse(wrapper.find('Card').exists());
});
it('toggles the share control element when the button is clicked', () => {
......@@ -118,7 +118,7 @@ describe('AnnotationShareControl', () => {
});
wrapper.update();
assert.isTrue(wrapper.find('.annotation-share-panel').exists());
assert.isTrue(wrapper.find('Card').exists());
});
it('renders the share URI in a readonly input field', () => {
......@@ -194,7 +194,7 @@ describe('AnnotationShareControl', () => {
const wrapper = createComponent({ isPrivate: testcase.isPrivate });
openElement(wrapper);
const permissionsEl = wrapper.find('.annotation-share-panel__details');
const permissionsEl = wrapper.find('[data-testid="share-details"]');
assert.equal(permissionsEl.text(), testcase.expected);
});
});
......@@ -204,7 +204,7 @@ describe('AnnotationShareControl', () => {
const wrapper = createComponent();
openElement(wrapper);
const detailsEl = wrapper.find('.annotation-share-panel__details');
const detailsEl = wrapper.find('[data-testid="share-details"]');
assert.include(
detailsEl.text(),
'This annotation cannot be shared in its original context'
......
......@@ -105,22 +105,6 @@
}
}
/**
* `panel` with tighter margins and padding, for use in more confined spaces
*/
@mixin panel--compact {
@include panel($rhythm: var.$layout-space--xsmall);
width: 24em;
// Keep panel constrained within annotation card boundaries and not cut off
// on left side when sidebar is extremely narrow
max-width: 85vw;
padding: var.$layout-space--small;
&__header {
padding-bottom: var.$layout-space--xsmall;
}
}
/**
* A full-width banner with optional "type" and styled icon at left
*/
......
@use '../../mixins/buttons';
@use '../../mixins/forms';
@use '../../mixins/layout';
@use '../../mixins/molecules';
@use '../../mixins/utils';
@use '../../variables' as var;
.AnnotationShareControl {
// Allow pointer arrow to be positioned absolutely relative to this container
position: relative;
}
// A compact panel that appears/disappears by tapping the "share" icon on a
// single annotation.
.annotation-share-panel {
@include molecules.panel--compact;
// Position panel to align with share-annotation icon and alignment arrow
position: absolute;
right: 5px;
bottom: 32px;
@media (pointer: coarse) {
// Adjust arrow/panel positioning to account for larger icon target
right: 13px;
bottom: 40px;
}
// Override the pointer cursor that applies to the entire card
cursor: default;
// Hide the bottom border on the panel's header if displaying
// input (with sharing link) directly below
&__header {
border-bottom: none;
}
&__inputs {
@include utils.font--small;
width: 100%;
}
&__details {
@include utils.font--small;
padding: var.$layout-space--xsmall 0;
}
// Position the pointer icon absolutely and flip it to make it point at the
// share icon
&__arrow {
display: inline;
@include molecules.menu-arrow($direction: 'down');
right: 0px;
bottom: -12px;
}
}
......@@ -12,7 +12,6 @@
// UI (Preact) Components
// ----------
@use './AnnotationShareControl';
@use './AutocompleteList';
@use './FilterSelect';
@use './FilterStatus';
......
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