Skip to content

[WIP] Enhance UI components for forms and layouts - #12

Merged
huangyiirene merged 3 commits into
mainfrom
copilot/complete-ui-component-setup
Jan 13, 2026
Merged

huangyiirene merged 3 commits into
mainfrom
copilot/complete-ui-component-setup

Conversation

Copilot AI commented Jan 13, 2026 •

Copy link
Copy Markdown
Contributor

Plan: Complete Component Library

Based on the problem statement, I need to implement/enhance the following components:

Forms Components

  • Input - Already implemented
  • Select - Already implemented
  • Checkbox - Already implemented
  • Radio - Already implemented (radio-group)
  • DatePicker - Implemented with calendar and input trigger
  • File Upload - Implemented with file selection and preview

Data Components

  • Table - Already implemented
  • List - Implemented ordered and unordered lists
  • Card - Already implemented
  • Tree View - Implemented collapsible tree structure

Layout Components

  • Grid - Implemented responsive grid layout
  • Flex - Implemented flexible box layout
  • Container - Implemented max-width container
  • Tabs - Already implemented

Feedback Components

  • Alerts - Already implemented
  • Toasts - Already implemented (toaster)
  • Dialogs - Already implemented (alert-dialog, dialog)
  • Loading States - Implemented loading spinner component

Implementation Complete

✅ All components have been implemented
✅ Added date-fns dependency for date formatting
✅ Updated index files to export new components
✅ Build successful
✅ Tests added and passing (9/9 tests)

Original prompt

