Skip to content

Commit

Permalink
Fix styling issues (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
rohit-gohri committed Mar 17, 2022
1 parent 0eff93b commit 70ced20
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/fifty-rockets-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'docusaurus-theme-redoc': patch
---

Fix nav sometimes hidden when logo is not present
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import clsx from 'clsx';
import { ThemeProvider } from 'styled-components';
import { SchemaDefinition } from 'redoc';
import { useSpec } from '../../hooks/useSpec';
import { useSpec } from '../../utils/useSpec';
import { useSpecData } from '../useSpecData';
import { ApiSchemaProps as Props } from '../../types/common';
import '../Redoc/styles.css';
Expand Down
11 changes: 7 additions & 4 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import clsx from 'clsx';
import { Redoc as RedocComponent } from 'redoc';
import { SpecProps } from '../../types/common';
import { useSpec } from '../../hooks/useSpec';
import { useSpec } from '../../utils/useSpec';
import { ServerStyles } from './Styles';
import './styles.css';

Expand All @@ -12,12 +13,14 @@ import './styles.css';
* Released under the MIT License
*/
function Redoc(props: SpecProps): JSX.Element {
const { store } = useSpec(props);
const { store, darkStore, lightStore, hasLogo } = useSpec(props);

return (
<>
<ServerStyles store={store} />
<div className="redocusaurus">
<ServerStyles lightStore={lightStore} darkStore={darkStore} />
<div
className={clsx(['redocusaurus', hasLogo && 'redocusaurus-has-logo'])}
>
<RedocComponent store={store} />
</div>
</>
Expand Down
97 changes: 87 additions & 10 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/ServerStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,94 @@ import { AppStore, Redoc } from 'redoc';
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';

export function ServerStyles({ store }: { store: AppStore }) {
const sheet = new ServerStyleSheet();
renderToString(sheet.collectStyles(React.createElement(Redoc, { store })));
const css = sheet.getStyleTags();
/**
* @see https://stackoverflow.com/a/54077142
*/
const prefixCssSelectors = function (rules: string, className: string) {
const classLen = className.length;
let char, nextChar, isAt, isIn;

// makes sure the className will not concatenate the selector
className += ' ';

// removes comments
rules = rules.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\/|[\r\n\t]+/g, '');

// makes sure nextChar will not target a space
rules = rules.replace(/}(\s*)@/g, '}@');
rules = rules.replace(/}(\s*)}/g, '}}');

for (let i = 0; i < rules.length - 2; i++) {
char = rules[i];
nextChar = rules[i + 1];

if (char === '@' && nextChar !== 'f') isAt = true;
if (!isAt && char === '{') isIn = true;
if (isIn && char === '}') isIn = false;

if (
!isIn &&
nextChar !== '@' &&
nextChar !== '}' &&
(char === '}' || char === ',' || ((char === '{' || char === ';') && isAt))
) {
rules = rules.slice(0, i + 1) + className + rules.slice(i + 1);
i += classLen;
isAt = false;
}
}

// prefix the first select if it is not `@media` and if it is not yet prefixed
if (rules.indexOf(className) !== 0 && rules.indexOf('@') !== 0)
rules = className + rules;

return rules;
};

const LIGHT_MODE_PREFIX = "html:not([data-theme='dark'])";
const DARK_MODE_PREFIX = "html([data-theme='dark'])";

