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

Replace `Button` with appropriate shared button component

parent f953ef10
...@@ -6,7 +6,7 @@ import { ...@@ -6,7 +6,7 @@ import {
import { isPrivate, permits } from '../../helpers/permissions'; import { isPrivate, permits } from '../../helpers/permissions';
import { withServices } from '../../service-context'; import { withServices } from '../../service-context';
import Button from '../Button'; import { IconButton } from '../../../shared/components/buttons';
import AnnotationShareControl from './AnnotationShareControl'; import AnnotationShareControl from './AnnotationShareControl';
...@@ -25,7 +25,7 @@ import AnnotationShareControl from './AnnotationShareControl'; ...@@ -25,7 +25,7 @@ import AnnotationShareControl from './AnnotationShareControl';
*/ */
/** /**
* A collection of `Button`s in the footer area of an annotation that take * A collection of buttons in the footer area of an annotation that take
* actions on the annotation. * actions on the annotation.
* *
* @param {AnnotationActionBarProps} props * @param {AnnotationActionBarProps} props
...@@ -89,11 +89,13 @@ function AnnotationActionBar({ ...@@ -89,11 +89,13 @@ function AnnotationActionBar({
return ( return (
<div className="AnnotationActionBar u-layout-row"> <div className="AnnotationActionBar u-layout-row">
{showEditAction && <Button icon="edit" title="Edit" onClick={onEdit} />} {showEditAction && (
<IconButton icon="edit" title="Edit" onClick={onEdit} />
)}
{showDeleteAction && ( {showDeleteAction && (
<Button icon="trash" title="Delete" onClick={onDelete} /> <IconButton icon="trash" title="Delete" onClick={onDelete} />
)} )}
<Button icon="reply" title="Reply" onClick={onReplyClick} /> <IconButton icon="reply" title="Reply" onClick={onReplyClick} />
{shareLink && ( {shareLink && (
<AnnotationShareControl <AnnotationShareControl
annotation={annotation} annotation={annotation}
...@@ -102,15 +104,15 @@ function AnnotationActionBar({ ...@@ -102,15 +104,15 @@ function AnnotationActionBar({
/> />
)} )}
{showFlagAction && !annotation.flagged && ( {showFlagAction && !annotation.flagged && (
<Button <IconButton
icon="flag" icon="flag"
title="Report this annotation to moderators" title="Report this annotation to moderators"
onClick={onFlag} onClick={onFlag}
/> />
)} )}
{showFlagAction && annotation.flagged && ( {showFlagAction && annotation.flagged && (
<Button <IconButton
isPressed={true} pressed={true}
icon="flag--active" icon="flag--active"
title="Annotation has been reported to the moderators" title="Annotation has been reported to the moderators"
/> />
......
import Button from '../Button'; import { LinkButton } from '../../../shared/components/buttons';
/** /**
* @typedef AnnotationReplyToggleProps * @typedef AnnotationReplyToggleProps
...@@ -22,11 +22,9 @@ function AnnotationReplyToggle({ ...@@ -22,11 +22,9 @@ function AnnotationReplyToggle({
const toggleText = `${toggleAction} (${replyCount})`; const toggleText = `${toggleAction} (${replyCount})`;
return ( return (
<Button <LinkButton onClick={onToggleReplies} title={toggleText}>
className="Annotation__reply-toggle" {toggleText}
onClick={onToggleReplies} </LinkButton>
buttonText={toggleText}
/>
); );
} }
......
...@@ -7,6 +7,8 @@ import { isPrivate } from '../../helpers/permissions'; ...@@ -7,6 +7,8 @@ import { isPrivate } from '../../helpers/permissions';
import { withServices } from '../../service-context'; import { withServices } from '../../service-context';
import { isIOS } from '../../../shared/user-agent'; import { isIOS } from '../../../shared/user-agent';
import { IconButton } from '../../../shared/components/buttons';
import Button from '../Button'; import Button from '../Button';
import ShareLinks from '../ShareLinks'; import ShareLinks from '../ShareLinks';
...@@ -119,11 +121,11 @@ function AnnotationShareControl({ ...@@ -119,11 +121,11 @@ function AnnotationShareControl({
return ( return (
<div className="AnnotationShareControl" ref={shareRef}> <div className="AnnotationShareControl" ref={shareRef}>
<Button <IconButton
icon="share" icon="share"
title="Share" title="Share"
onClick={toggleSharePanel} onClick={toggleSharePanel}
isExpanded={isOpen} expanded={isOpen}
/> />
{isOpen && ( {isOpen && (
<div className="annotation-share-panel"> <div className="annotation-share-panel">
......
...@@ -53,7 +53,7 @@ describe('AnnotationActionBar', () => { ...@@ -53,7 +53,7 @@ describe('AnnotationActionBar', () => {
}; };
const getButton = (wrapper, iconName) => { const getButton = (wrapper, iconName) => {
return wrapper.find('Button').filter({ icon: iconName }); return wrapper.find('IconButton').filter({ icon: iconName });
}; };
beforeEach(() => { beforeEach(() => {
......
...@@ -22,7 +22,7 @@ describe('AnnotationReplyToggle', () => { ...@@ -22,7 +22,7 @@ describe('AnnotationReplyToggle', () => {
beforeEach(() => { beforeEach(() => {
fakeOnToggleReplies = sinon.stub(); fakeOnToggleReplies = sinon.stub();
// Note that this component does not mock imported components // Note that this component does not mock imported components
// because it entirely consists of a `Button` // because it entirely consists of a `LinkButton`
}); });
it('renders expand wording if thread is collapsed', () => { it('renders expand wording if thread is collapsed', () => {
...@@ -44,7 +44,7 @@ describe('AnnotationReplyToggle', () => { ...@@ -44,7 +44,7 @@ describe('AnnotationReplyToggle', () => {
it('invokes the toggle callback when clicked', () => { it('invokes the toggle callback when clicked', () => {
const wrapper = createComponent(); const wrapper = createComponent();
const button = wrapper.find('Button'); const button = wrapper.find('LinkButton');
act(() => { act(() => {
button.props().onClick(); button.props().onClick();
......
...@@ -22,6 +22,10 @@ describe('AnnotationShareControl', () => { ...@@ -22,6 +22,10 @@ describe('AnnotationShareControl', () => {
return wrapper.find('Button').filter({ icon: iconName }); return wrapper.find('Button').filter({ icon: iconName });
}; };
const getIconButton = (wrapper, iconName) => {
return wrapper.find('IconButton').filter({ icon: iconName });
};
function createComponent(props = {}) { function createComponent(props = {}) {
return mount( return mount(
<AnnotationShareControl <AnnotationShareControl
...@@ -37,7 +41,7 @@ describe('AnnotationShareControl', () => { ...@@ -37,7 +41,7 @@ describe('AnnotationShareControl', () => {
function openElement(wrapper) { function openElement(wrapper) {
act(() => { act(() => {
wrapper.find('Button').props().onClick(); wrapper.find('IconButton').props().onClick();
}); });
wrapper.update(); wrapper.update();
} }
...@@ -111,7 +115,7 @@ describe('AnnotationShareControl', () => { ...@@ -111,7 +115,7 @@ describe('AnnotationShareControl', () => {
it('toggles the share control element when the button is clicked', () => { it('toggles the share control element when the button is clicked', () => {
const wrapper = createComponent(); const wrapper = createComponent();
const button = getButton(wrapper, 'share'); const button = getIconButton(wrapper, 'share');
act(() => { act(() => {
button.props().onClick(); button.props().onClick();
......
...@@ -2,7 +2,7 @@ import { useMemo } from 'preact/hooks'; ...@@ -2,7 +2,7 @@ import { useMemo } from 'preact/hooks';
import { countVisible } from '../helpers/thread'; import { countVisible } from '../helpers/thread';
import Button from './Button'; import { LabeledButton } from '../../shared/components/buttons';
import useRootThread from './hooks/use-root-thread'; import useRootThread from './hooks/use-root-thread';
import { useStoreProxy } from '../store/use-store'; import { useStoreProxy } from '../store/use-store';
...@@ -138,12 +138,14 @@ function SelectionFilterStatus({ filterState, rootThread }) { ...@@ -138,12 +138,14 @@ function SelectionFilterStatus({ filterState, rootThread }) {
const buttonText = showCount ? `Show all (${totalCount})` : 'Show all'; const buttonText = showCount ? `Show all (${totalCount})` : 'Show all';
const button = ( const button = (
<Button <LabeledButton
buttonText={buttonText} title={buttonText}
className="Button--primary" variant="primary"
onClick={() => store.clearSelection()} onClick={() => store.clearSelection()}
icon="cancel" icon="cancel"
/> >
{buttonText}
</LabeledButton>
); );
return ( return (
<FilterStatusPanel <FilterStatusPanel
...@@ -173,12 +175,14 @@ function QueryFilterStatus({ filterState, rootThread }) { ...@@ -173,12 +175,14 @@ function QueryFilterStatus({ filterState, rootThread }) {
const resultCount = visibleCount - filterState.forcedVisibleCount; const resultCount = visibleCount - filterState.forcedVisibleCount;
const button = ( const button = (
<Button <LabeledButton
icon="cancel" icon="cancel"
className="Button--primary" variant="primary"
buttonText="Clear search" title="Clear search"
onClick={() => store.clearSelection()} onClick={() => store.clearSelection()}
/> >
Clear search
</LabeledButton>
); );
return ( return (
...@@ -218,10 +222,10 @@ function FocusFilterStatus({ filterState, rootThread }) { ...@@ -218,10 +222,10 @@ function FocusFilterStatus({ filterState, rootThread }) {
if (filterState.forcedVisibleCount > 0) { if (filterState.forcedVisibleCount > 0) {
buttonProps.onClick = () => store.clearSelection(); buttonProps.onClick = () => store.clearSelection();
buttonProps.buttonText = 'Reset filters'; buttonProps.title = 'Reset filters';
} else { } else {
buttonProps.onClick = () => store.toggleFocusMode(); buttonProps.onClick = () => store.toggleFocusMode();
buttonProps.buttonText = filterState.focusActive buttonProps.title = filterState.focusActive
? 'Show all' ? 'Show all'
: `Show only ${filterState.focusDisplayName}`; : `Show only ${filterState.focusDisplayName}`;
} }
...@@ -229,7 +233,11 @@ function FocusFilterStatus({ filterState, rootThread }) { ...@@ -229,7 +233,11 @@ function FocusFilterStatus({ filterState, rootThread }) {
? filterState.focusDisplayName ? filterState.focusDisplayName
: ''; : '';
const button = <Button className="Button--primary" {...buttonProps} />; const button = (
<LabeledButton variant="primary" {...buttonProps}>
{buttonProps.title}
</LabeledButton>
);
return ( return (
<FilterStatusPanel <FilterStatusPanel
......
import { useStoreProxy } from '../store/use-store'; import { useStoreProxy } from '../store/use-store';
import Button from './Button'; import { LabeledButton } from '../../shared/components/buttons';
import SidebarPanel from './SidebarPanel'; import SidebarPanel from './SidebarPanel';
/** /**
...@@ -27,17 +27,13 @@ export default function LoginPromptPanel({ onLogin, onSignUp }) { ...@@ -27,17 +27,13 @@ export default function LoginPromptPanel({ onLogin, onSignUp }) {
panelName="loginPrompt" panelName="loginPrompt"
> >
<p>Please log in to create annotations or highlights.</p> <p>Please log in to create annotations or highlights.</p>
<div className="SidebarPanel__actions"> <div className="LoginPromptPanel__buttons">
<Button <LabeledButton title="Sign up" onClick={onSignUp}>
buttonText="Sign up" Sign up
className="SidebarPanel__button" </LabeledButton>
onClick={onSignUp} <LabeledButton title="Log in" variant="primary" onClick={onLogin}>
/> Log in
<Button </LabeledButton>
buttonText="Log in"
className="SidebarPanel__button--primary"
onClick={onLogin}
/>
</div> </div>
</SidebarPanel> </SidebarPanel>
); );
......
import { SvgIcon } from '@hypothesis/frontend-shared'; import { SvgIcon } from '@hypothesis/frontend-shared';
import Button from './Button'; import { LabeledButton } from '../../shared/components/buttons';
/** /**
* @typedef PanelProps * @typedef PanelProps
...@@ -29,7 +29,9 @@ export default function Panel({ children, icon, onClose, title }) { ...@@ -29,7 +29,9 @@ export default function Panel({ children, icon, onClose, title }) {
<h2 className="Panel__title u-stretch">{title}</h2> <h2 className="Panel__title u-stretch">{title}</h2>
{withCloseButton && ( {withCloseButton && (
<div> <div>
<Button icon="cancel" buttonText="Close" onClick={onClose} /> <LabeledButton icon="cancel" title="Close" onClick={onClose}>
Close
</LabeledButton>
</div> </div>
)} )}
</div> </div>
......
import { copyText } from '../util/copy-to-clipboard'; import { copyText } from '../util/copy-to-clipboard';
import { withServices } from '../service-context'; import { withServices } from '../service-context';
import Button from './Button'; import { LabeledButton } from '../../shared/components/buttons';
/** /**
* @typedef VersionInfoProps * @typedef VersionInfoProps
...@@ -41,11 +41,9 @@ function VersionInfo({ toastMessenger, versionData }) { ...@@ -41,11 +41,9 @@ function VersionInfo({ toastMessenger, versionData }) {
<dd className="VersionInfo__value">{versionData.timestamp}</dd> <dd className="VersionInfo__value">{versionData.timestamp}</dd>
</dl> </dl>
<div className="u-layout-row--justify-center"> <div className="u-layout-row--justify-center">
<Button <LabeledButton onClick={copyVersionData} icon="copy">
buttonText="Copy version details" Copy version details
onClick={copyVersionData} </LabeledButton>
icon="copy"
/>
</div> </div>
</div> </div>
); );
......
...@@ -64,9 +64,9 @@ describe('FilterStatus', () => { ...@@ -64,9 +64,9 @@ describe('FilterStatus', () => {
} }
function assertButton(wrapper, expected) { function assertButton(wrapper, expected) {
const buttonProps = wrapper.find('Button').props(); const buttonProps = wrapper.find('LabeledButton').props();
assert.equal(buttonProps.buttonText, expected.text); assert.equal(buttonProps.title, expected.text);
assert.equal(buttonProps.icon, expected.icon); assert.equal(buttonProps.icon, expected.icon);
buttonProps.onClick(); buttonProps.onClick();
assert.calledOnce(expected.callback); assert.calledOnce(expected.callback);
......
...@@ -42,9 +42,9 @@ describe('Panel', () => { ...@@ -42,9 +42,9 @@ describe('Panel', () => {
onClose: sinon.stub(), onClose: sinon.stub(),
}); });
const closeButton = wrapper.find('Button'); const closeButton = wrapper.find('LabeledButton');
assert.isTrue(closeButton.exists()); assert.isTrue(closeButton.exists());
assert.equal(closeButton.props().buttonText, 'Close'); assert.equal(closeButton.props().title, 'Close');
}); });
it('invokes `onClose` handler when close button is clicked', () => { it('invokes `onClose` handler when close button is clicked', () => {
...@@ -53,7 +53,7 @@ describe('Panel', () => { ...@@ -53,7 +53,7 @@ describe('Panel', () => {
onClose, onClose,
}); });
wrapper.find('Button').props().onClick(); wrapper.find('LabeledButton').props().onClick();
assert.calledOnce(onClose); assert.calledOnce(onClose);
}); });
......
...@@ -6,7 +6,7 @@ import { $imports } from '../VersionInfo'; ...@@ -6,7 +6,7 @@ import { $imports } from '../VersionInfo';
import mockImportedComponents from '../../../test-util/mock-imported-components'; import mockImportedComponents from '../../../test-util/mock-imported-components';
import { checkAccessibility } from '../../../test-util/accessibility'; import { checkAccessibility } from '../../../test-util/accessibility';
describe('VersionInfo', function () { describe('VersionInfo', () => {
let fakeVersionData; let fakeVersionData;
// Services // Services
let fakeToastMessenger; let fakeToastMessenger;
...@@ -66,7 +66,7 @@ describe('VersionInfo', function () { ...@@ -66,7 +66,7 @@ describe('VersionInfo', function () {
it('copies version info to clipboard when copy button clicked', () => { it('copies version info to clipboard when copy button clicked', () => {
const wrapper = createComponent(); const wrapper = createComponent();
wrapper.find('Button').props().onClick(); wrapper.find('LabeledButton').props().onClick();
assert.calledWith(fakeCopyToClipboard.copyText, 'fakeString'); assert.calledWith(fakeCopyToClipboard.copyText, 'fakeString');
}); });
...@@ -74,7 +74,7 @@ describe('VersionInfo', function () { ...@@ -74,7 +74,7 @@ describe('VersionInfo', function () {
it('confirms info copy when successful', () => { it('confirms info copy when successful', () => {
const wrapper = createComponent(); const wrapper = createComponent();
wrapper.find('Button').props().onClick(); wrapper.find('LabeledButton').props().onClick();
assert.calledWith( assert.calledWith(
fakeToastMessenger.success, fakeToastMessenger.success,
...@@ -86,7 +86,7 @@ describe('VersionInfo', function () { ...@@ -86,7 +86,7 @@ describe('VersionInfo', function () {
fakeCopyToClipboard.copyText.throws(); fakeCopyToClipboard.copyText.throws();
const wrapper = createComponent(); const wrapper = createComponent();
wrapper.find('Button').props().onClick(); wrapper.find('LabeledButton').props().onClick();
assert.calledWith( assert.calledWith(
fakeToastMessenger.error, fakeToastMessenger.error,
......
@use "../../mixins/layout";
@use "../../variables" as var;
.LoginPromptPanel__buttons {
@include layout.row;
@include layout.horizontal-rhythm(var.$layout-space--xsmall);
}
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
@use './components/HypothesisApp'; @use './components/HypothesisApp';
@use './components/LaunchErrorPanel'; @use './components/LaunchErrorPanel';
@use './components/LoggedOutMessage'; @use './components/LoggedOutMessage';
@use './components/LoginPromptPanel';
@use './components/MarkdownEditor'; @use './components/MarkdownEditor';
@use './components/MarkdownView'; @use './components/MarkdownView';
@use './components/Menu'; @use './components/Menu';
......
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