完善组件 Forms: Input, Select, Checkbox, Radio, DatePicker, File Upload
Data: Table, List, Card, Tree View
Layout: Grid, Flex, Container, Tabs
Feedback: Alerts, Toasts, Dialogs, Loading States


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits January 13, 2026 18:40
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
@huangyiirene
huangyiirene marked this pull request as ready for review January 13, 2026 18:44
@huangyiirene
huangyiirene merged commit c4637f4 into main Jan 13, 2026
Copilot AI requested a review from huangyiirene January 13, 2026 18:44
Copilot stopped work on behalf of huangyiirene due to an error January 13, 2026 18:44
@github-actions github-actions Bot mentioned this pull request Aug 3, 2026
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 3, 2026
…ce (objectstack-ai#3232) (objectstack-ai#3244)

The widget resolved its fullscreen affordance through a four-way `??` chain:
a `mobileFullscreen` (camelCase) prop, `field.mobile_fullscreen`, a
`mobile_fullscreen` prop, and `schema.mobile_fullscreen`. Three of the four
were permanently `undefined`:

- `mobileFullscreen` had no producer anywhere in the repo — the only two
  occurrences of that spelling were this widget's own read and the destructure
  that kept it off the DOM spread. The doc comment claimed "the host form
  passes `mobileFullscreen`", so it documented a contract that never held.
- `mobile_fullscreen` as a prop cannot arrive: `stripRegisteredFieldProps`
  (components/src/renderers/form/form.tsx) removes it, and `fullscreen`, from
  the props forwarded to registered field widgets.
- `schema.mobile_fullscreen` restates the object `field || schema` already
  resolves into `textareaField`.

What is left is the one live source: the field metadata flag ObjectForm stamps
onto long-text fields from `ObjectFormSchema.mobile.fullscreenLongText`. The
doc comment now describes that, names the producer, and records why there is
deliberately no host-override prop.

No behaviour change. The metadata path is pinned by new tests covering the
button, the dialog and the committed edit, so the cleanup cannot have removed
the working affordance; the retired spellings are pinned inert at compile time
(they are not on the closed `FieldWidgetComponentProps`, objectstack-ai#3221) and at runtime.

The built-in (unregistered) `textarea` branch of the form renderer, which reads
`mobile_fullscreen || fullscreen` off the form-field props and renders its own
`FullscreenTextarea`, is a separate live path and is untouched.

Per AGENTS.md #0.1 and Prime Directive objectstack-ai#12: divergence converges at the
producer, not by accumulating tolerance at the consumer.

Fixes objectstack-ai#3232


Claude-Session: https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Oct 7, 2026
…inside the `calendar` block; the flat spelling is the runtime handoff (objectui#8831) (objectstack-ai#11308)

Fixes objectstack-ai#8831

Clause-②: no

## What changes

`@objectstack/spec` refuses `startDateField` / `endDateField` /
`titleField` / `colorField` / `allDayField` written flat on an
`object-calendar` node. Its diagnostic prescribes `calendar: {
startDateField, endDateField, titleField, colorField, allDayField }`.
Since 17.5.0 the spec's `CalendarConfigSchema` declares all five,
`allDayField` included. This PR is ruled direction (a): objectui stops
teaching the flat spelling at the `object-calendar` position and teaches
the container.

- **`packages/plugin-calendar/README.md`**
- Both `object-calendar` snippets ("With ObjectQL Integration" and
"ObjectQL Integration") now write the five keys inside `calendar`, with
`allDayField` in the block. Both are compiled by `check:doc-snippets`.
- One paragraph names the flat spelling for what it is: the runtime
handoff `ObjectView` / `ListView` emit, which `getCalendarConfig` reads
only when the node has no `calendar` block. It is declared because the
renderer reads it, and it is not a second authorable spelling (Prime
Directive objectstack-ai#12).
- The snippet comment no longer says the block "proves" the flat keys
are declared. It now says what the annotation checks on the block
(values, not key names).
- The "gates the whole configuration" paragraph is rewritten for the
block, because it described the flat path. Its behavioural claims were
measured, see below.
- **`packages/types`, both faces of `ObjectCalendarSchema`**
- The five flat members' `.describe()` text (one shared helper,
`objectCalendarFlatField`) and TS docblocks call them the FLAT spelling,
read but not authored, and point at `calendar.KEY`.
  - The `calendar` member's text calls the block the authored spelling.
- The `allDayField` docblock no longer says the key is objectui-local.
It records that 17.5.0 declares it.
- **`ObjectCalendarBlockConfigSchema`'s `.extend({ allDayField })`.**
Only its description and comment changed: it no longer says the spec
refuses the key. See H2.
- **Pin.** The `calendar-flat-color-allday-8466` row "the README still
teaches all five together, which is what makes them authorable" is
inverted. It now reads the README's authored `object-calendar` nodes by
brace matching and asserts:
  - none writes a field-name key flat;
  - one `calendar` block carries all five;
- control, same instrument, opposite verdict: a `calendar-view` node is
seen writing `titleField` flat.

  The file's header gets a dated note.
- **Changesets.** New `.changeset/8831-calendar-flat-teaching-face.md`
(`@object-ui/types` patch, `@object-ui/plugin-calendar` patch). The
pending `.changeset/8466-calendar-color-allday-fields.md` says the
README "already teaches" the flat keys, which this release makes false.
It gets a dated, append-only note, and its frontmatter is byte-identical
(md5 of the first three lines unchanged).

## What is NOT changed

- **No accept set moves.** The flat members stay declared on both faces
with the same types, because `ObjectCalendar` reads them and
`ObjectView` / `ListView` emit them.
- Excluded regions are untouched: `ObjectCalendarSchema.objectName` and
`requireRecordSource` (held by objectui#11117), the `CalendarViewSchema`
declarations, `navigation`, and `registry-inputs-spec-parity.test.ts`
(held by objectui#11168).

## Premises, re-measured in this worktree (base `1ccb5ba7d`, installed
`@objectstack/spec` 17.5.0, single store copy)

- **Unlock predicate.** The card's probe exits **0**. Two lit controls
run beside it: `{ startDateField }` parses (`true`), and `{
startDateField, bogusKeyZz }` is refused (`false`, `unrecognized_keys`
naming `bogusKeyZz`). Shape keys: `allDayField, colorField,
endDateField, startDateField, titleField`.
- **The trap is real at the public row.**
- `ComponentPropsMap['object-calendar']` refuses the README's old first
snippet: `unrecognized_keys` on all five, and the message starts "Write
this as a key of the `calendar` config object instead".
  - It also refuses the second snippet (three keys).
  - It accepts the rewritten container form.
  - Control: a bogus key is refused.
- **H1, the `calendar-view` site.** `ComponentPropsMap` has no
`calendar-view` row (55 rows; the `object-calendar` control is present),
and `CalendarViewSchema` has no `calendar` container. So the flat keys
are that element's only spelling, and the container cannot be taught
there.
- Decision: keep the five-key sentence, scope it explicitly to
`calendar-view` ("on a `calendar-view` node ... here the flat keys are
the only spelling"), and point to the `object-calendar` block in the
next section.
- The compiler-pinned `CalendarViewNode` listing and the "Calendar Event
Structure" fence are `calendar-view`'s and stay.
- **H2, the `.extend({ allDayField })`.** It is now an identity. The
spec's `CalendarConfigSchema.partial()` member and the local
`z.string().optional()` agree on 8 of 8 values: two strings,
`undefined`, `42`, `true`, `null`, `{}`, an array. On the TS side,
`ObjectCalendarSchema['allDayField']` equals
`CalendarConfig['allDayField']`; a tsc probe checked this, and its
control fired.
- Only the description and comment changed. The member is kept: removing
it is an accept-set no-op, but the `zod-mirror-parity` ledger comment
names this extension, and that file is outside this claim.
- **H3, docs pages.** Falsified. Every `object-calendar` snippet on
`content/docs/plugins/plugin-calendar.mdx` already writes `calendar: {
... }`, and its Schema API fence lists no flat key. `git grep` found no
other `content/docs/**`, `examples/**` or `skills/**` site that authors
`object-calendar` with a flat key. The flat keys in
`content/docs/api/schema-reference.md` and the schema-catalog JSON are
`calendar-view`'s. ⇒ no docs page changed.
- **H4, the 8830 header.** Left as it is. It is framed "Measured on the
dispatch base, with `@objectstack/spec` 17.4.0 installed then", and the
test body's 17.5.0 row explains the move. A reader does not take it as
current.
- **README behavioural claims, measured.** A one-off render probe went
through the real `SchemaRenderer` and registry, and was deleted
afterwards (tree clean):
  - control: a correct block draws both rows, with no unscheduled area;
- a misspelt start key inside the block draws nothing, shows
`Unscheduled (2)`, and no refusal screen;
- a node with no `calendar` block renders "Calendar configuration
required".

## Verification, all at HEAD `bac7f8789`

Run from the worktree; heavy runs went through the shared verify lock.
The verdict lines are quoted.

| gate | result |
|---|---|
| `turbo run build` over `check:doc-snippets --build-filter` (36
packages, `--concurrency=2`) | `Tasks: 35 successful, 35 total`,
`VERDICT command-exit 0` |
| `pnpm check:doc-snippets` | exit 0, `Semantic phase: 698 of 698
block(s) judged, 0 failed.` |
| `pnpm check:readme-exports` | exit 0, `check-readme-exports: OK (...
554 real, 0 wrong-path, 0 fabricated ...)` |
| `pnpm --filter @object-ui/types type-check` (the script echoed: `tsc
--noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json`)
| exit 0. `tsc -p tsconfig.test.json --listFiles` counts the 8466 file
once, so the test face is in it |
| `pnpm exec vitest run --maxWorkers=2 packages/types/
packages/plugin-calendar/src/readme-calendar-view-schema.test.ts` |
`Test Files 302 passed (302)`, `Tests 7605 passed (7605)`, `VERDICT
command-exit 0` |
| eslint on the three changed TS files (`--no-inline-config`) | 0
errors. The 8466 file keeps exactly its 2 documented `no-explicit-any`
warnings |
| `check:doc-types`, `check:doc-fences`, `check:doc-example-ids`,
`check:installed-pin-claims`, `check:new-line-citations`,
`check:control-bytes`, `check:test-path-roots`,
`check:pending-changeset-literals`, `check:vi-mock-specifiers`,
`check:vi-mock-inherit`, `check:vi-mock-override-shape`,
`check:spec-symbols`, `check:component-surface-parity`,
`check:designer-field-key-parity`,
`check:element-data-source-declaration` | all exit 0 |
| `check-changeset-presence` / `-no-major` / `-fixed` | exit 0, `3
source file(s) of 1 released package(s) changed, and this change
declares 1 changeset(s)` |
| `markdown-test-inputs --audit` | exit 0, `107 candidate test files,
all adjudicated; 78 declared entries, all present.` |
| `check:comment-mask-corpus` | exit 0, within the residue objectui#7882
holds (1 file, 0 fabricated) |
| `check:changeset-claims`, `check-changeset-overwrite` (report-only) |
Read. 30 pending changesets name the touched files. The three that
mention calendar keys (7632, 7804, 9606) describe other regions and are
not made false. The overwrite report is case 2 (deliberate append,
declaration unchanged) |
| `check-governed-queue-guard --test` over the six paths | `NOT
GOVERNED` |

The repo-wide `pnpm lint` and the full CI matrix are left to CI.
`dispatch-gates.mjs --repo objectstack-ai/objectui` refuses (exit 2), as
it does for any objectui card, so this list is hand-derived from the
diff.

## Reverse verification (one-shot; each mutation landed through
`ablation-replace.mjs`, which checks the anchor count and the blob hash,
and was restored to the HEAD blob with `git diff HEAD` empty)

- **The new pin can fail.** A flat `titleField` was put back on the
README's second `object-calendar` node.
- Result: `× the README authors the five INSIDE the calendar block ...`,
`AssertionError: a README object-calendar node writes titleField flat`,
`Tests 1 failed | 18 passed`. Direction as expected: red.
- The first attempt was a no-op and is declared here: its replacement
contained the anchor, the tool refused it before running anything, and
no reading was taken.
- **`check:doc-snippets` judges the README block's values.**
- `allDayField: 'isAllDay'` was changed to `allDayField: 42` inside the
block.
- Result: `[semantic] packages/plugin-calendar/README.md ... TS2322:
Type 'number' is not assignable to type 'string'.`, `698 of 698 block(s)
judged, 1 failed`. Red, as expected.

## Round 2 (`a86a6afdb`)

Two findings from round 1, folded in on the seat's order. They are this
card's own subject (what the published faces teach about the `calendar`
container and `allDayField`), and neither could ride anywhere else.

- `content/docs/plugins/plugin-calendar.mdx`, section "CalendarConfig":
the paragraph that said neither published face of `ObjectCalendarSchema`
declares the `calendar` container (false since objectui#8651) now says
what holds on the installed 17.5.0:
  - Both faces declare the container, with the five keys as members.
- Values are checked: `calendar: { startDateField: 42 }` is refused, and
`dateField` / `endField` are refused by name (objectui#8355).
  - The block is `.passthrough()`, so any other key parses.
- On `object-calendar`, the spec declares the `calendar` key but not its
shape.
- On the list-view path, objectui's mirror is open while the spec's own
block is strict.
- Dated, append-only corrections, each with its frontmatter and existing
bytes identical (prefix md5 equal, 0 deleted lines):
- `.changeset/8026-objectcalendar-alldayfield-honoured.md`: its "Not
spec surface" paragraph. Made false by objectui#11073.
- `.changeset/8830-calendar-doc-key-set.md`: "objectui's own
`allDayField`". Made false by objectui#11073.
- `.changeset/olive-buckets-scream.md`: "the four `CalendarConfigSchema`
names plus objectui's `allDayField`", made false by objectui#11073; and
the kept `dateField` / `endField` rungs and the parsing
`calendar.dateField`, made false by objectui#8355.
- Left as dated history:
`.changeset/7928-listviews-by-reference-fold.md`, whose list of refused
named-view keys is labelled "Measured on 17.4.0".
- Gates at `a86a6afdb`, all exit 0:
- `check:doc-snippets` (698/698 judged, 0 failed), `check:doc-types`,
`check:doc-fences`, `check:doc-example-ids`;
- `check-changeset-presence` / `-no-major` / `-fixed` / `-overwrite`,
`check:changeset-claims`, `check:pending-changeset-literals`;
- `check:new-line-citations`, `check:control-bytes`,
`check:installed-pin-claims`, `check-doc-links`.
- The 19 tests that read the four changed markdown files: 773 passed.

## Acceptance notes

None of these was changed here. Each one is drift, outside this claim,
or both:

- `packages/plugin-calendar/src/ObjectCalendar.tsx`, the
`ObjectCalendarConfig` docblock, still says `allDayField` is not a spec
key. That sentence is already a `stale` entry in
`check-installed-spec-pin-claims.mjs`'s ledger. Carrier: none.
- `apps/console/src/__tests__/registry-inputs-spec-parity.test.ts` pin
text calls `allDayField` "an objectui-local extra key" and the spec side
"exactly the four documented keys". Carrier: objectui#11168, which holds
that file this round.
- `packages/types/src/__tests__/zod-mirror-parity.test.ts`, the ledger
comment beside `objectql.zod.ts#ObjectCalendarSchema`, still speaks of
the "four-key calendar config vocabulary" and objectui's "single local
knob". Removing the now-identity `allDayField` extension would make it
fully false, which is why that removal is not in this PR. Carrier: none;
objectui#6152 (another seat) holds that file.
- `packages/types/src/zod/objectql.zod.ts`, the list-view mirror note
("`.passthrough()` is kept ... because the renderers grow config knobs
ahead of the protocol (calendar's `allDayField`, for one)") cites an
example that has been out of date since 17.5.0. The list-view
`CalendarConfig` mirror now takes `allDayField` from the spec. The note
sits outside this card's region (PR objectstack-ai#11306 and objectui#11117 hold
neighbouring regions). Carrier: none.
- Round 1's two items on `plugin-calendar.mdx` and the three pending
changesets were folded into round 2 above.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants