diff --git a/package-lock.json b/package-lock.json
index 2490d43c..f5b1b4b1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10913,6 +10913,11 @@
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
},
+ "highlight-words-core": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz",
+ "integrity": "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg=="
+ },
"history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
@@ -27009,6 +27014,23 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
+ "react-highlight-words": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/react-highlight-words/-/react-highlight-words-0.16.0.tgz",
+ "integrity": "sha512-q34TwCSJOL+5pVDv6LUj3amaoyXdNDwd7zRqVAvceOrO9g1haWLAglK6WkGLMNUa3PFN8EgGedLg/k8Gpndxqg==",
+ "requires": {
+ "highlight-words-core": "^1.2.0",
+ "memoize-one": "^4.0.0",
+ "prop-types": "^15.5.8"
+ },
+ "dependencies": {
+ "memoize-one": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz",
+ "integrity": "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw=="
+ }
+ }
+ },
"react-image-gallery": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/react-image-gallery/-/react-image-gallery-0.9.1.tgz",
diff --git a/package.json b/package.json
index 588fa778..1a8a6ff4 100644
--- a/package.json
+++ b/package.json
@@ -70,6 +70,7 @@
"npm": "^6.13.7",
"react": "^16.13.0",
"react-component-queries": "^2.3.0",
+ "react-highlight-words": "^0.16.0",
"react-image-gallery": "^0.9.1",
"react-infinite-scroll-component": "^5.0.4",
"react-lazy-load-image-component": "^1.4.0",
diff --git a/src/actions/index.js b/src/actions/index.js
index 3beded30..62b393cb 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -1,9 +1,12 @@
import {
- SET_SECTION_TABS,
- GET_PARENT_FOLDER_DATA,
- GET_NAV_ITEMS
+ SET_SECTION_TABS,
+ GET_PARENT_FOLDER_DATA,
+ GET_NAV_ITEMS,
+ QUICK_RESET_SEARCH_CONTENT,
+ QUICK_SEARCH_CONTENT,
} from '~/constants/ActionTypes';
+import { compact, concat, isArray, join, map, pickBy, toPairs } from 'lodash';
export function setSectionTabs(payload) {
return {
@@ -12,7 +15,6 @@ export function setSectionTabs(payload) {
};
}
-
export function getParentFolderData(url) {
return {
type: GET_PARENT_FOLDER_DATA,
@@ -22,3 +24,55 @@ export function getParentFolderData(url) {
},
};
}
+
+export function quickSearchContent(url, options, subrequest = null) {
+ let queryArray = [];
+ const arrayOptions = pickBy(options, item => isArray(item));
+ console.log(options, arrayOptions);
+
+ queryArray = concat(
+ queryArray,
+ options
+ ? join(
+ map(toPairs(pickBy(options, item => !isArray(item))), item => {
+ if (item[0] === 'SearchableText') {
+ // Adds the wildcard to the SearchableText param
+ item[1] = `${item[1]}*`;
+ }
+ return join(item, '=');
+ }),
+ '&',
+ )
+ : '',
+ );
+
+ queryArray = concat(
+ queryArray,
+ arrayOptions
+ ? join(
+ map(pickBy(arrayOptions), (item, key) =>
+ join(item.map(value => `${key}:list=${value}`), '&'),
+ ),
+ '&',
+ )
+ : '',
+ );
+
+ const querystring = join(compact(queryArray), '&');
+
+ return {
+ type: QUICK_SEARCH_CONTENT,
+ subrequest,
+ request: {
+ op: 'get',
+ path: `${url}/@search${querystring ? `?${querystring}` : ''}`,
+ },
+ };
+}
+
+export function quickResetSearchContent(subrequest = null) {
+ return {
+ type: QUICK_RESET_SEARCH_CONTENT,
+ subrequest,
+ };
+}
diff --git a/src/components/theme/View/TabsChildView.jsx b/src/components/theme/View/TabsChildView.jsx
index 8c270e69..b0529e41 100644
--- a/src/components/theme/View/TabsChildView.jsx
+++ b/src/components/theme/View/TabsChildView.jsx
@@ -90,7 +90,7 @@ const DefaultView = props => {
return hasBlocksData(content) ? (
-
+
diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js
index 4aa5ef89..4ddbb776 100644
--- a/src/constants/ActionTypes.js
+++ b/src/constants/ActionTypes.js
@@ -1,5 +1,5 @@
export const SET_SECTION_TABS = 'SET_SECTION_TABS';
export const GET_PARENT_FOLDER_DATA = 'GET_PARENT_FOLDER_DATA';
export const GET_NAV_ITEMS = 'GET_NAV_ITEMS';
-
-
+export const QUICK_RESET_SEARCH_CONTENT = 'QUICK_RESET_SEARCH_CONTENT';
+export const QUICK_SEARCH_CONTENT = 'QUICK_SEARCH_CONTENT';
diff --git a/src/customizations/volto/components/theme/Search/Search.jsx b/src/customizations/volto/components/theme/Search/Search.jsx
new file mode 100644
index 00000000..901f7ea3
--- /dev/null
+++ b/src/customizations/volto/components/theme/Search/Search.jsx
@@ -0,0 +1,324 @@
+/**
+ * Search component.
+ * @module components/theme/Search/Search
+ */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import { Link } from 'react-router-dom';
+import { asyncConnect } from 'redux-connect';
+import { FormattedMessage } from 'react-intl';
+import { Portal } from 'react-portal';
+import { Container, Pagination } from 'semantic-ui-react';
+import qs from 'query-string';
+import moment from 'moment';
+
+import { settings } from '~/config';
+import { Helmet } from '@plone/volto/helpers';
+import { searchContent } from '@plone/volto/actions';
+import {
+ SearchTags,
+ SearchWidget,
+ Toolbar,
+ Icon,
+} from '@plone/volto/components';
+
+import paginationLeftSVG from '@plone/volto/icons/left-key.svg';
+import paginationRightSVG from '@plone/volto/icons/right-key.svg';
+
+const toSearchOptions = (searchableText, subject, path) => {
+ return {
+ ...(searchableText && { SearchableText: searchableText }),
+ ...(subject && {
+ Subject: subject,
+ }),
+ ...(path && {
+ path: path,
+ }),
+ };
+};
+
+/**
+ * Search class.
+ * @class SearchComponent
+ * @extends Component
+ */
+class Search extends Component {
+ /**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+ static propTypes = {
+ searchContent: PropTypes.func.isRequired,
+ searchableText: PropTypes.string,
+ subject: PropTypes.string,
+ path: PropTypes.string,
+ items: PropTypes.arrayOf(
+ PropTypes.shape({
+ '@id': PropTypes.string,
+ '@type': PropTypes.string,
+ title: PropTypes.string,
+ description: PropTypes.string,
+ }),
+ ),
+ pathname: PropTypes.string.isRequired,
+ };
+
+ /**
+ * Default properties.
+ * @property {Object} defaultProps Default properties.
+ * @static
+ */
+ static defaultProps = {
+ items: [],
+ searchableText: null,
+ subject: null,
+ path: null,
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = { currentPage: 1 };
+ }
+
+ /**
+ * Component will mount
+ * @method componentWillMount
+ * @returns {undefined}
+ */
+ UNSAFE_componentWillMount() {
+ this.doSearch(
+ this.props.searchableText,
+ this.props.subject,
+ this.props.path,
+ );
+ }
+
+ /**
+ * Component will receive props
+ * @method componentWillReceiveProps
+ * @param {Object} nextProps Next properties
+ * @returns {undefined}
+ */
+ UNSAFE_componentWillReceiveProps = nextProps => {
+ if (
+ nextProps.searchableText !== this.props.searchableText ||
+ nextProps.subject !== this.props.subject
+ ) {
+ this.doSearch(
+ nextProps.searchableText,
+ nextProps.subject,
+ this.props.path,
+ );
+ }
+ };
+
+ /**
+ * Search based on the given searchableText, subject and path.
+ * @method doSearch
+ * @param {string} searchableText The searchable text string
+ * @param {string} subject The subject (tag)
+ * @param {string} path The path to restrict the search to
+ * @returns {undefined}
+ */
+
+ doSearch = (searchableText, subject, path) => {
+ this.setState({ currentPage: 1 });
+ this.props.searchContent(
+ '',
+ toSearchOptions(searchableText, subject, path),
+ );
+ };
+
+ handleQueryPaginationChange = (e, { activePage }) => {
+ window.scrollTo(0, 0);
+ this.setState({ currentPage: activePage }, () => {
+ const options = toSearchOptions(
+ qs.parse(this.props.location.search).SearchableText,
+ qs.parse(this.props.location.search).Subject,
+ qs.parse(this.props.location.search).path,
+ );
+
+ this.props.searchContent('', {
+ ...options,
+ b_start: (this.state.currentPage - 1) * settings.defaultPageSize,
+ });
+ });
+ };
+
+ getTitle = pathArray => {
+ let header = pathArray.slice(2, pathArray.length).join(' ');
+ return header
+ ? header.charAt(0).toUpperCase() + header.slice(1) + ' search result'
+ : null;
+ };
+
+ /**
+ * Render method.
+ * @method render
+ * @returns {string} Markup for the component.
+ */
+ render() {
+ return (
+
+
+
+
+
+
+ {this.props.items.map(item => (
+
+ {item.title}
+
+ {item['@type'] ? {item['@type']} : ''}
+ {item['effective'] ? (
+
+ {moment(item['effective']).format('DD.MM.YYYY')}
+
+ ) : (
+ ''
+ )}
+
+ {item.description && (
+
+ {item.description}
+
+ )}
+
+
+
+
+
+
+
+ ))}
+
+ {this.props.search?.batching && (
+
+
,
+ icon: true,
+ 'aria-disabled': !this.props.search.batching.prev,
+ className: !this.props.search.batching.prev
+ ? 'disabled'
+ : null,
+ }}
+ nextItem={{
+ content:
,
+ icon: true,
+ 'aria-disabled': !this.props.search.batching.next,
+ className: !this.props.search.batching.next
+ ? 'disabled'
+ : null,
+ }}
+ />
+
+ )}
+
+
+
+
+ }
+ />
+
+
+ );
+ }
+}
+
+export const __test__ = connect(
+ (state, props) => ({
+ items: state.search.items,
+ searchableText: qs.parse(props.location.search).SearchableText,
+ subject: qs.parse(props.location.search).Subject,
+ path: qs.parse(props.location.search).path,
+ pathname: props.location.pathname,
+ }),
+ { searchContent },
+)(Search);
+
+export default compose(
+ connect(
+ (state, props) => ({
+ items: state.search.items,
+ searchableText: qs.parse(props.location.search).SearchableText,
+ subject: qs.parse(props.location.search).Subject,
+ path: qs.parse(props.location.search).path,
+ pathname: props.location.pathname,
+ }),
+ { searchContent },
+ ),
+ asyncConnect([
+ {
+ key: 'search',
+ promise: ({ location, store: { dispatch } }) =>
+ dispatch(
+ searchContent(
+ '',
+ toSearchOptions(
+ qs.parse(location.search).SearchableText,
+ qs.parse(location.search).Subject,
+ qs.parse(location.search).path,
+ ),
+ ),
+ ),
+ },
+ ]),
+)(Search);
diff --git a/src/customizations/volto/components/theme/SearchWidget/SearchWidget.jsx b/src/customizations/volto/components/theme/SearchWidget/SearchWidget.jsx
index a4f3b6b9..f20726bc 100644
--- a/src/customizations/volto/components/theme/SearchWidget/SearchWidget.jsx
+++ b/src/customizations/volto/components/theme/SearchWidget/SearchWidget.jsx
@@ -9,9 +9,18 @@ import { Form, Input } from 'semantic-ui-react';
import { compose } from 'redux';
import { PropTypes } from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
+import { connect } from 'react-redux';
+import qs from 'query-string';
import { Icon } from '@plone/volto/components';
import zoomSVG from '@plone/volto/icons/zoom.svg';
+import clearSVG from '@plone/volto/icons/clear.svg';
+
+import { settings } from '~/config';
+import { quickResetSearchContent, quickSearchContent } from '~/actions';
+
+import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
+import Highlighter from 'react-highlight-words';
const messages = defineMessages({
search: {
@@ -37,6 +46,8 @@ class SearchWidget extends Component {
*/
static propTypes = {
pathname: PropTypes.string.isRequired,
+ quickResetSearchContent: PropTypes.func.isRequired,
+ quickSearchContent: PropTypes.func.isRequired,
};
/**
@@ -47,26 +58,54 @@ class SearchWidget extends Component {
*/
constructor(props) {
super(props);
- this.onChangeText = this.onChangeText.bind(this);
this.onChangeSection = this.onChangeSection.bind(this);
this.onSubmit = this.onSubmit.bind(this);
+ this.onChange = this.onChange.bind(this);
+ this.handleClickOutside = this.handleClickOutside.bind(this);
this.state = {
- text: '',
+ text: this.props.initialText || '',
section: false,
+ active: false,
+ pathname: '',
};
+ this.linkFormContainer = React.createRef();
}
- /**
- * On change text
- * @method onChangeText
- * @param {object} event Event object.
- * @param {string} value Text value.
- * @returns {undefined}
- */
- onChangeText(event, { value }) {
- this.setState({
- text: value,
- });
+ componentDidMount() {
+ this.props.quickResetSearchContent();
+ document.addEventListener('mousedown', this.handleClickOutside, false);
+ (this.props.pathname?.split('/')[1] === 'glossary' ||
+ this.props.path?.split('/')[2] === 'glossary') &&
+ this.setState({
+ pathname: '/glossary',
+ section: true,
+ });
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('mousedown', this.handleClickOutside, false);
+ }
+
+ handleClickOutside = e => {
+ if (
+ this.linkFormContainer.current &&
+ doesNodeContainClick(this.linkFormContainer.current, e)
+ ) {
+ this.setState({ active: true });
+ } else {
+ this.setState({ active: false });
+ }
+ };
+
+ onChange(event, { value }) {
+ if (value && value !== '') {
+ this.props.quickSearchContent(this.state.pathname, {
+ Title: `*${value}*`,
+ });
+ } else {
+ this.props.quickResetSearchContent();
+ }
+ this.setState({ text: value });
}
/**
@@ -82,6 +121,30 @@ class SearchWidget extends Component {
});
}
+ componentDidUpdate(prevProps) {
+ if (prevProps.location?.state?.text && this.props?.location?.state?.text) {
+ if (prevProps.location.state.text !== this.props.location.state.text) {
+ this.setState(
+ {
+ text: this.props?.location?.state?.text,
+ },
+ () => {
+ const section = this.state.section
+ ? `&path=${new URL(settings.apiPath).pathname +
+ this.state.pathname}`
+ : '';
+
+ this.props.history.push({
+ pathname: `/search`,
+ search: `?SearchableText=${this.state.text}${section}`,
+ state: { text: this.state.text, section: section },
+ });
+ },
+ );
+ }
+ }
+ }
+
/**
* Submit handler
* @method onSubmit
@@ -89,13 +152,33 @@ class SearchWidget extends Component {
* @returns {undefined}
*/
onSubmit(event) {
- const section = this.state.section ? `&path=${this.props.pathname}` : '';
- this.props.history.push(
- `/search?SearchableText=${this.state.text}${section}`,
- );
- event.preventDefault();
+ const section = this.state.section
+ ? `&path=${new URL(settings.apiPath).pathname + this.state.pathname}`
+ : '';
+ this.props.history.push({
+ pathname: `/search`,
+ search: `?SearchableText=${this.state.text}${section}`,
+ state: { text: this.state.text, section: section },
+ });
+ this.setState({ active: false });
+ event && event.preventDefault();
}
+ onSelectItem = item => {
+ this.setState(
+ {
+ text: item.title,
+ },
+ () => this.onSubmit(),
+ );
+ this.onClose();
+ };
+
+ onClose = () => {
+ this.props.quickResetSearchContent();
+ this.setState({ active: false });
+ };
+
/**
* Render method.
* @method render
@@ -103,25 +186,87 @@ class SearchWidget extends Component {
*/
render() {
return (
-
-
+
-
+
+
+
+
+ {this.state.text.length ? (
+
{
+ this.setState({
+ text: '',
+ });
+ this.onClose();
+ }}
+ />
+ ) : (
+ ''
+ )}
+ {this.state.active &&
+ this.props.search &&
+ this.props.search.length ? (
+
+ {this.props.search.map((item, index) => (
+ - this.onSelectItem(item)}
+ role="presentation"
+ >
+
+
+ ))}
+
+ ) : (
+ ''
+ )}
+
+
+
+
+
);
}
}
-export default compose(withRouter, injectIntl)(SearchWidget);
\ No newline at end of file
+export default compose(
+ withRouter,
+ injectIntl,
+ connect(
+ (state, props) => ({
+ search: state.quicksearch.items,
+ path: qs.parse(props.location.search).path,
+ }),
+ { quickResetSearchContent, quickSearchContent },
+ ),
+)(SearchWidget);
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 8ba4aec2..2c1aeef0 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -1,11 +1,13 @@
import defaultReducers from '@plone/volto/reducers';
import section_tabs from './section_tabs';
-import parent_folder_data from "./parent_folder_data"
+import parent_folder_data from './parent_folder_data';
+import quicksearch from './quicksearch';
const reducers = {
- section_tabs,
- parent_folder_data,
- ...defaultReducers
-}
+ section_tabs,
+ parent_folder_data,
+ quicksearch,
+ ...defaultReducers,
+};
-export default reducers
\ No newline at end of file
+export default reducers;
diff --git a/src/reducers/quicksearch.js b/src/reducers/quicksearch.js
new file mode 100644
index 00000000..3d9ad3bb
--- /dev/null
+++ b/src/reducers/quicksearch.js
@@ -0,0 +1,131 @@
+/**
+ * Search reducer.
+ * @module reducers/search/search
+ */
+
+import { map, omit } from 'lodash';
+import { settings } from '~/config';
+
+import {
+ QUICK_RESET_SEARCH_CONTENT,
+ QUICK_SEARCH_CONTENT,
+} from '~/constants/ActionTypes';
+
+const initialState = {
+ error: null,
+ items: [],
+ total: 0,
+ loaded: false,
+ loading: false,
+ batching: {},
+ subrequests: {},
+};
+
+/**
+ * Search reducer.
+ * @function search
+ * @param {Object} state Current state.
+ * @param {Object} action Action to be handled.
+ * @returns {Object} New state.
+ */
+export default function search(state = initialState, action = {}) {
+ switch (action.type) {
+ case `${QUICK_SEARCH_CONTENT}_PENDING`:
+ return action.subrequest
+ ? {
+ ...state,
+ subrequests: {
+ ...state.subrequests,
+ [action.subrequest]: {
+ ...(state.subrequests[action.subrequest] || {
+ items: [],
+ total: 0,
+ batching: {},
+ }),
+ error: null,
+ loaded: false,
+ loading: true,
+ },
+ },
+ }
+ : {
+ ...state,
+ error: null,
+ loading: true,
+ loaded: false,
+ };
+ case `${QUICK_SEARCH_CONTENT}_SUCCESS`:
+ return action.subrequest
+ ? {
+ ...state,
+ subrequests: {
+ ...state.subrequests,
+ [action.subrequest]: {
+ error: null,
+ items: map(action.result.items, item => ({
+ ...item,
+ '@id': item['@id'].replace(settings.apiPath, ''),
+ })),
+ total: action.result.items_total,
+ loaded: true,
+ loading: false,
+ batching: { ...action.result.batching },
+ },
+ },
+ }
+ : {
+ ...state,
+ error: null,
+ items: map(action.result.items, item => ({
+ ...item,
+ '@id': item['@id'].replace(settings.apiPath, ''),
+ })),
+ total: action.result.items_total,
+ loaded: true,
+ loading: false,
+ batching: { ...action.result.batching },
+ };
+ case `${QUICK_SEARCH_CONTENT}_FAIL`:
+ return action.subrequest
+ ? {
+ ...state,
+ subrequests: {
+ ...state.subrequests,
+ [action.subrequest]: {
+ error: action.error,
+ items: [],
+ total: 0,
+ loading: false,
+ loaded: false,
+ batching: {},
+ },
+ },
+ }
+ : {
+ ...state,
+ error: action.error,
+ items: [],
+ total: 0,
+ loading: false,
+ loaded: false,
+ batching: {},
+ };
+ case QUICK_RESET_SEARCH_CONTENT:
+ return action.subrequest
+ ? {
+ ...state,
+ subrequests: omit(state.subrequests, [action.subrequest]),
+ }
+ : {
+ ...state,
+ error: null,
+ items: [],
+ total: 0,
+ loading: false,
+ loaded: false,
+ batching: {},
+ };
+ default:
+ return state;
+ }
+}
\ No newline at end of file
diff --git a/src/routes.js b/src/routes.js
index 8010f116..2e4a58d1 100644
--- a/src/routes.js
+++ b/src/routes.js
@@ -8,7 +8,6 @@ import { defaultRoutes } from '@plone/volto/routes';
import { addonRoutes } from '~/config';
import BrowseView from '~/components/theme/View/BrowseView/BrowseView';
-
/**
* Routes array.
* @array
@@ -24,8 +23,6 @@ const routes = [
path: '/browse',
component: BrowseView,
},
-
-
// {
// path: '/',
// component: HomepageView,
diff --git a/theme/site/globals/site.overrides b/theme/site/globals/site.overrides
index 029825ec..7eff7899 100644
--- a/theme/site/globals/site.overrides
+++ b/theme/site/globals/site.overrides
@@ -737,4 +737,119 @@ p {
.block.maps iframe {
height: unset!important;
+}
+
+.floating_search_results {
+ position: absolute;
+ z-index: 98;
+ top: 100%;
+ width: 100%;
+ margin: 0;
+ list-style-type: none;
+ max-height: 264px;
+ overflow: auto;
+ margin: 0;
+ padding: 1rem;
+ padding-left: 4rem;
+ background: white;
+ color: #000;
+ border: 1px solid #EDEDED;
+ border-radius: 5px;
+ width: 100%;
+ -webkit-box-shadow: 0px 2px 4px -3px rgba(0,0,0,0.75);
+ -moz-box-shadow: 0px 2px 4px -3px rgba(0,0,0,0.75);
+ box-shadow: 0px 2px 4px -3px rgba(0,0,0.75);
+ li {
+ cursor: pointer;
+ font-size: .8rem;
+ line-height: 1.9;
+ margin-bottom: .5rem;
+ &:hover {
+ font-weight: bold;
+ }
+ }
+}
+
+.ui.form.searchform {
+ position: relative!important;
+}
+
+.glossary-search {
+ &.search-page {
+ margin: 0;
+ margin-bottom: 1rem;
+ width: 100%;
+ }
+
+ .searchbox {
+ padding: 0!important;
+ div.input {
+ padding: 0 4rem;
+ border: 1px solid #606060;
+ }
+
+ .icon {
+ fill: #606060!important;
+ position: absolute;
+ z-index: 1;
+ left: 1rem;
+ top: 50%;
+ transform: translateY(-50%);
+ }
+
+ .clear.icon {
+ left: unset;
+ right: 1rem;
+ cursor: pointer;
+ }
+ }
+}
+
+.search-meta {
+ margin-bottom: 3rem;
+ span {
+ color: #000;
+ margin-right: 2rem;
+ font-size: 0.9rem;
+ }
+}
+
+.bold {
+ font-weight: bold;
+}
+
+.ma-0 {
+ margin: 0!important;
+}
+
+#page-search header {
+ margin-top: 3rem;
+ .documentFirstHeading {
+ margin-bottom: 2rem;
+ }
+}
+
+button.outline {
+ background: transparent;
+ color: #000;
+ border: 1px solid #000;
+ padding: 0.6rem 2rem;
+ border-radius: 2rem;
+ cursor: pointer;
+ text-transform: uppercase;
+ &.dark-blue {
+ border: 1px solid #32536B;
+ &:hover {
+ background: #32536B;
+ color: #fff;
+ }
+ }
+ &:hover {
+ background: #000;
+ color: #fff;
+ }
+}
+
+button.dark-blue {
+ color: #32536B;
}
\ No newline at end of file