diff --git a/composer.json b/composer.json index 950d4e9..7de062a 100644 --- a/composer.json +++ b/composer.json @@ -1,17 +1,20 @@ { "name": "zaknesler/tailwind-preset", "description": "A Tailwind CSS preset for Laravel.", - "keywords": ["laravel", "laravel preset", "preset", "tailwind", "tailwindcss"], + "keywords": ["laravel", "preset", "tailwind", "tailwindcss"], "license": "MIT", "authors": [ { "name": "Zak Nesler", - "email": "contact@zaknesler.com" + "email": "zak@nesler.dev" } ], "minimum-stability": "stable", "require": { - "laravel/framework": "^5.5|^6.0" + "php": "^7.2", + "laravel/ui": "^2.0", + "illuminate/filesystem": "^7.0", + "illuminate/support": "^7.0" }, "autoload": { "psr-4": { diff --git a/readme.md b/readme.md index 9b57d6c..01f278e 100644 --- a/readme.md +++ b/readme.md @@ -1,78 +1,77 @@ ## Tailwind CSS Laravel Front-end Preset -[![Latest Stable Version](https://poser.pugx.org/zaknesler/tailwind-preset/v/stable)](https://packagist.org/packages/zaknesler/tailwind-preset) -[![Total Downloads](https://poser.pugx.org/zaknesler/tailwind-preset/downloads)](https://packagist.org/packages/zaknesler/tailwind-preset) -[![License](https://poser.pugx.org/zaknesler/tailwind-preset/license)](https://packagist.org/packages/zaknesler/tailwind-preset) +[![Latest Stable Version](https://poser.pugx.org/zaknesler/tailwind-preset/v/stable)](https://packagist.org/packages/zaknesler/tailwind-preset) [![Total Downloads](https://poser.pugx.org/zaknesler/tailwind-preset/downloads)](https://packagist.org/packages/zaknesler/tailwind-preset) [![License](https://poser.pugx.org/zaknesler/tailwind-preset/license)](https://packagist.org/packages/zaknesler/tailwind-preset) -This is a Laravel front-end preset for [Tailwind CSS](https://tailwindcss.com). This preset replaces the default Bootstrap scaffolding, including the example Vue.js component. It also compiles the assets using [Laravel Mix](https://github.com/jeffreyway/laravel-mix) for convenience and [PurgeCSS](https://github.com/fullhuman/purgecss) to generate the smallest files possible. +A Laravel 7+ front-end preset for [Tailwind CSS](https://tailwindcss.com). This preset comes bundled with Vue.js and an example component, as well as a responsive navigation menu. -> **Deprecation Notice** – As of Laravel 6, all front-end presets have been extracted into the [laravel/ui](https://github.com/laravel/ui) repository. In soon time, a Tailwind preset by the maintainers of Laravel will be created. I will maintain development of this package until a Tailwind preset is created, after which this repository will be archived. +This preset uses Laravel Mix to compile and minify assets. Tailwind 1.4 includes PurgeCSS by default, and this preset is configured to purge the proper files. -> The reason I am confident in doing this is because I would think that an *official* Tailwind CSS preset would include a well-thought, elegant design. If, however, I am not a fan of the design, I would have no problem with continuing to maintain this package. +> This preset is built for Laravel 7 and up. For Laravel 5 or 6, please use [version 5.0](https://github.com/zaknesler/tailwind-preset/tree/a35309799e93fe384d16ead531add16b98b634e1). **[Live Demo](https://preset.zaknesler.com)** · [Example Repository](https://github.com/zaknesler/tw-preset-demo)
View screenshots - -![welcome.blade.php](https://user-images.githubusercontent.com/7189795/59567082-dfddce80-9036-11e9-952d-a535f21478e1.png) -![login.blade.php](https://user-images.githubusercontent.com/7189795/59567081-dfddce80-9036-11e9-8401-257eeb78a07c.png) +Welcome page -![home.blade.php](https://user-images.githubusercontent.com/7189795/59567080-dfddce80-9036-11e9-81be-20044b2b6cd4.png) +Login page + +Home page
### Warning -Laravel presets are meant to be used with a fresh installation of Laravel. Installing this preset will **overwrite** your existing views and assets. Please install with caution. +Laravel presets are meant to be installed onto a fresh instance of Laravel. This preset will **overwrite** your existing views, assets, and Home controller. Please use with caution. ### Installation -To install this preset, you must first require the composer dependency in your application. Laravel will automatically register the service provider for you. -``` -composer require zaknesler/tailwind-preset -``` +1. Require the composer dependency. Laravel will automatically register the package. -Now, install either the `tailwind` or the `tailwind-auth` preset. The `tailwind-auth` preset includes the authentication scaffolding normally generated when `php artisan make:auth` is executed. + ```bash + composer require zaknesler/tailwind-preset --dev + ``` -``` -php artisan preset tailwind +2. Install the preset: -// or + ```bash + php artisan ui tailwind --auth -php artisan preset tailwind-auth -``` + # Without authentication scaffolding + php artisan ui tailwind + ``` -> **Note:** If you install the `tailwind-auth` preset on a version of Laravel that is older than 5.7, you may delete the `views/auth/verify.blade.php` file, as it will not be used. -Install the NPM packages using your favorite package manager. +3. Install the npm dependencies using your preferred package manager: -``` -yarn // npm install -``` + ```bash + # Using Yarn + yarn -Now you can compile the assets using any of the Laravel build scripts (dev, prod, watch). + # Using npm + npm install + ``` -``` -yarn dev // npm run dev -``` +4. Compile assets: -Ensure that your database is properly configured and migrated, and you're done! + ```bash + # Using Yarn + yarn dev -### Localization + # Using npm + npm run dev + ``` -All of the text in the views that this preset provides are configured to be easily translatable. When you install the `tailwind-auth` preset, the file `en.json` will be copied into your application's `resources/lang` directory. +### Customization -This file includes all of the text found in this package. To update the default English text, simply update the values of any of the key-value pairs. To translate into a different language, duplicate `en.json` and rename it to `{locale}.json`; you can then translate the values into the destination language. For more about localization, please refer to the [Laravel documentation](https://laravel.com/docs/6.x/localization). +Tailwind is built to be fully customizable. The `tailwind.config.js` file that this preset provides includes a handful of customization options to help get you started, including adding [Inter](https://fonts.google.com/specimen/Inter) to the default font stack, as well as a `theme` color palette, as well as configuration for the [Tailwind custom-forms](https://tailwindcss-custom-forms.netlify.app/) plugin. -### EditorConfig +The `theme` color palette, by default, simply destructures Tailwind's blue color palette, but can be easily swapped out for your own color keys. For more information, visit the [Tailwind color customization page](https://tailwindcss.com/docs/customizing-colors). -To ensure proper guide highlighting in your text editor, it is recommended that you add the following to the end of the `.editorconfig` file: +I have tried to design this preset to use as many Tailwind features as possible. This includes using a plugin, overriding default theme values, configuration destructuring, and using PurgeCSS. To get the most out of Tailwind, it is recommended that you take a deep dive into Tailwind's [incredible documentation](https://tailwindcss.com/docs/installation), and more importantly... get your hands dirty with it! + +### Localization -``` -[{tailwind.config.js,webpack.mix.js}] -indent_style = space -indent_size = 2 -``` +This preset includes text that is already configured to be easily translated. An `en.json` file will be copied into your application's `resources/lang` directory when you install the authentication scaffolding. This file includes keys for all of the on-screen text found in this preset. -Alternatively, you may reindent both files to use an indent size of four, which is the default in a Laravel project. +To translate these values, duplicate the `en.json` file and rename it to `{language}.json`, and begin translating the values for each `"key": "value"` pair. For more about localization, please refer to the [Laravel documentation](https://laravel.com/docs/6.x/localization). diff --git a/src/Tailwind.php b/src/TailwindPreset.php similarity index 67% rename from src/Tailwind.php rename to src/TailwindPreset.php index fd2d86a..c870c93 100644 --- a/src/Tailwind.php +++ b/src/TailwindPreset.php @@ -3,18 +3,18 @@ namespace ZakNesler\TailwindPreset; use Illuminate\Support\Str; +use Laravel\Ui\Presets\Preset; use Illuminate\Container\Container; -use Illuminate\Support\Facades\File; -use Illuminate\Foundation\Console\Presets\Preset; +use Illuminate\Filesystem\Filesystem; -class Tailwind extends Preset +class TailwindPreset extends Preset { /** * Setup basic assets. * * @return void */ - private static function setup() + protected static function setup() { static::ensureResourceDirectoriesExist(); static::updatePackages(); @@ -45,15 +45,15 @@ public static function install() * * @return void */ - public static function installWithAuth() + public static function installAuth() { static::setup(); static::installAuthRoutes(); - static::makeViewDirectories([ - 'auth/passwords', - 'errors', - 'layouts/partials', + static::createResourceDirectories([ + 'views/auth/passwords', + 'views/errors', + 'views/layouts/partials', ]); static::installViews('auth', [ @@ -73,8 +73,13 @@ public static function installWithAuth() 'welcome.stub', ]); + copy( + base_path('vendor/laravel/ui/stubs/migrations/2014_10_12_100000_create_password_resets_table.php'), + base_path('database/migrations/2014_10_12_100000_create_password_resets_table.php') + ); + file_put_contents(app_path('Http/Controllers/HomeController.php'), static::compileControllerStub()); - File::copy(__DIR__.'/stubs/en.stub', resource_path('lang/en.json')); + copy(__DIR__.'/stubs/en.stub', resource_path('lang/en.json')); } /** @@ -91,24 +96,25 @@ protected static function updatePackageArray(array $packages) 'axios' => '^0.19', 'cross-env' => '^6.0', 'laravel-mix' => '^5.0', - 'laravel-mix-purgecss' => '^4.2', - 'tailwindcss' => '^1.1', + 'tailwindcss' => '^1.4', 'vue' => '^2.6', 'vue-template-compiler' => '^2.6', ]; } /** - * Create view directories. + * Create directories if they do not already exist. * - * @param array $directories + * @param array $dirs * @return void */ - protected static function makeViewDirectories($directories) + protected static function createResourceDirectories($dirs) { - foreach ($directories as $directory) { - if (! is_dir($directory = resource_path('views/'.$directory))) { - File::makeDirectory($directory, 0755, true); + $filesystem = new Filesystem; + + foreach ($dirs as $dir) { + if (! is_dir($dir = resource_path($dir))) { + $filesystem->makeDirectory($dir, 0755, true); } } } @@ -116,15 +122,17 @@ protected static function makeViewDirectories($directories) /** * Copy the view stubs over to the application and rename them. * - * @param string $baseDirectory + * @param string $baseDir * @param array $views * @return void */ - protected static function installViews($baseDirectory, $views) + protected static function installViews($baseDir, $views) { + $filesystem = new Filesystem; + foreach ($views as $view) { - File::copy( - __DIR__.'/stubs/views/'.$baseDirectory.'/'.$view, + $filesystem->copy( + __DIR__.'/stubs/views/'.$baseDir.'/'.$view, resource_path('views/'.str_replace('stub', 'blade.php', $view)) ); } @@ -169,10 +177,12 @@ protected static function compileControllerStub() */ protected static function ensureResourceDirectoriesExist() { + $filesystem = new Filesystem; + collect(['css', 'js/components']) - ->each(function ($directory) { - if (! is_dir(resource_path($directory))) { - File::makeDirectory(resource_path($directory), 0755, true); + ->each(function ($dir) use ($filesystem) { + if (! is_dir(resource_path($dir))) { + $filesystem->makeDirectory(resource_path($dir), 0755, true); } }); } @@ -184,13 +194,13 @@ protected static function ensureResourceDirectoriesExist() */ protected static function installScripts() { - File::delete(base_path('webpack.mix.js')); + (new Filesystem)->delete(base_path('webpack.mix.js')); - File::copy(__DIR__.'/stubs/tailwind.stub', base_path('tailwind.config.js')); - File::copy(__DIR__.'/stubs/webpack.stub', base_path('webpack.mix.js')); + copy(__DIR__.'/stubs/tailwind.stub', base_path('tailwind.config.js')); + copy(__DIR__.'/stubs/webpack.stub', base_path('webpack.mix.js')); - File::copy(__DIR__.'/stubs/js/app.stub', resource_path('js/app.js')); - File::copy(__DIR__.'/stubs/js/bootstrap.stub', resource_path('js/bootstrap.js')); + copy(__DIR__.'/stubs/js/app.stub', resource_path('js/app.js')); + copy(__DIR__.'/stubs/js/bootstrap.stub', resource_path('js/bootstrap.js')); } /** @@ -200,7 +210,7 @@ protected static function installScripts() */ protected static function installStyles() { - File::copy(__DIR__.'/stubs/css/tailwind.stub', resource_path('css/tailwind.css')); + copy(__DIR__.'/stubs/css/tailwind.stub', resource_path('css/tailwind.css')); } /** @@ -210,7 +220,7 @@ protected static function installStyles() */ protected static function updateExampleComponent() { - File::copy( + copy( __DIR__.'/stubs/js/components/ExampleComponent.stub', resource_path('js/components/ExampleComponent.vue') ); diff --git a/src/TailwindServiceProvider.php b/src/TailwindServiceProvider.php index 4e7929f..a2165b7 100644 --- a/src/TailwindServiceProvider.php +++ b/src/TailwindServiceProvider.php @@ -2,8 +2,8 @@ namespace ZakNesler\TailwindPreset; +use Laravel\Ui\UiCommand; use Illuminate\Support\ServiceProvider; -use Illuminate\Foundation\Console\PresetCommand; class TailwindServiceProvider extends ServiceProvider { @@ -14,28 +14,19 @@ class TailwindServiceProvider extends ServiceProvider */ public function boot() { - PresetCommand::macro('tailwind', function ($command) { - Tailwind::install(); + UiCommand::macro('tailwind', function ($command) { + if ($command->option('auth')) { + TailwindPreset::installAuth(); + $command->callSilent('ui:controllers'); - $this->installMessage($command); - }); + $command->info('Tailwind authentication scaffolding installed successfully.'); + } else { + TailwindPreset::install(); - PresetCommand::macro('tailwind-auth', function ($command) { - Tailwind::installWithAuth(); + $command->info('Tailwind scaffolding installed successfully.'); + } - $this->installMessage($command); + $command->comment('Please run "yarn && yarn dev" or "npm install && npm run dev" to compile your fresh scaffolding.'); }); } - - /** - * Print message after successful installation. - * - * @param \Illuminate\Console\Command $command - * @return void - */ - protected function installMessage($command) - { - $command->info('Tailwind scaffolding installed successfully.'); - $command->comment('Please run "yarn && yarn dev" or "npm install && npm run dev" to compile your fresh scaffolding.'); - } } diff --git a/src/stubs/controllers/HomeController.stub b/src/stubs/controllers/HomeController.stub index 8e0007a..63a1e36 100644 --- a/src/stubs/controllers/HomeController.stub +++ b/src/stubs/controllers/HomeController.stub @@ -19,7 +19,7 @@ class HomeController extends Controller /** * Show the application dashboard. * - * @return \Illuminate\Http\Response + * @return \Illuminate\Contracts\Support\Renderable */ public function index() { diff --git a/src/stubs/css/tailwind.stub b/src/stubs/css/tailwind.stub index f9cdc1d..94899ac 100644 --- a/src/stubs/css/tailwind.stub +++ b/src/stubs/css/tailwind.stub @@ -5,14 +5,8 @@ @tailwind base; @tailwind components; -@variants focus { - .shadow-transition { - transition: box-shadow 100ms ease-in-out; - } -} - .btn { - @apply px-6 py-3 bg-brand-500 font-semibold text-white rounded-lg border-none appearance-none; + @apply px-6 py-3 bg-brand-500 font-semibold text-white rounded-lg border-none appearance-none transition duration-100 transition-shadow; } .btn:hover { @@ -20,7 +14,7 @@ } .btn:focus { - @apply outline-none shadow-outline shadow-transition; + @apply outline-none shadow-outline; } @tailwind utilities; diff --git a/src/stubs/en.stub b/src/stubs/en.stub index af6e397..55d261b 100644 --- a/src/stubs/en.stub +++ b/src/stubs/en.stub @@ -11,7 +11,7 @@ "Create account": "Create account", "Didn't get the email?": "Didn't get the email?", "Email": "Email", - "Enter your email address and we'll send you a link to reset your password": "Enter your email address and we'll send you a link to reset your password", + "Enter your email and we'll send you a link to reset your password": "Enter your email and we'll send you a link to reset your password", "Forgot password?": "Forgot password?", "Have an account?": "Have an account?", "Home": "Home", diff --git a/src/stubs/js/components/ExampleComponent.stub b/src/stubs/js/components/ExampleComponent.stub index 1b8585a..3cc9a65 100644 --- a/src/stubs/js/components/ExampleComponent.stub +++ b/src/stubs/js/components/ExampleComponent.stub @@ -14,7 +14,7 @@ type: String, required: false, default: 'Example Component' - } + }, }, mounted() { diff --git a/src/stubs/tailwind.stub b/src/stubs/tailwind.stub index 4e0058a..87b7753 100644 --- a/src/stubs/tailwind.stub +++ b/src/stubs/tailwind.stub @@ -1,38 +1,55 @@ const defaultTheme = require('tailwindcss/defaultTheme') module.exports = { - theme: { - extend: { - colors: { - brand: { ...defaultTheme.colors.teal }, - }, - boxShadow: theme => ({ - outline: `0 0 0 3px ${theme('colors.brand.500')}60`, - }), - }, - customForms: theme => ({ - default: { - 'input, textarea, multiselect, select': { - borderRadius: theme('borderRadius.lg'), - }, - 'input, textarea, multiselect, select, checkbox, radio': { - '&:focus': { - borderColor: theme('colors.brand.400'), - boxShadow: theme('boxShadow.outline'), - transition: 'box-shadow 100ms ease-in-out', - }, - }, - 'checkbox, radio': { - '&:checked:focus': { - borderColor: theme('colors.brand.500'), - backgroundColor: theme('colors.brand.500'), - }, + theme: { + extend: { + colors: { + brand: { ...defaultTheme.colors.blue }, + }, + + fontFamily: { + sans: [ 'Inter', ...defaultTheme.fontFamily.sans ], + }, + + boxShadow: theme => ({ + outline: `0 0 0 3px ${theme('colors.brand.500')}60`, + }), }, - }, - }), - }, - variants: {}, - plugins: [ - require('@tailwindcss/custom-forms'), - ], + + customForms: theme => ({ + default: { + 'input, textarea, multiselect, select': { + borderRadius: theme('borderRadius.lg'), + }, + + 'input, textarea, multiselect, select, checkbox, radio': { + '&:focus': { + borderColor: theme('colors.brand.400'), + boxShadow: theme('boxShadow.outline'), + transition: 'box-shadow 100ms ease-in-out', + }, + }, + + 'checkbox, radio': { + '&:checked:focus': { + borderColor: theme('colors.brand.500'), + backgroundColor: theme('colors.brand.500'), + }, + }, + }, + }), + }, + + variants: {}, + + plugins: [ + require('@tailwindcss/custom-forms'), + ], + + purge: [ + './app/**/*.php', + './resources/**/*.vue', + './resources/**/*.js', + './resources/**/*.php', + ], } diff --git a/src/stubs/views/auth/auth/login.stub b/src/stubs/views/auth/auth/login.stub index 1269dba..3bc2f24 100644 --- a/src/stubs/views/auth/auth/login.stub +++ b/src/stubs/views/auth/auth/login.stub @@ -4,58 +4,72 @@ @section('show-header', false) @section('content-full') -
-
+
+
-
+
{{ __('Sign in to your account') }}
-
+ @csrf -
-