Skip to content

Commit

Permalink
feat: initial theming
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasbrugneaux committed May 19, 2022
1 parent ef35ecf commit 0e7d8c3
Show file tree
Hide file tree
Showing 32 changed files with 657 additions and 269 deletions.
4 changes: 3 additions & 1 deletion packages/example/components/buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ export function SecondaryButton(
return (
<button
{...props}
className={`px-4 py-2 border border-transparent rounded-md text-base font-medium text-gradient bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 outline-none focus:outline-none ${
className={`px-4 py-2 border border-transparent rounded-md text-base font-medium outline-none focus:outline-none ${
props.className || ''
} ${
props.disabled ? 'cursor-not-allowed text-slate-400' : 'text-purple-700'
}`}
/>
);
Expand Down
95 changes: 95 additions & 0 deletions packages/example/components/theme-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Theme } from '@celo/react-celo';

interface Props {
theme: Theme;
currentTheme: Theme | null;
onClick: (theme: Theme) => void;
}

export function ThemeButton({ theme, currentTheme, onClick }: Props) {
const selected = currentTheme === theme;
return (
<div
className={`flex flex-row rounded gap-y-1 justify-between border cursor-pointer text-xs`}
style={{
background: theme.background,
borderWidth: selected ? 2 : 1,
padding: selected ? 3 : 4,
borderColor: selected ? theme.primary : theme.muted,
}}
onClick={() => onClick(theme)}
>
<div className="flex flex-col gap-y-2 w-full">
<div
className="w-1/3 h-0.5 rounded"
style={{ background: theme.text }}
/>
<div
className="w-3/4 h-0.5 rounded"
style={{ background: theme.text }}
/>
<div
className="w-3/4 h-0.5 rounded"
style={{ background: theme.textTertiary }}
/>
<div
className="w-2/3 h-0.5 rounded"
style={{ background: theme.muted }}
/>
</div>
<div className="flex flex-row gap-x-2">
<div
className="w-3 h-full rounded"
style={{ background: theme.primary }}
/>
<div
className="w-3 h-full rounded"
style={{ background: theme.secondary }}
/>
</div>
</div>
);
}

const defaultDark = {
primary: '#eef2ff',
secondary: '#6366f1',
text: '#ffffff',
textSecondary: '#cbd5e1',
textTertiary: '#64748b',
muted: '#334155',
background: '#1e293b',
error: '#ef4444',
};
const defaultLight = {
primary: '#6366f1',
secondary: '#eef2ff',
text: '#000000',
textSecondary: '#1f2937',
textTertiary: '#64748b',
muted: '#e2e8f0',
background: '#ffffff',
error: '#ef4444',
};
const greenCustom = {
primary: '#34d399',
secondary: '#ecfccb',
text: '#fff',
textSecondary: '#d9f99d',
textTertiary: '#bef264',
muted: '#3f6212',
background: '#000',
error: '#ef4444',
};
const roseCustom = {
primary: '#e11d48',
secondary: '#fda4af',
text: '#fff',
textSecondary: '#ffe4e6',
textTertiary: '#fecdd3',
muted: '#3f3f46',
background: '#27272a',
error: '#ef4444',
};

export const themes = [defaultDark, defaultLight, greenCustom, roseCustom];
37 changes: 32 additions & 5 deletions packages/example/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useCallback, useEffect, useState } from 'react';
import Web3 from 'web3';

import { PrimaryButton, SecondaryButton, toast } from '../components';
import { ThemeButton, themes } from '../components/theme-button';
import { TYPED_DATA } from '../utils';

interface Summary {
Expand Down Expand Up @@ -39,6 +40,12 @@ const feeTokenMap: FeeTokenMap = {
function truncateAddress(address: string) {
return `${address.slice(0, 8)}...${address.slice(36)}`;
}
const html =
typeof document !== 'undefined' &&
(document.getElementsByTagName('html')[0] as HTMLElement);
function isDark() {
return html && html.classList.contains('tw-dark');
}

export default function Home(): React.ReactElement {
const {
Expand All @@ -54,8 +61,10 @@ export default function Home(): React.ReactElement {
walletType,
feeCurrency,
updateFeeCurrency,
updateTheme,
} = useCelo();

const [_theme, selectTheme] = useState(null);
const [summary, setSummary] = useState(defaultSummary);
const [sending, setSending] = useState(false);

Expand Down Expand Up @@ -170,11 +179,10 @@ export default function Home(): React.ReactElement {
};

const toggleDarkMode = useCallback(() => {
const html = document.getElementsByTagName('html')[0] as HTMLElement;
if (html.classList.contains('tw-dark')) {
html.classList.remove('tw-dark');
if (isDark()) {
html && html.classList.remove('tw-dark');
} else {
html.classList.add('tw-dark');
html && html.classList.add('tw-dark');
}
}, []);

Expand All @@ -196,7 +204,11 @@ export default function Home(): React.ReactElement {
<div className="toggle-dark">
<span>Toggle modal's dark mode</span>
<label className="switch">
<input type="checkbox" onChange={toggleDarkMode} />
<input
type="checkbox"
onChange={toggleDarkMode}
defaultValue={isDark() ? 'checked' : 'unchecked'}
/>
<span className="slider round"></span>
</label>
</div>
Expand Down Expand Up @@ -325,6 +337,21 @@ export default function Home(): React.ReactElement {
Example wallet
</a>
</div>
<div className="text-slate-600 mb-4">
<div className="grid grid-flow-col gap-4 my-4">
{themes.map((theme, i) => (
<ThemeButton
key={i}
theme={theme}
currentTheme={_theme}
onClick={(theme) => {
updateTheme(theme);
selectTheme(theme);
}}
/>
))}
</div>
</div>
<div className="flex flex-col items-center">
<div className="flex items-center justify-center space-x-8 mb-4">
<select
Expand Down
1 change: 1 addition & 0 deletions packages/example/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
display: flex;
top: 1rem;
right: 1rem;
z-index: 99999;
}
.toggle-dark span:first-child {
padding-right: 1rem;
Expand Down
45 changes: 45 additions & 0 deletions packages/react-celo/src/components/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';

import cls from '../utils/tailwind';
import useTheme from '../utils/useTheme';

const styles = cls({
button: `
tw-rounded
tw-px-2
tw-py-1
tw-font-medium`,
});

type anchorType = JSX.IntrinsicElements['a'];
type buttonType = JSX.IntrinsicElements['button'];
type extendType = anchorType & buttonType;

interface Props extends extendType {
as?: 'a' | 'button' | React.ComponentType<unknown>;
className?: string;
style?: Record<string, string | number>;
}

export default function Button({
as = 'button',
className,
style,
...props
}: Props) {
const theme = useTheme();

const Component = as;

return (
<Component
className={`${styles.button} ${className || ''}`}
style={{
color: theme.primary,
background: theme.secondary,
...style,
}}
{...props}
/>
);
}
33 changes: 13 additions & 20 deletions packages/react-celo/src/components/connector-screen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { ReactElement } from 'react';

import cls from '../utils/tailwind';
import useTheme from '../utils/useTheme';
import Button from './button';

interface Footer {
url: string;
Expand Down Expand Up @@ -30,7 +32,6 @@ const styles = cls({
title: `
tw-text-xl
tw-text-center
dark:tw-text-slate-200
tw-w-4/5
tw-self-center
tw-font-medium`,
Expand All @@ -46,40 +47,32 @@ const styles = cls({
tw-items-stretch
tw-text-sm self-end`,
footerText: `
tw-text-slate-500
tw-font-medium`,
footerCTA: `
tw-rounded
tw-bg-indigo-50
tw-text-indigo-500
dark:tw-text-indigo-50
dark:tw-bg-indigo-500
tw-px-2
tw-py-1
tw-font-medium`,
});

export default function ConnectorScreen({ title, content, footer }: Props) {
const theme = useTheme();

return (
<div className={styles.container}>
<h1 className={styles.title}>{title}</h1>
<h1 className={styles.title} style={{ color: theme.textSecondary }}>
{title}
</h1>
<div className={styles.contentContainer}>{content}</div>
{footer && (
<div className={styles.footer}>
<div>
<p className={styles.footerText}>
<p
className={styles.footerText}
style={{ color: theme.textTertiary }}
>
{'desc' in footer ? footer.desc : `Don't have ${footer.name}?`}
</p>
</div>
<div>
<a
href={footer.url}
target="_blank"
rel="noreferrer"
className={styles.footerCTA}
>
<Button as="a" href={footer.url} target="_blank" rel="noreferrer">
{footer.CTA || 'GET'}
</a>
</Button>
</div>
</div>
)}
Expand Down
21 changes: 13 additions & 8 deletions packages/react-celo/src/components/copy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@ import React, { useCallback, useState } from 'react';

import cls from '../utils/tailwind';
import { useIsMounted } from '../utils/useIsMounted';
import useTheme from '../utils/useTheme';

const styles = cls({
button: `
tw-flex
tw-items-center
tw-text-slate-700
dark:tw-text-slate-400
hover:tw-text-slate-500
hover:tw-opacity-80
focus:tw-outline-none`,
text: `
tw-mr-2`,
svg: `
tw-h-4
tw-w-4`,
copiedSvg: `
tw-text-green-500`,
tw-w-4
tw-text-current`,
});

interface Props {
Expand All @@ -28,6 +26,7 @@ interface Props {
export const CopyText: React.FC<Props> = ({ text, payload }: Props) => {
const [copied, setCopied] = useState(false);
const isMountedRef = useIsMounted();
const theme = useTheme();

const onClick = useCallback(async () => {
await navigator.clipboard.writeText(payload);
Expand All @@ -41,11 +40,17 @@ export const CopyText: React.FC<Props> = ({ text, payload }: Props) => {
}, [payload, isMountedRef]);

return (
<button onClick={onClick} className={styles.button}>
<button
onClick={onClick}
className={styles.button}
style={{
color: theme.textTertiary,
}}
>
<span className={styles.text}>{text}</span>
{copied ? (
<svg
className={`${styles.svg} ${styles.copiedSvg}`}
className={styles.svg}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
Expand Down
1 change: 0 additions & 1 deletion packages/react-celo/src/components/index.ts

This file was deleted.

Loading

0 comments on commit 0e7d8c3

Please sign in to comment.