Skip to content

Commit

Permalink
feat: Share buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
poplingue committed May 13, 2022
1 parent 4662910 commit f2b31e9
Show file tree
Hide file tree
Showing 14 changed files with 403 additions and 5 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,5 @@ Thanks to the internet world.
* [How to create an npm library from react components](https://dev.to/jimjunior/how-to-create-an-npm-library-from-react-components-2m2)

### TODO
* components v1.4
* bouton tertiaire
* bouton FranceConnect
* retour en haut de page
* Limit usage of colors to colorFamilies
* Add StoryBook
5 changes: 4 additions & 1 deletion example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ButtonGroupExample from './components/Button/ButtonGroup';
import CalloutExample from './components/Callout/Callout';
import CardExample from './components/Card/Card';
import CheckboxExample from './components/Checkbox/Checkbox';
// import ConsentManagerExample from './components/ConsentManager/ConsentManager';
import ConsentManagerExample from './components/ConsentManager/ConsentManager';
import FooterExample from './components/Footer/Footer';
import FileExample from './components/File/File';
import HeaderExample from './components/Header/Header';
Expand All @@ -36,6 +36,7 @@ import DownloadExample from './components/Download/Download';
import Element from './Element';
import Page1 from './Page-1';
import Page2 from './Page-2';
import ShareExample from './components/Share/Share';

const App = () => {
const elements = [
Expand All @@ -49,6 +50,7 @@ const App = () => {
{ title: 'Callout', component: <CalloutExample /> },
{ title: 'Card', component: <CardExample /> },
{ title: 'Checkbox', component: <CheckboxExample /> },
{ title: 'Consent', component: <ConsentManagerExample /> },
{ title: 'Download', component: <DownloadExample /> },
{ title: 'File', component: <FileExample /> },
{ title: 'Highlight', component: <HighlightExample /> },
Expand All @@ -68,6 +70,7 @@ const App = () => {
{ title: 'TextInput', component: <TextInputExample /> },
{ title: 'Tile - Tuile', component: <TileExample /> },
{ title: 'Toggle', component: <ToggleExample /> },
{ title: 'Share', component: <ShareExample /> },
];

return (
Expand Down
66 changes: 66 additions & 0 deletions example/src/components/Share/Share.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';

import {
Share, ShareButton,
} from '@dataesr/react-dsfr';

const ShareExampla = () => {
const onClickFacebook = () => {
window.open(
'https://www.facebook.com/sharer.php',
'Partager sur Facebook',
'toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=450',
);
};

const onClickTwitter = () => {
window.open(
'https://twitter.com/intent/tweet',
'Partager sur Twitter',
'toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=420',
);
};

const onClickLinkedin = () => {
window.open(
'https://www.linkedin.com/shareArticle',
'Partager sur Linkedin',
'toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=420',
);
};

const onCopy = () => {
navigator.clipboard.writeText(window.location);
};

return (
<Share title="Partager la page">
<ShareButton
onClick={onClickFacebook}
type="facebook"
label="Partager sur facebook"
href="https://www.facebook.com/sharer.php"
/>
<ShareButton
onClick={onClickTwitter}
type="twitter"
label="Partager sur twitter"
href="https://twitter.com/intent/tweet"
/>
<ShareButton
onClick={onClickLinkedin}
type="linkedin"
label="Partager sur linkedin"
href="https://www.linkedin.com/shareArticle"
/>
<ShareButton
type="mail"
label="Partager par email"
href="mailto:?subject=[À MODIFIER - objet du mail]&body=[À MODIFIER - titre ou texte descriptif de la page] [À MODIFIER - url de la page]"
/>
<ShareButton type="copy" label={'Copier l\'adresse'} onClick={onCopy} />
</Share>
);
};

export default ShareExampla;
16 changes: 16 additions & 0 deletions src/components/interface/Share/Share.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react';

export type ShareChildren = React.ReactNode[] | React.ReactNode;

export type ShareClassName = string | Object | any[];

export interface ShareProps {
title: string;
children: ShareChildren;
className?: ShareClassName;
}

declare const Share: React.FC<ShareProps>;

export default Share;

44 changes: 44 additions & 0 deletions src/components/interface/Share/Share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import dataAttributes from '../../../utils/data-attributes';

/*
* DSFR v1.5.0
*/
import '@gouvfr/dsfr/dist/component/share/share.css';

const Share = ({
children, className, title, ...remainingProps
}) => {
const _className = classNames('fr-share', className);

return (
<div
className={_className}
{...dataAttributes.getAll(remainingProps)}
>
<p className="fr-share__title">{title}</p>
<ul className="fr-btns-group">
{children}
</ul>
</div>
);
};

Share.defaultProps = {
className: '',
title: '',
};

Share.propTypes = {
children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
title: PropTypes.string,
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object,
PropTypes.array,
]),
};

export default Share;
16 changes: 16 additions & 0 deletions src/components/interface/Share/Share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Méta données
cf [Confluences](https://gouvfr.atlassian.net/wiki/spaces/DB/pages/771555355/Partage+-+Share)
<!-- Balises meta Open Graph -->
<meta property="og:title" content="[À MODIFIER | Système de Design de l&#39;État]">
<meta property="og:description" content="[À MODIFIER | Développer vos sites et applications en utilisant des composants prêts à l&#39;emploi, accessibles et ergonomiques]">
<meta property="og:image" content="[À MODIFIER | https://systeme-de-design.gouv.fr/src/img/systeme-de-design.gouv.fr.jpg]">
<meta property="og:type" content="website">
<meta property="og:url" content="[À MODIFIER | https://systeme-de-design.gouv.fr/]">
<meta property="og:site_name" content="[À MODIFIER | Site officiel du Système de Design de l&#39;État]">
<meta property="og:image:alt" content="[À MODIFIER | République Française - Système de Design de l&#39;État]">

<!-- Balise méta pour twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="[À MODIFIER | @usernameTwitter]">
<meta name="twitter:image:alt" content="[À MODIFIER | République Française - Système de Design de l&#39;État]">

16 changes: 16 additions & 0 deletions src/components/interface/Share/ShareButton.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react';

export type ShareButtonClassName = string | Object | any[];

export interface ShareButtonProps {
type: string;
label: string;
href?: string;
onClick?: (...args: any[]) => any;
className?: ShareButtonClassName;
}

declare const ShareButton: React.FC<ShareButtonProps>;

export default ShareButton;

85 changes: 85 additions & 0 deletions src/components/interface/Share/ShareButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import dataAttributes from '../../../utils/data-attributes';

/*
* DSFR v1.5.0
*/
import '@gouvfr/dsfr/dist/component/share/share.css';

const ShareButton = ({
label, href, className, type, onClick, ...remainingProps
}) => {
const _className = classNames('fr-share', className);

const _onClick = (e) => {
e.preventDefault();
onClick(e);
};

const renderLink = () => {
let link = (
<a
className={`fr-btn fr-btn--${type}`}
onClick={_onClick}
href={href}
target="_blank"
rel="noopener noreferrer"
>
{label}
</a>
);

if (type === 'mail') {
link = (
<a
className={`fr-btn fr-btn--${type}`}
href={href}
target="_blank"
rel="noopener noreferrer"
>
{label}
</a>
);
}

return link;
};

return (
<li className={_className} {...dataAttributes.getAll(remainingProps)}>
{type === 'copy' ? (
<button
type="button"
className="fr-btn--copy fr-btn"
onClick={_onClick}
>
{label}
</button>
) : (
renderLink()
)}
</li>
);
};

ShareButton.defaultProps = {
className: '',
href: '',
onClick: undefined,
};

ShareButton.propTypes = {
href: PropTypes.string,
label: PropTypes.string.isRequired,
onClick: PropTypes.func,
type: PropTypes.oneOf(['facebook', 'twitter', 'linkedin', 'copy', 'mail']).isRequired,
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object,
PropTypes.array,
]),
};

export default ShareButton;
54 changes: 54 additions & 0 deletions src/components/interface/Share/__tests__/Share.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';

import Enzyme, { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import React from 'react';
import { Share, ShareButton } from '..';

Enzyme.configure({ adapter: new Adapter() });

jest.mock('uuid', () => ({
v4: jest.fn(),
}));

describe('<Share />', () => {
let wrapper;

beforeEach(() => {
wrapper = (props = {}) => shallow(
<ShareButton
onClick={props.onClick}
type="facebook"
label="Partager sur facebook"
href="https://www.facebook.com/sharer.php"
/>,
);
});

it('should render Share properly', () => {
const component = renderer
.create(
<Share title="Partager la page">
<ShareButton
onClick={() => {}}
type="facebook"
label="Partager sur facebook"
href="https://www.facebook.com/sharer.php"
/>
</Share>,
)
.toJSON();
expect(component).toMatchSnapshot();
});

test('onClick Share facebook', () => {
const mockClick = jest.fn();
const props = {
onClick: mockClick,
};

const component = wrapper({ ...props });
component.find('.fr-btn--facebook').simulate('click', { preventDefault: () => {} });
expect(mockClick).toHaveBeenCalled();
});
});
Loading

0 comments on commit f2b31e9

Please sign in to comment.