diff --git a/client/src/components/Dashboard/Counters.js b/client/src/components/Dashboard/Counters.js index 9f780c2e..42b22a9c 100644 --- a/client/src/components/Dashboard/Counters.js +++ b/client/src/components/Dashboard/Counters.js @@ -4,10 +4,10 @@ import { Trans, useTranslation } from 'react-i18next'; import round from 'lodash/round'; import { shallowEqual, useSelector } from 'react-redux'; import Card from '../ui/Card'; -import IconTooltip from '../ui/IconTooltip'; import { formatNumber } from '../../helpers/helpers'; import LogsSearchLink from '../ui/LogsSearchLink'; import { RESPONSE_FILTER } from '../../helpers/constants'; +import Tooltip from '../ui/Tooltip'; const Row = ({ label, count, response_status, tooltipTitle, translationComponents, @@ -19,7 +19,12 @@ const Row = ({ return <tr key={label}> <td> <Trans components={translationComponents}>{label}</Trans> - <IconTooltip text={tooltipTitle} type="tooltip-custom--narrow" /> + <Tooltip content={tooltipTitle} placement="top" + className="tooltip-container tooltip-custom--narrow text-center"> + <svg className="icons icon--20 icon--lightgray ml-1"> + <use xlinkHref="#question" /> + </svg> + </Tooltip> </td> <td className="text-right"><strong>{content}</strong></td> </tr>; diff --git a/client/src/components/Dashboard/DomainCell.js b/client/src/components/Dashboard/DomainCell.js index c613c268..fbbb8615 100644 --- a/client/src/components/Dashboard/DomainCell.js +++ b/client/src/components/Dashboard/DomainCell.js @@ -1,18 +1,67 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { getTrackerData } from '../../helpers/trackers/trackers'; -import Popover from '../ui/Popover'; +import { Trans } from 'react-i18next'; +import { getSourceData, getTrackerData } from '../../helpers/trackers/trackers'; +import Tooltip from '../ui/Tooltip'; +import { captitalizeWords } from '../../helpers/helpers'; + +const renderLabel = (value) => <strong><Trans>{value}</Trans></strong>; + +const renderLink = ({ url, name }) => <a + className="tooltip-custom__content-link" + target="_blank" + rel="noopener noreferrer" + href={url} +> + <strong>{name}</strong> +</a>; + + +const getTrackerInfo = (trackerData) => [{ + key: 'name_table_header', + value: trackerData, + render: renderLink, +}, +{ + key: 'category_label', + value: captitalizeWords(trackerData.category), + render: renderLabel, +}, +{ + key: 'source_label', + value: getSourceData(trackerData), + render: renderLink, +}]; const DomainCell = ({ value }) => { const trackerData = getTrackerData(value); + const content = trackerData && <div className="popover__list"> + <div className="tooltip-custom__content-title mb-1"> + <Trans>found_in_known_domain_db</Trans> + </div> + {getTrackerInfo(trackerData) + .map(({ key, value, render }) => <div + key={key} + className="tooltip-custom__content-item" + > + <Trans>{key}</Trans>: {render(value)} + </div>)} + </div>; + return ( <div className="logs__row"> <div className="logs__text" title={value}> {value} </div> - {trackerData && <Popover data={trackerData} />} + {trackerData + && <Tooltip content={content} placement="top" + className="tooltip-container tooltip-custom--wide"> + <svg className="icons icon--24 icon--green ml-1"> + <use xlinkHref="#privacy" /> + </svg> + </Tooltip>} </div> ); }; @@ -21,4 +70,9 @@ DomainCell.propTypes = { value: PropTypes.string.isRequired, }; +renderLink.propTypes = { + url: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, +}; + export default DomainCell; diff --git a/client/src/components/Filters/Rewrites/Table.js b/client/src/components/Filters/Rewrites/Table.js index 9240e0e5..bc197f73 100644 --- a/client/src/components/Filters/Rewrites/Table.js +++ b/client/src/components/Filters/Rewrites/Table.js @@ -63,11 +63,11 @@ class Table extends Component { defaultPageSize={10} minRows={5} previousText={ - <svg className="icons icon--small icon--gray"> + <svg className="icons icon--24 icon--gray"> <use xlinkHref="#arrow-left" /> </svg>} nextText={ - <svg className="icons icon--small icon--gray"> + <svg className="icons icon--24 icon--gray"> <use xlinkHref="#arrow-right" /> </svg>} loadingText={t('loading_table_status')} diff --git a/client/src/components/Filters/Table.js b/client/src/components/Filters/Table.js index cb86a9ea..0ae87097 100644 --- a/client/src/components/Filters/Table.js +++ b/client/src/components/Filters/Table.js @@ -139,11 +139,11 @@ class Table extends Component { noDataText={whitelist ? t('no_whitelist_added') : t('no_blocklist_added')} getPaginationProps={() => ({ className: 'custom-pagination' })} previousText={ - <svg className="icons icon--small icon--gray w-100 h-100"> + <svg className="icons icon--24 icon--gray w-100 h-100"> <use xlinkHref="#arrow-left" /> </svg>} nextText={ - <svg className="icons icon--small icon--gray w-100 h-100"> + <svg className="icons icon--24 icon--gray w-100 h-100"> <use xlinkHref="#arrow-right" /> </svg>} /> diff --git a/client/src/components/Header/Header.css b/client/src/components/Header/Header.css index 08b0b1fc..b67840f3 100644 --- a/client/src/components/Header/Header.css +++ b/client/src/components/Header/Header.css @@ -1,6 +1,6 @@ .nav-tabs .nav-link.active { - border-color: #66b574; - color: #66b574; + border-color: var(--green-74); + color: var(--green-74); background: transparent; } @@ -18,7 +18,7 @@ .nav-tabs .nav-link.active .nav-icon, .nav-tabs .nav-item.show .nav-icon { - stroke: #66b574; + stroke: var(--green-74); } .nav-tabs .nav-link.active:hover .nav-icon, @@ -74,9 +74,9 @@ } .nav-tabs .nav-item.show .nav-link { - color: #66b574; + color: var(--green-74); background-color: #fff; - border-bottom-color: #66b574; + border-bottom-color: var(--green-74); } .header__right { diff --git a/client/src/components/Logs/Cells/Tooltip.css b/client/src/components/Logs/Cells/IconTooltip.css similarity index 98% rename from client/src/components/Logs/Cells/Tooltip.css rename to client/src/components/Logs/Cells/IconTooltip.css index 30e5cded..966f036f 100644 --- a/client/src/components/Logs/Cells/Tooltip.css +++ b/client/src/components/Logs/Cells/IconTooltip.css @@ -1,4 +1,4 @@ -.tooltip__container { +.tooltip-custom__container { padding: 1rem 1.5rem 1.25rem 1.5rem; font-size: 16px !important; box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); diff --git a/client/src/components/Logs/Cells/getClientCell.js b/client/src/components/Logs/Cells/getClientCell.js index 00d5536c..2891f9b8 100644 --- a/client/src/components/Logs/Cells/getClientCell.js +++ b/client/src/components/Logs/Cells/getClientCell.js @@ -3,7 +3,7 @@ import { nanoid } from 'nanoid'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import { formatClientCell } from '../../../helpers/formatClientCell'; -import getHintElement from './getHintElement'; +import getIconTooltip from './getIconTooltip'; import { checkFiltered } from '../../../helpers/helpers'; import { BLOCK_ACTIONS } from '../../../helpers/constants'; @@ -37,7 +37,7 @@ const getClientCell = ({ 'white-space--nowrap': isDetailed, }); - const hintClass = classNames('icons mr-4 icon--small cursor--pointer icon--light-gray', { + const hintClass = classNames('icons mr-4 icon--24 icon--lightgray', { 'my-3': isDetailed, }); @@ -68,7 +68,7 @@ const getClientCell = ({ return ( <div className="logs__row o-hidden h-100"> - {getHintElement({ + {getIconTooltip({ className: hintClass, columnClass: 'grid grid--limited', tooltipClass: 'px-5 pb-5 pt-4 mw-75', diff --git a/client/src/components/Logs/Cells/getDomainCell.js b/client/src/components/Logs/Cells/getDomainCell.js index de142977..5de05e69 100644 --- a/client/src/components/Logs/Cells/getDomainCell.js +++ b/client/src/components/Logs/Cells/getDomainCell.js @@ -1,7 +1,7 @@ import React from 'react'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import getHintElement from './getHintElement'; +import getIconTooltip from './getIconTooltip'; import { DEFAULT_SHORT_DATE_FORMAT_OPTIONS, LONG_TIME_FORMAT, @@ -21,14 +21,14 @@ const getDomainCell = (props) => { const hasTracker = !!tracker; - const lockIconClass = classNames('icons icon--small d-none d-sm-block cursor--pointer', { - 'icon--active': answer_dnssec, + const lockIconClass = classNames('icons icon--24 d-none d-sm-block', { + 'icon--green': answer_dnssec, 'icon--disabled': !answer_dnssec, 'my-3': isDetailed, }); - const privacyIconClass = classNames('icons mx-2 icon--small d-none d-sm-block cursor--pointer', { - 'icon--active': hasTracker, + const privacyIconClass = classNames('icons mx-2 icon--24 d-none d-sm-block', { + 'icon--green': hasTracker, 'icon--disabled': !hasTracker, 'my-3': isDetailed, }); @@ -72,7 +72,7 @@ const getDomainCell = (props) => { const renderContent = hasTracker ? requestDetails.concat(getGrid(knownTrackerDataObj, 'known_tracker', 'pt-4')) : requestDetails; - const trackerHint = getHintElement({ + const trackerHint = getIconTooltip({ className: privacyIconClass, tooltipClass: 'pt-4 pb-5 px-5 mw-75', xlinkHref: 'privacy', @@ -90,7 +90,7 @@ const getDomainCell = (props) => { return ( <div className="logs__row o-hidden"> - {dnssec_enabled && getHintElement({ + {dnssec_enabled && getIconTooltip({ className: lockIconClass, tooltipClass: 'py-4 px-5 pb-45', canShowTooltip: answer_dnssec, diff --git a/client/src/components/Logs/Cells/getHintElement.js b/client/src/components/Logs/Cells/getIconTooltip.js similarity index 54% rename from client/src/components/Logs/Cells/getHintElement.js rename to client/src/components/Logs/Cells/getIconTooltip.js index 93477bf3..3f5327cd 100644 --- a/client/src/components/Logs/Cells/getHintElement.js +++ b/client/src/components/Logs/Cells/getIconTooltip.js @@ -1,14 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; -import TooltipTrigger from 'react-popper-tooltip'; import { Trans } from 'react-i18next'; import classNames from 'classnames'; -import './Tooltip.css'; -import 'react-popper-tooltip/dist/styles.css'; -import { HIDE_TOOLTIP_DELAY } from '../../../helpers/constants'; import { processContent } from '../../../helpers/helpers'; +import Tooltip from '../../ui/Tooltip'; +import 'react-popper-tooltip/dist/styles.css'; +import './IconTooltip.css'; -const getHintElement = ({ +const getIconTooltip = ({ className, contentItemClass, columnClass, @@ -24,30 +23,27 @@ const getHintElement = ({ <Trans>{item || '—'}</Trans> </div>, ) : null, -}) => <TooltipTrigger placement={placement} trigger="hover" delayHide={HIDE_TOOLTIP_DELAY} tooltip={ - ({ - tooltipRef, - getTooltipProps, - }) => <div {...getTooltipProps({ - ref: tooltipRef, - className: classNames('tooltip__container', tooltipClass, { 'd-none': !canShowTooltip }), - })} - > - {title && <div className="pb-4 h-25 grid-content font-weight-bold"> - <Trans>{title}</Trans> - </div>} +}) => { + const tooltipContent = <> + {title + && <div className="pb-4 h-25 grid-content font-weight-bold"><Trans>{title}</Trans></div>} <div className={classNames(columnClass)}>{renderContent}</div> - </div> -}>{({ - getTriggerProps, triggerRef, -}) => <span {...getTriggerProps({ ref: triggerRef })}> - {xlinkHref && <svg className={className}> - <use xlinkHref={`#${xlinkHref}`} /> - </svg>} - </span>} -</TooltipTrigger>; + </>; -getHintElement.propTypes = { + const tooltipClassName = classNames('tooltip-custom__container', tooltipClass, { 'd-none': !canShowTooltip }); + + return <Tooltip + className={tooltipClassName} + content={tooltipContent} + placement={placement} + > + {xlinkHref && <svg className={className}> + <use xlinkHref={`#${xlinkHref}`} /> + </svg>} + </Tooltip>; +}; + +getIconTooltip.propTypes = { className: PropTypes.string, contentItemClass: PropTypes.string, columnClass: PropTypes.string, @@ -63,4 +59,4 @@ getHintElement.propTypes = { renderContent: PropTypes.arrayOf(PropTypes.element), }; -export default getHintElement; +export default getIconTooltip; diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js index 6690c0f6..0c3fd77e 100644 --- a/client/src/components/Logs/Cells/getResponseCell.js +++ b/client/src/components/Logs/Cells/getResponseCell.js @@ -5,7 +5,7 @@ import { FILTERED_STATUS, FILTERED_STATUS_TO_META_MAP, } from '../../../helpers/constants'; -import getHintElement from './getHintElement'; +import getIconTooltip from './getIconTooltip'; const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => { const { @@ -95,8 +95,8 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => { return ( <div className="logs__row"> - {getHintElement({ - className: classNames('icons mr-4 icon--small cursor--pointer icon--light-gray', { 'my-3': isDetailed }), + {getIconTooltip({ + className: classNames('icons mr-4 icon--24 icon--lightgray', { 'my-3': isDetailed }), columnClass: 'grid grid--limited', tooltipClass: 'px-5 pb-5 pt-4 mw-75 custom-tooltip__response-details', contentItemClass: 'text-truncate key-colon o-hidden', diff --git a/client/src/components/Logs/Filters/Form.js b/client/src/components/Logs/Filters/Form.js index d70153c1..d9323a06 100644 --- a/client/src/components/Logs/Filters/Form.js +++ b/client/src/components/Logs/Filters/Form.js @@ -12,10 +12,10 @@ import { RESPONSE_FILTER, RESPONSE_FILTER_QUERIES, } from '../../../helpers/constants'; -import IconTooltip from '../../ui/IconTooltip'; import { setLogsFilter } from '../../../actions/queryLogs'; import useDebounce from '../../../helpers/useDebounce'; import { createOnBlurHandler, getLogsUrlParams } from '../../../helpers/helpers'; +import Tooltip from '../../ui/Tooltip'; const renderFilterField = ({ input, @@ -35,7 +35,7 @@ const renderFilterField = ({ return <> <div className="input-group-search input-group-search__icon--magnifier"> - <svg className="icons icon--small icon--gray"> + <svg className="icons icon--24 icon--gray"> <use xlinkHref="#magnifier" /> </svg> </div> @@ -53,12 +53,16 @@ const renderFilterField = ({ /> <div className={classNames('input-group-search input-group-search__icon--cross', { invisible: input.value.length < 1 })}> - <svg className="icons icon--smallest icon--gray" onClick={onClearInputClick}> + <svg className="icons icon--20 icon--gray" onClick={onClearInputClick}> <use xlinkHref="#cross" /> </svg> </div> <span className="input-group-search input-group-search__icon--tooltip"> - <IconTooltip text={tooltip} type='tooltip-custom--logs' /> + <Tooltip content={tooltip} className="tooltip-container"> + <svg className="icons icon--20 icon--gray"> + <use xlinkHref="#question" /> + </svg> + </Tooltip> </span> {!disabled && touched diff --git a/client/src/components/Logs/Filters/index.js b/client/src/components/Logs/Filters/index.js index 6484b69a..d89771b2 100644 --- a/client/src/components/Logs/Filters/index.js +++ b/client/src/components/Logs/Filters/index.js @@ -12,7 +12,7 @@ const Filters = ({ filter, refreshLogs, setIsLoading }) => ( className="btn btn-icon--green ml-3 bg-transparent" onClick={refreshLogs} > - <svg className="icons icon--small"> + <svg className="icons icon--24"> <use xlinkHref="#update" /> </svg> </button> diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 4d734b53..81d1f0a5 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -399,10 +399,6 @@ top: 0.5rem; } -.icon--light-gray { - color: var(--gray-8); -} - .link--green { color: var(--green79); } diff --git a/client/src/components/Logs/Table.js b/client/src/components/Logs/Table.js index fcf8daa4..7a05bf18 100644 --- a/client/src/components/Logs/Table.js +++ b/client/src/components/Logs/Table.js @@ -154,27 +154,23 @@ const Table = (props) => { headerClassName: 'logs__text', }, { - Header: () => { - const plainSelected = classNames('cursor--pointer', { - 'icon--selected': !isDetailed, - }); - - const detailedSelected = classNames('cursor--pointer', { - 'icon--selected': isDetailed, - }); - + Header: function Header() { return <div className="d-flex justify-content-between"> {t('client_table_header')} {<span> <svg - className={`icons icon--small icon--active mr-2 cursor--pointer ${plainSelected}`} + className={classNames('icons icon--24 icon--green mr-2 cursor--pointer', { + 'icon--selected': !isDetailed, + })} onClick={() => toggleDetailedLogs(false)} > <title><Trans>compact</Trans></title> <use xlinkHref='#list' /> </svg> <svg - className={`icons icon--small icon--active cursor--pointer ${detailedSelected}`} + className={classNames('icons icon--24 icon--green cursor--pointer', { + 'icon--selected': isDetailed, + })} onClick={() => toggleDetailedLogs(true)} > <title><Trans>default</Trans></title> @@ -261,12 +257,12 @@ const Table = (props) => { getPaginationProps={() => ({ className: 'custom-pagination custom-pagination--padding' })} getTbodyProps={() => ({ className: 'd-block' })} previousText={ - <svg className="icons icon--small icon--gray w-100 h-100 cursor--pointer"> + <svg className="icons icon--24 icon--gray w-100 h-100 cursor--pointer"> <title><Trans>previous_btn</Trans></title> <use xlinkHref="#arrow-left" /> </svg>} nextText={ - <svg className="icons icon--small icon--gray w-100 h-100 cursor--pointer"> + <svg className="icons icon--24 icon--gray w-100 h-100 cursor--pointer"> <title><Trans>next_btn</Trans></title> <use xlinkHref="#arrow-right" /> </svg>} diff --git a/client/src/components/Logs/index.js b/client/src/components/Logs/index.js index f889fead..ff3c96e3 100644 --- a/client/src/components/Logs/index.js +++ b/client/src/components/Logs/index.js @@ -245,7 +245,7 @@ const Logs = (props) => { }} > <svg - className="icon icon--small icon-cross d-block d-md-none cursor--pointer" + className="icon icon--24 icon-cross d-block d-md-none cursor--pointer" onClick={closeModal}> <use xlinkHref="#cross" /> </svg> diff --git a/client/src/components/Settings/Clients/AutoClients.js b/client/src/components/Settings/Clients/AutoClients.js index 1fd8224e..072d7108 100644 --- a/client/src/components/Settings/Clients/AutoClients.js +++ b/client/src/components/Settings/Clients/AutoClients.js @@ -89,11 +89,11 @@ class AutoClients extends Component { showPageJump={false} renderTotalPagesCount={() => false} previousText={ - <svg className="icons icon--small icon--gray w-100 h-100"> + <svg className="icons icon--24 icon--gray w-100 h-100"> <use xlinkHref="#arrow-left" /> </svg>} nextText={ - <svg className="icons icon--small icon--gray w-100 h-100"> + <svg className="icons icon--24 icon--gray w-100 h-100"> <use xlinkHref="#arrow-right" /> </svg>} loadingText={t('loading_table_status')} diff --git a/client/src/components/Settings/Clients/ClientsTable.js b/client/src/components/Settings/Clients/ClientsTable.js index a179ac30..76df4021 100644 --- a/client/src/components/Settings/Clients/ClientsTable.js +++ b/client/src/components/Settings/Clients/ClientsTable.js @@ -301,11 +301,11 @@ class ClientsTable extends Component { showPageJump={false} renderTotalPagesCount={() => false} previousText={ - <svg className="icons icon--small icon--gray w-100 h-100"> + <svg className="icons icon--24 icon--gray w-100 h-100"> <use xlinkHref="#arrow-left" /> </svg>} nextText={ - <svg className="icons icon--small icon--gray w-100 h-100"> + <svg className="icons icon--24 icon--gray w-100 h-100"> <use xlinkHref="#arrow-right" /> </svg>} loadingText={t('loading_table_status')} diff --git a/client/src/components/Settings/Clients/Form.js b/client/src/components/Settings/Clients/Form.js index 5c7bf471..cb5458dd 100644 --- a/client/src/components/Settings/Clients/Form.js +++ b/client/src/components/Settings/Clients/Form.js @@ -88,7 +88,7 @@ const renderFieldsWrapper = (placeholder, buttonTitle) => function cell(row) { onClick={() => fields.push()} title={buttonTitle} > - <svg className="icon icon--small"> + <svg className="icon icon--24"> <use xlinkHref="#plus" /> </svg> </button> diff --git a/client/src/components/ui/Dropdown.css b/client/src/components/ui/Dropdown.css index 6af28594..25efec81 100644 --- a/client/src/components/ui/Dropdown.css +++ b/client/src/components/ui/Dropdown.css @@ -1,6 +1,6 @@ .dropdown-item.active, .dropdown-item:active { - background-color: #66b574; + background-color: var(--green-74); } .dropdown-menu { diff --git a/client/src/components/ui/IconTooltip.css b/client/src/components/ui/IconTooltip.css deleted file mode 100644 index 32903064..00000000 --- a/client/src/components/ui/IconTooltip.css +++ /dev/null @@ -1,73 +0,0 @@ -.tooltip-custom { - position: relative; - top: -1px; - display: inline-block; - vertical-align: middle; - width: 18px; - height: 18px; - flex-shrink: 0; - background-image: url("./svg/help-circle.svg"); - background-size: 100%; - cursor: pointer; -} - -.tooltip-custom:before { - content: attr(data-tooltip); - display: block; - position: absolute; - bottom: calc(100% + 10px); - left: 50%; - padding: 10px 15px; - font-size: 0.85rem; - text-align: center; - color: #fff; - background-color: #585965; - border-radius: 3px; - transform: translateX(-50%); - visibility: hidden; - opacity: 0; -} - -.tooltip-custom:after { - content: ""; - position: relative; - top: -7px; - left: calc(50% - 6px); - visibility: hidden; - opacity: 0; - width: 0; - height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-top: 6px solid #585965; -} - -.tooltip-custom:hover:before, -.tooltip-custom:hover:after { - visibility: visible; - opacity: 1; -} - -.tooltip-custom--narrow:before { - width: 220px; -} - -.tooltip-custom--logs { - border-radius: 50%; - background-image: url("./svg/help-circle-gray.svg"); -} - -.tooltip-custom--logs:before { - bottom: initial; - top: calc(100% + 10px); - right: -10px; - left: initial; - width: 255px; - transform: none; -} - -.tooltip-custom--logs:after { - top: 8px; - border-top: none; - border-bottom: 6px solid #585965; -} diff --git a/client/src/components/ui/IconTooltip.js b/client/src/components/ui/IconTooltip.js deleted file mode 100644 index 7a7af2fa..00000000 --- a/client/src/components/ui/IconTooltip.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import './IconTooltip.css'; -import { useTranslation } from 'react-i18next'; - -const IconTooltip = ({ text, type = '' }) => { - const { t } = useTranslation(); - - return <div data-tooltip={t(text)} - className={`tooltip-custom ml-1 ${type}`} />; -}; - -IconTooltip.propTypes = { - text: PropTypes.string.isRequired, - type: PropTypes.string, -}; - -export default IconTooltip; diff --git a/client/src/components/ui/Icons.css b/client/src/components/ui/Icons.css index f5387c68..24d71538 100644 --- a/client/src/components/ui/Icons.css +++ b/client/src/components/ui/Icons.css @@ -4,24 +4,36 @@ height: 100%; } -.icon--small { - width: 1.5rem; - height: 1.5rem; +.icon--24 { + --size: 1.5rem; + width: var(--size); + height: var(--size); } -.icon--smallest { - width: 1.2rem; - height: 1.2rem; +.icon--20 { + --size: 1.25rem; + width: var(--size); + height: var(--size); +} + +.icon--18 { + --size: 1.125rem; + width: var(--size); + height: var(--size); } .icon--gray { color: var(--gray-a5); } +.icon--green { + color: var(--green-74); +} + .icon--disabled { color: var(--gray-d8); } -.icon--active { - color: #66b574; +.icon--lightgray { + color: var(--gray-8); } diff --git a/client/src/components/ui/Popover.css b/client/src/components/ui/Popover.css deleted file mode 100644 index 250848af..00000000 --- a/client/src/components/ui/Popover.css +++ /dev/null @@ -1,151 +0,0 @@ -.popover-wrap { - position: relative; - top: 1px; - display: inline-block; - vertical-align: middle; - align-self: flex-start; -} - -.popover__trigger { - position: relative; - top: 3px; - margin: 0 8px; - cursor: pointer; -} - -.popover__trigger:after { - content: ""; - position: absolute; - top: -6px; - left: -3px; - width: 26px; - height: 24px; -} - -.popover__trigger--address { - top: 0; - margin: 0; - line-height: 1.2; -} - -.popover__trigger--address:after { - display: none; -} - -.popover__body { - content: ""; - display: flex; - position: absolute; - bottom: calc(100% + 3px); - left: 50%; - z-index: 1; - min-width: 275px; - padding: 10px 15px; - font-size: 0.8rem; - white-space: normal; - color: #fff; - background-color: #585965; - border-radius: 3px; - transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out; - transform: translateX(-50%); - visibility: hidden; - opacity: 0; -} - -.popover__body--filter { - min-width: 100%; -} - -.popover__body:after { - content: ""; - position: absolute; - bottom: -5px; - left: calc(50% - 6px); - width: 0; - height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-top: 6px solid #585965; -} - -.popover__body--address { - top: calc(100% + 10px); - right: 0; - left: initial; - bottom: initial; - z-index: 1; - min-width: 100px; - padding: 12px 18px; - font-weight: 700; - text-align: left; - white-space: nowrap; - transform: none; - cursor: default; -} - -.popover__body--address:after { - top: -11px; - left: initial; - right: 40px; - border-top: 6px solid transparent; - border-bottom: 6px solid #585965; -} - -.popover__body--address:before { - content: ""; - position: absolute; - top: -7px; - left: 0; - width: 100%; - height: 10px; -} - -.popover__trigger:hover + .popover__body, -.popover__body:hover { - visibility: visible; - opacity: 1; -} - -.popover__icon { - width: 20px; - height: 20px; - stroke: #9aa0ac; - color: #9aa0ac; -} - -.popover__icon--green { - color: #66b574; - stroke: #66b574; -} - -.popover__list--bold { - font-weight: 700; -} - -.popover__list-title { - margin-bottom: 3px; -} - -.popover__list-item { - margin-bottom: 2px; -} - -.popover__list-item--nowrap { - max-width: 300px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.popover__list-item:last-child { - margin-bottom: 0; -} - -.popover__link { - color: #66b586; -} - -.popover__link:hover, -.popover__link:focus { - color: #66b586; -} diff --git a/client/src/components/ui/Popover.js b/client/src/components/ui/Popover.js deleted file mode 100644 index 7ab6b5ac..00000000 --- a/client/src/components/ui/Popover.js +++ /dev/null @@ -1,69 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Trans, withTranslation } from 'react-i18next'; -import { getSourceData } from '../../helpers/trackers/trackers'; -import { captitalizeWords } from '../../helpers/helpers'; - -import './Popover.css'; - -class Popover extends Component { - render() { - const { data } = this.props; - - const sourceData = getSourceData(data); - - const source = ( - <div className="popover__list-item"> - <Trans>source_label</Trans>: <a className="popover__link" target="_blank" - rel="noopener noreferrer" - href={sourceData.url}> - <strong>{sourceData.name}</strong> - </a> - </div> - ); - - const tracker = ( - <div className="popover__list-item"> - <Trans>name_table_header</Trans>: <a className="popover__link" target="_blank" - rel="noopener noreferrer" - href={data.url}> - <strong>{data.name}</strong> - </a> - </div> - ); - - const categoryName = captitalizeWords(data.category); - - return ( - <div className="popover-wrap"> - <div className="popover__trigger"> - <svg className="popover__icon" xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 24 24" fill="none" strokeWidth="2" strokeLinecap="round" - strokeLinejoin="round"> - <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path> - <circle cx="12" cy="12" r="3"></circle> - </svg> - </div> - <div className="popover__body"> - <div className="popover__list"> - <div className="popover__list-title"> - <Trans>found_in_known_domain_db</Trans> - </div> - {tracker} - <div className="popover__list-item"> - <Trans>category_label</Trans>: <strong> - <Trans>{categoryName}</Trans></strong> - </div> - {source} - </div> - </div> - </div> - ); - } -} - -Popover.propTypes = { - data: PropTypes.object.isRequired, -}; - -export default withTranslation()(Popover); diff --git a/client/src/components/ui/PopoverFilter.js b/client/src/components/ui/PopoverFilter.js deleted file mode 100644 index 39a2778a..00000000 --- a/client/src/components/ui/PopoverFilter.js +++ /dev/null @@ -1,52 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Trans, withTranslation } from 'react-i18next'; - -import './Popover.css'; - -class PopoverFilter extends Component { - render() { - const { rule, filter, service } = this.props; - - if (!rule && !service) { - return ''; - } - - return ( - <div className="popover-wrap"> - <div className="popover__trigger popover__trigger--filter"> - <svg className="popover__icon popover__icon--green"> - <use xlinkHref="#question" /> - </svg> - </div> - <div className="popover__body popover__body--filter"> - <div className="popover__list"> - {rule && ( - <div className="popover__list-item popover__list-item--nowrap"> - <Trans>rule_label</Trans>: <strong>{rule}</strong> - </div> - )} - {filter && ( - <div className="popover__list-item popover__list-item--nowrap"> - <Trans>list_label</Trans>: <strong>{filter}</strong> - </div> - )} - {service && ( - <div className="popover__list-item popover__list-item--nowrap"> - <Trans>blocked_service</Trans>: <strong>{service}</strong> - </div> - )} - </div> - </div> - </div> - ); - } -} - -PopoverFilter.propTypes = { - rule: PropTypes.string, - filter: PropTypes.string, - service: PropTypes.string, -}; - -export default withTranslation()(PopoverFilter); diff --git a/client/src/components/ui/Tabler.css b/client/src/components/ui/Tabler.css index 7792f3e0..d11e0ce6 100644 --- a/client/src/components/ui/Tabler.css +++ b/client/src/components/ui/Tabler.css @@ -19,10 +19,13 @@ Dashboard UI --orange: #fd9644; --yellow: #f1c40f; --green: #5eba00; + --green-74: #66b574; + --green-86: #66b586; --teal: #2bcbba; --cyan: #17a2b8; --white: #fff; --gray: #868e96; + --gray-ac: #9aa0ac; --gray-dark: #343a40; --azure: #45aaf2; --lime: #7bd235; diff --git a/client/src/components/ui/Tooltip.css b/client/src/components/ui/Tooltip.css new file mode 100644 index 00000000..ea7ff281 --- /dev/null +++ b/client/src/components/ui/Tooltip.css @@ -0,0 +1,27 @@ +.tooltip-custom--narrow { + max-width: 13.75rem; +} + +.tooltip-custom--wide { + max-width: 18rem; +} + +.tooltip-custom__trigger { + cursor: pointer; +} + +.tooltip-custom__content-title { + margin-bottom: 0.1875rem; +} + +.tooltip-custom__content-item { + margin-bottom: 0.125rem; +} + +.tooltip-custom__content-item:last-child { + margin-bottom: 0; +} + +.tooltip-custom__content-link { + color: var(--green-86); +} diff --git a/client/src/components/ui/Tooltip.js b/client/src/components/ui/Tooltip.js new file mode 100644 index 00000000..84ce7209 --- /dev/null +++ b/client/src/components/ui/Tooltip.js @@ -0,0 +1,58 @@ +import React from 'react'; +import TooltipTrigger from 'react-popper-tooltip'; +import propTypes from 'prop-types'; +import { useTranslation } from 'react-i18next'; +import { HIDE_TOOLTIP_DELAY } from '../../helpers/constants'; +import 'react-popper-tooltip/dist/styles.css'; +import './Tooltip.css'; + +const Tooltip = ({ + children, + content, + triggerClass = 'tooltip-custom__trigger', + className = 'tooltip-container', + placement = 'bottom', + trigger = 'hover', + delayHide = HIDE_TOOLTIP_DELAY, +}) => { + const { t } = useTranslation(); + + return <TooltipTrigger + placement={placement} + trigger={trigger} + delayHide={delayHide} + tooltip={({ + tooltipRef, + getTooltipProps, + }) => <div {...getTooltipProps({ + ref: tooltipRef, + className, + })}> + {typeof content === 'string' ? t(content) : content} + </div> + }>{({ getTriggerProps, triggerRef }) => <span + {...getTriggerProps({ + ref: triggerRef, + className: triggerClass, + })} + >{children}</span>} + </TooltipTrigger>; +}; + +Tooltip.propTypes = { + children: propTypes.element.isRequired, + content: propTypes.oneOfType( + [ + propTypes.string, + propTypes.element, + propTypes.arrayOf(propTypes.element), + ], + ).isRequired, + placement: propTypes.string, + trigger: propTypes.string, + delayHide: propTypes.string, + className: propTypes.string, + triggerClass: propTypes.string, +}; + +export default Tooltip; diff --git a/client/src/components/ui/svg/help-circle.svg b/client/src/components/ui/svg/help-circle.svg index 3e0e832d..2d557131 100644 --- a/client/src/components/ui/svg/help-circle.svg +++ b/client/src/components/ui/svg/help-circle.svg @@ -1 +1,6 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#66b574" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-help-circle"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12" y2="17"></line></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#66b574" + stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-help-circle"> + <circle cx="12" cy="12" r="10"></circle> + <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path> + <line x1="12" y1="17" x2="12" y2="17"></line> +</svg> diff --git a/client/src/helpers/form.js b/client/src/helpers/form.js index 67cfbe71..b1755038 100644 --- a/client/src/helpers/form.js +++ b/client/src/helpers/form.js @@ -90,7 +90,7 @@ export const renderGroupField = ({ className="btn btn-secondary btn-icon btn-icon--green" onClick={removeField} > - <svg className="icon icon--small"> + <svg className="icon icon--24"> <use xlinkHref="#cross" /> </svg> </button>