Skip to content

Commit dba89bf

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
refactor(design): centralize EMCN ownership decisions
1 parent 15daae2 commit dba89bf

28 files changed

Lines changed: 513 additions & 150 deletions

‎.agents/skills/ship/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ When the user runs `/ship`:
102102
103103
## Committed design check
104104
105-
When central EMCN sources, global styles, recipes or `@designAllow`/`@designProtect` metadata change, run the design diff check and review its central-system findings. The checker derives metadata independently from the base and proposed source; no generated artifact needs to be committed.
105+
When central EMCN sources, global styles, recipes or `packages/emcn/src/design-ownership.json` change, run the design diff check and review its central-system findings. The checker derives metadata independently from the base and proposed source; no generated artifact needs to be committed.
106106
107107
During product UI work, run `bun run check:design --base origin/staging --working-tree` so staged, unstaged and nonignored new files are included. Review findings against EMCN and `globals.css`; explain intentional new Extras rather than weakening the checker. After committing and before **every push**, run this from the repository root with the repository-pinned Bun version:
108108

‎.claude/rules/emcn-components.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ Color tokens and icon-size conventions are canonical in `.claude/rules/sim-styli
5151

5252
## Source-derived design contracts
5353

54-
The diff check derives public API, styling, recipe and ownership facts from both source revisions; the full scan publishes current facts in `scan.json`. Ownership is derived from implementation; intentional customization belongs in component TSDoc (`@designAllow <slot> <CSS properties or policy groups>`, `@designProtect` for ownership that cannot be inferred). Review central source changes in the diff findings. Browser reports and captures remain local, outside the repository.
54+
The diff check derives public API, styling, recipe and ownership facts from both source revisions; the full scan publishes current facts in `scan.json`. Ownership is derived from implementation; exceptional customization and protection decisions belong in `packages/emcn/src/design-ownership.json` with a reason. Review central source changes in the diff findings. Browser reports and captures remain local, outside the repository.

‎.cursor/rules/emcn-components.mdc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ Color tokens and icon-size conventions are canonical in `.claude/rules/sim-styli
5252

5353
## Source-derived design contracts
5454

55-
The diff check derives public API, styling, recipe and ownership facts from both source revisions; the full scan publishes current facts in `scan.json`. Ownership is derived from implementation; intentional customization belongs in component TSDoc (`@designAllow <slot> <CSS properties or policy groups>`, `@designProtect` for ownership that cannot be inferred). Review central source changes in the diff findings. Browser reports and captures remain local, outside the repository.
55+
The diff check derives public API, styling, recipe and ownership facts from both source revisions; the full scan publishes current facts in `scan.json`. Ownership is derived from implementation; exceptional customization and protection decisions belong in `packages/emcn/src/design-ownership.json` with a reason. Review central source changes in the diff findings. Browser reports and captures remain local, outside the repository.

‎packages/emcn/src/AGENTS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ Applies to `packages/emcn/**`. Read `.claude/rules/emcn-components.md` before ch
77
- TSDoc for public components and APIs.
88

99
Central component, recipe and icon changes are design-system decisions. Run `bun run check:design --base origin/staging --working-tree` (using the actual PR target as the base) and explain intended shared changes in the PR. Review warnings remain visible. See `scripts/design-conformance/README.md`.
10+
Exceptional styling permissions and protections belong in `packages/emcn/src/design-ownership.json`, not in component TSDoc. Ordinary component facts are discovered from source.

‎packages/emcn/src/components/banner/banner.tsx‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export interface BannerProps
3232
textClassName?: string
3333
}
3434

35-
/** @designAllow textClassName typography */
3635
export function Banner({
3736
actionClassName,
3837
actionDisabled,

‎packages/emcn/src/components/button/button.tsx‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,6 @@ export interface ButtonProps
8484
iconPadding?: VariantProps<typeof buttonVariants>['iconPadding']
8585
}
8686

87-
/**
88-
* Consumers may stretch the button to their surrounding layout.
89-
* @designAllow className width
90-
* @designAllow style width
91-
*/
9287
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
9388
({ className, variant, size, iconPadding, ...props }, ref) => {
9489
return (

‎packages/emcn/src/components/chip-input/chip-input.tsx‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ export interface ChipInputProps extends Omit<React.InputHTMLAttributes<HTMLInput
5050
/**
5151
* Forwards its ref to the inner `<input>` so callers can focus or measure the
5252
* field directly, exactly like a native input.
53-
* @designProtect className colours font-family font-size padding height gap border-radius borders box-shadow
54-
* @designProtect style colours font-family font-size padding height gap border-radius borders box-shadow
55-
* @designAllow inputClassName typography
5653
*/
5754
export const ChipInput = React.forwardRef<HTMLInputElement, ChipInputProps>(
5855
(

‎packages/emcn/src/components/chip-modal/chip-modal.tsx‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,6 @@ export type ChipModalFieldProps =
774774
* static permission list). For a multi-email chip-list input, prefer
775775
* `type='emails'` over a `type='custom'` `TagInput` wrapper — it internalizes
776776
* chip rendering, dedupe, format validation, paste, and Backspace handling.
777-
* @designProtect className colours typography padding height gap border-radius borders box-shadow flex-direction align-items justify-content
778777
*/
779778
function ChipModalField(props: ChipModalFieldProps) {
780779
const id = React.useId()

‎packages/emcn/src/components/chip-textarea/chip-textarea.tsx‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ export interface ChipTextareaProps
3939
viewOnly?: boolean
4040
}
4141

42-
/** Forwards its ref to the underlying `<textarea>`, exactly like a native textarea. * @designProtect className colours font-family font-size padding gap border-radius borders box-shadow
43-
* @designProtect style colours font-family font-size padding gap border-radius borders box-shadow
44-
*/
42+
/** Forwards its ref to the underlying `<textarea>`, exactly like a native textarea. */
4543
export const ChipTextarea = React.forwardRef<HTMLTextAreaElement, ChipTextareaProps>(
4644
({ className, error, resizable = false, viewOnly = false, readOnly, ...props }, ref) => (
4745
<textarea

‎packages/emcn/src/components/dropdown-menu/dropdown-menu.tsx‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,6 @@ interface DropdownMenuContentProps
290290
onOpenAutoFocus?: (event: Event) => void
291291
}
292292

293-
/**
294-
* Menu dimensions adapt to the consumer's content and viewport.
295-
* @designAllow className dimensions
296-
* @designAllow style dimensions
297-
*/
298293
const DropdownMenuContent = React.forwardRef<
299294
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
300295
DropdownMenuContentProps

0 commit comments

Comments
 (0)