diff --git a/AGENTS.md b/AGENTS.md index 4ee650360a1..42b6f935639 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -174,6 +174,7 @@ Conventions: - **Use:** `admin-x-framework` for API hooks (`useBrowse`, `useEdit`, etc.) - **Use:** `shade` design system for new components (not admin-x-design-system) - **Translations:** Add to `packages/i18n/locales/en/ghost.json` +- **Deploy skew:** Ghost Admin and Ghost core deploy independently. New admin UI that depends on new settings, endpoints, or config must feature-detect backend support (e.g. settings-key presence in the browse response, as in `social-accounts.tsx`) and hide or no-op when absent. Labs flags alone are not a deploy-skew guard. Add an acceptance test for the “backend not deployed yet” case. ### When Working on Public UI - **Edit:** `apps/portal`, `apps/comments-ui`, etc. @@ -187,6 +188,8 @@ Conventions: - **Services:** `ghost/core/core/server/services/` - **Models:** `ghost/core/core/server/models/` - **Frontend & theme rendering:** `ghost/core/core/frontend/` +- **TypeScript by default:** New code under `ghost/core/core/server/services/` is TypeScript unless extending an existing JS module. Follow the gifts/donations pattern: domain logic as `.ts` with named exports; thin CJS `index.js` / `*-wrapper.js` only where boot/`require` still needs them. +- **Service init:** New services get an explicit `init()` call from `ghost/core/core/boot.js` (same Promise.all as donations/gifts). Keep the wrapper’s `init()` idempotent so early callers are safe, but boot owns construction — not first request. ### Design System Usage - **New components:** Use `shade` (shadcn/ui-inspired) diff --git a/apps/shade/src/components/ui/card.tsx b/apps/shade/src/components/ui/card.tsx index 06c90daec1a..5f9e051cd1e 100644 --- a/apps/shade/src/components/ui/card.tsx +++ b/apps/shade/src/components/ui/card.tsx @@ -14,7 +14,7 @@ const cardVariants = cva( { variants: { variant: { - outline: 'rounded-xl border transition-all hover:shadow-xs', + outline: 'rounded-xl border border-border-default transition-all hover:shadow-xs', plain: '' } }, @@ -44,7 +44,7 @@ const cardHeaderVariants = cva( variants: { variant: { outline: 'p-6', - plain: 'border-b py-5' + plain: 'border-b border-border-default py-5' } }, defaultVariants: { @@ -98,7 +98,7 @@ const cardContentVariants = cva( variants: { variant: { outline: 'p-6 pt-0', - plain: 'border-b' + plain: 'border-b border-border-default' } }, defaultVariants: { @@ -159,7 +159,7 @@ const EmptyCard = React.forwardRef< >(({className, ...props}, ref) => (
)); diff --git a/apps/shade/test/unit/components/ui/card.test.tsx b/apps/shade/test/unit/components/ui/card.test.tsx index 9079efeb274..096928a1545 100644 --- a/apps/shade/test/unit/components/ui/card.test.tsx +++ b/apps/shade/test/unit/components/ui/card.test.tsx @@ -7,7 +7,8 @@ import { CardFooter, CardTitle, CardDescription, - CardContent + CardContent, + EmptyCard } from '../../../../src/components/ui/card'; import {render} from '../../utils/test-utils'; @@ -18,7 +19,7 @@ describe('Card Components', () => { assert.ok(card, 'Card should be rendered'); assert.equal(card.textContent, 'Card Content', 'Card should render its content'); - assert.ok(card.className.includes('rounded-xl border'), 'Should have outline variant styling'); + assert.ok(card.className.includes('rounded-xl border border-border-default'), 'Should have outline variant styling'); }); it('renders Card with plain variant', () => { @@ -36,6 +37,13 @@ describe('Card Components', () => { assert.ok(card.className.includes('custom-card-class'), 'Should have custom class'); }); + it('renders EmptyCard with the default container border', () => { + render(