diff --git a/src/components/CodeShowcase/index.tsx b/src/components/CodeShowcase/index.tsx new file mode 100644 index 0000000..fd5bea8 --- /dev/null +++ b/src/components/CodeShowcase/index.tsx @@ -0,0 +1,175 @@ +import React, { useState } from 'react'; +import CodeBlock from '@theme/CodeBlock'; +import Heading from '@theme/Heading'; +import styles from './styles.module.css'; + +interface CodeExample { + title: string; + description: string; + code: string; + output?: string; +} + +const examples: CodeExample[] = [ + { + title: 'Simple Build', + description: 'A basic build workflow with dependencies', + code: `# Simple psakeFile.ps1 +Task Default -Depends Build + +Task Build -Depends Clean, Compile { + Write-Host "Build completed!" -ForegroundColor Green +} + +Task Clean { + Remove-Item ./bin -Recurse -Force -ErrorAction Ignore +} + +Task Compile { + dotnet build -c Release +}`, + output: `psake version 4.9.0 +Copyright (c) 2010-2024 James Kovacs & Contributors + +Executing Clean +Executing Compile +Executing Build +Build completed! + +Build Succeeded!` + }, + { + title: 'CI/CD Pipeline', + description: 'Automated testing and deployment pipeline', + code: `# CI/CD psakeFile.ps1 +Task Default -Depends Test + +Task CI -Depends Clean, Build, Test, Deploy + +Task Build { + dotnet build -c Release +} + +Task Test -Depends Build { + dotnet test --no-build --logger "trx" +} + +Task Deploy -Depends Test -RequiredVariables Environment { + Write-Host "Deploying to $Environment" -ForegroundColor Cyan + # Deployment logic +} + +Task Clean { + Remove-Item ./bin, ./TestResults -Recurse -Force -ErrorAction Ignore +}`, + output: `Executing CI +Executing Clean +Executing Build +Executing Test +Test run for MyProject.Tests.dll (.NETCoreApp,Version=v8.0) +Passed! - Tests: 42 (42 passed, 0 failed, 0 skipped) +Executing Deploy +Deploying to Production + +Build Succeeded!` + }, + { + title: 'Multi-Environment', + description: 'Deploy to different environments with configurations', + code: `# Environment-aware psakeFile.ps1 +Properties { + $Environment = "Dev" + $Version = "1.0.0" +} + +Task Default -Depends Deploy + +Task Deploy -Depends Build { + switch ($Environment) { + "Dev" { + Write-Host "Deploying to Dev..." -ForegroundColor Yellow + Invoke-Expression "./scripts/deploy-dev.ps1" + } + "Staging" { + Write-Host "Deploying to Staging..." -ForegroundColor Cyan + Invoke-Expression "./scripts/deploy-staging.ps1" + } + "Production" { + Write-Host "Deploying to Production..." -ForegroundColor Magenta + Invoke-Expression "./scripts/deploy-prod.ps1" + } + } +} + +Task Build { + dotnet publish -c Release -p:Version=$Version +}`, + output: `Properties: + Environment = Dev + Version = 1.0.0 + +Executing Deploy +Executing Build +Deploying to Dev... + +Build Succeeded!` + } +]; + +export default function CodeShowcase(): JSX.Element { + const [activeTab, setActiveTab] = useState(0); + const activeExample = examples[activeTab]; + + return ( +
+
+
+ See psake in Action +

+ Real-world examples showing how psake simplifies build automation +

+
+ +
+
+ {examples.map((example, index) => ( + + ))} +
+ +
+

{activeExample.description}

+ +
+
+
+ psakeFile.ps1 +
+ + {activeExample.code} + +
+ + {activeExample.output && ( +
+
+ Terminal Output +
+ + {activeExample.output} + +
+ )} +
+
+
+
+
+ ); +} diff --git a/src/components/CodeShowcase/styles.module.css b/src/components/CodeShowcase/styles.module.css new file mode 100644 index 0000000..4b16f08 --- /dev/null +++ b/src/components/CodeShowcase/styles.module.css @@ -0,0 +1,156 @@ +.showcaseSection { + padding: 4rem 0; + background: var(--ifm-background-surface-color); +} + +[data-theme='dark'] .showcaseSection { + background: var(--ifm-background-color); +} + +.showcaseHeader { + text-align: center; + margin-bottom: 3rem; +} + +.showcaseHeader h2 { + font-size: 2.5rem; + margin-bottom: 1rem; +} + +.showcaseSubtitle { + font-size: 1.25rem; + color: var(--ifm-color-emphasis-700); + max-width: 600px; + margin: 0 auto; +} + +.tabContainer { + max-width: 1200px; + margin: 0 auto; +} + +.tabs { + display: flex; + gap: 0.5rem; + margin-bottom: 2rem; + border-bottom: 2px solid var(--ifm-color-emphasis-200); + overflow-x: auto; + flex-wrap: wrap; +} + +.tab { + background: transparent; + border: none; + padding: 1rem 1.5rem; + font-size: 1rem; + font-weight: 500; + color: var(--ifm-color-emphasis-600); + cursor: pointer; + border-bottom: 3px solid transparent; + transition: all 0.2s ease; + white-space: nowrap; +} + +.tab:hover { + color: var(--ifm-color-primary); + background: var(--ifm-color-emphasis-100); +} + +.tabActive { + color: var(--ifm-color-primary) !important; + border-bottom-color: var(--ifm-color-primary) !important; + font-weight: 600; +} + +[data-theme='dark'] .tab:hover { + background: var(--ifm-color-emphasis-200); +} + +.tabContent { + animation: fadeIn 0.3s ease; +} + +.exampleDescription { + font-size: 1.125rem; + color: var(--ifm-color-emphasis-700); + margin-bottom: 1.5rem; + text-align: center; +} + +.codeOutputGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1.5rem; +} + +@media screen and (max-width: 996px) { + .codeOutputGrid { + grid-template-columns: 1fr; + } +} + +.codeBlock, +.outputBlock { + background: var(--ifm-background-color); + border-radius: 8px; + overflow: hidden; + border: 1px solid var(--ifm-color-emphasis-200); +} + +[data-theme='dark'] .codeBlock, +[data-theme='dark'] .outputBlock { + background: #1e1e1e; + border-color: var(--ifm-color-emphasis-300); +} + +.codeBlockHeader { + background: var(--ifm-color-emphasis-100); + padding: 0.75rem 1rem; + font-family: var(--ifm-font-family-monospace); + font-size: 0.875rem; + color: var(--ifm-color-emphasis-800); + border-bottom: 1px solid var(--ifm-color-emphasis-200); + font-weight: 500; +} + +[data-theme='dark'] .codeBlockHeader { + background: #2d2d2d; + color: var(--ifm-color-emphasis-600); + border-bottom-color: var(--ifm-color-emphasis-300); +} + +.codeBlock pre, +.outputBlock pre { + margin: 0 !important; + border-radius: 0 !important; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media screen and (max-width: 768px) { + .showcaseHeader h2 { + font-size: 2rem; + } + + .showcaseSubtitle { + font-size: 1rem; + } + + .tabs { + gap: 0.25rem; + } + + .tab { + padding: 0.75rem 1rem; + font-size: 0.875rem; + } +} diff --git a/src/components/FeatureGrid/index.tsx b/src/components/FeatureGrid/index.tsx new file mode 100644 index 0000000..82f9b3b --- /dev/null +++ b/src/components/FeatureGrid/index.tsx @@ -0,0 +1,115 @@ +import React from 'react'; +import CodeBlock from '@theme/CodeBlock'; +import Heading from '@theme/Heading'; +import styles from './styles.module.css'; + +interface Feature { + icon: string; + title: string; + description: string; + code?: string; +} + +const features: Feature[] = [ + { + icon: '🔗', + title: 'Task Dependencies', + description: 'Define clear dependencies between tasks for organized, predictable builds', + code: `Task Deploy -Depends Build, Test { + # Deploy only after build and test succeed +}` + }, + { + icon: '🌍', + title: 'Cross-Platform', + description: 'Runs on Windows, macOS, and Linux with PowerShell 7+', + code: `# Works everywhere PowerShell runs +Task Build { + dotnet build -c Release +}` + }, + { + icon: '⚡', + title: 'Simple Syntax', + description: 'Clean, readable task definitions that are easy to understand and maintain', + code: `Task Clean { + Remove-Item ./bin -Recurse -Force +}` + }, + { + icon: '🔍', + title: 'Built-in Assertions', + description: 'Validate conditions and fail fast with helpful error messages', + code: `Task Deploy { + Assert (Test-Path ./build) "Build folder required" +}` + }, + { + icon: '🚀', + title: 'CI/CD Ready', + description: 'Integrates seamlessly with GitHub Actions, Azure DevOps, and Jenkins', + code: `# GitHub Actions +- run: Invoke-psake -taskList CI + shell: pwsh` + }, + { + icon: '📦', + title: 'Flexible Properties', + description: 'Configure builds with properties and override them at runtime', + code: `Properties { + $Configuration = "Release" +} +# Override: Invoke-psake -properties @{Configuration="Debug"}` + }, + { + icon: '🎯', + title: 'Preconditions', + description: 'Skip tasks conditionally based on your build environment', + code: `Task Deploy -Precondition { $Env -eq "Prod" } { + # Only runs in production +}` + }, + { + icon: '🛠️', + title: 'PowerShell Ecosystem', + description: 'Use any PowerShell module or script in your build tasks', + code: `Task Test { + Invoke-Pester -Path ./tests + # Use Pester, PSScriptAnalyzer, etc. +}` + } +]; + +export default function FeatureGrid(): JSX.Element { + return ( +
+
+
+ Why Choose psake? +

+ Powerful features designed for modern build automation +

+
+ +
+ {features.map((feature, index) => ( +
+
{feature.icon}
+ + {feature.title} + +

{feature.description}

+ {feature.code && ( +
+ + {feature.code} + +
+ )} +
+ ))} +
+
+
+ ); +} diff --git a/src/components/FeatureGrid/styles.module.css b/src/components/FeatureGrid/styles.module.css new file mode 100644 index 0000000..27ac552 --- /dev/null +++ b/src/components/FeatureGrid/styles.module.css @@ -0,0 +1,138 @@ +.featureSection { + padding: 4rem 0; + background: var(--ifm-background-color); +} + +.header { + text-align: center; + margin-bottom: 3rem; +} + +.header h2 { + font-size: 2.5rem; + margin-bottom: 1rem; +} + +.subtitle { + font-size: 1.25rem; + color: var(--ifm-color-emphasis-700); +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + max-width: 1200px; + margin: 0 auto; +} + +.featureCard { + background: var(--ifm-background-surface-color); + padding: 2rem; + border-radius: 12px; + border: 1px solid var(--ifm-color-emphasis-200); + transition: all 0.3s ease; + display: flex; + flex-direction: column; + animation: fadeInUp 0.6s ease-out backwards; +} + +.featureCard:nth-child(1) { animation-delay: 0.05s; } +.featureCard:nth-child(2) { animation-delay: 0.1s; } +.featureCard:nth-child(3) { animation-delay: 0.15s; } +.featureCard:nth-child(4) { animation-delay: 0.2s; } +.featureCard:nth-child(5) { animation-delay: 0.25s; } +.featureCard:nth-child(6) { animation-delay: 0.3s; } +.featureCard:nth-child(7) { animation-delay: 0.35s; } +.featureCard:nth-child(8) { animation-delay: 0.4s; } + +.featureCard:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + border-color: var(--ifm-color-primary); +} + +[data-theme='dark'] .featureCard { + background: #1e1e1e; + border-color: var(--ifm-color-emphasis-300); +} + +[data-theme='dark'] .featureCard:hover { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); +} + +.featureIcon { + font-size: 3rem; + margin-bottom: 1rem; + line-height: 1; +} + +.featureTitle { + font-size: 1.375rem; + margin-bottom: 0.75rem; + color: var(--ifm-color-primary); +} + +.featureDescription { + color: var(--ifm-color-emphasis-700); + margin-bottom: 1rem; + flex-grow: 1; +} + +.featureCode { + margin-top: auto; +} + +.featureCode pre { + margin: 0 !important; + font-size: 0.75rem !important; + padding: 0.75rem !important; + background: var(--ifm-color-emphasis-100) !important; + border-radius: 6px; +} + +[data-theme='dark'] .featureCode pre { + background: #2d2d2d !important; +} + +.miniCode { + font-size: 0.75rem; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media screen and (max-width: 768px) { + .grid { + grid-template-columns: 1fr; + gap: 1.5rem; + } + + .header h2 { + font-size: 2rem; + } + + .subtitle { + font-size: 1rem; + } + + .featureCard { + padding: 1.5rem; + } + + .featureIcon { + font-size: 2.5rem; + } + + .featureTitle { + font-size: 1.25rem; + } +} diff --git a/src/components/GitHubStats/index.tsx b/src/components/GitHubStats/index.tsx new file mode 100644 index 0000000..cbb79f2 --- /dev/null +++ b/src/components/GitHubStats/index.tsx @@ -0,0 +1,65 @@ +import React, { useEffect, useState } from 'react'; +import styles from './styles.module.css'; + +interface GitHubStatsProps { + repo?: string; +} + +interface RepoStats { + stars: number; + forks: number; + watchers: number; +} + +export default function GitHubStats({ repo = 'psake/psake' }: GitHubStatsProps): JSX.Element { + const [stats, setStats] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch(`https://api.github.com/repos/${repo}`) + .then(res => res.json()) + .then(data => { + setStats({ + stars: data.stargazers_count || 0, + forks: data.forks_count || 0, + watchers: data.subscribers_count || 0, + }); + setLoading(false); + }) + .catch(() => { + setLoading(false); + }); + }, [repo]); + + if (loading) { + return ( +
+
+ ... + Stars +
+
+ ); + } + + if (!stats) { + return null; + } + + return ( +
+
+ {stats.stars.toLocaleString()} + ⭐ Stars +
+
+ {stats.forks.toLocaleString()} + 🍴 Forks +
+
+ {stats.watchers.toLocaleString()} + 👁️ Watchers +
+
+ ); +} diff --git a/src/components/GitHubStats/styles.module.css b/src/components/GitHubStats/styles.module.css new file mode 100644 index 0000000..7415797 --- /dev/null +++ b/src/components/GitHubStats/styles.module.css @@ -0,0 +1,46 @@ +.statsContainer { + display: flex; + gap: 2rem; + justify-content: center; + align-items: center; + margin: 1.5rem 0; + flex-wrap: wrap; +} + +.statItem { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.25rem; +} + +.statValue { + font-size: 1.75rem; + font-weight: bold; + color: var(--ifm-color-primary); +} + +[data-theme='dark'] .statValue { + color: var(--ifm-color-primary-lighter); +} + +.statLabel { + font-size: 0.875rem; + color: var(--ifm-color-emphasis-600); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +@media screen and (max-width: 768px) { + .statsContainer { + gap: 1rem; + } + + .statValue { + font-size: 1.5rem; + } + + .statLabel { + font-size: 0.75rem; + } +} diff --git a/src/components/HeroCodePreview/index.tsx b/src/components/HeroCodePreview/index.tsx new file mode 100644 index 0000000..b847660 --- /dev/null +++ b/src/components/HeroCodePreview/index.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import CodeBlock from '@theme/CodeBlock'; +import styles from './styles.module.css'; + +const sampleCode = `# psakeFile.ps1 +Task Default -Depends Test, Build + +Task Build -Depends Clean { + Write-Host "Building project..." -ForegroundColor Green + dotnet build -c Release +} + +Task Test { + Write-Host "Running tests..." -ForegroundColor Cyan + dotnet test --no-build +} + +Task Clean { + Write-Host "Cleaning output..." -ForegroundColor Yellow + Remove-Item ./bin -Recurse -Force -ErrorAction Ignore +} + +Task Deploy -Depends Build { + Write-Host "Deploying to production..." -ForegroundColor Magenta + # Your deployment logic here +}`; + +export default function HeroCodePreview(): JSX.Element { + return ( +
+
+
+ + + +
+
psakeFile.ps1
+
+
+ + {sampleCode} + +
+
+ ); +} diff --git a/src/components/HeroCodePreview/styles.module.css b/src/components/HeroCodePreview/styles.module.css new file mode 100644 index 0000000..cfc88d1 --- /dev/null +++ b/src/components/HeroCodePreview/styles.module.css @@ -0,0 +1,96 @@ +.codePreview { + background: var(--ifm-background-surface-color); + border-radius: 12px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + border: 1px solid var(--ifm-color-emphasis-200); + max-width: 600px; + animation: fadeInUp 0.6s ease-out; +} + +[data-theme='dark'] .codePreview { + background: #1e1e1e; + border-color: var(--ifm-color-emphasis-300); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); +} + +.terminalHeader { + display: flex; + align-items: center; + padding: 0.75rem 1rem; + background: var(--ifm-color-emphasis-100); + border-bottom: 1px solid var(--ifm-color-emphasis-200); + gap: 1rem; +} + +[data-theme='dark'] .terminalHeader { + background: #2d2d2d; + border-bottom-color: var(--ifm-color-emphasis-300); +} + +.terminalButtons { + display: flex; + gap: 0.5rem; +} + +.terminalButton { + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--ifm-color-emphasis-400); +} + +.terminalButton:nth-child(1) { + background: #ff5f56; +} + +.terminalButton:nth-child(2) { + background: #ffbd2e; +} + +.terminalButton:nth-child(3) { + background: #27c93f; +} + +.terminalTitle { + font-size: 0.875rem; + color: var(--ifm-color-emphasis-700); + font-family: var(--ifm-font-family-monospace); + flex: 1; + text-align: center; + margin-right: 4rem; +} + +.codeWrapper { + padding: 0; + max-height: 400px; + overflow-y: auto; +} + +.codeWrapper pre { + margin: 0 !important; + padding: 1.5rem !important; + background: transparent !important; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media screen and (max-width: 996px) { + .codePreview { + max-width: 100%; + margin: 2rem 0; + } + + .codeWrapper { + max-height: 300px; + } +} diff --git a/src/components/QuickStartSteps/index.tsx b/src/components/QuickStartSteps/index.tsx new file mode 100644 index 0000000..cdbf81c --- /dev/null +++ b/src/components/QuickStartSteps/index.tsx @@ -0,0 +1,120 @@ +import React, { useState } from 'react'; +import CodeBlock from '@theme/CodeBlock'; +import Heading from '@theme/Heading'; +import styles from './styles.module.css'; + +interface Step { + number: number; + title: string; + description: string; + code: string; + language?: string; +} + +const steps: Step[] = [ + { + number: 1, + title: 'Install psake', + description: 'Install psake from the PowerShell Gallery', + code: 'Install-Module -Name psake -Scope CurrentUser', + language: 'powershell' + }, + { + number: 2, + title: 'Create psakeFile.ps1', + description: 'Define your build tasks in a psakeFile.ps1', + code: `Task Default -Depends Build + +Task Build { + Write-Host "Building project..." -ForegroundColor Green + # Your build logic here +}`, + language: 'powershell' + }, + { + number: 3, + title: 'Run Your Build', + description: 'Execute psake to run your tasks', + code: 'Invoke-psake', + language: 'powershell' + } +]; + +export default function QuickStartSteps(): JSX.Element { + const [copiedIndex, setCopiedIndex] = useState(null); + + const handleCopy = (code: string, index: number) => { + navigator.clipboard.writeText(code); + setCopiedIndex(index); + setTimeout(() => setCopiedIndex(null), 2000); + }; + + return ( +
+
+
+ Get Started in 3 Steps +

+ Start automating your builds in minutes +

+
+ +
+ {steps.map((step, index) => ( +
+
{step.number}
+
+ + {step.title} + +

{step.description}

+
+ + + {step.code} + +
+
+ {index < steps.length - 1 && ( +
+ + + +
+ )} +
+ ))} +
+ +
+ + Read Full Tutorial + + + Command Reference + +
+
+
+ ); +} diff --git a/src/components/QuickStartSteps/styles.module.css b/src/components/QuickStartSteps/styles.module.css new file mode 100644 index 0000000..de36d46 --- /dev/null +++ b/src/components/QuickStartSteps/styles.module.css @@ -0,0 +1,199 @@ +.quickStartSection { + padding: 4rem 0; + background: linear-gradient(180deg, var(--ifm-background-color) 0%, var(--ifm-background-surface-color) 100%); +} + +.header { + text-align: center; + margin-bottom: 3rem; +} + +.header h2 { + font-size: 2.5rem; + margin-bottom: 1rem; +} + +.subtitle { + font-size: 1.25rem; + color: var(--ifm-color-emphasis-700); +} + +.stepsContainer { + max-width: 900px; + margin: 0 auto; + position: relative; +} + +.step { + display: flex; + gap: 2rem; + margin-bottom: 2rem; + position: relative; + animation: fadeInUp 0.6s ease-out backwards; +} + +.step:nth-child(1) { + animation-delay: 0.1s; +} + +.step:nth-child(2) { + animation-delay: 0.2s; +} + +.step:nth-child(3) { + animation-delay: 0.3s; +} + +.stepNumber { + flex-shrink: 0; + width: 60px; + height: 60px; + border-radius: 50%; + background: linear-gradient(135deg, var(--ifm-color-primary), var(--ifm-color-primary-dark)); + color: white; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.75rem; + font-weight: bold; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.stepContent { + flex: 1; + background: var(--ifm-background-color); + padding: 1.5rem; + border-radius: 12px; + border: 1px solid var(--ifm-color-emphasis-200); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.stepContent:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); +} + +[data-theme='dark'] .stepContent { + background: #1e1e1e; + border-color: var(--ifm-color-emphasis-300); +} + +.stepTitle { + font-size: 1.5rem; + margin-bottom: 0.5rem; + color: var(--ifm-color-primary); +} + +.stepDescription { + color: var(--ifm-color-emphasis-700); + margin-bottom: 1rem; +} + +.codeContainer { + position: relative; +} + +.copyButton { + position: absolute; + top: 0.5rem; + right: 0.5rem; + background: var(--ifm-color-primary); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 6px; + cursor: pointer; + font-size: 0.875rem; + font-weight: 500; + z-index: 1; + transition: background 0.2s ease; +} + +.copyButton:hover { + background: var(--ifm-color-primary-dark); +} + +.stepConnector { + position: absolute; + left: 30px; + top: 60px; + height: calc(100% - 40px); + display: flex; + align-items: center; +} + +.ctaContainer { + display: flex; + justify-content: center; + gap: 1rem; + margin-top: 3rem; + flex-wrap: wrap; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media screen and (max-width: 768px) { + .step { + gap: 1rem; + } + + .stepNumber { + width: 50px; + height: 50px; + font-size: 1.5rem; + } + + .stepContent { + padding: 1rem; + } + + .stepTitle { + font-size: 1.25rem; + } + + .header h2 { + font-size: 2rem; + } + + .subtitle { + font-size: 1rem; + } + + .stepConnector { + left: 25px; + } +} + +@media screen and (max-width: 480px) { + .step { + flex-direction: column; + gap: 1rem; + } + + .stepNumber { + align-self: flex-start; + } + + .stepConnector { + display: none; + } + + .ctaContainer { + flex-direction: column; + align-items: stretch; + } + + .ctaContainer a { + width: 100%; + } +} diff --git a/src/css/custom.css b/src/css/custom.css index ee4edba..3b9fa50 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -28,3 +28,75 @@ --ifm-color-primary-lighter: #a7c76c; --ifm-color-primary-lightest: #b9d289; } + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Enhanced button styles */ +.button { + font-weight: 600; + transition: all 0.2s ease; +} + +.button:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.button--primary { + background: linear-gradient(135deg, var(--ifm-color-primary), var(--ifm-color-primary-dark)); + border: none; +} + +.button--primary:hover { + background: linear-gradient(135deg, var(--ifm-color-primary-dark), var(--ifm-color-primary-darkest)); +} + +/* Code block enhancements */ +.prism-code { + font-size: 0.875rem; + border-radius: 8px; +} + +/* Link hover effects */ +a { + transition: color 0.2s ease; +} + +/* Section spacing */ +section { + scroll-margin-top: 80px; +} + +/* Improved scrollbar for code blocks */ +.prism-code::-webkit-scrollbar { + height: 8px; + width: 8px; +} + +.prism-code::-webkit-scrollbar-track { + background: var(--ifm-color-emphasis-200); + border-radius: 4px; +} + +.prism-code::-webkit-scrollbar-thumb { + background: var(--ifm-color-emphasis-400); + border-radius: 4px; +} + +.prism-code::-webkit-scrollbar-thumb:hover { + background: var(--ifm-color-emphasis-600); +} + +/* Accessibility improvements */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/pages/index.module.css b/src/pages/index.module.css index 9f71a5d..efa30bb 100644 --- a/src/pages/index.module.css +++ b/src/pages/index.module.css @@ -4,20 +4,191 @@ */ .heroBanner { - padding: 4rem 0; - text-align: center; + padding: 6rem 0; position: relative; overflow: hidden; + background: linear-gradient(135deg, + var(--ifm-color-primary-lightest) 0%, + var(--ifm-background-color) 50%, + var(--ifm-color-primary-lightest) 100% + ); } -@media screen and (max-width: 996px) { - .heroBanner { - padding: 2rem; - } +[data-theme='dark'] .heroBanner { + background: linear-gradient(135deg, + rgba(150, 188, 79, 0.1) 0%, + var(--ifm-background-color) 50%, + rgba(150, 188, 79, 0.1) 100% + ); +} + +.heroContent { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + align-items: center; + min-height: 500px; +} + +.heroText { + display: flex; + flex-direction: column; + gap: 1.5rem; + justify-content: center; +} + +.heroTitleContainer { + display: flex; + align-items: center; + gap: 1.5rem; + animation: fadeInDown 0.6s ease-out; +} + +.heroLogo { + width: 80px; + height: 80px; + flex-shrink: 0; +} + +.heroTitle { + font-size: 4rem; + font-weight: 800; + line-height: 1.1; + margin: 0; + color: white; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); +} + +.heroSubtitle { + font-size: 1.5rem; + color: white; + margin: 0; + animation: fadeInDown 0.6s ease-out 0.1s backwards; + text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3); +} + +.buttonGroup { + display: flex; + gap: 1rem; + flex-wrap: wrap; + animation: fadeInDown 0.6s ease-out 0.2s backwards; +} + +.githubIcon { + margin-right: 0.5rem; } -.buttons { +.badges { + display: flex; + gap: 1rem; + flex-wrap: wrap; + animation: fadeInDown 0.6s ease-out 0.3s backwards; +} + +.badges img { + height: 20px; +} + +.heroCode { display: flex; align-items: center; justify-content: center; } + +@keyframes fadeInDown { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media screen and (max-width: 996px) { + .heroBanner { + padding: 3rem 2rem; + } + + .heroContent { + grid-template-columns: 1fr; + gap: 3rem; + min-height: auto; + } + + .heroText { + text-align: center; + align-items: center; + } + + .heroTitleContainer { + flex-direction: column; + gap: 1rem; + } + + .heroLogo { + width: 60px; + height: 60px; + } + + .heroTitle { + font-size: 3rem; + } + + .heroSubtitle { + font-size: 1.25rem; + } + + .buttonGroup { + justify-content: center; + } + + .badges { + justify-content: center; + } +} + +@media screen and (max-width: 768px) { + .heroBanner { + padding: 2rem 1rem; + } + + .heroLogo { + width: 50px; + height: 50px; + } + + .heroTitle { + font-size: 2.5rem; + } + + .heroSubtitle { + font-size: 1.125rem; + } + + .buttonGroup { + flex-direction: column; + width: 100%; + } + + .buttonGroup a { + width: 100%; + text-align: center; + } +} + +@media screen and (max-width: 480px) { + .heroLogo { + width: 40px; + height: 40px; + } + + .heroTitle { + font-size: 2rem; + } + + .heroSubtitle { + font-size: 1rem; + } +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 56c3218..297d625 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,26 +2,59 @@ import clsx from 'clsx'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; -import HomepageFeatures from '@site/src/components/HomepageFeatures'; import Heading from '@theme/Heading'; +import GitHubStats from '@site/src/components/GitHubStats'; +import HeroCodePreview from '@site/src/components/HeroCodePreview'; +import FeatureGrid from '@site/src/components/FeatureGrid'; +import CodeShowcase from '@site/src/components/CodeShowcase'; +import QuickStartSteps from '@site/src/components/QuickStartSteps'; + import styles from './index.module.css'; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); return ( -
+
- - {siteConfig.title} - -

{siteConfig.tagline}

-
- - psake Tutorial - 5min ⏱️ - +
+
+
+ psake logo + + {siteConfig.title} + +
+

{siteConfig.tagline}

+ +
+ + Get Started + + + View on GitHub + +
+ + + + +
+ +
+ +
@@ -36,7 +69,9 @@ export default function Home(): JSX.Element { description="A build automation tool written in PowerShell">
- + + +
);