mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 09:51:36 +00:00
feat(contained-list): add ContainedList
, ContainedListItem
(#1971)
This commit is contained in:
parent
cf41756cf4
commit
b6df277647
11 changed files with 484 additions and 2 deletions
|
@ -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
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
|||
- [`Column`](#column)
|
||||
- [`ComboBox`](#combobox)
|
||||
- [`ComposedModal`](#composedmodal)
|
||||
- [`ContainedList`](#containedlist)
|
||||
- [`ContainedListItem`](#containedlistitem)
|
||||
- [`Content`](#content)
|
||||
- [`ContentSwitcher`](#contentswitcher)
|
||||
- [`ContextMenu`](#contextmenu)
|
||||
|
@ -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" | "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" | "md" | "lg" | "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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"total": 169,
|
||||
"total": 171,
|
||||
"components": [
|
||||
{
|
||||
"moduleName": "Accordion",
|
||||
|
@ -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",
|
||||
|
|
122
docs/src/pages/components/ContainedList.svx
Normal file
122
docs/src/pages/components/ContainedList.svx
Normal file
|
@ -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
src/ContainedList/ContainedList.svelte
Normal file
54
src/ContainedList/ContainedList.svelte
Normal file
|
@ -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>
|
49
src/ContainedList/ContainedListItem.svelte
Normal file
49
src/ContainedList/ContainedListItem.svelte
Normal file
|
@ -0,0 +1,49 @@
|
|||
<script>
|
||||
// @ts-check
|
||||
|
||||
/** Set to `true` to render a `button` element instead of a `div` */
|
||||
export let interactive = false;
|
||||
|
||||
/** Set to `true` to disable the list item. */
|
||||
export let disabled = false;
|
||||
|
||||
/**
|
||||
* Specify the icon to render
|
||||
* Icon is rendered to the left of the label text
|
||||
* @type {typeof import("svelte").SvelteComponent<any>}
|
||||
*/
|
||||
export let icon = undefined;
|
||||
|
||||
$: tag = interactive ? "button" : "div";
|
||||
$: props = {
|
||||
type: interactive ? "button" : undefined,
|
||||
disabled: interactive ? disabled : undefined,
|
||||
};
|
||||
</script>
|
||||
|
||||
<li
|
||||
class:bx--contained-list-item="{true}"
|
||||
class:bx--contained-list-item--clickable="{interactive}"
|
||||
class:bx--contained-list-item--with-icon="{icon}"
|
||||
class:bx--contained-list-item--with-action="{$$slots.action}"
|
||||
>
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<svelte:element
|
||||
this="{tag}"
|
||||
{...props}
|
||||
on:click
|
||||
class:bx--contained-list-item__content="{true}"
|
||||
>
|
||||
{#if icon}
|
||||
<div class:bx--contained-list-item__icon="{true}">
|
||||
<svelte:component this="{icon}" />
|
||||
</div>
|
||||
{/if}
|
||||
<slot />
|
||||
</svelte:element>
|
||||
{#if $$slots.action}
|
||||
<div class:bx--contained-list__action="{true}">
|
||||
<slot name="action" />
|
||||
</div>
|
||||
{/if}
|
||||
</li>
|
2
src/ContainedList/index.js
Normal file
2
src/ContainedList/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default as ContainedList } from "./ContainedList.svelte";
|
||||
export { default as ContainedListItem } from "./ContainedListItem.svelte";
|
|
@ -22,6 +22,7 @@ export {
|
|||
ModalBody,
|
||||
ModalFooter,
|
||||
} from "./ComposedModal";
|
||||
export { ContainedList, ContainedListItem } from "./ContainedList";
|
||||
export { CodeSnippet, CodeSnippetSkeleton } from "./CodeSnippet";
|
||||
export {
|
||||
DataTable,
|
||||
|
|
9
tests/ContainedList.test.svelte
Normal file
9
tests/ContainedList.test.svelte
Normal file
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { ContainedList, ContainedListItem } from "../types";
|
||||
</script>
|
||||
|
||||
<ContainedList labelText="Title" kind="on-page">
|
||||
<div slot="labelText">Title</div>
|
||||
<ContainedListItem interactive disabled on:click>Item 1</ContainedListItem>
|
||||
<svelte:fragment slot="action" />
|
||||
</ContainedList>
|
38
types/ContainedList/ContainedList.svelte.d.ts
vendored
Normal file
38
types/ContainedList/ContainedList.svelte.d.ts
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
import type { SvelteComponentTyped } from "svelte";
|
||||
|
||||
export interface ContainedListProps {
|
||||
/**
|
||||
* @default "on-page"
|
||||
*/
|
||||
kind?: "on-page" | "disclosed";
|
||||
|
||||
/**
|
||||
* Specify the label text
|
||||
* @default ""
|
||||
*/
|
||||
labelText?: string;
|
||||
|
||||
/**
|
||||
* Specify the size of the list
|
||||
* @default "md"
|
||||
*/
|
||||
size?: "sm" | "md" | "lg" | "xl";
|
||||
|
||||
/**
|
||||
* Set to `true` for lines between list items to be inset.
|
||||
* @default false
|
||||
*/
|
||||
inset?: boolean;
|
||||
|
||||
/**
|
||||
* Set an id for the list
|
||||
* @default "ccs-" + Math.random().toString(36)
|
||||
*/
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export default class ContainedList extends SvelteComponentTyped<
|
||||
ContainedListProps,
|
||||
Record<string, any>,
|
||||
{ default: {}; action: {}; labelText: {} }
|
||||
> {}
|
28
types/ContainedList/ContainedListItem.svelte.d.ts
vendored
Normal file
28
types/ContainedList/ContainedListItem.svelte.d.ts
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
import type { SvelteComponentTyped } from "svelte";
|
||||
|
||||
export interface ContainedListItemProps {
|
||||
/**
|
||||
* Set to `true` to render a `button` element instead of a `div`
|
||||
* @default false
|
||||
*/
|
||||
interactive?: boolean;
|
||||
|
||||
/**
|
||||
* Set to `true` to disable the list item.
|
||||
* @default false
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* Specify the icon to render
|
||||
* Icon is rendered to the left of the label text
|
||||
* @default undefined
|
||||
*/
|
||||
icon?: typeof import("svelte").SvelteComponent<any>;
|
||||
}
|
||||
|
||||
export default class ContainedListItem extends SvelteComponentTyped<
|
||||
ContainedListItemProps,
|
||||
{ click: WindowEventMap["click"] },
|
||||
{ default: {}; action: {} }
|
||||
> {}
|
2
types/index.d.ts
vendored
2
types/index.d.ts
vendored
|
@ -26,6 +26,8 @@ export { default as ComposedModal } from "./ComposedModal/ComposedModal.svelte";
|
|||
export { default as ModalHeader } from "./ComposedModal/ModalHeader.svelte";
|
||||
export { default as ModalBody } from "./ComposedModal/ModalBody.svelte";
|
||||
export { default as ModalFooter } from "./ComposedModal/ModalFooter.svelte";
|
||||
export { default as ContainedList } from "./ContainedList/ContainedList.svelte";
|
||||
export { default as ContainedListItem } from "./ContainedList/ContainedListItem.svelte";
|
||||
export { default as CodeSnippet } from "./CodeSnippet/CodeSnippet.svelte";
|
||||
export { default as CodeSnippetSkeleton } from "./CodeSnippet/CodeSnippetSkeleton.svelte";
|
||||
export { default as DataTable } from "./DataTable/DataTable.svelte";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue