Skip to content

Guidelines/tailwind #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .ai/core.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
## Conventions
- You must follow all existing code conventions used in this project. When creating or editing a file, check sibling files for the correct structure, approach, naming.
- Use descriptive names. For example, `isRegisteredForDiscounts` not `discount()`.
- Check for existing components to reuse before writing one anew.

## Verification Scripts
- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important.
Expand Down
2 changes: 2 additions & 0 deletions .ai/tailwindcss/3/core.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Always use Tailwind CSS v3, verify you're using only supported classes.
- Use the `search-docs` tool to find exactly what's supported in this project's Tailwind setup.
31 changes: 31 additions & 0 deletions .ai/tailwindcss/4/core.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
- Always use Tailwind CSS v4, do not use the deprecated utilities.
- Use the `search-docs` tool to find exactly what's supported in this project's Tailwind setup.
- In Tailwind v4 you import Tailwind using a regular CSS `@import` statement, not using the `@tailwind` directives used in v3:
@verbatim
<code-snippet name="Tailwind v4 import tailwind diff" lang="diff"
- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";
</code-snippet>
@endverbatim
- `corePlugins` is not supported in v4.

## Replaced utilities
- Tailwind v4 removed deprecated utilities. Do not use the deprecated option, use the replacement.
- Opacity values are still numeric.

| Deprecated | Replacement |
|------------+--------------|
| bg-opacity-* | bg-black/* |
| text-opacity-* | text-black/* |
| border-opacity-* | border-black/* |
| divide-opacity-* | divide-black/* |
| ring-opacity-* | ring-black/* |
| placeholder-opacity-* | placeholder-black/* |
| flex-shrink-* | shrink-* |
| flex-grow-* | grow-* |
| overflow-ellipsis | text-ellipsis |
| decoration-slice | box-decoration-slice |
| decoration-clone | box-decoration-clone |

19 changes: 18 additions & 1 deletion .ai/tailwindcss/core.blade.php
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way.
- Use Tailwind CSS classes to style HTML, check and use existing tailwind conventions within the project before writing your own.
- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc..)
- Think through class placement, order, priority, and defaults - remove redundant classes, add classes to parent or child carefully to limit repetition, group elements logically

## Spacing
- Use gap utilities for spacing, don't use margins
@verbatim
<code-snippet name="Valid Flex gap spacing example" lang="html">
<div class="flex gap-8">
<div>Superior</div>
<div>Michigan</div>
<div>Erie</div>
</div>
</code-snippet>
@endverbatim

## Tailwind Dark Mode
- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
141 changes: 85 additions & 56 deletions art/boost.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/Console/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ private function enactMcpServers(): void
try {
$result = $ide->installMcp(
key: 'herd',
command: PHP_BINARY,
command: 'php',
args: [$this->herd->mcpPath()],
env: ['SITE_PATH' => base_path()]
);
Expand Down
2 changes: 1 addition & 1 deletion src/Install/Herd.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function mcpPath(): string
return $this->getHomePath().'/.config/herd/bin/herd-mcp.phar';
}

return $this->getHomePath().'/Library/Application Support/Herd/bin/herd-mcp.phar';
return '/Applications/Herd.app/Contents/Resources/herd-mcp.phar';
}

public function isWindowsPlatform(): bool
Expand Down
35 changes: 12 additions & 23 deletions tests/Unit/Install/HerdTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,11 @@ function getHerdTestTempDir(): string
return $herdTestCleanupData['tempDir'];
}

test('mcpPath builds correct path from HOME on non-Windows', function () {
$testHome = getHerdTestTempDir().'/home';
mkdir($testHome, 0755, true);
$_SERVER['HOME'] = $testHome;

$herd = new Herd();
$expected = $testHome.'/Library/Application Support/Herd/bin/herd-mcp.phar';

expect($herd->mcpPath())->toBe($expected);
})->skipOnWindows();

test('mcpPath builds correct Windows path from USERPROFILE when HOME missing', function () {
unset($_SERVER['HOME']);
$_SERVER['USERPROFILE'] = 'C:\\Users\\TestUser';

$herd = new Herd();
$herd = new Herd;
$expected = 'C:/Users/TestUser/.config/herd/bin/herd-mcp.phar';

expect($herd->mcpPath())->toBe($expected);
Expand All @@ -93,7 +82,7 @@ function getHerdTestTempDir(): string
mkdir($testHome, 0755, true);
$_SERVER['HOME'] = $testHome;

$herd = new Herd();
$herd = new Herd;

expect($herd->isMcpAvailable())->toBeFalse();
});
Expand All @@ -103,7 +92,7 @@ function getHerdTestTempDir(): string
mkdir($testHome, 0755, true);
$_SERVER['HOME'] = $testHome;

$herd = new Herd();
$herd = new Herd;
$mcpPath = $herd->mcpPath();

$mcpDir = dirname($mcpPath);
Expand All @@ -112,14 +101,14 @@ function getHerdTestTempDir(): string
file_put_contents($mcpPath, 'test phar content');

expect($herd->isMcpAvailable())->toBeTrue();
});
})->onlyOnWindows();

test('isMcpAvailable returns false after MCP file is removed', function () {
$testHome = getHerdTestTempDir().'/home';
mkdir($testHome, 0755, true);
$_SERVER['HOME'] = $testHome;

$herd = new Herd();
$herd = new Herd;
$mcpPath = $herd->mcpPath();

$mcpDir = dirname($mcpPath);
Expand All @@ -132,14 +121,14 @@ function getHerdTestTempDir(): string
unlink($mcpPath);

expect($herd->isMcpAvailable())->toBeFalse();
});
})->onlyOnWindows();

test('getHomePath returns HOME on non-Windows', function () {
$testHome = getHerdTestTempDir().'/home';
mkdir($testHome, 0755, true);
$_SERVER['HOME'] = $testHome;

$herd = new Herd();
$herd = new Herd;

expect($herd->getHomePath())->toBe($testHome);
})->skipOnWindows();
Expand All @@ -148,7 +137,7 @@ function getHerdTestTempDir(): string
unset($_SERVER['HOME']);
$_SERVER['USERPROFILE'] = 'C:\\Users\\TestUser';

$herd = new Herd();
$herd = new Herd;

expect($herd->getHomePath())->toBe('C:/Users/TestUser');
})->onlyOnWindows();
Expand All @@ -161,7 +150,7 @@ function getHerdTestTempDir(): string
$configDir = $testHome.'/.config/herd';
mkdir($configDir, 0755, true);

$herd = new Herd();
$herd = new Herd;

expect($herd->isInstalled())->toBeTrue();
})->onlyOnWindows();
Expand All @@ -171,19 +160,19 @@ function getHerdTestTempDir(): string
mkdir($testHome, 0755, true);
$_SERVER['HOME'] = $testHome;

$herd = new Herd();
$herd = new Herd;

expect($herd->isInstalled())->toBeFalse();
})->onlyOnWindows();

test('isWindowsPlatform returns true on Windows', function () {
$herd = new Herd();
$herd = new Herd;

expect($herd->isWindowsPlatform())->toBeTrue();
})->onlyOnWindows();

test('isWindowsPlatform returns false on non-Windows platforms', function () {
$herd = new Herd();
$herd = new Herd;

expect($herd->isWindowsPlatform())->toBeFalse();
})->skipOnWindows();