Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collection view: table columns definition #1249

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/lemon-ladybugs-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@keystatic/core': patch
'keystatic-docs': patch
---

Implement columns definition for collection view.
28 changes: 26 additions & 2 deletions docs/keystatic.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ const markdocConfig: Config = {
},
},
paragraph: { ...Markdoc.nodes.paragraph, render: 'Paragraph' },
table: { ...Markdoc.nodes.table, render: 'Table' },
fence: {
render: 'CodeBlock',
attributes: {
Expand Down Expand Up @@ -295,7 +296,14 @@ export default config({
contentField: 'content',
},
previewUrl: makePreviewUrl('/blog/{slug}'),
columns: ['title', 'publishedOn'],
columns: {
definition: [
{ key: 'title', isRowHeader: true },
{ key: 'draft', label: 'Draft', width: 140 },
{ key: 'publishedOn', label: 'Published', width: 140, align: 'end' },
],
defaultSort: { column: 'publishedOn', direction: 'descending' },
},
schema: {
title: fields.slug({
name: {
Expand Down Expand Up @@ -372,7 +380,16 @@ export default config({
path: 'src/content/projects/*',
format: { contentField: 'content' },
entryLayout: 'content',
columns: ['title', 'type', 'url', 'repoUrl', 'sortIndex'],
columns: {
definition: [
{ key: 'title', isRowHeader: true },
{ key: 'type', width: 120 },
{ key: 'url', allowsSorting: false },
{ key: 'repoUrl', label: 'Repo', allowsSorting: false },
{ key: 'sortIndex', label: 'Sort', width: 80, align: 'end' },
],
defaultSort: { column: 'sortIndex', direction: 'ascending' },
},
schema: {
title: fields.slug({ name: { label: 'Title' } }),
type: fields.select({
Expand Down Expand Up @@ -417,6 +434,13 @@ export default config({
label: 'Resources',
path: 'src/content/resources/*',
slugField: 'title',
columns: {
definition: [
{ key: 'title', isRowHeader: true },
{ key: 'sortIndex', label: 'Sort', width: 80, align: 'end' },
],
defaultSort: { column: 'sortIndex', direction: 'ascending' },
},
schema: {
title: fields.slug({ name: { label: 'Title' } }),
type: fields.conditional(
Expand Down
21 changes: 21 additions & 0 deletions docs/src/components/markdoc-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,27 @@ const getRenderers = (highlighter: shiki.Highlighter | undefined) => ({
</div>
);
},
Table: (props: { children: ReactNode }) => {
return (
<table
className="w-full border-collapse text-left
[&_td:not(:first-child)]:pl-4
[&_td:not(:last-child)]:pr-4
[&_td]:border-b
[&_td]:border-slate-3
[&_td]:py-2
[&_th:not(:first-child)]:pl-4
[&_th:not(:last-child)]:pr-4
[&_th]:border-b
[&_th]:border-slate-5
[&_th]:py-2
[&_th]:font-medium
"
>
{props.children}
</table>
);
},
CloudImage: ({
src,
alt,
Expand Down
83 changes: 69 additions & 14 deletions docs/src/content/pages/collections.mdoc
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
---
title: Collections
summary: >-
Think of a collection as anything you'd want multiple instances of. A series
Think of a collection as anything youd want multiple instances of. A series
of blog posts, cooking recipes, or testimonials from happy customers.
---
Think of a `collection` as anything you'd want multiple instances of. A series of blog posts, cooking recipes, or testimonials from happy customers.
Think of a `collection` as anything youd want multiple instances of. A series of blog posts, cooking recipes, or testimonials from happy customers.

Collections are defined within the `collections` key of the Keystatic `config`. Each collection has its own key and is wrapped in a `collection()` function.

## Example

Here's how you'd define a `testimonial` collection, where each entry has an `author` and a `quote` fields:
Heres how youd define a `testimonial` collection, where each entry has an `author` and a `quote` fields:

```jsx
// keystatic.config.ts
Expand All @@ -37,29 +37,84 @@ export default config({

### Columns

`columns` — show additional fields in the collection list view.
By default, only the “slug” of each entry is displayed in the collection table. You can show additional fields by passing a `columns` option.
Copy link
Member

Choose a reason for hiding this comment

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

By default, only the “slug” of each entry is displayed in the collection table. You can show additional fields by passing a columns option.

This is no longer true with this PR, columns now removes the slug instead of just adding other columns. I don't think we should land this without preserving the ability to show the slug and other fields.


By default, only the `slug` of each entry is displayed in the collection list.
{% aside icon="⏱️" %}
Fetching data for each entry takes time. Large collections may benefit from displaying the slug only.
{% /aside %}

You can show additional fields by passing a `columns` option, which is an array of field keys:
#### Basic columns

Pass an array of field keys to show them in the collection table:

```ts
columns: ['title', 'publishedOn']
```

### Label
#### Columns definition

For more control, use a `columns` object with a `definition` array. Column definitions require a `defaultSort` option.

```ts
columns: {
definition: [
{ key: 'title', isRowHeader: true },
{
key: 'publishedOn',
label: 'Published',
width: 140,
align: 'end'
},
],
defaultSort: {
column: 'publishedOn',
direction: 'descending'
}
}
```

{% table %}
- Property
- Description
---
- `align`
- The alignment of the column’s contents relative to its allotted width.
---
- `allowsSorting`
- Whether the column allows sorting. Defaults to `true`.
---
- `isRowHeader`
- Whether a column is a [row header](https://www.w3.org/TR/wai-aria-1.1/#rowheader) and should be announced by assistive technology during row navigation.
---
- `key` (required)
- The key of the column.
---
- `label`
- The label of the column. Defaults to the label of the matching schema field, by `key`.
---
- `maxWidth`
- The maximum width of the column.
---
- `minWidth`
- The minimum width of the column.
---
- `width`
- The width of the column.
{% /table %}

### Label

`label` — defines the name of the collection. This is used in the Admin UI to label the collection.

### Entry layout

`entryLayout` — change the layout of the Admin UI for a collection entry.
`entryLayout` — change the layout of the Admin UI for a collection entry.

Learn more on the [Entry Layout](/docs/entry-layout) page.

### Format

`format` — provides options around the data format of your collection entries.
`format` — provides options around the data format of your collection entries.

Learn more on the [Format Options](/docs/format-options) page.

Expand All @@ -75,23 +130,23 @@ By default, Keystatic will store entries at the root of your project, in a direc

You can learn more about the `path` option on the [Content organisation page](/docs/content-organisation).

### Parse slug for sort
### Parse slug for sort

`parseSlugForSort` — a function to transform the `slug` of each entry into a value to be used for sorting the collection list view.

### Preview URL

`previewURL` — used to configure [Real-time Previews](/docs/recipes/real-time-previews) of your content.

### Schema
### Schema

`schema` — defines the fields that each entry in the collection should have.

### Slug field

`slugField` — defines what field in your collection `schema` should be used as the slug for each item.
`slugField` — defines what field in your collection `schema` should be used as the slug for each item.

It's recommended to combine it with the [slug field](/docs/fields/slug) to let users customise and regenerate each slug in the Admin UI.
Its recommended to combine it with the [slug field](/docs/fields/slug) to let users customise and regenerate each slug in the Admin UI.

```typescript
testimonials: collection({
Expand All @@ -105,7 +160,7 @@ testimonials: collection({

### Template

`template` — the path to a content file (existing collection entry or "template") to use as a starting point for new entries.
`template` — the path to a content file (existing collection entry or template) to use as a starting point for new entries.

---

Expand Down
Loading
Loading