Skip to content

Commit

Permalink
feat(contained-list): add ContainedList, ContainedListItem (#1971)
Browse files Browse the repository at this point in the history
  • Loading branch information
metonym committed May 8, 2024
1 parent cf41756 commit b6df277
Show file tree
Hide file tree
Showing 11 changed files with 484 additions and 2 deletions.
51 changes: 50 additions & 1 deletion COMPONENT_INDEX.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Component Index

> 169 components exported from carbon-components-svelte@1.0.0-next.1.
> 171 components exported from carbon-components-svelte@1.0.0-next.1.
## Components

Expand All @@ -23,6 +23,8 @@
- [`Column`](#column)
- [`ComboBox`](#combobox)
- [`ComposedModal`](#composedmodal)
- [`ContainedList`](#containedlist)
- [`ContainedListItem`](#containedlistitem)
- [`Content`](#content)
- [`ContentSwitcher`](#contentswitcher)
- [`ContextMenu`](#contextmenu)
Expand Down Expand Up @@ -723,6 +725,53 @@ export interface ComboBoxItem {
| close | dispatched | <code>null</code> |
| open | dispatched | <code>null</code> |

## `ContainedList`

### Props

| Prop name | Required | Kind | Reactive | Type | Default value | Description |
| :-------- | :------- | :--------------- | :------- | ----------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------- |
| kind | No | <code>let</code> | No | <code>"on-page" &#124; "disclosed"</code> | <code>"on-page"</code> | -- |
| labelText | No | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the label text |
| size | No | <code>let</code> | No | <code>"sm" &#124; "md" &#124; "lg" &#124; "xl"</code> | <code>"md"</code> | Specify the size of the list |
| inset | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` for lines between list items to be inset. |
| id | No | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the list |

### Slots

| Slot name | Default | Props | Fallback |
| :-------- | :------ | :---- | :----------------------- |
| -- | Yes | -- | -- |
| action | No | -- | -- |
| labelText | No | -- | <code>{labelText}</code> |

### Events

None.

## `ContainedListItem`

### Props

| Prop name | Required | Kind | Reactive | Type | Default value | Description |
| :---------- | :------- | :--------------- | :------- | --------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------ |
| interactive | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to render a `button` element instead of a `div` |
| disabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the list item. |
| icon | No | <code>let</code> | No | <code>typeof import("svelte").SvelteComponent<any></code> | <code>undefined</code> | Specify the icon to render<br />Icon is rendered to the left of the label text |

### Slots

| Slot name | Default | Props | Fallback |
| :-------- | :------ | :---- | :------- |
| -- | Yes | -- | -- |
| action | No | -- | -- |

### Events

| Event name | Type | Detail |
| :--------- | :-------- | :----- |
| click | forwarded | -- |

## `Content`

### Props
Expand Down
130 changes: 129 additions & 1 deletion docs/src/COMPONENT_API.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"total": 169,
"total": 171,
"components": [
{
"moduleName": "Accordion",
Expand Down Expand Up @@ -1847,6 +1847,134 @@
"typedefs": [],
"rest_props": { "type": "Element", "name": "div" }
},
{
"moduleName": "ContainedList",
"filePath": "src/ContainedList/ContainedList.svelte",
"props": [
{
"name": "kind",
"kind": "let",
"type": "\"on-page\" | \"disclosed\"",
"value": "\"on-page\"",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "labelText",
"kind": "let",
"description": "Specify the label text",
"type": "string",
"value": "\"\"",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "size",
"kind": "let",
"description": "Specify the size of the list",
"type": "\"sm\" | \"md\" | \"lg\" | \"xl\"",
"value": "\"md\"",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "inset",
"kind": "let",
"description": "Set to `true` for lines between list items to be inset.",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "id",
"kind": "let",
"description": "Set an id for the list",
"type": "string",
"value": "\"ccs-\" + Math.random().toString(36)",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
}
],
"moduleExports": [],
"slots": [
{ "name": "__default__", "default": true, "slot_props": "{}" },
{ "name": "action", "default": false, "slot_props": "{}" },
{
"name": "labelText",
"default": false,
"fallback": "{labelText}",
"slot_props": "{}"
}
],
"events": [],
"typedefs": []
},
{
"moduleName": "ContainedListItem",
"filePath": "src/ContainedList/ContainedListItem.svelte",
"props": [
{
"name": "interactive",
"kind": "let",
"description": "Set to `true` to render a `button` element instead of a `div`",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "disabled",
"kind": "let",
"description": "Set to `true` to disable the list item.",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "icon",
"kind": "let",
"description": "Specify the icon to render\nIcon is rendered to the left of the label text",
"type": "typeof import(\"svelte\").SvelteComponent<any>",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
}
],
"moduleExports": [],
"slots": [
{ "name": "__default__", "default": true, "slot_props": "{}" },
{ "name": "action", "default": false, "slot_props": "{}" }
],
"events": [
{ "type": "forwarded", "name": "click", "element": "svelte:element" }
],
"typedefs": []
},
{
"moduleName": "Content",
"filePath": "src/UIShell/Content.svelte",
Expand Down
122 changes: 122 additions & 0 deletions docs/src/pages/components/ContainedList.svx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<script>
import { Button, Search, ContainedList, ContainedListItem } from "carbon-components-svelte";
import Add from "carbon-icons-svelte/lib/Add.svelte";
import Close from "carbon-icons-svelte/lib/Close.svelte";
import Preview from "../../components/Preview.svelte";
</script>

## Default

The `ContainedList` component is used to display a list of items in a container.

It uses a `md` size by default.

<ContainedList labelText="List title">
<ContainedListItem>Item 1</ContainedListItem>
<ContainedListItem>Item 2</ContainedListItem>
<ContainedListItem>Item 3</ContainedListItem>
</ContainedList>

## Small size

<ContainedList labelText="List title" size="sm">
<ContainedListItem>Item 1</ContainedListItem>
<ContainedListItem>Item 2</ContainedListItem>
<ContainedListItem>Item 3</ContainedListItem>
</ContainedList>

## Large size

<ContainedList labelText="List title" size="lg">
<ContainedListItem>Item 1</ContainedListItem>
<ContainedListItem>Item 2</ContainedListItem>
<ContainedListItem>Item 3</ContainedListItem>
</ContainedList>

## Extra-large size

<ContainedList labelText="List title" size="xl">
<ContainedListItem>Item 1</ContainedListItem>
<ContainedListItem>Item 2</ContainedListItem>
<ContainedListItem>Item 3</ContainedListItem>
</ContainedList>

## Inset items

<ContainedList labelText="List title" inset>
<ContainedListItem>Item 1</ContainedListItem>
<ContainedListItem>Item 2</ContainedListItem>
<ContainedListItem>Item 3</ContainedListItem>
</ContainedList>

## Disclosed

Set `kind="disclosed"` for the list title to be sticky positioned.

When scrolling, the list title will stick to the top of the container.

<div style:height="200px" style:overflow-y="auto">
<ContainedList labelText="List title 1" kind="disclosed">
{#each Array.from({ length: 6 }) as i}
<ContainedListItem>Item</ContainedListItem>
{/each}
</ContainedList>
<ContainedList labelText="List title 2" kind="disclosed">
{#each Array.from({ length: 6 }) as i}
<ContainedListItem>Item</ContainedListItem>
{/each}
</ContainedList>
</div>

## With icons

<ContainedList labelText="List title">
<ContainedListItem icon={Add}>Item 1</ContainedListItem>
<ContainedListItem icon={Add}>Item 2</ContainedListItem>
<ContainedListItem icon={Add}>Item 3</ContainedListItem>
</ContainedList>

## With expandable search

Use the `action` slot to add an expandable search.

<ContainedList labelText="List title">
<Search slot="action" expandable />
<ContainedListItem>Item 1</ContainedListItem>
<ContainedListItem>Item 2</ContainedListItem>
<ContainedListItem>Item 3</ContainedListItem>
</ContainedList>

## Interactive items

Set `interactive` to make the items render as a `button`.

<ContainedList labelText="List title">
<ContainedListItem interactive on:click={() => console.log('click')}>
Item 1
</ContainedListItem>
<ContainedListItem interactive disabled>Item 2</ContainedListItem>
<ContainedListItem interactive>Item 3</ContainedListItem>
</ContainedList>

## Interactive items with actions

Similarly to `ContainedList`, you can add an action to `ContainedListItem` using the `action` slot.

<ContainedList labelText="List title">
<ContainedListItem interactive on:click={() => console.log('click')}>
Item 1
<Button
slot="action"
kind="ghost"
iconDescription="Dismiss"
icon={Close}
on:click={() => console.log('click close')}
/>
</ContainedListItem>
<ContainedListItem interactive disabled>Item 2</ContainedListItem>
<ContainedListItem interactive>
Item 3
</ContainedListItem>
</ContainedList>

54 changes: 54 additions & 0 deletions src/ContainedList/ContainedList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<script>
// @ts-check
/** @type {"on-page" | "disclosed"} */
export let kind = "on-page";
/** Specify the label text */
export let labelText = "";
/**
* Specify the size of the list
* @type {"sm" | "md" | "lg" | "xl"}
*/
export let size = "md";
/** Set to `true` for lines between list items to be inset. */
export let inset = false;
/** Set an id for the list */
export let id = "ccs-" + Math.random().toString(36);
$: labelId = `label-${id}`;
</script>

<div
class:bx--contained-list="{true}"
class:bx--contained-list--inset-rulers="{inset}"
class:bx--contained-list--sm="{size === 'sm'}"
class:bx--contained-list--md="{size === 'md'}"
class:bx--contained-list--lg="{size === 'lg'}"
class:bx--contained-list--xl="{size === 'xl'}"
class:bx--layout--size-sm="{size === 'sm'}"
class:bx--layout--size-md="{size === 'md'}"
class:bx--layout--size-lg="{size === 'lg'}"
class:bx--layout--size-xl="{size === 'xl'}"
class:bx--contained-list--on-page="{kind === 'on-page'}"
class:bx--contained-list--disclosed="{kind === 'disclosed'}"
>
<div class:bx--contained-list__header="{true}">
<div id="{labelId}" class:bx--contained-list__label="{true}">
<slot name="labelText">
{labelText}
</slot>
</div>
{#if $$slots.action}
<div class:bx--contained-list__action="{true}">
<slot name="action" />
</div>
{/if}
</div>
<ul role="list" aria-labelledby="{labelId}">
<slot />
</ul>
</div>

0 comments on commit b6df277

Please sign in to comment.