Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c76e36f

Browse filesBrowse files
committed
docs: improve layout
1 parent 7ad6008 commit c76e36f
Copy full SHA for c76e36f

14 files changed

+284
-161
lines changed
+116Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import React, { forwardRef, HTMLAttributes, useMemo, useRef } from 'react'
2+
import { Link } from 'gatsby'
3+
import { CContainer, CNav, CNavItem, CNavLink } from '@coreui/react'
4+
import useStickyObserver from '../hooks/useStickyObserver' // Adjust the path as needed
5+
6+
type Fields = {
7+
slug: string
8+
}
9+
10+
type Node = {
11+
id: string
12+
fields: Fields
13+
}
14+
15+
export interface Item {
16+
node: Node
17+
}
18+
19+
export interface ComponentSubNavProps extends HTMLAttributes<HTMLDivElement> {
20+
nodes: Item[]
21+
}
22+
23+
const findShortestSlug = (items: Item[]): string | undefined => {
24+
if (items.length === 0) {
25+
return undefined
26+
}
27+
28+
let shortestSlug = items[0].node.fields.slug
29+
30+
for (const item of items) {
31+
const currentSlug = item.node.fields.slug
32+
if (currentSlug.length < shortestSlug.length) {
33+
shortestSlug = currentSlug
34+
}
35+
}
36+
37+
return shortestSlug
38+
}
39+
40+
const ComponentSubNav = forwardRef<HTMLDivElement, ComponentSubNavProps>(
41+
({ nodes, ...rest }, ref) => {
42+
const parentPathname = findShortestSlug(nodes)
43+
const hasNavAccessibility = useMemo(
44+
() => nodes.some((edge) => edge.node.fields.slug.includes('accessibility')),
45+
[nodes],
46+
)
47+
const hasNavAPI = useMemo(
48+
() => nodes.some((edge) => edge.node.fields.slug.includes('api')),
49+
[nodes],
50+
)
51+
const hasNavStyling = useMemo(
52+
() => nodes.some((edge) => edge.node.fields.slug.includes('styling')),
53+
[nodes],
54+
)
55+
56+
// Ref for the sentinel element
57+
const sentinelRef = useRef<HTMLDivElement>(null)
58+
59+
// Use the custom hook to track sticky state
60+
const isSticky = useStickyObserver(sentinelRef)
61+
62+
return (
63+
<>
64+
<div ref={sentinelRef} style={{ height: '1px' }} />
65+
<div
66+
className={`component-sub-nav-wrapper bg-body position-sticky z-3 ${isSticky ? 'sticky shadow-sm' : ''}`}
67+
ref={ref}
68+
{...rest}
69+
>
70+
<CContainer lg className="px-3 px-sm-4">
71+
<CNav
72+
className="docs-nav component-sub-nav"
73+
variant="underline-border"
74+
role={undefined}
75+
>
76+
<CNavItem>
77+
<CNavLink as={Link} to={parentPathname} activeClassName="active">
78+
Features
79+
</CNavLink>
80+
</CNavItem>
81+
{hasNavAPI && (
82+
<CNavItem>
83+
<CNavLink as={Link} to={`${parentPathname}api/`} activeClassName="active">
84+
API
85+
</CNavLink>
86+
</CNavItem>
87+
)}
88+
{hasNavStyling && (
89+
<CNavItem>
90+
<CNavLink as={Link} to={`${parentPathname}styling/`} activeClassName="active">
91+
Styling
92+
</CNavLink>
93+
</CNavItem>
94+
)}
95+
{hasNavAccessibility && (
96+
<CNavItem>
97+
<CNavLink
98+
as={Link}
99+
to={`${parentPathname}accessibility/`}
100+
activeClassName="active"
101+
>
102+
Accessibility
103+
</CNavLink>
104+
</CNavItem>
105+
)}
106+
</CNav>
107+
</CContainer>
108+
</div>
109+
</>
110+
)
111+
},
112+
)
113+
114+
ComponentSubNav.displayName = 'ComponentSubNav'
115+
116+
export default ComponentSubNav

