Skip to content

Conversation

@lucaslyl
Copy link
Contributor

@lucaslyl lucaslyl commented Jan 15, 2026

linear: https://linear.app/cardstack/issue/CS-10042/make-field-configuration-playground-editable-without-server-writes-for

Changes

1. Extracted 5 reusable components from base spec.gts:

  • SpecHeader — Displays icon, title, and description with support for edit and view modes

  • SpecReadmeSection — Renders the README section with optional "Generate README" button

  • SpecExamplesSection — Handles examples display (linked/contained) with primitive field handling

  • ExamplesWithInteractive — New component for interactive field usage examples

    • Provides permissions context (canWrite: true, canRead: true) via @provide(PermissionsContextName)
    • Allows UI interaction without server writes, even for users without write permissions
    • Used in field spec subclasses to show interactive playground examples
  • SpecModuleSection — Displays module URL and exported name information

2. Add @disabled support to form inputs across catalog-realm fields:

  • Image and multiple-image field components (upload, preview, remove buttons)
  • Audio field (file inputs, change button)
  • DateRangePicker component in boxel-ui
  • BoxelSelect/dropdown components (quarter, day, month, year, etc.)
  • BoxelInput components (slider, time, week, month-year, quantity)
  • Rating field buttons
  • Number input component

3. Field spec updates

  • Import the new components from https://cardstack.com/base/spec
  • Use the modular components instead of inline templates
  • Maintain the same functionality with cleaner, more maintainable code

Demo:

image

@lucaslyl lucaslyl self-assigned this Jan 15, 2026
@github-actions
Copy link

github-actions bot commented Jan 15, 2026

@lucaslyl lucaslyl requested a review from a team January 15, 2026 14:06
@github-actions
Copy link

github-actions bot commented Jan 15, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   1h 41m 27s ⏱️ + 1m 45s
1 897 tests ±0  1 880 ✅ ±0  17 💤 ±0  0 ❌ ±0 
1 912 runs  ±0  1 895 ✅ ±0  17 💤 ±0  0 ❌ ±0 

Results for commit e90142e. ± Comparison against base commit 143407c.

♻️ This comment has been updated with latest results.

Comment on lines 56 to 69
<button
type='button'
class='copy-button'
title='Copy code'
{{on 'click' this.copyCode}}
>
{{#if this.isCopied}}
<CopyCheckIcon width='14' height='14' />
<span>Copied</span>
{{else}}
<CopyIcon width='14' height='14' />
<span>Copy</span>
{{/if}}
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the boxel-ui/copy-button here: https://boxel-ui.stack.cards/?s=Components&ss=%3CCopyButton%3E. You can send an arg for what shows up in the tooltip too.

Element: HTMLDivElement;
}

export default class CodeSnippet extends GlimmerComponent<CodeSnippetSignature> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check out the CSSField in card-api and CSSValueField in base realm. I think the component you want here is similar to those.

Comment on lines 83 to 84
background-color: var(--muted, #f1f5f9);
border: 1px solid var(--border, #e0e0e0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it doesn't actually help to have these fallback values hardcoded like this all over the css because they may need to be different for dark mode for example. It's better to specify it in the beginning like: --_code-muted: var(--muted, #f1f5f9) and then use var(--_code-muted) in places where you need it. This is for colors only

Comment on lines 102 to 109
font-family: var(
--font-mono,
'Monaco',
'Menlo',
'Ubuntu Mono',
'Consolas',
monospace
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be: var(--font-mono, var(--boxel-monospace-font-family))

border-radius: var(--radius, 0.375rem) var(--radius, 0.375rem) 0 0;
}
.code-snippet-label {
font-family: var(--font-sans, system-ui, sans-serif);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you shouldn't need to specify the sans-serif, I think it's default

}
.code-snippet-label {
font-family: var(--font-sans, system-ui, sans-serif);
font-size: 0.75rem;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is var(--boxel-caption-font-size)

font-weight: 500;
color: var(--muted-foreground, #64748b);
text-transform: uppercase;
letter-spacing: 0.05em;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--boxel-lsp-xxs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your advise! I've updated the styling based on your feedback and aligned it with the new variable guidelines in variables.css

>
{{#if field.component}}
<field.component @format='edit' />
<field.component @format='edit' @canEdit={{true}} />
Copy link
Contributor

@tintinthong tintinthong Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukemelia this is where lucas implemented the usage of the box component. Here the field showcase fields need to be be able to be interacted with ( Not disabled ) so we have to flag the UI to render the component as tho its editable.

Here the motive of rendering with a box component here is lucas created a generic component field-spec-template bcos he didn't want to make the components on the spec shareable and he didn't want to repeat hardcoded templates with @fields instantitions -- otherwise, he wud have to do it with all the fields. FieldRenderer was a previous component introduced by me to support rendering all types of fields inside of a table form (this component does some internal implementation to prevent flickering during edits). Looks like he used this component and hence has access to the boxComponent itself.

In my opinon, I don't see usage of box component too bad but even if we just stuck to a pattern whereby we lock ourselves into @fields, I think we wud still need to string thru an arg like @canedit to the box component to get the behaviour we want. In addition, lucas didnt have to fuse the field-renderer -- it was just a convenience for him

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in addition,

canEdit is a funny name for the api layer we r changing.

I was thinking an argument like displayAsEditable might be clearer. and it separates from the understanding of canEdit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tintinthong I think I'm going to need a walkthrough on this. These spec field showcases should function as examples for how to use the fields. More verbose isolated & edit templates with standard field delegation would be better than a clever shared template that uses something most card authors should likely not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lucaslyl I have discussed with Luke about this

we want to make the field usage more explicit here for clarity to the user as opposed to using a very ad-hoc internal api to render the field such as the box component

This means

  • we need to render the fields using @field api
  • every field that you intend to have field configuration showcase should subclass the spec AND override its template. NOT provide a generic template that has some special treatment
  • spec template has to be broken up into components such that these components can be re-used in your subclassed field spec
  • we should not introduce a new argument canEdit. Rather we should dynamically provide this context using "FormatsProvider" pattern

@lucaslyl lucaslyl marked this pull request as ready for review January 21, 2026 13:26
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.

5 participants