Skip to content

Commit

Permalink
[HTD-13]: Adds theme toggle (#8)
Browse files Browse the repository at this point in the history
* feat(HTD-13): add initial theme toggle

* feat(HTD-13): adds theme toggle component

* feat(HTD-13): add support to change the theme with handleKeyPress

* feat(HTD-13): adds temp showcase component

* feat(HTD-13): add more text examples

* feat(HTD-13): add more text examples

* feat(HTD-13): remove unused ts nocheck

* feat(HTD-13): add support for text gradient
  • Loading branch information
nephlin7 authored Feb 24, 2024
1 parent 9d810f8 commit 1fc00c1
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 84 deletions.
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { StyledLayout } from '@/components/layout/styled-layout';
import { siteMetadata } from '@/lib/site-metadata';
import StyledComponentsRegistry from '@/styles/styled-component-registry';

const dmSansFont = DM_Sans({ subsets: ['latin'] });
const dmSansFont = DM_Sans({ subsets: ['latin'], weight: ['400', '500', '600', '700'] });

export const metadata: Metadata = {
title: 'Create Next App',
Expand Down
98 changes: 73 additions & 25 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,83 @@
import { Container } from '@/components/elements/container';
import { Heading } from '@/components/elements/heading';
import ShowCase from '@/components/elements/showcase';
import { Text } from '@/components/elements/text';
import { ThemeToggle } from '@/components/elements/theme-toggle';

export default async function Home() {
return (
<Container>
<Heading>What is HTTP Toolkit? - XL</Heading>
<Heading as="h2" fontSize="l">
What is HTTP Toolkit? - L
</Heading>
<Heading as="h3" fontSize="m">
What is HTTP Toolkit? - M
</Heading>
<Heading as="h4" fontSize="s" color="cinnarbarRed">
What is HTTP Toolkit? - S
</Heading>
<Heading as="h5" fontSize="xs">
What is HTTP Toolkit? - XS
</Heading>
<Text textAlign="center">
This is a paragraph Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or
inject errors
</Text>
<Text color="electricLightBlue">
This is a paragraph Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or
inject errors
</Text>
<Text color="cinnarbarRed" fontWeight="medium">
This is a paragraph orange and bold, Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite,
redirect, or inject errors
</Text>
<ShowCase title="Heading">
<Heading color="textGradient">XL Text Gradient</Heading>
<Heading color="cinnarbarRed">What is HTTP Toolkit? - XL</Heading>
<Heading as="h2" fontSize="l">
What is HTTP Toolkit? - L
</Heading>
<Heading as="h3" fontSize="m">
What is HTTP Toolkit? - M
</Heading>
<Heading as="h4" fontSize="s">
What is HTTP Toolkit? - S
</Heading>
<Heading as="h4" fontSize="s" fontWeight="medium">
What is HTTP Toolkit? - S Medium
</Heading>
<Heading as="h5" fontSize="xs">
What is HTTP Toolkit? - XS
</Heading>
<Heading as="h5" fontSize="xs" fontWeight="medium">
What is HTTP Toolkit? - XS Medium
</Heading>
</ShowCase>

<ShowCase title="Text">
<Text fontSize="xl">
XL Regular: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors.
</Text>
<Text fontSize="xl" fontWeight="medium">
XL Medium: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors.
</Text>
<Text fontSize="l">
L Regular: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors
</Text>
<Text fontSize="l" fontWeight="medium">
L Medium: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors
</Text>
<Text fontSize="l" fontWeight="semibold">
L Semibold: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors
</Text>
<Text fontSize="m">
M: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject errors
</Text>
<Text fontSize="s">
S: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject errors
</Text>
<Text fontSize="s" fontWeight="medium">
S Medium: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors
</Text>
<Text fontSize="s" fontWeight="semibold">
S Semibold: Intercept & view all your HTTP(S) Mock endpoints or entire servers Rewrite, redirect, or inject
errors
</Text>
<Text as="span" fontSize="xll" fontWeight="bold">
Label XL
</Text>
<Text as="span" fontSize="l" fontWeight="bold">
Label L
</Text>
<Text as="span" fontSize="s" fontWeight="bold">
Label M
</Text>
</ShowCase>
<ShowCase title="Theme toggle">
<ThemeToggle />
</ShowCase>
</Container>
);
}
12 changes: 7 additions & 5 deletions src/components/elements/heading/heading.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import type { HeadingProps } from './heading.types';
import { styled } from '@/styles';

const lineHeightMap = {
xl: '110%',
l: '110%',
m: '110%',
s: '130%',
xs: '130%',
xl: 1.1,
l: 1.1,
m: 1.1,
s: 1.3,
xs: 1.3,
};

export const StyledHeading = styled.h1<HeadingProps>`
Expand All @@ -19,6 +19,8 @@ export const StyledHeading = styled.h1<HeadingProps>`
line-height: ${({ fontSize }) => lineHeightMap[fontSize || 'xl']};
text-align: ${({ textAlign: align }) => align || 'initial'};
${({ color, theme }) => color === 'textGradient' && theme.colors.text.textGradient}
@media (min-width: ${({ theme }) => theme.screens.xl}) {
font-size: ${({ theme, fontSize }) => theme.fontSizes.heading.desktop[fontSize || 'xl'].toString()};
}
Expand Down
28 changes: 28 additions & 0 deletions src/components/elements/showcase/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use client';

import { styled } from '@/styles';

const ShowCaseWrapper = styled.fieldset`
border: 1px dashed ${({ theme }) => theme.colors.cinnarbarRed};
padding: 20px;
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 5px;
border-radius: 5px;
`;

interface ShowCaseProps {
title: string;
}

const ShowCase = ({ children, title }: Component<ShowCaseProps>) => {
return (
<ShowCaseWrapper>
<legend>{title}</legend>
{children}
</ShowCaseWrapper>
);
};

export default ShowCase;
5 changes: 3 additions & 2 deletions src/components/elements/text/text.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { styled } from '@/styles';

export const StyledText = styled.p<TextProps>`
font-size: ${({ theme, fontSize }) => theme.fontSizes.text[fontSize || 'm']};
color: ${({ theme, color }) => theme.colors.text[color || 'lightGrey']};
color: ${({ theme, color }) => theme.colors.text[color || 'darkGrey']};
font-weight: ${({ theme, fontWeight }) => theme.fontWeight[fontWeight || 'normal']};
text-align: ${({ textAlign }) => textAlign || 'initial'};
line-height: 150%;
line-height: ${({ as }) => (as === 'span' ? 1.1 : 1.5)};
letter-spacing: ${({ as }) => (as === 'span' ? '0.06rem' : 'initial')};
`;
47 changes: 47 additions & 0 deletions src/components/elements/theme-toggle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use client';

import type { ChangeEvent, KeyboardEvent } from 'react';
import { useEffect, useState } from 'react';

import {
StyledIconsWrapper,
StyledInput,
StyledLabel,
StyledMoon,
StyledSun,
StyledSwitch,
} from './theme-toggle.styles';

export const ThemeToggle = () => {
const [isLight, setIsLight] = useState(false);

useEffect(() => {
const html = document.querySelector('html') as HTMLHtmlElement;
if (isLight) {
html.classList.add('light');
} else {
html.classList.remove('light');
}
}, [isLight]);

const handleThemeChange = (e: ChangeEvent<HTMLInputElement>) => {
setIsLight(e.target.checked);
};

const handleKeyPress = (event: KeyboardEvent<HTMLLabelElement>) => {
if (event.key === 'Enter') {
setIsLight(v => !v);
}
};

return (
<StyledLabel tabIndex={1} onKeyDown={handleKeyPress}>
<StyledIconsWrapper>
<StyledMoon weight="fill" data-is-active={!isLight} />
<StyledSun weight="fill" data-is-active={isLight} />
</StyledIconsWrapper>
<StyledInput checked={isLight} type="checkbox" aria-checked={isLight} onChange={handleThemeChange} />
<StyledSwitch />
</StyledLabel>
);
};
79 changes: 79 additions & 0 deletions src/components/elements/theme-toggle/theme-toggle.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use client';

import type { IconProps } from '@phosphor-icons/react';
import { Moon, Sun } from '@phosphor-icons/react';

import { styled, css } from '@/styles';

const iconStyles = css`
fill: ${({ theme }) => theme.colors.text.darkGrey};
&[data-is-active='true'] {
fill: ${({ theme }) => theme.colors.white};
}
`;

export const StyledLabel = styled.label`
--icon-size: 48px;
max-width: 98px;
border-radius: 12px;
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
box-shadow: 0 0 8px ${({ theme }) => theme.colors.shadowDefault};
`;

export const StyledMoon = styled(Moon)<IconProps>`
${iconStyles};
`;

export const StyledSun = styled(Sun)<IconProps>`
${iconStyles};
`;

export const StyledSwitch = styled.div`
position: relative;
width: 98px;
height: 50px;
background: ${({ theme }) => theme.colors.inkBlack};
border-radius: 12px;
padding: 4px;
transition: 350ms all ease-in;
border: 1px solid ${({ theme }) => theme.colors.mediumGrey};
&:before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: var(--icon-size);
height: var(--icon-size);
border-radius: 11px;
background: ${({ theme }) => theme.colors.darkGrey};
transform: translate(0, -50%);
transition: 350ms all ease-in;
}
`;

export const StyledInput = styled.input`
opacity: 0;
position: absolute;
&:checked + ${StyledSwitch} {
background: ${({ theme }) => theme.colors.inkBlack};
&:before {
transform: translate(var(--icon-size), -50%);
}
}
`;

export const StyledIconsWrapper = styled.span`
position: absolute;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-around;
width: 96px;
`;
Loading

0 comments on commit 1fc00c1

Please sign in to comment.