Skip to content

Commit

Permalink
Merge pull request #145 from rsksmart/feat/search-and-tag-page
Browse files Browse the repository at this point in the history
Search page and Single Tag page redesign
  • Loading branch information
owans authored Nov 7, 2024
2 parents 9f0fb12 + 3ade2c9 commit db9e6d9
Show file tree
Hide file tree
Showing 7 changed files with 798 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/scss/base/_forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ label {
box-shadow: none;
background: var(--rsk-input-focus-bg, #1A1A1A);
}

&--xl{
--rsk-input-focus-bg: var(--bs-body-bg);
--rsk-input-bg: var(--bs-body-bg);
font: 400 #{$f20}/1.2 $font-family-base;
padding: 14px 24px;
border-radius: 28px;
letter-spacing: 0.01em;
}
}

.form-select {
Expand Down
6 changes: 6 additions & 0 deletions src/scss/base/_theme-variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ html:root {
--ifm-color-primary-lighter: #359962;
--ifm-color-primary-lightest: #3cad6e;
--ifm-code-font-size: 95%;
--ifm-color-content-secondary: #{$gray-600};

--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);

//Search
Expand Down Expand Up @@ -252,6 +254,9 @@ html:root {
--rsk-input-placeholder-color: #{$gray-550};
--rsk-input-border-color-focus: var(--bs-primary);
--rsk-input-focus-bg: #{$gray-100};

//Highlight
--bs-highlight-bg: #{$yellow};
}


Expand All @@ -278,6 +283,7 @@ html:root {
--ifm-color-primary-light: #29d5b0;
--ifm-color-primary-lighter: #32d8b4;
--ifm-color-primary-lightest: #4fddbf;
--ifm-color-content-secondary: #{$gray-500};
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);

--bs-body-color: var(--bs-white);
Expand Down
3 changes: 3 additions & 0 deletions src/scss/base/_typography.scss
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,6 @@ h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
.badge{
letter-spacing: 0.05em;
}
.text-purple{
color: var(--bs-purple);
}
179 changes: 179 additions & 0 deletions src/theme/DocTagDocListPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import React, { useState } from 'react'
import clsx from 'clsx'
import Link from '@docusaurus/Link'
import {
PageMetadata,
HtmlClassNameProvider,
ThemeClassNames,
usePluralForm,
} from '@docusaurus/theme-common'
import Translate, { translate } from '@docusaurus/Translate'
import SearchMetadata from '@theme/SearchMetadata'
import Unlisted from '@theme/Unlisted'
import Heading from '@theme/Heading'
import Button from '../../components/Button'
import { useHistory } from 'react-router-dom'

// Very simple pluralization: probably good enough for now
function useNDocsTaggedPlural () {
const { selectMessage } = usePluralForm()
return (count) =>
selectMessage(
count,
translate(
{
id: 'theme.docs.tagDocListPageTitle.nDocsTagged',
description:
'Pluralized label for "{count} docs tagged". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
message: 'One doc tagged|{count} docs tagged',
},
{ count },
),
)
}

function usePageTitle (props) {
const nDocsTaggedPlural = useNDocsTaggedPlural()
return translate(
{
id: 'theme.docs.tagDocListPageTitle',
description: 'The title of the page for a docs tag',
message: '{nDocsTagged} with "{tagName}"',
},
{ nDocsTagged: nDocsTaggedPlural(props.tag.count), tagName: props.tag.label },
)
}

function DocItem ({ doc, searchQuery }) {
const highlightText = (text, query) => {
if (!query) return text
const parts = text.split(new RegExp(`(${query})`, 'gi'))
return parts.map((part, index) =>
part.toLowerCase() === query.toLowerCase() ? <mark key={index}>{part}</mark> : part
)
}
return (
<article className="py-14 border-bottom border-gray-600 d-flex gap-12 gap-lg-24 flex-column flex-lg-row">
<div className="d-flex gap-12 align-items-stretch col-lg-5 align-self-lg-start">
<svg width="24" height="24" className="text-purple flex-shrink-0">
<use xlinkHref="#icon-doc"/>
</svg>
<div className="d-flex align-items-center">
<Link to={doc.permalink}>
<Heading as="h2" className="m-0 link-base fs-14 fw-medium lh-base">
{highlightText(doc.title, searchQuery)}
</Heading>
</Link>
</div>
</div>
{doc.description &&
<div className="d-flex align-items-center">
<p className="m-0 text-body opacity-75 fs-14">{doc.description}</p>
</div>
}
</article>
)
}

function DocTagDocListPageMetadata ({ title, tag }) {
return (
<>
<PageMetadata title={title} description={tag.description}/>
<SearchMetadata tag="doc_tag_doc_list"/>
</>
)
}

function SearchBar ({ onSearch }) {
const [query, setQuery] = useState('')

const handleInputChange = (e) => {
const value = e.target.value
setQuery(value)
onSearch(value)
}

return (
<div className="d-flex mb-24 position-relative">
<input
type="text"
value={query}
onChange={handleInputChange}
placeholder="Search documents..."
className="form-control form-control--xl form-control-lg ps-56"
/>
<svg width={20} height={20} className="text-body opacity-75 position-absolute start-0 top-50 translate-middle-y ms-20 pe-none">
<use xlinkHref="#icon-search"/>
</svg>
</div>
)
}

function DocTagDocListPageContent ({ tag, title }) {
const [filteredItems, setFilteredItems] = useState(tag.items)
const [query, setQuery] = useState('')

let history = useHistory()

const handleSearch = (query) => {
const filtered = tag.items.filter((doc) =>
doc.title.toLowerCase().includes(query.toLowerCase())
)
setQuery(query)
setFilteredItems(filtered)
}
return (
<HtmlClassNameProvider
className={clsx(ThemeClassNames.page.docsTagDocListPage)}>
<main>
{tag.unlisted && <Unlisted/>}
<header className="mb-24">
<div className="d-flex flex-column flex-md-row gap-24 align-items-start align-items-md-center mb-24">
<Button size={'sm'} className={`px-12 py-3`} onClick={() => history.goBack()}>
<svg width={24} height={24}>
<use xlinkHref="#icon-arrow-l"/>
</svg>
<span className="visually-hidden">
<Translate
id="theme.common.back">
Back
</Translate>
</span>
</Button>

<Heading as="h1" className="m-0">{title}</Heading>
</div>

{tag.description && <p>{tag.description}</p>}
</header>
<SearchBar onSearch={handleSearch}/>
{filteredItems.length > 0 ? (
<section className="border-top border-gray-600">
{filteredItems.map((doc) => (
<DocItem key={doc.id} doc={doc} searchQuery={query}/>
))}
</section>
) : (
<p>
<Translate
id="theme.SearchPage.noResultsText"
description="The paragraph for empty search result">
No results were found
</Translate>
</p>
)}
</main>
</HtmlClassNameProvider>
)

}

export default function DocTagDocListPage (props) {
const title = usePageTitle(props)
return (
<>
<DocTagDocListPageMetadata {...props} title={title}/>
<DocTagDocListPageContent {...props} title={title}/>
</>
)
}
8 changes: 7 additions & 1 deletion src/theme/Layout/SVGSprite/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit db9e6d9

Please sign in to comment.