Skip to content

Commit

Permalink
feat: add theming
Browse files Browse the repository at this point in the history
  • Loading branch information
jrea committed Apr 4, 2022
1 parent 18cfc93 commit d04e1fa
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 38 deletions.
22 changes: 0 additions & 22 deletions packages/dashboard/CHANGELOG.md

This file was deleted.

16 changes: 7 additions & 9 deletions packages/react/src/components/SignUpForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import { useNile } from '../../context';
import Button from '../_Button';
import { Label, Input } from '../_Themeable';

import { Props } from './types';

export default function SignUpForm(props: Props) {
Expand All @@ -25,15 +27,11 @@ export default function SignUpForm(props: Props) {

return (
<form>
<br />
<input type="text" placeholder="email" id="email"></input>
<br />
<label htmlFor="email">Password</label>
<br />
<input type="password" placeholder="password" id="password"></input>
<br />
<br />
<Button onClick={handleSubmit}>Sign up</Button>
<Label htmlFor="email" text="Email"></Label>
<Input name="email" />
<Label htmlFor="password" text="Password" />
<Input name="password" />
<Button onClick={handleSubmit} name="signupButton" text="Sign up" />
</form>
);
}
19 changes: 19 additions & 0 deletions packages/react/src/components/_Button/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { render, screen } from '@testing-library/react'

import Button from '.';

describe('Button', () => {
it('renders non-themed', () => {
render(<Button onClick={jest.fn()} text="mario" name="signupButton" />);
expect(screen.getByRole('button').className).toEqual('nile');
})
it('renders themed string', () => {
render(<Button onClick={jest.fn()} text="mario" name="signupButton" />);
expect(screen.getByRole('button').className).toEqual('nile');
})
it('renders themed component', () => {
render(<Button onClick={jest.fn()} text="mario" name="signupButton" />);
expect(screen.getByRole('button').className).toEqual('nile');
})
})
16 changes: 12 additions & 4 deletions packages/react/src/components/_Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import React from 'react';
import { useTheme } from '../../theme';

type ButtonProps = {
type?: 'button' | 'submit' | 'reset';
children: string;
onClick?: () => void;
name: 'signupButton';
text: string;
};

export default function Button(props: ButtonProps) {
const { type, children, onClick } = props;
const { type, text, onClick, name } = props;
const theme = useTheme(name);
if (typeof theme === 'function') {
return <>{theme}</>
}


return (
<button type={type ?? 'button'} onClick={onClick}>
{children}
<button className={theme} type={type ?? 'button'} onClick={onClick} role="button">
{text}
</button>
);
}
24 changes: 24 additions & 0 deletions packages/react/src/components/_Themeable/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

import React from 'react';

import { useTheme, InputThemeName } from '../../theme';

export function Input({ name }: { name: InputThemeName }) {
const theme = useTheme(name);
if (typeof theme === 'function') {
return <>{theme}</>
}

return <input className={theme} type="text" placeholder={name} id={name} > </input>

}

export function Label({ htmlFor, text }: { text: string, htmlFor: InputThemeName}) {

const theme = useTheme(htmlFor);
if (typeof theme === 'function') {
return <>{theme}</>
}

return <label className={theme} htmlFor={htmlFor}>{text}</label>
}
12 changes: 10 additions & 2 deletions packages/react/src/context/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { useRef, useMemo, createContext, useContext } from 'react';
import { NileContext, NileProviderProps } from './types';
import Nile, {NileService} from '@theniledev/js';
import { Theme } from '../global-types';
import Nile, { NileService } from '@theniledev/js';

const defaultContext: NileContext = {
instance: Nile({ apiUrl: '' }),
theme: 'nile'
};

const context = createContext<NileContext>(defaultContext);
const { Provider } = context;

Expand All @@ -20,8 +23,9 @@ export const NileProvider = (props: NileProviderProps) => {
initalized.current = true;
return {
instance: Nile({ apiUrl: props.apiUrl }),
theme: props.theme,
};
}, [props.apiUrl]);
}, [props.apiUrl, props.theme]);

return <Provider value={values}>{children}</Provider>;
};
Expand All @@ -33,3 +37,7 @@ const useNileContext = (): NileContext => {
export const useNile = (): NileService => {
return useNileContext().instance;
};

export const useNileContextTheme = (): string | Theme => {
return useNileContext().theme;
}
5 changes: 4 additions & 1 deletion packages/react/src/context/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import {NileService} from '@theniledev/js';
import { NileService } from '@theniledev/js';
import React from 'react';
import { Theme } from '../global-types'

export interface NileContext {
instance: NileService;
theme: Theme | string
}

export interface NileProviderProps {
children: React.ReactNode;
apiUrl: string;
theme: Theme | string,
}
7 changes: 7 additions & 0 deletions packages/react/src/global-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";

export interface Theme {
email?: React.ReactNode
password?: React.ReactNode
signupButton?: React.ReactNode
};
21 changes: 21 additions & 0 deletions packages/react/src/theme/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useMemo } from 'react';
import { useNileContextTheme } from '../context';


const ThemeConfig = {
'email': 'email',
'password': 'password',
'signupButton': 'signupButton'
}
export type InputThemeName = 'email' | 'password' | 'signupButton';

export const useTheme = (name: InputThemeName) => {
const contextTheme = useNileContextTheme();
const override = typeof contextTheme === 'object' && contextTheme[name];
return useMemo(() => {
if (typeof override === 'function') {
return override;
}
return `${contextTheme}-${ThemeConfig[name]}`;
}, [name]);
};

0 comments on commit d04e1fa

Please sign in to comment.