mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(panel): equal-height conventions cards + scrollable module list
Each row of the Conventions editor grid now stretches its two cards to an equal height (Waivers and Custom rules line up; Module boundaries and Rules line up), and the Module-boundaries list scrolls internally so it matches the Rules card instead of running long. Single column on mobile is unchanged.
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|||||||
- **`ollama-init` is best-effort and gates startup on the models being present**, so a slow or unreachable model registry can no longer down a fully-cached deployment.
|
- **`ollama-init` is best-effort and gates startup on the models being present**, so a slow or unreachable model registry can no longer down a fully-cached deployment.
|
||||||
- **A PM can recover its own coordination task from `needs_revision`**, and lifecycle-transition notes are kept off the human-facing `quick_context` / `dev_notes` columns.
|
- **A PM can recover its own coordination task from `needs_revision`**, and lifecycle-transition notes are kept off the human-facing `quick_context` / `dev_notes` columns.
|
||||||
- **Panel:** a copyable task-id chip with a stable, non-shifting task header, clickable Branch / PR links with a branch-copy button, and clearer agent status badges.
|
- **Panel:** a copyable task-id chip with a stable, non-shifting task header, clickable Branch / PR links with a branch-copy button, and clearer agent status badges.
|
||||||
- **Panel:** the per-project Conventions editor lays out in a responsive two-column grid (Module boundaries | Rules, then Waivers | Custom rules) with Recent violations full-width, inside a wider modal on large viewports — instead of one long single column. It collapses to a single column on mobile and is capped so it stays sane up to a 27" display.
|
- **Panel:** the per-project Conventions editor lays out in a responsive two-column grid (Module boundaries | Rules, then Waivers | Custom rules) with Recent violations full-width, inside a wider modal on large viewports — instead of one long single column. Each row's two cards share an equal height, and the Module-boundaries list scrolls internally so it matches the Rules card instead of running long. It collapses to a single column on mobile and is capped so it stays sane up to a 27" display.
|
||||||
|
|
||||||
## [0.8.0] - 2026-06-20
|
## [0.8.0] - 2026-06-20
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export function ConventionsTab({ projectId }: { projectId: string }) {
|
|||||||
const usingDefaults = status === "missing" || status === "unknown";
|
const usingDefaults = status === "missing" || status === "unknown";
|
||||||
|
|
||||||
const moduleBoundaries = (
|
const moduleBoundaries = (
|
||||||
<Card>
|
<Card className="lg:flex lg:flex-col">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-sm">Module boundaries</CardTitle>
|
<CardTitle className="text-sm">Module boundaries</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
@@ -173,52 +173,60 @@ export function ConventionsTab({ projectId }: { projectId: string }) {
|
|||||||
toggle it.
|
toggle it.
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-3">
|
<CardContent className="space-y-3 lg:flex lg:min-h-0 lg:flex-1 lg:flex-col">
|
||||||
{standard.modules.length === 0 && (
|
<div className="space-y-3 lg:min-h-0 lg:flex-1 lg:overflow-y-auto lg:pr-1">
|
||||||
<p className="text-sm text-muted-foreground">
|
{standard.modules.length === 0 && (
|
||||||
No modules mapped yet.
|
<p className="text-sm text-muted-foreground">
|
||||||
</p>
|
No modules mapped yet.
|
||||||
)}
|
</p>
|
||||||
{standard.modules.map((module, index) => (
|
)}
|
||||||
<div
|
{standard.modules.map((module, index) => (
|
||||||
key={index}
|
<div
|
||||||
className="space-y-2 rounded-md border border-border p-3"
|
key={index}
|
||||||
>
|
className="space-y-2 rounded-md border border-border p-3"
|
||||||
<div className="flex items-center gap-2">
|
>
|
||||||
<Input
|
<div className="flex items-center gap-2">
|
||||||
value={module.path}
|
<Input
|
||||||
placeholder="path/to/module"
|
value={module.path}
|
||||||
onChange={(e) => updateModule(index, { path: e.target.value })}
|
placeholder="path/to/module"
|
||||||
/>
|
onChange={(e) =>
|
||||||
<Button
|
updateModule(index, { path: e.target.value })
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => removeModule(index)}
|
|
||||||
>
|
|
||||||
Remove
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<Input
|
|
||||||
value={module.purpose}
|
|
||||||
placeholder="what this module is for"
|
|
||||||
onChange={(e) => updateModule(index, { purpose: e.target.value })}
|
|
||||||
/>
|
|
||||||
<div className="flex flex-wrap gap-1">
|
|
||||||
{FORBIDDABLE_KINDS.map((kind) => (
|
|
||||||
<Badge
|
|
||||||
key={kind}
|
|
||||||
variant={
|
|
||||||
module.forbidden.includes(kind) ? "destructive" : "outline"
|
|
||||||
}
|
}
|
||||||
className="cursor-pointer"
|
/>
|
||||||
onClick={() => toggleForbidden(index, kind)}
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => removeModule(index)}
|
||||||
>
|
>
|
||||||
no {kind}
|
Remove
|
||||||
</Badge>
|
</Button>
|
||||||
))}
|
</div>
|
||||||
|
<Input
|
||||||
|
value={module.purpose}
|
||||||
|
placeholder="what this module is for"
|
||||||
|
onChange={(e) =>
|
||||||
|
updateModule(index, { purpose: e.target.value })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{FORBIDDABLE_KINDS.map((kind) => (
|
||||||
|
<Badge
|
||||||
|
key={kind}
|
||||||
|
variant={
|
||||||
|
module.forbidden.includes(kind)
|
||||||
|
? "destructive"
|
||||||
|
: "outline"
|
||||||
|
}
|
||||||
|
className="cursor-pointer"
|
||||||
|
onClick={() => toggleForbidden(index, kind)}
|
||||||
|
>
|
||||||
|
no {kind}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
<Button variant="outline" size="sm" onClick={addModule}>
|
<Button variant="outline" size="sm" onClick={addModule}>
|
||||||
Add module
|
Add module
|
||||||
</Button>
|
</Button>
|
||||||
@@ -430,9 +438,11 @@ export function ConventionsTab({ projectId }: { projectId: string }) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Two columns on wide viewports so the modal isn't a long single column;
|
{/* Two columns on wide viewports so the modal isn't a long single column;
|
||||||
Module boundaries | Rules, then Waivers | Custom rules. Each cell keeps
|
Module boundaries | Rules, then Waivers | Custom rules. items-stretch
|
||||||
its natural height (items-start) and stacks to one column on mobile. */}
|
makes each row's two cards equal height; Module boundaries scrolls
|
||||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:items-start">
|
internally (below) so it matches Rules instead of running long. Stacks
|
||||||
|
to one column on mobile. */}
|
||||||
|
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:items-stretch">
|
||||||
{moduleBoundaries}
|
{moduleBoundaries}
|
||||||
{rules}
|
{rules}
|
||||||
{waivers}
|
{waivers}
|
||||||
|
|||||||
Reference in New Issue
Block a user