Skip to content

Commit

Permalink
feat!: Full theming and CSS injection for every component
Browse files Browse the repository at this point in the history
  • Loading branch information
Inlustra committed Jul 2, 2021
1 parent 9acb950 commit adbae34
Show file tree
Hide file tree
Showing 21 changed files with 385 additions and 154 deletions.
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"plugins": [
[
"babel-plugin-styled-components",
{ "ssr": true, "displayName": false, "preprocess": false }
{ "ssr": true, "displayName": true, "preprocess": false }
]
],
"presets": ["next/babel"]
Expand Down
4 changes: 2 additions & 2 deletions client/components/Category/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from "react";
import styled from "styled-components";
import { Item, ItemProps } from "../Item";
import { getTheme } from "../theme";
import { getComponentTheme } from "../../theme";

export type CategoryThemeable = "Title" | "Container" | "Containers";

const getCategoryTheme = (component: CategoryThemeable) =>
getTheme("Category", component);
getComponentTheme("Category", component);

export interface CategoryTheme {
Title: string;
Expand Down
4 changes: 2 additions & 2 deletions client/components/ConnectionStatus/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useHarmonicIntervalFn } from "react-use";
import styled from "styled-components";
import { formatDistanceToNowShort } from "../../../lib/utils/format-distance-to-now-short";
import { StatusBox } from "../StatusBox";
import { getTheme } from "../theme";
import { getComponentTheme } from "../../theme";

export type ConnectionStatusThemable =
| "StatusBoxContainer"
Expand All @@ -13,7 +13,7 @@ export type ConnectionStatusThemable =
| "ConnectionStatusId";

const getConnectionStatusTheme = (component: ConnectionStatusThemable) =>
getTheme("ConnectionStatus", component);
getComponentTheme("ConnectionStatus", component);

function toTitleCase(str: string) {
return str.replace(/\w\S*/g, function (txt) {
Expand Down
23 changes: 11 additions & 12 deletions client/components/Item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import styled from "styled-components";
import { DynamicIcon } from "../icons";
import { SSRPopover } from "../SSRPopover";
import { ArrowContainer } from "react-tiny-popover";
import { getTheme } from "../theme";
import { getColor, getComponentTheme, Theme } from "../../theme";
import { useTheme } from "styled-components";

export type ItemThemable =
| "PopoverContainer"
Expand All @@ -29,7 +30,8 @@ export type ItemThemable =
| "Margins"
| "ExternalLinkContainerColumnSeparator";

const getItemTheme = (component: ItemThemable) => getTheme("Item", component);
const getItemTheme = (component: ItemThemable) =>
getComponentTheme("Item", component);

interface ItemData {
iconName?: string | null;
Expand Down Expand Up @@ -162,14 +164,7 @@ interface StatusBarProps {
const StatusBar = styled.div<StatusBarProps>`
width: 6px;
border-radius: 6px;
background: ${({ state }) =>
state === "GREEN"
? "green"
: state === "YELLOW"
? "yellow"
: state === "GREY"
? "grey"
: "red"};
background: ${({ state }) => getColor(state)};
${getItemTheme("StatusBar")}
`;
Expand Down Expand Up @@ -230,6 +225,10 @@ export const Item: React.FC<ItemProps> = ({
: BsQuestion,
[connectorType]
);
const theme = useTheme() as Theme;

const arrowColor =
theme?.components?.Item?.PopoverContainer?.background ?? "white";
return (
<>
<SSRPopover
Expand All @@ -240,7 +239,7 @@ export const Item: React.FC<ItemProps> = ({
position={position}
childRect={childRect}
popoverRect={popoverRect}
arrowColor="white"
arrowColor={arrowColor.toString()}
arrowSize={10}
>
<Popover entities={children} />
Expand All @@ -249,7 +248,7 @@ export const Item: React.FC<ItemProps> = ({
>
<Container
href={link}
onMouseOver={() => setPopoverOpen(true)}
onMouseOver={() => setPopoverOpen(children.length > 0)}
onMouseLeave={() => setPopoverOpen(false)}
>
<StatusBar state={state} />
Expand Down
13 changes: 3 additions & 10 deletions client/components/StatusBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import styled from "styled-components";
import { getTheme } from "../theme";
import { getColor, getComponentTheme } from "../../theme";

export type StatusBoxThemeables =
| "Title"
Expand All @@ -11,7 +11,7 @@ export type StatusBoxThemeables =
| "StatusBar";

const getStatusBoxTheme = (component: StatusBoxThemeables) =>
getTheme("StatusBox", component);
getComponentTheme("StatusBox", component);

export interface StatusBoxProps {
title: string;
Expand Down Expand Up @@ -68,14 +68,7 @@ interface StatusBarProps {
const StatusBar = styled.div<StatusBarProps>`
height: 6px;
border-radius: 6px;
background: ${({ status }) =>
status === "GREEN"
? "green"
: status === "YELLOW"
? "yellow"
: status === "GREY"
? "grey"
: "red"};
background: ${({ status }) => getColor(status)};
${getStatusBoxTheme("StatusBar")}
`;
Expand Down
31 changes: 8 additions & 23 deletions client/components/theme.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,14 @@
import { css } from "styled-components";
import { CSSObject, StyledComponent } from "styled-components";
import { CSSObject } from "styled-components";
import { CategoryThemeable } from "./Category";
import { ConnectionStatusThemable } from "./ConnectionStatus";
import { ItemThemable } from "./Item";
import { StatusBoxThemeables } from "./StatusBox";

type CSSThemeable<T extends string> = { [key in T]: CSSObject };
type CSSThemeable<T extends string> = { [key in T]?: CSSObject | undefined };

export interface ComponentThemes {
Category?: CSSThemeable<CategoryThemeable>;
ConnectionStatus?: CSSThemeable<ConnectionStatusThemable>;
Item?: CSSThemeable<ItemThemable>;
StatusBox?: CSSThemeable<StatusBoxThemeables>;
}

export interface Theme {
components: ComponentThemes;
}

export function getTheme<
P extends keyof ComponentThemes,
T extends ComponentThemes[P]
>(parent: P, component: T) {
return ({ theme }: { theme: any }) =>
css(theme.components?.[parent]?.[component] ?? {});
}

getTheme('ConnectionStatus', '')
export type ComponentThemes = {
Category: CSSThemeable<CategoryThemeable>;
ConnectionStatus: CSSThemeable<ConnectionStatusThemable>;
Item: CSSThemeable<ItemThemable>;
StatusBox: CSSThemeable<StatusBoxThemeables>;
};
5 changes: 5 additions & 0 deletions client/default-theme.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Theme } from "./";

declare module "styled-components" {
export interface DefaultTheme extends Theme {}
}
5 changes: 5 additions & 0 deletions client/pages/Home/Home.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ fragment FullConnection on Connection {
}

query Init {
theme
serverTime
categories {
...FullCategory
Expand All @@ -51,3 +52,7 @@ subscription Categories {
subscription ServerTime {
serverTime
}

subscription Theme {
theme
}
Loading

0 comments on commit adbae34

Please sign in to comment.