forked from sombochea/verdaccio-ui
feat(style): added dark mode (#446)
This commit is contained in:
parent
91434cc814
commit
cdad5cf70d
@ -133,6 +133,7 @@
|
|||||||
"sorry-we-could-not-find-it": "Entschuldigung, wir konnten es nicht finden..."
|
"sorry-we-could-not-find-it": "Entschuldigung, wir konnten es nicht finden..."
|
||||||
},
|
},
|
||||||
"app-context-not-correct-used": "Der App-Kontext wurde nicht korrekt verwendet",
|
"app-context-not-correct-used": "Der App-Kontext wurde nicht korrekt verwendet",
|
||||||
|
"theme-context-not-correct-used": "Der Theme-Kontext wurde nicht korrekt verwendet",
|
||||||
"package-meta-is-required-at-detail-context": "packageMeta wird bei DetailContext benötigt"
|
"package-meta-is-required-at-detail-context": "packageMeta wird bei DetailContext benötigt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,7 @@
|
|||||||
"sorry-we-could-not-find-it": "Sorry, we couldn't find it..."
|
"sorry-we-could-not-find-it": "Sorry, we couldn't find it..."
|
||||||
},
|
},
|
||||||
"app-context-not-correct-used": "The app context was not correct used",
|
"app-context-not-correct-used": "The app context was not correct used",
|
||||||
|
"theme-context-not-correct-used": "The theme context was not correct used",
|
||||||
"package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext"
|
"package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -133,6 +133,7 @@
|
|||||||
"sorry-we-could-not-find-it": "Lo siento, no hemos podido encontrarlo..."
|
"sorry-we-could-not-find-it": "Lo siento, no hemos podido encontrarlo..."
|
||||||
},
|
},
|
||||||
"app-context-not-correct-used": "El contexto de la aplicación no fue correctamente usado",
|
"app-context-not-correct-used": "El contexto de la aplicación no fue correctamente usado",
|
||||||
|
"theme-context-not-correct-used": "El contexto del tema no fue correctamente usado",
|
||||||
"package-meta-is-required-at-detail-context": "packageMeta es requerido en DetailContext"
|
"package-meta-is-required-at-detail-context": "packageMeta es requerido en DetailContext"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,7 @@
|
|||||||
"sorry-we-could-not-find-it": "Desculpe, não conseguimos encontrar..."
|
"sorry-we-could-not-find-it": "Desculpe, não conseguimos encontrar..."
|
||||||
},
|
},
|
||||||
"app-context-not-correct-used": "O contexto do aplicativo não foi usado corretamente",
|
"app-context-not-correct-used": "O contexto do aplicativo não foi usado corretamente",
|
||||||
|
"theme-context-not-correct-used": "O contexto do tema não foi usado corretamente",
|
||||||
"package-meta-is-required-at-detail-context": "packageMeta é requerido em DetailContext"
|
"package-meta-is-required-at-detail-context": "packageMeta é requerido em DetailContext"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,7 +19,7 @@ import AppRoute, { history } from './AppRoute';
|
|||||||
import loadDayJSLocale from './load-dayjs-locale';
|
import loadDayJSLocale from './load-dayjs-locale';
|
||||||
|
|
||||||
const StyledBox = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
const StyledBox = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
backgroundColor: theme && theme.palette.white,
|
backgroundColor: theme?.palette.background.default,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledBoxContent = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
const StyledBoxContent = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
|
@ -522,6 +522,30 @@ exports[`<App /> should display the Header component 1`] = `
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit"
|
||||||
|
tabindex="0"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
|
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
|
||||||
data-testid="header--button-login"
|
data-testid="header--button-login"
|
||||||
@ -1176,6 +1200,30 @@ exports[`<App /> should display the Loading component at the beginning 1`] = `
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit"
|
||||||
|
tabindex="0"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
|
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
|
||||||
data-testid="header--button-login"
|
data-testid="header--button-login"
|
||||||
|
@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { default as MuiTabs } from '../../muiComponents/Tabs';
|
import { default as MuiTabs } from '../../muiComponents/Tabs';
|
||||||
import Tab from '../../muiComponents/Tab';
|
import Tab from '../../muiComponents/Tab';
|
||||||
|
import { Theme } from '../../design-tokens/theme';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onChange: (event, newValue) => void;
|
onChange: (event, newValue) => void;
|
||||||
@ -14,12 +15,7 @@ const DetailContainerTabs: React.FC<Props> = ({ tabPosition, onChange }) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs color={'primary'} indicatorColor={'primary'} onChange={onChange} value={tabPosition} variant={'fullWidth'}>
|
||||||
indicatorColor={'primary'}
|
|
||||||
onChange={onChange}
|
|
||||||
textColor={'primary'}
|
|
||||||
value={tabPosition}
|
|
||||||
variant={'fullWidth'}>
|
|
||||||
<Tab data-testid={'readme-tab'} id={'readme-tab'} label={t('tab.readme')} />
|
<Tab data-testid={'readme-tab'} id={'readme-tab'} label={t('tab.readme')} />
|
||||||
<Tab data-testid={'dependencies-tab'} id={'dependencies-tab'} label={t('tab.dependencies')} />
|
<Tab data-testid={'dependencies-tab'} id={'dependencies-tab'} label={t('tab.dependencies')} />
|
||||||
<Tab data-testid={'versions-tab'} id={'versions-tab'} label={t('tab.versions')} />
|
<Tab data-testid={'versions-tab'} id={'versions-tab'} label={t('tab.versions')} />
|
||||||
@ -30,6 +26,6 @@ const DetailContainerTabs: React.FC<Props> = ({ tabPosition, onChange }) => {
|
|||||||
|
|
||||||
export default DetailContainerTabs;
|
export default DetailContainerTabs;
|
||||||
|
|
||||||
const Tabs = styled(MuiTabs)({
|
const Tabs = styled(MuiTabs)<{ theme?: Theme }>({
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
});
|
});
|
||||||
|
@ -10,6 +10,7 @@ exports[`DetailContainer renders correctly 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="MuiTabs-root emotion-0 emotion-1"
|
class="MuiTabs-root emotion-0 emotion-1"
|
||||||
|
color="primary"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="MuiTabs-scroller MuiTabs-fixed"
|
class="MuiTabs-scroller MuiTabs-fixed"
|
||||||
@ -21,7 +22,7 @@ exports[`DetailContainer renders correctly 1`] = `
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
class="MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary Mui-selected MuiTab-fullWidth"
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit Mui-selected MuiTab-fullWidth"
|
||||||
data-testid="readme-tab"
|
data-testid="readme-tab"
|
||||||
id="readme-tab"
|
id="readme-tab"
|
||||||
role="tab"
|
role="tab"
|
||||||
@ -39,7 +40,7 @@ exports[`DetailContainer renders correctly 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary MuiTab-fullWidth"
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit MuiTab-fullWidth"
|
||||||
data-testid="dependencies-tab"
|
data-testid="dependencies-tab"
|
||||||
id="dependencies-tab"
|
id="dependencies-tab"
|
||||||
role="tab"
|
role="tab"
|
||||||
@ -57,7 +58,7 @@ exports[`DetailContainer renders correctly 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary MuiTab-fullWidth"
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit MuiTab-fullWidth"
|
||||||
data-testid="versions-tab"
|
data-testid="versions-tab"
|
||||||
id="versions-tab"
|
id="versions-tab"
|
||||||
role="tab"
|
role="tab"
|
||||||
@ -75,7 +76,7 @@ exports[`DetailContainer renders correctly 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary MuiTab-fullWidth"
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit MuiTab-fullWidth"
|
||||||
data-testid="uplinks-tab"
|
data-testid="uplinks-tab"
|
||||||
id="uplinks-tab"
|
id="uplinks-tab"
|
||||||
role="tab"
|
role="tab"
|
||||||
|
@ -15,10 +15,6 @@ import { Theme } from '../../design-tokens/theme';
|
|||||||
import DetailSidebarTitle from './DetailSidebarTitle';
|
import DetailSidebarTitle from './DetailSidebarTitle';
|
||||||
import DetailSidebarFundButton from './DetailSidebarFundButton';
|
import DetailSidebarFundButton from './DetailSidebarFundButton';
|
||||||
|
|
||||||
const StyledPaper = styled(Paper)<{ theme?: Theme }>(({ theme }) => ({
|
|
||||||
padding: theme.spacing(3, 2),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const DetailSidebar: React.FC = () => {
|
const DetailSidebar: React.FC = () => {
|
||||||
const detailContext = useContext(DetailContext);
|
const detailContext = useContext(DetailContext);
|
||||||
|
|
||||||
@ -50,3 +46,7 @@ const DetailSidebar: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default DetailSidebar;
|
export default DetailSidebar;
|
||||||
|
|
||||||
|
const StyledPaper = styled(Paper)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
|
padding: theme?.spacing(3, 2),
|
||||||
|
}));
|
||||||
|
@ -13,15 +13,6 @@ interface Props {
|
|||||||
isLatest: boolean;
|
isLatest: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledHeading = styled(Heading)({
|
|
||||||
fontSize: '1rem',
|
|
||||||
fontWeight: 700,
|
|
||||||
});
|
|
||||||
|
|
||||||
const StyledBoxVersion = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
|
||||||
color: theme && theme.palette.text.secondary,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const DetailSidebarTitle: React.FC<Props> = ({ description, packageName, version, isLatest }) => {
|
const DetailSidebarTitle: React.FC<Props> = ({ description, packageName, version, isLatest }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
@ -36,3 +27,12 @@ const DetailSidebarTitle: React.FC<Props> = ({ description, packageName, version
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default DetailSidebarTitle;
|
export default DetailSidebarTitle;
|
||||||
|
|
||||||
|
const StyledHeading = styled(Heading)({
|
||||||
|
fontSize: '1rem',
|
||||||
|
fontWeight: 700,
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledBoxVersion = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
|
color: theme && theme.palette.text.secondary,
|
||||||
|
}));
|
||||||
|
@ -93,7 +93,7 @@ exports[`test Developers should render the component for contributors with items
|
|||||||
margin="10px 0 10px 0"
|
margin="10px 0 10px 0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="MuiBox-root MuiBox-root-60 emotion-8 emotion-9"
|
className="MuiBox-root MuiBox-root-91 emotion-8 emotion-9"
|
||||||
>
|
>
|
||||||
<ForwardRef(ToolTip)
|
<ForwardRef(ToolTip)
|
||||||
key="dave.methvin@gmail.com"
|
key="dave.methvin@gmail.com"
|
||||||
|
@ -3,10 +3,10 @@ import styled from '@emotion/styled';
|
|||||||
import Icon from '../Icon/Icon';
|
import Icon from '../Icon/Icon';
|
||||||
import { Theme } from '../../design-tokens/theme';
|
import { Theme } from '../../design-tokens/theme';
|
||||||
|
|
||||||
export const Wrapper = styled('div')<{ theme?: Theme }>(props => ({
|
export const Wrapper = styled('div')<{ theme?: Theme }>(({ theme }) => ({
|
||||||
background: props.theme && props.theme.palette.snow,
|
background: theme?.palette.type === 'dark' ? theme?.palette.primary.main : theme?.palette.snow,
|
||||||
borderTop: `1px solid ${props.theme && props.theme.palette.greyGainsboro}`,
|
borderTop: `1px solid ${theme?.palette.greyGainsboro}`,
|
||||||
color: props.theme && props.theme.palette.nobel01,
|
color: theme?.palette.type === 'dark' ? theme?.palette.white : theme?.palette.nobel01,
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
padding: '20px',
|
padding: '20px',
|
||||||
}));
|
}));
|
||||||
|
@ -30,7 +30,6 @@ const Header: React.FC<Props> = ({ withoutSearch }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { user, scope, setUser } = appContext;
|
const { user, scope, setUser } = appContext;
|
||||||
const logo = window.VERDACCIO_LOGO;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logouts user
|
* Logouts user
|
||||||
@ -46,7 +45,7 @@ const Header: React.FC<Props> = ({ withoutSearch }) => {
|
|||||||
<>
|
<>
|
||||||
<NavBar data-testid="header" position="static">
|
<NavBar data-testid="header" position="static">
|
||||||
<InnerNavBar>
|
<InnerNavBar>
|
||||||
<HeaderLeft logo={logo} />
|
<HeaderLeft />
|
||||||
<HeaderRight
|
<HeaderRight
|
||||||
onLogout={handleLogout}
|
onLogout={handleLogout}
|
||||||
onOpenRegistryInfoDialog={() => setOpenInfoDialog(true)}
|
onOpenRegistryInfoDialog={() => setOpenInfoDialog(true)}
|
||||||
|
@ -3,23 +3,22 @@ import styled from '@emotion/styled';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import Search from '../Search/';
|
import Search from '../Search/';
|
||||||
|
import Logo from '../Logo';
|
||||||
|
|
||||||
import HeaderLogo from './HeaderLogo';
|
|
||||||
import { LeftSide, SearchWrapper } from './styles';
|
import { LeftSide, SearchWrapper } from './styles';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
withoutSearch?: boolean;
|
withoutSearch?: boolean;
|
||||||
logo?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledLink = styled(Link)({
|
const StyledLink = styled(Link)({
|
||||||
marginRight: '1em',
|
marginRight: '1em',
|
||||||
});
|
});
|
||||||
|
|
||||||
const HeaderLeft: React.FC<Props> = ({ withoutSearch = false, logo }) => (
|
const HeaderLeft: React.FC<Props> = ({ withoutSearch = false }) => (
|
||||||
<LeftSide>
|
<LeftSide>
|
||||||
<StyledLink to={'/'}>
|
<StyledLink to={'/'}>
|
||||||
<HeaderLogo logo={logo} />
|
<Logo />
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
{!withoutSearch && (
|
{!withoutSearch && (
|
||||||
<SearchWrapper>
|
<SearchWrapper>
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import Logo from '../Logo';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
logo?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const HeaderLogo: React.FC<Props> = ({ logo }) => {
|
|
||||||
if (logo) {
|
|
||||||
const Wrapper = styled('div')({
|
|
||||||
fontSize: 0,
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<img alt="logo" height="40px" src={logo} />
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Logo />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HeaderLogo;
|
|
@ -1,7 +1,8 @@
|
|||||||
import React, { useState, useEffect, MouseEvent } from 'react';
|
import React, { useState, useEffect, useContext, MouseEvent } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import Button from '../../muiComponents/Button';
|
import Button from '../../muiComponents/Button';
|
||||||
|
import ThemeContext from '../../design-tokens/ThemeContext';
|
||||||
|
|
||||||
import { RightSide } from './styles';
|
import { RightSide } from './styles';
|
||||||
import HeaderToolTip from './HeaderToolTip';
|
import HeaderToolTip from './HeaderToolTip';
|
||||||
@ -24,10 +25,16 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
onToggleMobileNav,
|
onToggleMobileNav,
|
||||||
onOpenRegistryInfoDialog,
|
onOpenRegistryInfoDialog,
|
||||||
}) => {
|
}) => {
|
||||||
|
const themeContext = useContext(ThemeContext);
|
||||||
const [anchorEl, setAnchorEl] = useState();
|
const [anchorEl, setAnchorEl] = useState();
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState();
|
const [isMenuOpen, setIsMenuOpen] = useState();
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
if (!themeContext) {
|
||||||
|
throw Error(t('theme-context-not-correct-used'));
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsMenuOpen(Boolean(anchorEl));
|
setIsMenuOpen(Boolean(anchorEl));
|
||||||
}, [anchorEl]);
|
}, [anchorEl]);
|
||||||
@ -54,6 +61,12 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
onToggleLogin();
|
onToggleLogin();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleToggleDarkLightMode = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
themeContext.setIsDarkMode(!themeContext.isDarkMode);
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RightSide data-testid="header-right">
|
<RightSide data-testid="header-right">
|
||||||
{!withoutSearch && (
|
{!withoutSearch && (
|
||||||
@ -61,6 +74,12 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
<HeaderToolTip title={t('header.documentation')} tooltipIconType={'help'} />
|
<HeaderToolTip title={t('header.documentation')} tooltipIconType={'help'} />
|
||||||
<HeaderToolTip onClick={onOpenRegistryInfoDialog} title={t('header.registry-info')} tooltipIconType={'info'} />
|
<HeaderToolTip onClick={onOpenRegistryInfoDialog} title={t('header.registry-info')} tooltipIconType={'info'} />
|
||||||
|
<HeaderToolTip
|
||||||
|
onClick={handleToggleDarkLightMode}
|
||||||
|
title={t('header.documentation')}
|
||||||
|
tooltipIconType={themeContext.isDarkMode ? 'dark-mode' : 'light-mode'}
|
||||||
|
/>
|
||||||
|
|
||||||
{username ? (
|
{username ? (
|
||||||
<HeaderMenu
|
<HeaderMenu
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
|
@ -2,12 +2,14 @@ import React, { forwardRef } from 'react';
|
|||||||
import Info from '@material-ui/icons/Info';
|
import Info from '@material-ui/icons/Info';
|
||||||
import Help from '@material-ui/icons/Help';
|
import Help from '@material-ui/icons/Help';
|
||||||
import Search from '@material-ui/icons/Search';
|
import Search from '@material-ui/icons/Search';
|
||||||
|
import NightsStay from '@material-ui/icons/NightsStay';
|
||||||
|
import WbSunny from '@material-ui/icons/WbSunny';
|
||||||
|
|
||||||
import IconButton from '../../muiComponents/IconButton';
|
import IconButton from '../../muiComponents/IconButton';
|
||||||
|
|
||||||
import { IconSearchButton, StyledLink } from './styles';
|
import { IconSearchButton, StyledLink } from './styles';
|
||||||
|
|
||||||
export type TooltipIconType = 'search' | 'help' | 'info';
|
export type TooltipIconType = 'search' | 'help' | 'info' | 'dark-mode' | 'light-mode';
|
||||||
interface Props {
|
interface Props {
|
||||||
tooltipIconType: TooltipIconType;
|
tooltipIconType: TooltipIconType;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
@ -50,6 +52,21 @@ const HeaderToolTipIcon = forwardRef<HeaderToolTipIconRef, Props>(function Heade
|
|||||||
<Search />
|
<Search />
|
||||||
</IconSearchButton>
|
</IconSearchButton>
|
||||||
);
|
);
|
||||||
|
case 'dark-mode':
|
||||||
|
// todo(Priscila): Add Zoom transition effect
|
||||||
|
return (
|
||||||
|
<IconButton color="inherit" onClick={onClick} ref={ref}>
|
||||||
|
<NightsStay />
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'light-mode':
|
||||||
|
// todo(Priscila): Add Zoom transition effect
|
||||||
|
return (
|
||||||
|
<IconButton color="inherit" onClick={onClick} ref={ref}>
|
||||||
|
<WbSunny />
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -302,6 +302,30 @@ exports[`<Header /> component with logged in state should load the component in
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit"
|
||||||
|
tabindex="0"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit"
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit"
|
||||||
data-testid="header--menu-accountcircle"
|
data-testid="header--menu-accountcircle"
|
||||||
@ -635,6 +659,30 @@ exports[`<Header /> component with logged in state should load the component in
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit"
|
||||||
|
tabindex="0"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="presentation"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
|
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-colorInherit"
|
||||||
data-testid="header--button-login"
|
data-testid="header--button-login"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { Theme } from '../../design-tokens/theme';
|
||||||
|
|
||||||
export const Wrapper = styled('div')({
|
export const Wrapper = styled('div')({
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
@ -7,9 +9,9 @@ export const Wrapper = styled('div')({
|
|||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Badge = styled('div')({
|
export const Badge = styled('div')<{ theme?: Theme }>(({ theme }) => ({
|
||||||
margin: '0 0 30px 0',
|
margin: '0 0 30px 0',
|
||||||
borderRadius: 25,
|
borderRadius: 25,
|
||||||
boxShadow: '0 10px 20px 0 rgba(69, 58, 100, 0.2)',
|
boxShadow: '0 10px 20px 0 rgba(69, 58, 100, 0.2)',
|
||||||
background: '#f7f8f6',
|
background: theme?.palette.type === 'dark' ? theme?.palette.black : '#f7f8f6',
|
||||||
});
|
}));
|
||||||
|
@ -8,13 +8,14 @@ import { Theme } from '../../design-tokens/theme';
|
|||||||
import { LoginError } from '../../utils/login';
|
import { LoginError } from '../../utils/login';
|
||||||
|
|
||||||
const StyledSnackbarContent = styled(SnackbarContent)<{ theme?: Theme }>(({ theme }) => ({
|
const StyledSnackbarContent = styled(SnackbarContent)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
backgroundColor: theme.palette.error.dark,
|
backgroundColor: theme?.palette.error.dark,
|
||||||
|
color: theme?.palette.white,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledErrorIcon = styled(Error)<{ theme?: Theme }>(({ theme }) => ({
|
const StyledErrorIcon = styled(Error)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
opacity: 0.9,
|
opacity: 0.9,
|
||||||
marginRight: theme.spacing(1),
|
marginRight: theme?.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export interface FormValues {
|
export interface FormValues {
|
||||||
|
@ -13,6 +13,7 @@ import { Theme } from '../../design-tokens/theme';
|
|||||||
const StyledAvatar = styled(Avatar)<{ theme?: Theme }>(({ theme }) => ({
|
const StyledAvatar = styled(Avatar)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
margin: theme.spacing(1),
|
margin: theme.spacing(1),
|
||||||
backgroundColor: theme.palette.primary.main,
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: theme.palette.white,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledIconButton = styled(IconButton)<{ theme?: Theme }>(({ theme }) => ({
|
const StyledIconButton = styled(IconButton)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
|
@ -1,31 +1,52 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import logo from './img/logo.svg';
|
import { Theme } from '../../design-tokens/theme';
|
||||||
|
|
||||||
|
import defaultLogo from './img/logo.svg';
|
||||||
|
import blackAndWithLogo from './img/logo-black-and-white.svg';
|
||||||
|
|
||||||
export enum Size {
|
export enum Size {
|
||||||
Small = '40px',
|
Small = '40px',
|
||||||
Big = '90px',
|
Big = '90px',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logos = {
|
||||||
|
light: defaultLogo,
|
||||||
|
dark: blackAndWithLogo,
|
||||||
|
};
|
||||||
|
|
||||||
|
const logo = window.VERDACCIO_LOGO;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
size?: Size;
|
size?: Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledLogo = styled('div')<Props>(props => ({
|
const Logo: React.FC<Props> = ({ size = Size.Small }) => {
|
||||||
|
if (logo) {
|
||||||
|
return (
|
||||||
|
<ImageLogo>
|
||||||
|
<img alt="logo" height="40px" src={logo} />
|
||||||
|
</ImageLogo>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <StyledLogo size={size} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Logo;
|
||||||
|
|
||||||
|
const ImageLogo = styled('div')({
|
||||||
|
fontSize: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledLogo = styled('div')<Props & { theme?: Theme }>(({ size, theme }) => ({
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
backgroundPosition: 'center',
|
backgroundPosition: 'center',
|
||||||
backgroundSize: 'contain',
|
backgroundSize: 'contain',
|
||||||
backgroundImage: `url(${logo})`,
|
backgroundImage: `url(${logos[theme?.palette.type]})`,
|
||||||
backgroundRepeat: ' no-repeat',
|
backgroundRepeat: ' no-repeat',
|
||||||
width: props.size,
|
width: size,
|
||||||
height: props.size,
|
height: size,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Logo: React.FC<Props> = ({ size = Size.Small }) => {
|
|
||||||
return <StyledLogo size={size} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Logo;
|
|
||||||
|
1
src/components/Logo/img/logo-black-and-white.svg
Normal file
1
src/components/Logo/img/logo-black-and-white.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><filter x="-19.8%" y="-11.7%" width="139.6%" height="140.4%" filterUnits="objectBoundingBox" id="a"><feOffset dy="4" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0906646286 0" in="shadowBlurOuter1"/></filter><filter x="-33.9%" y="-50%" width="167.9%" height="272.7%" filterUnits="objectBoundingBox" id="c"><feOffset dy="4" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0906646286 0" in="shadowBlurOuter1"/></filter><path id="b" d="M48 16.729L32.672 47h-8.874L0 0h15.328l12.907 25.492 4.437-8.763H48z"/><path d="M35.2 11H28V8.643h8.4l1.2-2.357H32V3.929h6.8l.8-1.572H36V0h20l-5.6 11H35.2z" id="d"/></defs><g fill="none" fill-rule="evenodd"><rect fill="#000" width="100" height="100" rx="37"/><g transform="translate(22 30)"><use fill="#000" filter="url(#a)" xlink:href="#b"/><use fill-opacity=".6" fill="#FFF" xlink:href="#b"/></g><g transform="translate(22 30)"><use fill="#000" filter="url(#c)" xlink:href="#d"/><use fill="#FFF" xlink:href="#d"/></g><path fill="#FFF" d="M54.785 77H45.88L22 30h15.38L58 70.718z"/></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -15,7 +15,7 @@ export const OverviewItem = styled('span')<{ theme?: Theme }>(({ theme }) => ({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
margin: '0 0 0 16px',
|
margin: '0 0 0 16px',
|
||||||
color: theme && theme.palette.greyLight2,
|
color: theme?.palette.type === 'light' ? theme?.palette.greyLight2 : theme?.palette.dodgerBlue,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
[`@media (max-width: ${theme && theme.breakPoints.medium}px)`]: {
|
[`@media (max-width: ${theme && theme.breakPoints.medium}px)`]: {
|
||||||
':nth-of-type(3)': {
|
':nth-of-type(3)': {
|
||||||
@ -29,20 +29,20 @@ export const OverviewItem = styled('span')<{ theme?: Theme }>(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Icon = styled(Ico)<{ theme?: Theme }>(props => ({
|
export const Icon = styled(Ico)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
margin: '2px 10px 0 0',
|
margin: '2px 10px 0 0',
|
||||||
fill: props.theme && props.theme.palette.greyLight2,
|
fill: theme?.palette.type === 'light' ? theme?.palette.greyLight2 : theme?.palette.dodgerBlue,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Published = styled('span')<{ theme?: Theme }>(props => ({
|
export const Published = styled('span')<{ theme?: Theme }>(({ theme }) => ({
|
||||||
color: props.theme && props.theme.palette.greyLight2,
|
color: theme?.palette.type === 'light' ? theme?.palette.greyLight2 : theme?.palette.dodgerBlue,
|
||||||
margin: '0 5px 0 0',
|
margin: '0 5px 0 0',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Text = styled(Label)<{ theme?: Theme }>(props => ({
|
export const Text = styled(Label)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
fontWeight: props.theme && props.theme.fontWeight.semiBold,
|
fontWeight: theme?.fontWeight.semiBold,
|
||||||
color: props.theme && props.theme.palette.greyLight2,
|
color: theme?.palette.type === 'light' ? theme?.palette.greyLight2 : theme?.palette.dodgerBlue,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Details = styled('span')({
|
export const Details = styled('span')({
|
||||||
@ -71,11 +71,8 @@ export const PackageTitle = styled('span')<{ theme?: Theme }>(({ theme }) => ({
|
|||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
display: 'block',
|
display: 'block',
|
||||||
marginBottom: 12,
|
marginBottom: 12,
|
||||||
color: theme && theme.palette.eclipse,
|
color: theme?.palette.type == 'dark' ? theme?.palette.white : theme?.palette.eclipse,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
':hover': {
|
|
||||||
color: theme && theme.palette.black,
|
|
||||||
},
|
|
||||||
[`@media (max-width: ${theme && theme.breakPoints.small}px)`]: {
|
[`@media (max-width: ${theme && theme.breakPoints.small}px)`]: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
@ -86,14 +83,15 @@ export const GridRightAligned = styled(Grid)({
|
|||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PackageList = styled(List)<{ theme?: Theme }>(props => ({
|
export const PackageList = styled(List)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
padding: '12px 0 12px 0',
|
padding: '12px 0 12px 0',
|
||||||
':hover': {
|
':hover': {
|
||||||
backgroundColor: props.theme && props.theme.palette.greyLight3,
|
backgroundColor: theme?.palette?.type == 'dark' ? theme?.palette?.primary.main : theme?.palette?.greyLight3,
|
||||||
},
|
},
|
||||||
'> :last-child': {
|
'> :last-child': {
|
||||||
paddingTop: 0,
|
paddingTop: 0,
|
||||||
},
|
},
|
||||||
|
borderRadius: 4,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const IconButton = styled(MuiIconButton)({
|
export const IconButton = styled(MuiIconButton)({
|
||||||
|
@ -12,7 +12,9 @@ describe('<Readme /> component', () => {
|
|||||||
|
|
||||||
test('should dangerously set html', () => {
|
test('should dangerously set html', () => {
|
||||||
const wrapper = mount(<Readme description="<h1>This is a test string</h1>" />);
|
const wrapper = mount(<Readme description="<h1>This is a test string</h1>" />);
|
||||||
expect(wrapper.html()).toEqual('<div class="markdown-body"><h1>This is a test string</h1></div>');
|
expect(wrapper.html()).toEqual(
|
||||||
|
'<div class="markdown-body css-beaqbv-Wrapper ecnabbe0"><h1>This is a test string</h1></div>'
|
||||||
|
);
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import 'github-markdown-css';
|
import 'github-markdown-css';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { Theme } from '../../design-tokens/theme';
|
||||||
|
|
||||||
import { Props } from './types';
|
import { Props } from './types';
|
||||||
|
|
||||||
const Readme: React.FC<Props> = ({ description }) => (
|
const Readme: React.FC<Props> = ({ description }) => (
|
||||||
<div className="markdown-body" dangerouslySetInnerHTML={{ __html: description }} />
|
<Wrapper className="markdown-body" dangerouslySetInnerHTML={{ __html: description }} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export default Readme;
|
export default Readme;
|
||||||
|
|
||||||
|
const Wrapper = styled('div')<{ theme?: Theme }>(({ theme }) => ({
|
||||||
|
background: theme?.palette.white,
|
||||||
|
color: theme?.palette.black,
|
||||||
|
padding: theme?.spacing(2, 3),
|
||||||
|
}));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`<Readme /> component should dangerously set html 1`] = `"<div class=\\"markdown-body\\"><h1>This is a test string</h1></div>"`;
|
exports[`<Readme /> component should dangerously set html 1`] = `"<div class=\\"markdown-body css-beaqbv-Wrapper ecnabbe0\\"><h1>This is a test string</h1></div>"`;
|
||||||
|
|
||||||
exports[`<Readme /> component should load the component in default state 1`] = `"<div class=\\"markdown-body\\">test</div>"`;
|
exports[`<Readme /> component should load the component in default state 1`] = `"<div class=\\"markdown-body css-beaqbv-Wrapper ecnabbe0\\">test</div>"`;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { css } from '@emotion/core';
|
|
||||||
|
|
||||||
import CopyToClipBoard from '../CopyToClipBoard';
|
import CopyToClipBoard from '../CopyToClipBoard';
|
||||||
import { getCLISetRegistry, getCLIChangePassword, getCLISetConfigRegistry } from '../../utils/cli-utils';
|
import { getCLISetRegistry, getCLIChangePassword, getCLISetConfigRegistry } from '../../utils/cli-utils';
|
||||||
@ -48,10 +47,10 @@ const RegistryInfoContent: React.FC<Props> = props => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
color={'primary'}
|
||||||
data-testid={'tabs-el'}
|
data-testid={'tabs-el'}
|
||||||
indicatorColor="primary"
|
indicatorColor={'primary'}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
textColor="primary"
|
|
||||||
value={tabPosition}
|
value={tabPosition}
|
||||||
variant="fullWidth">
|
variant="fullWidth">
|
||||||
<Tab data-testid={'npm-tab'} label={NODE_MANAGER.npm} />
|
<Tab data-testid={'npm-tab'} label={NODE_MANAGER.npm} />
|
||||||
@ -69,14 +68,7 @@ const RegistryInfoContent: React.FC<Props> = props => {
|
|||||||
const TabContainer = ({ children }): JSX.Element => {
|
const TabContainer = ({ children }): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<CommandContainer>
|
<CommandContainer>
|
||||||
<Typography
|
<Typography component="div">{children}</Typography>
|
||||||
// className={css`
|
|
||||||
// padding: 0;
|
|
||||||
// min-height: 170;
|
|
||||||
// `}
|
|
||||||
component="div">
|
|
||||||
{children}
|
|
||||||
</Typography>
|
|
||||||
</CommandContainer>
|
</CommandContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,7 @@ export const Title = styled(DialogTitle)<{ theme?: Theme }>(props => ({
|
|||||||
fontSize: props.theme && props.theme.fontSize.lg,
|
fontSize: props.theme && props.theme.fontSize.lg,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Content = styled(DialogContent)({
|
export const Content = styled(DialogContent)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
padding: '0 24px',
|
padding: '0 24px',
|
||||||
});
|
backgroundColor: theme?.palette.background.default,
|
||||||
|
}));
|
||||||
|
@ -6,6 +6,7 @@ import Avatar from '../../muiComponents/Avatar';
|
|||||||
import Text from '../../muiComponents/Text';
|
import Text from '../../muiComponents/Text';
|
||||||
import ListItem from '../../muiComponents/ListItem';
|
import ListItem from '../../muiComponents/ListItem';
|
||||||
import ListItemText from '../../muiComponents/ListItemText';
|
import ListItemText from '../../muiComponents/ListItemText';
|
||||||
|
import Link from '../Link';
|
||||||
import { isURL } from '../../utils/url';
|
import { isURL } from '../../utils/url';
|
||||||
import CopyToClipBoard from '../CopyToClipBoard';
|
import CopyToClipBoard from '../CopyToClipBoard';
|
||||||
import List from '../../muiComponents/List';
|
import List from '../../muiComponents/List';
|
||||||
@ -19,8 +20,11 @@ const StyledText = styled(Text)<{ theme?: Theme }>(props => ({
|
|||||||
textTransform: 'capitalize',
|
textTransform: 'capitalize',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const GithubLink = styled('a')<{ theme?: Theme }>(props => ({
|
const GithubLink = styled(Link)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
color: props.theme && props.theme.palette.primary.main,
|
color: theme?.palette.type === 'light' ? theme?.palette.primary.main : theme?.palette.white,
|
||||||
|
':hover': {
|
||||||
|
color: theme?.palette.dodgerBlue,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const RepositoryListItem = styled(ListItem)({
|
const RepositoryListItem = styled(ListItem)({
|
||||||
@ -72,7 +76,7 @@ const Repository: React.FC = () => {
|
|||||||
<RepositoryListItemText
|
<RepositoryListItemText
|
||||||
primary={
|
primary={
|
||||||
<CopyToClipBoard text={repositoryURL}>
|
<CopyToClipBoard text={repositoryURL}>
|
||||||
<GithubLink href={repositoryURL} target="_blank">
|
<GithubLink external={true} to={repositoryURL}>
|
||||||
{repositoryURL}
|
{repositoryURL}
|
||||||
</GithubLink>
|
</GithubLink>
|
||||||
</CopyToClipBoard>
|
</CopyToClipBoard>
|
||||||
|
@ -19,6 +19,6 @@ export const Wrapper = styled('div')<WrapperProps>(props => ({
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Circular = styled(CircularProgress)<{ theme?: Theme }>(props => ({
|
export const Circular = styled(CircularProgress)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
color: props.theme && props.theme.palette.primary.main,
|
color: theme?.palette.type === 'dark' ? theme?.palette.white : theme?.palette.primary.main,
|
||||||
}));
|
}));
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
exports[`<UpLinks /> component should render the component when there is no uplink 1`] = `"<h6 class=\\"MuiTypography-root MuiTypography-subtitle1 MuiTypography-gutterBottom\\">uplinks.no-items</h6>"`;
|
exports[`<UpLinks /> component should render the component when there is no uplink 1`] = `"<h6 class=\\"MuiTypography-root MuiTypography-subtitle1 MuiTypography-gutterBottom\\">uplinks.no-items</h6>"`;
|
||||||
|
|
||||||
exports[`<UpLinks /> component should render the component with uplinks 1`] = `"<h6 class=\\"MuiTypography-root css-5wp24z-StyledText e14i1sy10 MuiTypography-subtitle1\\">uplinks.title</h6><ul class=\\"MuiList-root MuiList-padding\\"><li class=\\"MuiListItem-root MuiListItem-gutters\\"><div class=\\"MuiListItemText-root css-1pxn9ma-ListItemText e14i1sy12\\"><span class=\\"MuiTypography-root MuiListItemText-primary MuiTypography-body1\\">npmjs</span></div><div class=\\"css-t1rp47-Spacer e14i1sy11\\"></div><div class=\\"MuiListItemText-root css-1pxn9ma-ListItemText e14i1sy12\\"><span class=\\"MuiTypography-root MuiListItemText-primary MuiTypography-body1\\">2 years ago</span></div></li></ul>"`;
|
exports[`<UpLinks /> component should render the component with uplinks 1`] = `"<h6 class=\\"MuiTypography-root css-5wp24z-StyledText e14i1sy10 MuiTypography-subtitle1\\">uplinks.title</h6><ul class=\\"MuiList-root MuiList-padding\\"><li class=\\"MuiListItem-root MuiListItem-gutters\\"><div class=\\"MuiListItemText-root css-1ork7s0-ListItemText e14i1sy12\\"><span class=\\"MuiTypography-root MuiListItemText-primary MuiTypography-body1\\">npmjs</span></div><div class=\\"css-4lqckn-Spacer e14i1sy11\\"></div><div class=\\"MuiListItemText-root css-1ork7s0-ListItemText e14i1sy12\\"><span class=\\"MuiTypography-root MuiListItemText-primary MuiTypography-body1\\">2 years ago</span></div></li></ul>"`;
|
||||||
|
@ -8,15 +8,15 @@ export const StyledText = styled(Text)<{ theme?: Theme }>(props => ({
|
|||||||
fontWeight: props.theme && props.theme.fontWeight.bold,
|
fontWeight: props.theme && props.theme.fontWeight.bold,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Spacer = styled('div')({
|
export const Spacer = styled('div')<{ theme?: Theme }>(({ theme }) => ({
|
||||||
flex: '1 1 auto',
|
flex: '1 1 auto',
|
||||||
borderBottom: '1px dotted rgba(0, 0, 0, 0.2)',
|
borderBottom: `1px dotted ${theme?.palette.type == 'light' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)'} `,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
height: '0.5em',
|
height: '0.5em',
|
||||||
});
|
}));
|
||||||
|
|
||||||
export const ListItemText = styled(MuiListItemText)({
|
export const ListItemText = styled(MuiListItemText)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
flex: 'none',
|
flex: 'none',
|
||||||
color: 'black',
|
color: theme?.palette.type == 'light' ? theme?.palette.black : theme?.palette.white,
|
||||||
opacity: 0.6,
|
opacity: 0.6,
|
||||||
});
|
}));
|
||||||
|
@ -7,6 +7,7 @@ import { DIST_TAGS } from '../../../lib/constants';
|
|||||||
import { StyledText } from './styles';
|
import { StyledText } from './styles';
|
||||||
import VersionsTagList from './VersionsTagList';
|
import VersionsTagList from './VersionsTagList';
|
||||||
import VersionsHistoryList from './VersionsHistoryList';
|
import VersionsHistoryList from './VersionsHistoryList';
|
||||||
|
|
||||||
const Versions: React.FC = () => {
|
const Versions: React.FC = () => {
|
||||||
const detailContext = useContext(DetailContext);
|
const detailContext = useContext(DetailContext);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -9,19 +9,19 @@ export const StyledText = styled(Text)<{ theme?: Theme }>(props => ({
|
|||||||
fontWeight: props.theme && props.theme.fontWeight.bold,
|
fontWeight: props.theme && props.theme.fontWeight.bold,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Spacer = styled('div')({
|
export const Spacer = styled('div')<{ theme?: Theme }>(({ theme }) => ({
|
||||||
flex: '1 1 auto',
|
flex: '1 1 auto',
|
||||||
borderBottom: '1px dotted rgba(0, 0, 0, 0.2)',
|
borderBottom: `1px dotted ${theme?.palette.type == 'light' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)'} `,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
height: '0.5em',
|
height: '0.5em',
|
||||||
margin: '0 16px',
|
margin: '0 16px',
|
||||||
});
|
}));
|
||||||
|
|
||||||
export const ListItemText = styled(MuiListItemText)({
|
export const ListItemText = styled(MuiListItemText)<{ theme?: Theme }>(({ theme }) => ({
|
||||||
flex: 'none',
|
flex: 'none',
|
||||||
color: 'black',
|
|
||||||
opacity: 0.6,
|
opacity: 0.6,
|
||||||
});
|
color: theme?.palette.type == 'light' ? theme?.palette.black : theme?.palette.white,
|
||||||
|
}));
|
||||||
|
|
||||||
export const StyledLink = styled(Link)({
|
export const StyledLink = styled(Link)({
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
|
10
src/design-tokens/ThemeContext.ts
Normal file
10
src/design-tokens/ThemeContext.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isDarkMode: boolean;
|
||||||
|
setIsDarkMode: (isDarkMode: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeContext = createContext<undefined | Props>(undefined);
|
||||||
|
|
||||||
|
export default ThemeContext;
|
@ -2,12 +2,23 @@ import React from 'react';
|
|||||||
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';
|
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';
|
||||||
import { ThemeProvider as EmotionThemeProvider } from 'emotion-theming';
|
import { ThemeProvider as EmotionThemeProvider } from 'emotion-theming';
|
||||||
|
|
||||||
import theme from './theme';
|
import ThemeContext from './ThemeContext';
|
||||||
|
import { getTheme, ThemeMode } from './theme';
|
||||||
|
import useLocalStorage from './useLocalStorage';
|
||||||
|
|
||||||
const ThemeProvider: React.FC = ({ children }) => (
|
const ThemeProvider: React.FC = ({ children }) => {
|
||||||
<EmotionThemeProvider theme={theme}>
|
const isDarkModeDefault = window?.__VERDACCIO_BASENAME_UI_OPTIONS?.darkMode;
|
||||||
<MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>
|
const [isDarkMode, setIsDarkMode] = useLocalStorage('darkMode', !!isDarkModeDefault);
|
||||||
</EmotionThemeProvider>
|
|
||||||
);
|
const themeMode: ThemeMode = isDarkMode ? 'dark' : 'light';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={{ isDarkMode, setIsDarkMode }}>
|
||||||
|
<EmotionThemeProvider theme={getTheme(themeMode)}>
|
||||||
|
<MuiThemeProvider theme={getTheme(themeMode)}>{children}</MuiThemeProvider>
|
||||||
|
</EmotionThemeProvider>
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default ThemeProvider;
|
export default ThemeProvider;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
|
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
|
||||||
|
|
||||||
// Main colors
|
|
||||||
// -------------------------
|
|
||||||
const colors = {
|
const colors = {
|
||||||
black: '#000',
|
black: '#000',
|
||||||
white: '#fff',
|
white: '#fff',
|
||||||
@ -25,9 +23,23 @@ const colors = {
|
|||||||
nobel02: '#9f9f9f',
|
nobel02: '#9f9f9f',
|
||||||
primary: window.VERDACCIO_PRIMARY_COLOR || '#4b5e40',
|
primary: window.VERDACCIO_PRIMARY_COLOR || '#4b5e40',
|
||||||
secondary: '#20232a',
|
secondary: '#20232a',
|
||||||
|
background: '#fff',
|
||||||
|
dodgerBlue: '#1ba1f2',
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Colors = keyof typeof colors;
|
const themeModes = {
|
||||||
|
light: {
|
||||||
|
...colors,
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
...colors,
|
||||||
|
primary: '#253341',
|
||||||
|
secondary: '#20232a',
|
||||||
|
background: '#1A202C',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ThemeMode = keyof typeof themeModes;
|
||||||
|
|
||||||
const fontSize = {
|
const fontSize = {
|
||||||
xxl: 26,
|
xxl: 26,
|
||||||
@ -67,20 +79,27 @@ const customizedTheme = {
|
|||||||
|
|
||||||
type CustomizedTheme = typeof customizedTheme;
|
type CustomizedTheme = typeof customizedTheme;
|
||||||
|
|
||||||
export const theme = createMuiTheme({
|
export const getTheme = (themeMode: ThemeMode) => {
|
||||||
typography: {
|
const palette = themeModes[themeMode];
|
||||||
fontFamily: 'inherit',
|
return createMuiTheme({
|
||||||
},
|
typography: {
|
||||||
palette: {
|
fontFamily: 'inherit',
|
||||||
...colors,
|
},
|
||||||
primary: { main: colors.primary },
|
palette: {
|
||||||
secondary: { main: colors.secondary },
|
type: themeMode,
|
||||||
error: { main: colors.red },
|
...palette,
|
||||||
},
|
primary: { main: palette.primary },
|
||||||
...customizedTheme,
|
secondary: { main: palette.secondary },
|
||||||
});
|
error: { main: palette.red },
|
||||||
|
background: {
|
||||||
|
default: palette.background,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...customizedTheme,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export type Theme = typeof theme;
|
export type Theme = ReturnType<typeof getTheme>;
|
||||||
|
|
||||||
declare module '@material-ui/core/styles/createMuiTheme' {
|
declare module '@material-ui/core/styles/createMuiTheme' {
|
||||||
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
|
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
|
||||||
@ -111,6 +130,8 @@ declare module '@material-ui/core/styles/createPalette' {
|
|||||||
love: string;
|
love: string;
|
||||||
nobel01: string;
|
nobel01: string;
|
||||||
nobel02: string;
|
nobel02: string;
|
||||||
|
background: string;
|
||||||
|
dodgerBlue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
|
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
|
||||||
@ -118,5 +139,3 @@ declare module '@material-ui/core/styles/createPalette' {
|
|||||||
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
|
/* eslint-disable-next-line @typescript-eslint/no-empty-interface */
|
||||||
interface PaletteOptions extends Partial<CustomPalette> {}
|
interface PaletteOptions extends Partial<CustomPalette> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { ...theme };
|
|
||||||
|
38
src/design-tokens/useLocalStorage.ts
Normal file
38
src/design-tokens/useLocalStorage.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
// based on https://usehooks.com/useLocalStorage/
|
||||||
|
const useLocalStorage = <V>(key: string, initialValue: V) => {
|
||||||
|
// State to store our value
|
||||||
|
// Pass initial state function to useState so logic is only executed once
|
||||||
|
const [storedValue, setStoredValue] = useState(() => {
|
||||||
|
try {
|
||||||
|
// Get from local storage by key
|
||||||
|
const item = window.localStorage.getItem(key);
|
||||||
|
// Parse stored json or if none return initialValue
|
||||||
|
return item ? JSON.parse(item) : initialValue;
|
||||||
|
} catch (error) {
|
||||||
|
// If error also return initialValue
|
||||||
|
console.error('An error occurred getting a sessionStorage key', error);
|
||||||
|
return initialValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return a wrapped version of useState's setter function that ...
|
||||||
|
// ... persists the new value to localStorage.
|
||||||
|
const setValue = (value: V) => {
|
||||||
|
try {
|
||||||
|
// Allow value to be a function so we have same API as useState
|
||||||
|
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
||||||
|
// Save state
|
||||||
|
setStoredValue(valueToStore);
|
||||||
|
// Save to local storage
|
||||||
|
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('An error occurred writing to sessionStorage', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return [storedValue, setValue];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useLocalStorage;
|
7
src/design-tokens/useTheme.ts
Normal file
7
src/design-tokens/useTheme.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { useTheme as muiUseTheme } from '@material-ui/styles';
|
||||||
|
|
||||||
|
import { Theme } from './theme';
|
||||||
|
|
||||||
|
const useTheme = () => muiUseTheme<Theme>();
|
||||||
|
|
||||||
|
export default useTheme;
|
@ -41,7 +41,6 @@ export default {
|
|||||||
}),
|
}),
|
||||||
title: 'Verdaccio Dev UI',
|
title: 'Verdaccio Dev UI',
|
||||||
scope: '',
|
scope: '',
|
||||||
logo: 'https://verdaccio.org/img/logo/symbol/svg/verdaccio-tiny.svg',
|
|
||||||
filename: 'index.html',
|
filename: 'index.html',
|
||||||
verdaccioURL: '//localhost:4872',
|
verdaccioURL: '//localhost:4872',
|
||||||
template: `${env.SRC_ROOT}/template/index.html`,
|
template: `${env.SRC_ROOT}/template/index.html`,
|
||||||
|
@ -3,6 +3,7 @@ export interface VerdaccioOptions {
|
|||||||
url_prefix: string;
|
url_prefix: string;
|
||||||
base: string;
|
base: string;
|
||||||
language?: string;
|
language?: string;
|
||||||
|
darkMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
Loading…
Reference in New Issue
Block a user