mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
[create-astro] Finalize developer experience... with gradients 🚀 (#3313)
* wip: port gradient helpers from sandbox ideas
* feat: wire up rocket gradient 🚀
* feat: wire up rocket gradient on install step
* refactor: update "next steps" wording
* deps: add chalk (for rendering gradient)
* chore: changeset
* chore: clean up sstray template string
This commit is contained in:
parent
f40705d906
commit
1a5335ed9a
5 changed files with 124 additions and 24 deletions
5
.changeset/strong-students-tie.md
Normal file
5
.changeset/strong-students-tie.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'create-astro': patch
|
||||
---
|
||||
|
||||
Update "next steps" with more informative text on each CLI command. Oh, and gradients. A lot more gradients.
|
|
@ -30,6 +30,7 @@
|
|||
"dependencies": {
|
||||
"@types/degit": "^2.8.3",
|
||||
"@types/prompts": "^2.0.14",
|
||||
"chalk": "^5.0.1",
|
||||
"degit": "^2.8.4",
|
||||
"execa": "^6.1.0",
|
||||
"kleur": "^4.1.4",
|
||||
|
|
91
packages/create-astro/src/gradient.ts
Normal file
91
packages/create-astro/src/gradient.ts
Normal file
|
@ -0,0 +1,91 @@
|
|||
import chalk from 'chalk';
|
||||
import ora from 'ora';
|
||||
import type { Ora } from 'ora';
|
||||
|
||||
const gradientColors = [
|
||||
`#ff5e00`,
|
||||
`#ff4c29`,
|
||||
`#ff383f`,
|
||||
`#ff2453`,
|
||||
`#ff0565`,
|
||||
`#ff007b`,
|
||||
`#f5008b`,
|
||||
`#e6149c`,
|
||||
`#d629ae`,
|
||||
`#c238bd`,
|
||||
];
|
||||
|
||||
export const rocketAscii = '■■▶';
|
||||
|
||||
// get a reference to scroll through while loading
|
||||
// visual representation of what this generates:
|
||||
// gradientColors: "..xxXX"
|
||||
// referenceGradient: "..xxXXXXxx....xxXX"
|
||||
const referenceGradient = [
|
||||
...gradientColors,
|
||||
// draw the reverse of the gradient without
|
||||
// accidentally mutating the gradient (ugh, reverse())
|
||||
...[...gradientColors].reverse(),
|
||||
...gradientColors,
|
||||
];
|
||||
|
||||
// async-friendly setTimeout
|
||||
const sleep = (time: number) =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(resolve, time);
|
||||
});
|
||||
|
||||
function getGradientAnimFrames() {
|
||||
const frames = [];
|
||||
for (let start = 0; start < gradientColors.length * 2; start++) {
|
||||
const end = start + gradientColors.length - 1;
|
||||
frames.push(
|
||||
referenceGradient
|
||||
.slice(start, end)
|
||||
.map((g) => chalk.bgHex(g)(' '))
|
||||
.join('')
|
||||
);
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
function getIntroAnimFrames() {
|
||||
const frames = [];
|
||||
for (let end = 1; end <= gradientColors.length; end++) {
|
||||
const leadingSpacesArr = Array.from(
|
||||
new Array(Math.abs(gradientColors.length - end - 1)),
|
||||
() => ' '
|
||||
);
|
||||
const gradientArr = gradientColors.slice(0, end).map((g) => chalk.bgHex(g)(' '));
|
||||
frames.push([...leadingSpacesArr, ...gradientArr].join(''));
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate loading spinner with rocket flames!
|
||||
* @param text display text next to rocket
|
||||
* @returns Ora spinner for running .stop()
|
||||
*/
|
||||
export async function loadWithRocketGradient(text: string): Promise<Ora> {
|
||||
const frames = getIntroAnimFrames();
|
||||
const intro = ora({
|
||||
spinner: {
|
||||
interval: 30,
|
||||
frames,
|
||||
},
|
||||
text: `${rocketAscii} ${text}`,
|
||||
});
|
||||
intro.start();
|
||||
await sleep((frames.length - 1) * intro.interval);
|
||||
intro.stop();
|
||||
const spinner = ora({
|
||||
spinner: {
|
||||
interval: 80,
|
||||
frames: getGradientAnimFrames(),
|
||||
},
|
||||
text: `${rocketAscii} ${text}`,
|
||||
}).start();
|
||||
|
||||
return spinner;
|
||||
}
|
|
@ -8,6 +8,7 @@ import ora from 'ora';
|
|||
import { TEMPLATES } from './templates.js';
|
||||
import { logger, defaultLogLevel } from './logger.js';
|
||||
import { execa, execaCommand } from 'execa';
|
||||
import { loadWithRocketGradient, rocketAscii } from './gradient.js';
|
||||
|
||||
// NOTE: In the v7.x version of npm, the default behavior of `npm init` was changed
|
||||
// to no longer require `--` to pass args and instead pass `--` directly to us. This
|
||||
|
@ -42,10 +43,6 @@ export async function main() {
|
|||
logger.debug('Verbose logging turned on');
|
||||
console.log(`\n${bold('Welcome to Astro!')} ${gray(`(create-astro v${version})`)}`);
|
||||
|
||||
let spinner = ora({ color: 'green', text: 'Prepare for liftoff.' });
|
||||
|
||||
spinner.succeed();
|
||||
|
||||
let cwd = args['_'][2] as string;
|
||||
|
||||
if (cwd && isEmpty(cwd)) {
|
||||
|
@ -95,6 +92,8 @@ export async function main() {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const templateSpinner = await loadWithRocketGradient('Copying project files...');
|
||||
|
||||
const hash = args.commit ? `#${args.commit}` : '';
|
||||
|
||||
const templateTarget = `withastro/astro/examples/${options.template}#latest`;
|
||||
|
@ -111,8 +110,6 @@ export async function main() {
|
|||
verbose: defaultLogLevel === 'debug' ? true : false,
|
||||
});
|
||||
|
||||
spinner = ora({ color: 'green', text: 'Copying project files...' }).start();
|
||||
|
||||
// Copy
|
||||
if (!args.dryrun) {
|
||||
try {
|
||||
|
@ -152,7 +149,7 @@ export async function main() {
|
|||
)
|
||||
);
|
||||
}
|
||||
spinner.fail();
|
||||
templateSpinner.fail();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
@ -167,8 +164,8 @@ export async function main() {
|
|||
);
|
||||
}
|
||||
|
||||
spinner.succeed();
|
||||
console.log(bold(green('✔') + ' Done!'));
|
||||
templateSpinner.text = green('Template copied!');
|
||||
templateSpinner.succeed();
|
||||
|
||||
const installResponse = await prompts({
|
||||
type: 'confirm',
|
||||
|
@ -184,15 +181,18 @@ export async function main() {
|
|||
if (installResponse.install && !args.dryrun) {
|
||||
const installExec = execa(pkgManager, ['install'], { cwd });
|
||||
const installingPackagesMsg = `Installing packages${emojiWithFallback(' 📦', '...')}`;
|
||||
spinner = ora({ color: 'green', text: installingPackagesMsg }).start();
|
||||
const installSpinner = await loadWithRocketGradient(installingPackagesMsg);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
installExec.stdout?.on('data', function (data) {
|
||||
spinner.text = `${installingPackagesMsg}\n${bold(`[${pkgManager}]`)} ${data}`;
|
||||
installSpinner.text = `${rocketAscii} ${installingPackagesMsg}\n${bold(
|
||||
`[${pkgManager}]`
|
||||
)} ${data}`;
|
||||
});
|
||||
installExec.on('error', (error) => reject(error));
|
||||
installExec.on('close', () => resolve());
|
||||
});
|
||||
spinner.succeed();
|
||||
installSpinner.text = green('Packages installed!');
|
||||
installSpinner.succeed();
|
||||
}
|
||||
|
||||
const astroAddCommand = installResponse.install
|
||||
|
@ -240,21 +240,22 @@ export async function main() {
|
|||
await execaCommand('git init', { cwd });
|
||||
}
|
||||
|
||||
ora({ text: green('Done. Ready for liftoff!') }).succeed();
|
||||
console.log(`\n${bgCyan(black(' Next steps '))}\n`);
|
||||
|
||||
const relative = path.relative(process.cwd(), cwd);
|
||||
const startCommand = [];
|
||||
if (relative !== '') {
|
||||
startCommand.push(bold(cyan(`cd ${relative}`)));
|
||||
}
|
||||
if (!installResponse.install) {
|
||||
startCommand.push(bold(cyan(`${pkgManager} install`)));
|
||||
}
|
||||
startCommand.push(bold(cyan(pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`)));
|
||||
console.log(startCommand.join(' && '));
|
||||
const projectDir = path.relative(process.cwd(), cwd);
|
||||
const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`;
|
||||
|
||||
console.log(`\nTo close the dev server, hit ${bold(cyan('Ctrl-C'))}`);
|
||||
console.log(`Stuck? Visit us at ${cyan('https://astro.build/chat')}\n`);
|
||||
console.log(
|
||||
`You can now ${bold(cyan('cd'))} into the ${bold(cyan(projectDir))} project directory.`
|
||||
);
|
||||
console.log(
|
||||
`Run ${bold(cyan(devCmd))} to start the Astro dev server. ${bold(cyan('CTRL-C'))} to close.`
|
||||
);
|
||||
if (!installResponse.install) {
|
||||
console.log(yellow(`Remember to install dependencies first!`));
|
||||
}
|
||||
console.log(`\nStuck? Come join us at ${bold(cyan('https://astro.build/chat'))}`);
|
||||
}
|
||||
|
||||
function emojiWithFallback(char: string, fallback: string) {
|
||||
|
|
|
@ -1256,6 +1256,7 @@ importers:
|
|||
'@types/yargs-parser': ^21.0.0
|
||||
astro-scripts: workspace:*
|
||||
chai: ^4.3.6
|
||||
chalk: ^5.0.1
|
||||
degit: ^2.8.4
|
||||
execa: ^6.1.0
|
||||
kleur: ^4.1.4
|
||||
|
@ -1267,6 +1268,7 @@ importers:
|
|||
dependencies:
|
||||
'@types/degit': 2.8.3
|
||||
'@types/prompts': 2.0.14
|
||||
chalk: 5.0.1
|
||||
degit: 2.8.4
|
||||
execa: 6.1.0
|
||||
kleur: 4.1.4
|
||||
|
|
Loading…
Reference in a new issue