Skip to content

Commit 3eb7f1a

Browse files
authored
Make search responsive + Current package search (#933)
## Issue #928 ## Changes - [x] Fix mobile design for search - [x] Add a row to allow search in current - [x] Hide form on search block, display just button `Search` - [x] Fix empty scope in search params ## Screenshot ### New row <img width="808" alt="image" src="https://github.com/user-attachments/assets/066885b1-0206-4617-aa7c-47fff282c2b6" /> ### New implementation of search block <img width="1131" alt="image" src="https://github.com/user-attachments/assets/b8602e92-262c-401d-ab86-fd68b25201f2" /> > ⚠️ HTML structure have been changed, this involves a build
1 parent a049d83 commit 3eb7f1a

File tree

56 files changed

+229
-254
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+229
-254
lines changed

packages/typo3-api/template/components/header.html.twig

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<option value="">Search all</option>
2525
</select>
2626
<input autocomplete="off" class="form-control shadow-none" id="globalsearchinput" name="q" placeholder="TYPO3 documentation..." type="text" value="">
27-
<button class="btn btn-light search__submit" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
27+
<button class="btn btn-light" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
2828
</div>
2929
</form>
3030
</search>

packages/typo3-docs-theme/assets/js/search.js

+12-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/typo3-docs-theme/assets/sass/components/_search.scss

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
background: transparent;
8181
padding: 0;
8282
flex-grow: 1;
83+
max-width: 100%;
84+
overflow: hidden;
85+
text-overflow: ellipsis;
86+
white-space: nowrap;
8387

8488
&:focus {
8589
outline: none;
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
.search__scope {
22
flex: .4 !important;
33
}
4-
.search__submit {
5-
&:hover {
6-
background: $gray-200;
7-
outline: 2px solid $secondary;
8-
}
9-
}
4+

packages/typo3-docs-theme/assets/sass/layout/_structure.scss

+2-9
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,9 @@
2929
.menu-search-wrapper {
3030
display: flex;
3131
align-items: center;
32+
justify-content: end;
3233
gap: 0.4em;
33-
34-
search {
35-
flex-grow: 1;
36-
}
37-
38-
@media screen and (max-width: 576px) {
39-
flex-direction: column;
40-
align-items: start;
41-
}
34+
height: 100%;
4235
}
4336

4437
/**

packages/typo3-docs-theme/resources/js/components/GlobalSearch.jsx

+17-28
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,28 @@
11
import React, { useEffect, useState } from 'react';
22
import SearchModal from './SearchModal';
33

4-
const GlobalSearch = () => {
4+
const GlobalSearch = ({ displayInput = false }) => {
55
const [isModalOpen, setIsModalOpen] = useState(false);
6+
const [searchQuery, setSearchQuery] = useState('');
67

7-
const handleInputClick = () => {
8-
setIsModalOpen(true);
9-
};
8+
useEffect(() => {
9+
const url = new URL(window.location.href);
10+
const queryParam = url.searchParams.get('q');
11+
if (queryParam) {
12+
setSearchQuery(queryParam);
13+
}
14+
}, []);
1015

1116
const handleButtonClick = (e) => {
1217
e.preventDefault();
1318
setIsModalOpen(true);
1419
};
1520

1621
useEffect(() => {
17-
let globalSearchInput = document.getElementById('globalsearchinput');
18-
let globalSearchButton = document.querySelector('#global-search-form button');
19-
20-
if (!globalSearchInput) {
21-
globalSearchInput = document.getElementById('searchinput');
22+
const form = document.getElementById('global-search-form');
23+
if (form) {
24+
form.hidden = true;
2225
}
23-
24-
if (globalSearchInput) {
25-
globalSearchInput.addEventListener('click', handleInputClick);
26-
}
27-
28-
if (globalSearchButton) {
29-
globalSearchButton.addEventListener('click', handleButtonClick);
30-
globalSearchButton.classList.add('here');
31-
}
32-
33-
return () => {
34-
if (globalSearchInput) {
35-
globalSearchInput.removeEventListener('click', handleInputClick);
36-
}
37-
if (globalSearchButton) {
38-
globalSearchButton.removeEventListener('click', handleButtonClick);
39-
globalSearchButton.classList.remove('here');
40-
}
41-
};
4226
}, []);
4327

4428
return (
@@ -47,6 +31,11 @@ const GlobalSearch = () => {
4731
isOpen={isModalOpen}
4832
onClose={() => setIsModalOpen(false)}
4933
/>}
34+
{displayInput ? <div class="input-group mb-3 mt-sm-3" onClick={handleButtonClick}>
35+
<input autocomplete="off" class="form-control shadow-none" id="globalsearchinput" name="q" placeholder="TYPO3 documentation..." type="text" value={searchQuery}></input>
36+
<button class="btn btn-light"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
37+
</div> :
38+
<button onClick={handleButtonClick} class="btn btn-light"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>}
5039
</>
5140
);
5241
};

packages/typo3-docs-theme/resources/js/components/SearchModal.jsx

+22-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import SuggestRow from './SuggestRow';
77
const SearchModal = ({ isOpen, onClose }) => {
88
const [searchQuery, setSearchQuery] = useState('');
99
const [scopes, setScopes] = useSearchScopes();
10+
const [currentScopes, setCurrentScopes] = useState([]);
1011
const [activeIndex, setActiveIndex] = useState(-1);
1112
const suggestionsRef = useRef([]);
1213
const inputRef = useRef();
@@ -20,6 +21,17 @@ const SearchModal = ({ isOpen, onClose }) => {
2021
fetchSuggestions
2122
} = useSearchSuggestions();
2223

24+
useEffect(() => {
25+
const select = document.getElementById('searchscope');
26+
const currentScopeValue = select?.children?.[1]?.value ?? null;
27+
if (currentScopeValue) {
28+
const packageName = currentScopeValue.split('/').slice(1, 3).join('/');
29+
const version = currentScopeValue.split('/').slice(3, 4)[0]?.split('.')[0];
30+
setCurrentScopes([{ type: 'manual', title: packageName, slug: packageName }, { type: 'version', title: version }]);
31+
}
32+
33+
}, []);
34+
2335
useEffect(() => {
2436
const url = new URL(window.location.href);
2537
const queryParam = url.searchParams.get('q');
@@ -88,9 +100,18 @@ const SearchModal = ({ isOpen, onClose }) => {
88100
tooltip: 'Search all',
89101
href: buildHref([], searchQuery)
90102
});
103+
104+
if (currentScopes.length > 0) {
105+
decomposed.push({
106+
scopes: currentScopes,
107+
title: searchQuery,
108+
tooltip: 'Search in current',
109+
href: buildHref(currentScopes, searchQuery)
110+
});
111+
}
91112
}
92113
return decomposed;
93-
}, [scopes, searchQuery, buildHref]);
114+
}, [scopes, searchQuery, buildHref, currentScopes]);
94115

95116
const handleScopeSelect = useCallback((title, type, slug) => {
96117
setScopes(prevScopes => {
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,28 @@
1-
import { useState, useEffect } from 'react';
1+
import { useEffect, useState } from 'react';
22

33
export const useSearchScopes = () => {
44
const [scopes, setScopes] = useState([]);
5-
const [currentScope, setCurrentScope] = useState(null);
6-
7-
useEffect(() => {
8-
const select = document.getElementById('searchscope');
9-
10-
const scope = (event) => {
11-
const slug = event.target.value.split('/').filter(Boolean).join('/');
12-
setCurrentScope(slug);
13-
};
14-
15-
select?.addEventListener('change', scope);
16-
setCurrentScope(select?.value);
17-
18-
return () => {
19-
select?.removeEventListener('change', scope);
20-
};
21-
}, []);
225

236
useEffect(() => {
247
const initialScopes = [];
25-
26-
if (currentScope) {
27-
const packageName = currentScope.split('/').slice(1, 3).join('/');
28-
const version = currentScope.split('/').slice(3, 4)[0]?.split('.')[0];
29-
initialScopes.push({ type: 'manual', title: packageName, slug: currentScope });
30-
initialScopes.push({ type: 'version', title: version });
31-
} else {
32-
const url = new URL(window.location.href);
33-
url.searchParams?.forEach((value, key) => {
34-
if (key === 'scope') {
35-
const slug = decodeURIComponent(value).split('/').filter(Boolean).join('/');
36-
const packageName = slug.split('/').slice(1, 3).join('/');
37-
initialScopes.push({ type: 'manual', title: packageName, slug });
38-
} else if (key.startsWith('filters[')) {
39-
const filterExp = new RegExp(/filters\[(.*?)\]\[(.*?)\]/);
40-
const [, type, filterValue] = key.match(filterExp);
41-
initialScopes.push({
42-
type: type === 'optionsaggs' ? 'option' : type,
43-
title: filterValue
44-
});
45-
}
46-
});
47-
}
8+
const url = new URL(window.location.href);
9+
url.searchParams?.forEach((value, key) => {
10+
if (key === 'scope' && value) {
11+
const slug = decodeURIComponent(value).split('/').filter(Boolean).join('/');
12+
const packageName = slug.split('/').slice(1, 3).join('/');
13+
initialScopes.push({ type: 'manual', title: packageName, slug });
14+
} else if (key.startsWith('filters[')) {
15+
const filterExp = new RegExp(/filters\[(.*?)\]\[(.*?)\]/);
16+
const [, type, filterValue] = key.match(filterExp);
17+
initialScopes.push({
18+
type: type === 'optionsaggs' ? 'option' : type,
19+
title: filterValue
20+
});
21+
}
22+
});
4823

4924
setScopes(initialScopes);
50-
}, [currentScope]);
25+
}, []);
5126

5227
return [scopes, setScopes];
5328
};

packages/typo3-docs-theme/resources/js/search.jsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ document.addEventListener('DOMContentLoaded', () => {
88
const container = document.getElementById('global-search-root');
99
if (container) {
1010
const root = createRoot(container);
11-
root.render(<GlobalSearch />);
11+
root.render(<GlobalSearch/>);
12+
}
13+
14+
const resultsContainer = document.getElementById('global-search-results');
15+
if (resultsContainer) {
16+
const root = createRoot(resultsContainer);
17+
root.render(<GlobalSearch displayInput={true} />);
1218
}
1319
});

packages/typo3-docs-theme/resources/public/css/theme.css

+6-14
Original file line numberDiff line numberDiff line change
@@ -27197,6 +27197,10 @@ figure.uml-diagram {
2719727197
background: transparent;
2719827198
padding: 0;
2719927199
flex-grow: 1;
27200+
max-width: 100%;
27201+
overflow: hidden;
27202+
text-overflow: ellipsis;
27203+
white-space: nowrap;
2720027204
}
2720127205
.search-modal__input:focus {
2720227206
outline: none;
@@ -28188,11 +28192,6 @@ header {
2818828192
flex: 0.4 !important;
2818928193
}
2819028194

28191-
.search__submit:hover {
28192-
background: rgb(242.25, 242.25, 242.25);
28193-
outline: 2px solid #333333;
28194-
}
28195-
2819628195
.page {
2819728196
display: flex;
2819828197
flex-direction: column;
@@ -28227,16 +28226,9 @@ header {
2822728226
.menu-search-wrapper {
2822828227
display: flex;
2822928228
align-items: center;
28229+
justify-content: end;
2823028230
gap: 0.4em;
28231-
}
28232-
.menu-search-wrapper search {
28233-
flex-grow: 1;
28234-
}
28235-
@media screen and (max-width: 576px) {
28236-
.menu-search-wrapper {
28237-
flex-direction: column;
28238-
align-items: start;
28239-
}
28231+
height: 100%;
2824028232
}
2824128233

2824228234
/**

packages/typo3-docs-theme/resources/public/js/theme.min.js

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/typo3-docs-theme/resources/template/structure/layoutParts/pageHeader.html.twig

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
<div class="page-header">
1010
<div class="page-header-inner">
1111
<div class="row">
12-
<div class="col-md-2 col-lg-4">
12+
<div class="col-2 col-lg-4">
1313
<a class="logo" href="https://docs.typo3.org/" title="TYPO3 Documentation">
1414
<img alt="TYPO3 Logo" class="logo-image" src="{{ getRelativePath('_resources/img/typo3-logo.svg') }}" width="484" height="130">
1515
</a>
1616
</div>
17-
<div class="col-md-10 col-lg-8">
17+
<div class="col-10 col-lg-8">
1818
<div class="menu-search-wrapper">
1919
{% if isRenderedForDeployment() -%}
2020
<all-documentations-menu></all-documentations-menu>
@@ -29,7 +29,7 @@
2929
<option value="">Search all</option>
3030
</select>
3131
<input autocomplete="off" class="form-control shadow-none" id="globalsearchinput" name="q" placeholder="TYPO3 documentation..." type="text" value="">
32-
<button class="btn btn-light search__submit" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
32+
<button class="btn btn-light" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
3333
</div>
3434
</form>
3535
<div id="global-search-root"></div>

tests/Integration/tests-full/breadcrumb/expected/index.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636
<div class="page-header">
3737
<div class="page-header-inner">
3838
<div class="row">
39-
<div class="col-md-2 col-lg-4">
39+
<div class="col-2 col-lg-4">
4040
<a class="logo" href="https://docs.typo3.org/" title="TYPO3 Documentation">
4141
<img alt="TYPO3 Logo" class="logo-image" src="_resources/img/typo3-logo.svg" width="484" height="130">
4242
</a>
4343
</div>
44-
<div class="col-md-10 col-lg-8">
44+
<div class="col-10 col-lg-8">
4545
<div class="menu-search-wrapper">
4646
<all-documentations-menu data-override-url="https://render-guides.ddev.site/_resources/js/menu-proxy.php"></all-documentations-menu>
4747
<search role="search">
@@ -52,7 +52,7 @@
5252
<option value="">Search all</option>
5353
</select>
5454
<input autocomplete="off" class="form-control shadow-none" id="globalsearchinput" name="q" placeholder="TYPO3 documentation..." type="text" value="">
55-
<button class="btn btn-light search__submit" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
55+
<button class="btn btn-light" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
5656
</div>
5757
</form>
5858
<div id="global-search-root"></div>

tests/Integration/tests-full/breadcrumb/expected/page.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@
3737
<div class="page-header">
3838
<div class="page-header-inner">
3939
<div class="row">
40-
<div class="col-md-2 col-lg-4">
40+
<div class="col-2 col-lg-4">
4141
<a class="logo" href="https://docs.typo3.org/" title="TYPO3 Documentation">
4242
<img alt="TYPO3 Logo" class="logo-image" src="_resources/img/typo3-logo.svg" width="484" height="130">
4343
</a>
4444
</div>
45-
<div class="col-md-10 col-lg-8">
45+
<div class="col-10 col-lg-8">
4646
<div class="menu-search-wrapper">
4747
<all-documentations-menu data-override-url="https://render-guides.ddev.site/_resources/js/menu-proxy.php"></all-documentations-menu>
4848
<search role="search">
@@ -53,7 +53,7 @@
5353
<option value="">Search all</option>
5454
</select>
5555
<input autocomplete="off" class="form-control shadow-none" id="globalsearchinput" name="q" placeholder="TYPO3 documentation..." type="text" value="">
56-
<button class="btn btn-light search__submit" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
56+
<button class="btn btn-light" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
5757
</div>
5858
</form>
5959
<div id="global-search-root"></div>

tests/Integration/tests-full/breadcrumb/expected/yetAnotherPage.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636
<div class="page-header">
3737
<div class="page-header-inner">
3838
<div class="row">
39-
<div class="col-md-2 col-lg-4">
39+
<div class="col-2 col-lg-4">
4040
<a class="logo" href="https://docs.typo3.org/" title="TYPO3 Documentation">
4141
<img alt="TYPO3 Logo" class="logo-image" src="_resources/img/typo3-logo.svg" width="484" height="130">
4242
</a>
4343
</div>
44-
<div class="col-md-10 col-lg-8">
44+
<div class="col-10 col-lg-8">
4545
<div class="menu-search-wrapper">
4646
<all-documentations-menu data-override-url="https://render-guides.ddev.site/_resources/js/menu-proxy.php"></all-documentations-menu>
4747
<search role="search">
@@ -52,7 +52,7 @@
5252
<option value="">Search all</option>
5353
</select>
5454
<input autocomplete="off" class="form-control shadow-none" id="globalsearchinput" name="q" placeholder="TYPO3 documentation..." type="text" value="">
55-
<button class="btn btn-light search__submit" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
55+
<button class="btn btn-light" type="submit"><i class="fa fa-search"></i>&nbsp;<span class="d-none d-md-inline">Search</span></button>
5656
</div>
5757
</form>
5858
<div id="global-search-root"></div>

0 commit comments

Comments
 (0)