export function ServerStyles({
lightStore,
darkStore,
}: {
lightStore: AppStore;
darkStore: AppStore;
}) {
const css = {
light: '',
dark: '',
};
const lightSheet = new ServerStyleSheet();
renderToString(
lightSheet.collectStyles(React.createElement(Redoc, { store: lightStore })),
);
const lightStyleTag = lightSheet.getStyleTags();
let lightCss = lightStyleTag.slice(lightStyleTag.indexOf('>') + 1);
lightCss = lightCss.slice(0, lightCss.indexOf('<style'));
css.light = prefixCssSelectors(lightCss, LIGHT_MODE_PREFIX);

const darkSheet = new ServerStyleSheet();
renderToString(
darkSheet.collectStyles(React.createElement(Redoc, { store: darkStore })),
);
const darkStyleTag = darkSheet.getStyleTags();
let darkCss = darkStyleTag.slice(darkStyleTag.indexOf('>') + 1);
darkCss = darkCss.slice(0, darkCss.indexOf('<style'));
css.dark = prefixCssSelectors(darkCss, DARK_MODE_PREFIX).slice(
DARK_MODE_PREFIX.length + 1,
);

return (
<div
className="redocusaurus-styles"
dangerouslySetInnerHTML={{
__html: css,
}}
/>
<div className="redocusaurus-styles">
<style
key="light-mode-styles"
dangerouslySetInnerHTML={{ __html: css.light }}
/>
<style
key="dark-mode-styles"
dangerouslySetInnerHTML={{ __html: css.dark }}
/>
</div>
);
}
14 changes: 10 additions & 4 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/Styles.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import React from 'react';
import type { AppStore } from 'redoc';

function ClientStyles(_props: { store: AppStore }) {
return null;
/**
* Don't hydrate/replace server styles
* @see https://github.com/facebook/react/issues/10923#issuecomment-338715787
*/
export function ServerStyles(_props: {
lightStore: AppStore;
darkStore: AppStore;
}) {
return <div className="redocusaurus-styles"></div>;
}

export { ClientStyles as ServerStyles };
11 changes: 9 additions & 2 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/styles.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.redocusaurus-styles {
display: none;
}

.redocusaurus .redoc-wrap {
border-bottom: 1px solid var(--ifm-toc-border-color);
}
Expand Down Expand Up @@ -33,8 +37,11 @@ html[data-theme='dark'] .redocusaurus h2 > a:nth-child(1)::before {
border-right: 1px solid var(--ifm-toc-border-color);
}

/* Hide Logo as already in navbar*/
.redocusaurus .menu-content div:first-child {
/**
* Hide Logo as already in navbar
* @see https://github.com/rohit-gohri/redocusaurus/issues/123
*/
.redocusaurus-has-logo .menu-content div:first-child {
display: none;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMemo } from 'react';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useIsBrowser from '@docusaurus/useIsBrowser';
import { usePluginData } from '@docusaurus/useGlobalData';
import { useColorMode } from '@docusaurus/theme-common';
import { AppStore, RedocRawOptions } from 'redoc';
Expand All @@ -14,28 +15,39 @@ import { GlobalData } from '../types/options';
*/
export function useSpec({ spec, url }: SpecProps) {
const fullUrl = useBaseUrl(url);
const isBrowser = useIsBrowser();
const { isDarkTheme } = useColorMode();
const themeOptions = usePluginData<GlobalData>('docusaurus-theme-redoc');

const result = useMemo(() => {
const { lightTheme, darkTheme, options: redocOptions } = themeOptions;
const theme = isDarkTheme ? darkTheme : lightTheme;

const options: RedocRawOptions = {
...redocOptions,
theme,
const commonOptions: Partial<RedocRawOptions> = {
// Disable offset when server rendering
scrollYOffset:
typeof window === 'undefined' ? 0 : redocOptions.scrollYOffset,
scrollYOffset: isBrowser ? redocOptions.scrollYOffset : 0,
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const store = new AppStore(spec as any, fullUrl, options);
const lightStore = new AppStore(spec as any, fullUrl, {
...redocOptions,
...commonOptions,
theme: lightTheme,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const darkStore = new AppStore(spec as any, fullUrl, {
...redocOptions,
...commonOptions,
theme: darkTheme,
});

return {
store,
options,
// @ts-expect-error extra prop
hasLogo: !!spec.info?.['x-logo'],
lightStore,
darkStore,
store: isBrowser && isDarkTheme ? darkStore : lightStore,
};
}, [spec, fullUrl, themeOptions, isDarkTheme]);
}, [isBrowser, spec, fullUrl, themeOptions, isDarkTheme]);

return result;
}

0 comments on commit 70ced20

Please sign in to comment.