‎packages/docs/src/components/ExampleSnippet.tsx

Copy file name to clipboardExpand all lines: packages/docs/src/components/ExampleSnippet.tsx
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ const ExampleSnippet: FC<ExampleSnippetProps> = ({
122122
)}
123123
</div>
124124
<div className="highlight-toolbar border-top">
125-
<CNav className="px-3" variant="underline-border">
125+
<CNav as="div" className="px-3" variant="underline-border" role={undefined}>
126126
{showJSTab && (
127127
<CNavLink as="button" active={language === 'js'} onClick={() => setLanguage('js')}>
128128
JavaScript

‎packages/docs/src/components/Footer.tsx

Copy file name to clipboardExpand all lines: packages/docs/src/components/Footer.tsx
+11-20Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,21 @@ import pkg from './../../package.json'
77

88
const Footer: FC = () => {
99
return (
10-
<CFooter className="docs-footer p-3 p-md-5 mt-5 text-center text-sm-start">
11-
<CContainer>
12-
<ul className="docs-footer-links ps-0 mb-3">
13-
<li className="d-inline-block">
14-
<a href="https://github.com/coreui">GitHub</a>
15-
</li>
16-
<li className="d-inline-block ms-3">
17-
<a href="https://twitter.com/core_ui">Twitter</a>
18-
</li>
19-
<li className="d-inline-block ms-3 ps-3 border-start border-2">
20-
<a href="https://coreui.io/">CoreUI (Vanilla)</a>
21-
</li>
22-
<li className="d-inline-block ms-3">
23-
<a href="https://coreui.io/angular/">CoreUI for Angular</a>
24-
</li>
25-
<li className="d-inline-block ms-3">
26-
<a href="https://coreui.io/vue/">CoreUI for Vue.js</a>
27-
</li>
28-
</ul>
10+
<CFooter className="docs-footer py-md-5 mt-5 text-center text-sm-start">
11+
<CContainer lg className="px-4">
12+
<div className="docs-footer-links mb-3 d-flex flex-column flex-sm-row gap-3">
13+
<a href="https://github.com/coreui">GitHub</a>
14+
<a href="https://twitter.com/core_ui">Twitter</a>
15+
<span className="border-start border-start-2 d-none d-sm-flex"></span>
16+
<a href="https://coreui.io/bootstrap/">CoreUI (Vanilla)</a>
17+
<a href="https://coreui.io/angular/">CoreUI for Angular</a>
18+
<a href="https://coreui.io/vue/">CoreUI for Vue.js</a>
19+
</div>
2920
<p className="mb-0">CoreUI for React is Open Source UI Components Library for React.js.</p>
3021
<p className="mb-0">
3122
Currently v{pkg.version}. CoreUI code licensed{' '}
3223
<a
33-
href="https://github.com/coreui/coreui/blob/main/LICENSE"
24+
href="https://github.com/coreui/coreui-react/blob/main/LICENSE"
3425
target="_blank"
3526
rel="noreferrer"
3627
>

‎packages/docs/src/components/Header.tsx

Copy file name to clipboardExpand all lines: packages/docs/src/components/Header.tsx
+6-8Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FC } from 'react'
1+
import React, { forwardRef } from 'react'
22
import { DocSearch } from '@docsearch/react'
33

44
import CIcon from '@coreui/icons-react'
@@ -28,13 +28,13 @@ import {
2828
} from '@coreui/react/src'
2929
import { AppContext } from './../AppContext'
3030

31-
const Header: FC = () => {
31+
const Header = forwardRef<HTMLDivElement>(({}, ref) => {
3232
const { colorMode, setColorMode } = useColorModes('coreui-react-docs-theme')
3333
return (
3434
<>
3535
<AppContext.Consumer>
3636
{(context) => (
37-
<CHeader className="mb-5" position="sticky">
37+
<CHeader className="mb-5" position="sticky" ref={ref}>
3838
<CHeaderToggler
3939
className="ms-md-3"
4040
aria-label="Close"
@@ -49,8 +49,7 @@ const Header: FC = () => {
4949
indexName="coreui-react"
5050
apiKey="6e3f7692d2589d042bb40426b75df1b7"
5151
/>
52-
{/* <div className="docs-search" id="docsearch"></div> */}
53-
<CHeaderNav className="ms-auto">
52+
<CHeaderNav className="ms-auto" role={undefined}>
5453
<CNavItem
5554
href="https://github.com/coreui/coreui-react/"
5655
aria-label="Visit our GitHub"
@@ -70,9 +69,8 @@ const Header: FC = () => {
7069
<div className="vr d-none d-lg-flex h-100 mx-lg-2 text-body text-opacity-75"></div>
7170
<hr className="d-lg-none my-2 text-white-50" />
7271
</li>
73-
<CDropdown placement="bottom-end">
72+
<CDropdown placement="bottom-end" variant="nav-item">
7473
<CDropdownToggle
75-
className="nav-link"
7674
color="link"
7775
caret={false}
7876
aria-label="Light/Dark mode switch"
@@ -148,7 +146,7 @@ const Header: FC = () => {
148146
</AppContext.Consumer>
149147
</>
150148
)
151-
}
149+
})
152150

153151
Header.displayName = 'Header'
154152

‎packages/docs/src/components/Sidebar.tsx

Copy file name to clipboardExpand all lines: packages/docs/src/components/Sidebar.tsx
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { FC } from 'react'
2+
import { Link } from 'gatsby'
23

34
import {
45
CDropdown,
@@ -27,7 +28,12 @@ const Sidebar: FC = () => {
2728
context.setSidebarVisible && context.setSidebarVisible(value)
2829
}
2930
>
30-
<CSidebarBrand className="justify-content-start ps-3">
31+
<CSidebarBrand
32+
as={Link}
33+
className="justify-content-start ps-3"
34+
to="/"
35+
aria-label="Go to CoreUI for React.js documentation"
36+
>
3137
<svg
3238
xmlns="http://www.w3.org/2000/svg"
3339
viewBox="0 0 615 134"

‎packages/docs/src/components/Toc.tsx

Copy file name to clipboardExpand all lines: packages/docs/src/components/Toc.tsx
+13-7Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FC, useState } from 'react'
1+
import React, { forwardRef, useState } from 'react'
22
import { CCollapse, CNav } from '@coreui/react/src/index'
33

44
export type TocItem = {
@@ -32,12 +32,16 @@ const toc = (items: TocItem[]) => {
3232
)
3333
}
3434

35-
const Toc: FC<TocProps> = ({ items }) => {
35+
const Toc = forwardRef<HTMLDivElement, TocProps>(({ items, ...rest }, ref) => {
3636
const [visible, setVisible] = useState(false)
3737
return (
38-
<div className="docs-toc mt-4 mb-5 my-md-0 ps-xl-5 mb-lg-5 text-body-secondary">
38+
<div
39+
className="docs-toc mt-4 mb-5 my-lg-0 ps-xl-5 mb-lg-5 text-body-secondary"
40+
ref={ref}
41+
{...rest}
42+
>
3943
<button
40-
className="btn btn-link p-md-0 mb-2 mb-md-0 text-decoration-none docs-toc-toggle d-md-none"
44+
className="btn btn-link p-lg-0 mb-2 mb-lg-0 text-decoration-none docs-toc-toggle d-lg-none"
4145
type="button"
4246
aria-expanded={visible ? true : false}
4347
aria-controls="tocContents"
@@ -46,7 +50,7 @@ const Toc: FC<TocProps> = ({ items }) => {
4650
On this page
4751
<svg
4852
xmlns="http://www.w3.org/2000/svg"
49-
className="icon d-md-none ms-2"
53+
className="icon d-lg-none ms-2"
5054
aria-hidden="true"
5155
viewBox="0 0 512 512"
5256
>
@@ -57,14 +61,16 @@ const Toc: FC<TocProps> = ({ items }) => {
5761
/>
5862
</svg>
5963
</button>
60-
<strong className="d-none d-md-block h6 mb-2 pb-2 border-bottom">On this page</strong>
64+
<strong className="d-none d-lg-block h6 mb-2 pb-2 border-bottom">On this page</strong>
6165
<CCollapse className="docs-toc-collapse" id="tocContents" visible={visible}>
6266
<CNav as="nav">
6367
<ul>{toc(items)}</ul>
6468
</CNav>
6569
</CCollapse>
6670
</div>
6771
)
68-
}
72+
})
73+
74+
Toc.displayName = 'Toc'
6975

7076
export default Toc

‎packages/docs/src/components/index.ts

Copy file name to clipboardExpand all lines: packages/docs/src/components/index.ts
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Banner from './Banner'
33
import Callout from './Callout'
44
import CodeBlock from './CodeBlock'
55
import ClassNamesDocs from './ClassNamesDocs'
6+
import ComponentSubNav from './ComponentSubNav'
67
import Example from './Example'
78
import ExampleSnippet from './ExampleSnippet'
89
import Footer from './Footer'
@@ -20,6 +21,7 @@ export {
2021
Callout,
2122
CodeBlock,
2223
ClassNamesDocs,
24+
ComponentSubNav,
2325
Example,
2426
ExampleSnippet,
2527
Footer,
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { useEffect, useState, RefObject } from 'react'
2+
3+
const useStickyObserver = (
4+
sentinelRef: RefObject<HTMLElement>,
5+
options?: IntersectionObserverInit,
6+
): boolean => {
7+
const [isSticky, setIsSticky] = useState(false)
8+
9+
useEffect(() => {
10+
const sentinel = sentinelRef.current
11+
if (!sentinel) return
12+
13+
const observerOptions = options || {
14+
root: null,
15+
rootMargin: '0px',
16+
threshold: 0,
17+
}
18+
19+
const observerCallback: IntersectionObserverCallback = (entries) => {
20+
entries.forEach((entry) => {
21+
setIsSticky(!entry.isIntersecting)
22+
})
23+
}
24+
25+
const observer = new IntersectionObserver(observerCallback, observerOptions)
26+
observer.observe(sentinel)
27+
28+
return () => {
29+
observer.unobserve(sentinel)
30+
}
31+
}, [sentinelRef, options])
32+
33+
return isSticky
34+
}
35+
36+
export default useStickyObserver
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.component-sub-nav-wrapper {
2+
@include transition(box-shadow 0.2s linear);
3+
&:before {
4+
position: absolute;
5+
z-index: -1;
6+
content: '';
7+
right: 0;
8+
bottom: 0;
9+
left: 0;
10+
height: 2px;
11+
width: 90%;
12+
max-width: 1140px;
13+
margin: 0 auto;
14+
background: var(--cui-border-color);
15+
@include transition(max-width .2s ease-in-out, width .2s ease-in-out);
16+
}
17+
18+
.component-sub-nav {
19+
.nav-link {
20+
@include transition(padding .2s linear);
21+
}
22+
}
23+
24+
&.sticky {
25+
&::before {
26+
width: 100%;
27+
max-width: 100%;
28+
}
29+
30+
.component-sub-nav {
31+
.nav-link {
32+
--cui-nav-underline-border-link-padding-y: .75rem;
33+
}
34+
}
35+
}
36+
}

‎packages/docs/src/styles/_footer.scss

Copy file name to clipboardExpand all lines: packages/docs/src/styles/_footer.scss
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
@include font-size(.875rem);
88

99
a {
10-
color: var(--#{$prefix}tertiary-color);
11-
text-decoration: none;
10+
color: var(--#{$prefix}secondary-color);
11+
// text-decoration: none;
1212

1313
&:hover,
1414
&:focus {
1515
color: var(--cui-link-hover-color);
16-
text-decoration: underline;
1716
}
1817
}
1918
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.