├── .eslintrc.json
├── src
├── app
│ ├── globals.css
│ ├── page.tsx
│ └── layout.tsx
├── lib
│ └── utils.ts
└── components
│ ├── Footer.tsx
│ ├── About.tsx
│ ├── Hero.tsx
│ ├── ui
│ ├── badge.tsx
│ └── button.tsx
│ ├── Skills.tsx
│ └── Navbar.tsx
├── next.config.js
├── postcss.config.js
├── public
├── favicon.svg
├── vercel.svg
└── next.svg
├── components.json
├── README.md
├── .gitignore
├── tsconfig.json
├── package.json
└── tailwind.config.ts
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {}
3 |
4 | module.exports = nextConfig
5 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { type ClassValue, clsx } from "clsx"
2 | import { twMerge } from "tailwind-merge"
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs))
6 | }
7 |
--------------------------------------------------------------------------------
/public/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "\u0015src/app/globals.css",
9 | "baseColor": "slate",
10 | "cssVariables": false
11 | },
12 | "aliases": {
13 | "components": "@/components",
14 | "utils": "@/lib/utils"
15 | }
16 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dynamic Island
2 |
3 | Dynamic Island is a responsive navbar feature that you can use on your own website. Try it [Dynamic Island](https://dynamic-island-self.vercel.app/)
4 |
5 | ## Feature
6 |
7 | - Dynamic Navbar
8 | - Responsive Design
9 | - Shadcn UI componets
10 | - Tailwind Css
11 |
12 | ## Tech Stack
13 |
14 | - Next.js
15 | - Typescript
16 | - Tailwind Css
17 | - Shadcn UI
18 | - Framer Motion
19 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import About from '@/components/About';
2 | import { Footer } from '@/components/Footer';
3 | import { Hero } from '@/components/Hero';
4 | import Navbar from '@/components/Navbar';
5 | import Skills from '@/components/Skills';
6 |
7 | export default function Home() {
8 | return (
9 | <>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | >
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./src/*"]
23 | }
24 | },
25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from 'next';
2 | import { Inter, Roboto_Mono } from 'next/font/google';
3 | import './globals.css';
4 |
5 | // const inter = Inter({ subsets: ['latin'] });
6 | const robotoMono = Roboto_Mono({ subsets: ['latin'] });
7 |
8 | export const metadata: Metadata = {
9 | title: 'Dynamic island ',
10 | description: 'created by spacecode',
11 | };
12 |
13 | export default function RootLayout({
14 | children,
15 | }: {
16 | children: React.ReactNode;
17 | }) {
18 | return (
19 |
20 |
21 |
22 |
23 | {children}
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dynamic-island",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@radix-ui/react-slot": "^1.0.2",
13 | "class-variance-authority": "^0.7.0",
14 | "clsx": "^2.0.0",
15 | "framer-motion": "^10.16.5",
16 | "lucide-react": "^0.292.0",
17 | "next": "14.0.2",
18 | "react": "^18",
19 | "react-dom": "^18",
20 | "tailwind-merge": "^2.0.0",
21 | "tailwindcss-animate": "^1.0.7"
22 | },
23 | "devDependencies": {
24 | "@types/node": "^20",
25 | "@types/react": "^18",
26 | "@types/react-dom": "^18",
27 | "autoprefixer": "^10.0.1",
28 | "eslint": "^8",
29 | "eslint-config-next": "14.0.2",
30 | "postcss": "^8",
31 | "tailwindcss": "^3.3.0",
32 | "typescript": "^5"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { GithubIcon, Twitter } from 'lucide-react';
2 | import Link from 'next/link';
3 |
4 | export const Footer = () => {
5 | return (
6 |
7 |
8 | ©2023 This page is just a sample of Dynamic Island
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/components/About.tsx:
--------------------------------------------------------------------------------
1 | export default function About() {
2 | return (
3 |
7 |
8 | {'//About'}
9 |
10 |
11 |
12 | Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo
13 | deleniti provident, nesciunt voluptate temporibus, deserunt iure
14 | cumque hic ab maiores, non nulla repellendus possimus odio aliquid
15 | ipsa obcaecati ex soluta.
16 |
17 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint dolor
18 | rem excepturi, est rerum itaque velit dignissimos deleniti facilis eos
19 | non, nulla aut corrupti assumenda provident laborum voluptas sed
20 | eligendi?
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/Hero.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from './ui/button';
2 |
3 | export const Hero = () => {
4 | return (
5 |
6 |
7 |
8 |
9 | Welcome to my
10 |
11 | Front-end Developer
12 |
13 | Portfolio
14 |
15 |
16 |
17 |
18 | Contact
19 |
20 | Download CV
21 |
22 |
23 |
24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/ui/badge.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { cva, type VariantProps } from 'class-variance-authority';
3 |
4 | import { cn } from '@/lib/utils';
5 |
6 | const badgeVariants = cva(
7 | 'inline-flex items-center rounded-full border border-slate-200 px-2.5 py-0.5 text-base font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 dark:border-slate-800 dark:focus:ring-slate-300',
8 | {
9 | variants: {
10 | variant: {
11 | default:
12 | 'border-transparent bg-slate-900 text-slate-50 hover:bg-slate-900/80 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/80',
13 | secondary:
14 | 'border-transparent bg-slate-100 text-slate-900 hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80',
15 | destructive:
16 | 'border-transparent bg-red-500 text-slate-50 hover:bg-red-500/80 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/80',
17 | outline: 'text-slate-950 dark:text-slate-50',
18 | },
19 | },
20 | defaultVariants: {
21 | variant: 'default',
22 | },
23 | }
24 | );
25 |
26 | export interface BadgeProps
27 | extends React.HTMLAttributes,
28 | VariantProps {}
29 |
30 | function Badge({ className, variant, ...props }: BadgeProps) {
31 | return (
32 |
33 | );
34 | }
35 |
36 | export { Badge, badgeVariants };
37 |
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | darkMode: ['class'],
4 | content: [
5 | './pages/**/*.{ts,tsx}',
6 | './components/**/*.{ts,tsx}',
7 | './app/**/*.{ts,tsx}',
8 | './src/**/*.{ts,tsx}',
9 | ],
10 | theme: {
11 | container: {
12 | center: true,
13 | padding: '2rem',
14 | screens: {
15 | '2xl': '1400px',
16 | },
17 | },
18 | extend: {
19 | keyframes: {
20 | 'accordion-down': {
21 | from: { height: 0 },
22 | to: { height: 'var(--radix-accordion-content-height)' },
23 | },
24 | 'accordion-up': {
25 | from: { height: 'var(--radix-accordion-content-height)' },
26 | to: { height: 0 },
27 | },
28 | animatedgradient: {
29 | '0%': { backgroundPosition: '0% 50%' },
30 | '50%': { backgroundPosition: '100% 50%' },
31 | '100%': { backgroundPosition: '0% 50%' },
32 | },
33 | },
34 | backgroundSize: {
35 | '300%': '300%',
36 | },
37 | animation: {
38 | 'accordion-down': 'accordion-down 0.2s ease-out',
39 | 'accordion-up': 'accordion-up 0.2s ease-out',
40 | gradient: 'animatedgradient 6s ease infinite alternate',
41 | },
42 | colors: {
43 | primary: '#1B1B1F',
44 | secondary: '#3F96FE',
45 | accent: '#6A52FF',
46 | white: '#FCFCFC',
47 | beige: '#F8F7F4',
48 | },
49 | },
50 | },
51 | plugins: [require('tailwindcss-animate')],
52 | };
53 |
--------------------------------------------------------------------------------
/src/components/Skills.tsx:
--------------------------------------------------------------------------------
1 | import { Badge } from './ui/badge';
2 |
3 | export default function Skills() {
4 | return (
5 |
9 | {'//Skills'}
10 |
11 |
12 |
13 |
Tech Stack |
14 | Design
15 |
16 |
17 |
18 |
19 | HTML
20 | CSS
21 | Javascript
22 | Tailwind
23 | Typescript
24 | React
25 | Next.js
26 | Figma
27 | Shadcn UI
28 | MUI
29 |
30 |
31 |
32 |
Soft Skills
33 |
34 |
35 | Communication
36 | Deep Work
37 | Time-management
38 |
39 |
40 |
41 |
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Slot } from '@radix-ui/react-slot';
3 | import { cva, type VariantProps } from 'class-variance-authority';
4 |
5 | import { cn } from '@/lib/utils';
6 |
7 | const buttonVariants = cva(
8 | 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-slate-950 dark:focus-visible:ring-slate-300',
9 | {
10 | variants: {
11 | variant: {
12 | default:
13 | 'bg-slate-900 text-slate-50 hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90',
14 | destructive:
15 | 'bg-red-500 text-slate-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/90',
16 | outline:
17 | 'border border-slate-200 bg-white hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50',
18 | secondary:
19 | 'bg-slate-100 text-slate-900 hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80',
20 | ghost:
21 | 'hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-slate-800 dark:hover:text-slate-50',
22 | link: 'text-slate-900 underline-offset-4 hover:underline dark:text-slate-50',
23 | accent:
24 | 'bg-gradient-to-tl from-secondary hover:from-10% to-accent hover:to-60% rounded-[18px]',
25 | },
26 | size: {
27 | default: 'h-10 px-4 py-2',
28 | sm: 'h-9 rounded-md px-3',
29 | lg: 'h-11 rounded-md px-8',
30 | icon: 'h-10 w-10',
31 | },
32 | },
33 | defaultVariants: {
34 | variant: 'default',
35 | size: 'default',
36 | },
37 | }
38 | );
39 |
40 | export interface ButtonProps
41 | extends React.ButtonHTMLAttributes,
42 | VariantProps {
43 | asChild?: boolean;
44 | }
45 |
46 | const Button = React.forwardRef(
47 | ({ className, variant, size, asChild = false, ...props }, ref) => {
48 | const Comp = asChild ? Slot : 'button';
49 | return (
50 |
55 | );
56 | }
57 | );
58 | Button.displayName = 'Button';
59 |
60 | export { Button, buttonVariants };
61 |
--------------------------------------------------------------------------------
/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import Image from 'next/image';
4 | import { Button } from './ui/button';
5 | import { ChevronDown, ChevronUp } from 'lucide-react';
6 | import { motion, useScroll, useMotionValueEvent } from 'framer-motion';
7 | import { useState } from 'react';
8 | import Link from 'next/link';
9 |
10 | export default function Navbar() {
11 | const [showNav, setShowNav] = useState(false);
12 | const [hidden, setHidden] = useState(false);
13 |
14 | const { scrollY } = useScroll();
15 |
16 | useMotionValueEvent(scrollY, 'change', (latest) => {
17 | const previous = scrollY.getPrevious();
18 |
19 | if (latest > previous && latest > 150) {
20 | setHidden(true);
21 | setShowNav(false);
22 | } else {
23 | setHidden(false);
24 | }
25 | });
26 |
27 | return (
28 |
56 |
57 |
58 |
59 |
83 |
84 | {'//About'}
85 |
86 |
87 | {'//Skills'}
88 |
89 |
90 | {'//Projects'}
91 |
92 |
93 |
94 |
109 |
110 | Contact
111 |
112 |
113 |
114 | {
119 | setHidden(false);
120 | setShowNav((prev) => !prev);
121 | }}
122 | >
123 | {showNav ? : }
124 |
125 |
126 | );
127 | }
128 |
--------------------------------------------------------------------------------