diff --git a/src/components/DrumMachine/DrumMachine.jsx b/src/components/DrumMachine/DrumMachine.jsx
index eea40a0..3e7bdb7 100644
--- a/src/components/DrumMachine/DrumMachine.jsx
+++ b/src/components/DrumMachine/DrumMachine.jsx
@@ -1,7 +1,30 @@
+'use client';
import React from 'react';
+import useSound from 'use-sound';
+
+import styles from './DrumMachine.module.css';
+
+const SOUND_SRC = '/909-drums.mp3';
function DrumMachine() {
- return
;
+ const [play] = useSound(SOUND_SRC, {
+ sprite: {
+ kick: [0, 350],
+ hihat: [374, 160],
+ snare: [666, 290],
+ cowbell: [968, 200],
+ },
+ soundEnabled: true,
+ });
+
+ return (
+
+
+
+
+
+
+ );
}
export default DrumMachine;
diff --git a/src/components/DrumMachine/DrumMachine.module.css b/src/components/DrumMachine/DrumMachine.module.css
new file mode 100644
index 0000000..e536138
--- /dev/null
+++ b/src/components/DrumMachine/DrumMachine.module.css
@@ -0,0 +1,28 @@
+.wrapper {
+ display: flex;
+ gap: 8px;
+}
+
+.wrapper button {
+ background: hsl(234deg 54% 53%);
+ color: white;
+ font-size: 1.5rem;
+ font-weight: 900;
+ flex: 1;
+ padding-block: 8px;
+ border: 4px solid;
+ border-top-color: hsl(234deg 54% 72%);
+ border-left-color: hsl(234deg 54% 65%);
+ border-right-color: hsl(234deg 54% 60%);
+ border-bottom-color: hsl(234deg 54% 30%);
+ border-radius: 2px;
+ cursor: pointer;
+}
+
+.wrapper button:active {
+ background: hsl(234deg 54% 45%);
+ border-top-color: hsl(234deg 54% 30%);
+ border-left-color: hsl(234deg 54% 40%);
+ border-right-color: hsl(234deg 54% 45%);
+ border-bottom-color: hsl(234deg 54% 60%);
+}
diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx
index 6731459..1dba373 100644
--- a/src/components/Header/Header.jsx
+++ b/src/components/Header/Header.jsx
@@ -1,7 +1,36 @@
+'use client';
import React from 'react';
+import { Volume2, VolumeX } from 'react-feather';
+import Link from 'next/link';
+
+import VisuallyHidden from '../VisuallyHidden';
+import MaxWidthWrapper from '../MaxWidthWrapper';
+import styles from './Header.module.css';
function Header() {
- return ;
+ const id = React.useId();
+
+ // TODO: Global state?
+ const soundEnabled = true;
+
+ return (
+
+
+ Kool Website
+
+
+
+
+ );
}
export default Header;
diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css
new file mode 100644
index 0000000..fcbe5a0
--- /dev/null
+++ b/src/components/Header/Header.module.css
@@ -0,0 +1,47 @@
+.wrapper {
+ padding: 16px;
+ margin-bottom: 6rem;
+ background: hsl(234deg 70% 85% / 0.9);
+ backdrop-filter: blur(4px);
+ border-bottom: 8px dashed hsl(234deg 54% 53%);
+ outline: 4px solid hsl(234deg 70% 85% / 0.9);
+ /* prettier-ignore */
+ box-shadow:
+ 0px 2px 4px hsl(234deg 40% 30% / 0.2),
+ 0px 4px 8px hsl(234deg 40% 30% / 0.2),
+ 0px 8px 16px hsl(234deg 40% 30% / 0.2),
+ 0px 16px 32px hsl(234deg 40% 30% / 0.2);
+}
+
+.innerWrapper {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.innerWrapper a {
+ font-size: 1.5rem;
+ color: inherit;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+.innerWrapper button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 48px;
+ height: 48px;
+ border: 3px solid hsl(0deg 0% 85%);
+ border-top-color: hsl(0deg 0% 100%);
+ border-bottom-color: hsl(0deg 0% 70%);
+ background: hsl(0deg 0% 93%);
+}
+
+.innerWrapper button:active {
+ border-top-color: hsl(0deg 0% 60%);
+ border-left-color: hsl(0deg 0% 75%);
+ border-right-color: hsl(0deg 0% 75%);
+ border-bottom-color: hsl(0deg 0% 92%);
+ background: hsl(0deg 0% 85%);
+}
diff --git a/src/components/MaxWidthWrapper/MaxWidthWrapper.jsx b/src/components/MaxWidthWrapper/MaxWidthWrapper.jsx
index 620a063..f3d3f9f 100644
--- a/src/components/MaxWidthWrapper/MaxWidthWrapper.jsx
+++ b/src/components/MaxWidthWrapper/MaxWidthWrapper.jsx
@@ -1,7 +1,17 @@
import React from 'react';
+import styles from './MaxWidthWrapper.module.css';
-function MaxWidthWrapper() {
- return ;
+function MaxWidthWrapper({
+ children,
+ as: Tag = 'div',
+ className = '',
+ ...delegated
+}) {
+ return (
+
+ {children}
+
+ );
}
export default MaxWidthWrapper;
diff --git a/src/components/MaxWidthWrapper/MaxWidthWrapper.module.css b/src/components/MaxWidthWrapper/MaxWidthWrapper.module.css
new file mode 100644
index 0000000..a08e97d
--- /dev/null
+++ b/src/components/MaxWidthWrapper/MaxWidthWrapper.module.css
@@ -0,0 +1,5 @@
+.wrapper {
+ max-width: 700px;
+ margin-inline: auto;
+ padding-inline: 16px;
+}
diff --git a/src/components/VisuallyHidden/VisuallyHidden.jsx b/src/components/VisuallyHidden/VisuallyHidden.jsx
index 8c2d072..cc0b70d 100644
--- a/src/components/VisuallyHidden/VisuallyHidden.jsx
+++ b/src/components/VisuallyHidden/VisuallyHidden.jsx
@@ -1,7 +1,24 @@
-import React from 'react';
+// These styles will make sure the component
+// is not visible, but will still be announced
+// by screen readers.
+//
+// Adding “display: none” would hide the
+// element from ALL users, including those
+// using screen-readers.
+const hiddenStyles = {
+ display: 'inline-block',
+ position: 'absolute',
+ overflow: 'hidden',
+ clip: 'rect(0 0 0 0)',
+ height: 1,
+ width: 1,
+ margin: -1,
+ padding: 0,
+ border: 0,
+};
-function VisuallyHidden() {
- return ;
-}
+const VisuallyHidden = ({ children }) => {
+ return {children};
+};
export default VisuallyHidden;