mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 05:06:55 +04:00
Add item slots, sizes, selectable and nested items to list group (#3272)
This commit is contained in:
1 parent
5aad08b7c1
commit
69c1114f7a
10 files changed
+898
-112
No files matched your search
@@ -18,7 +18,7 @@ interface Props {
|
||||
class?: string
|
||||
}
|
||||
|
||||
const { offset = 0, hoverable = false, checkbox, checkedIds, title = 'Last commits', class: className } = Astro.props
|
||||
const { offset = 0, hoverable = false, checkbox = false, checkedIds, title = 'Last commits', class: className } = Astro.props
|
||||
|
||||
const limit = 8
|
||||
|
||||
@@ -44,40 +44,25 @@ const rows = people.slice(offset, offset + limit).map((person, idx) => {
|
||||
<div class="card-header">
|
||||
<CardTitle>{title}</CardTitle>
|
||||
</div>
|
||||
<ListGroup flush hoverable={hoverable}>
|
||||
<ListGroup flush hoverable={hoverable} selectable={checkbox}>
|
||||
{
|
||||
rows.map((row) => (
|
||||
<ListGroupItem active={row.checked}>
|
||||
<div class="row align-items-center">
|
||||
{checkbox ? (
|
||||
<div class="col-auto">
|
||||
<input type="checkbox" class="form-check-input" checked={row.checked} />
|
||||
</div>
|
||||
) : (
|
||||
<div class="col-auto">
|
||||
<span class={`badge${row.color !== 'x' ? ` bg-${row.color}` : ''}`} />
|
||||
</div>
|
||||
)}
|
||||
<div class="col-auto">
|
||||
<a href="#" tabindex="-1" aria-hidden="true">
|
||||
<Avatar person={row.person} />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col text-truncate">
|
||||
<a href="#" class="text-reset d-block">
|
||||
{row.person.full_name}
|
||||
</a>
|
||||
<div class="d-block text-secondary text-truncate mt-n1">{row.description}</div>
|
||||
</div>
|
||||
{hoverable && (
|
||||
<div class="col-auto">
|
||||
<a href="#" class={`list-group-item-actions${row.checked ? ' show' : ''}`} aria-label={row.checked ? 'Remove from favorites' : 'Add to favorites'}>
|
||||
<Icon name="star" class={row.starColor} />
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ListGroupItem active={!checkbox && row.checked} showActions={row.checked}>
|
||||
<Fragment slot="media">
|
||||
{checkbox ? <input type="checkbox" class="form-check-input list-group-selectable-check m-0" checked={row.checked} aria-label={`Select ${row.person.full_name}`} /> : <span class={`badge${row.color !== 'x' ? ` bg-${row.color}` : ''}`} />}
|
||||
<a href="#" class="ms-3" tabindex="-1" aria-hidden="true">
|
||||
<Avatar person={row.person} />
|
||||
</a>
|
||||
</Fragment>
|
||||
<a href="#" class="list-group-item-title">
|
||||
{row.person.full_name}
|
||||
</a>
|
||||
<div class="list-group-item-description">{row.description}</div>
|
||||
{hoverable && (
|
||||
<a href="#" slot="actions" aria-label={row.checked ? 'Remove from favorites' : 'Add to favorites'}>
|
||||
<Icon name="star" class={row.starColor} />
|
||||
</a>
|
||||
)}
|
||||
</ListGroupItem>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -39,19 +39,13 @@ const rows = sorted.map((person, idx) => {
|
||||
<>
|
||||
{row.header && <ListGroupHeader class="sticky-top">{row.header}</ListGroupHeader>}
|
||||
<ListGroupItem>
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<a href="#" tabindex="-1" aria-hidden="true">
|
||||
<Avatar person={row.person} />
|
||||
</a>
|
||||
</div>
|
||||
<div class="col text-truncate">
|
||||
<a href="#" class="text-body d-block">
|
||||
{row.person.full_name}
|
||||
</a>
|
||||
<div class="text-secondary text-truncate mt-n1">{row.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" slot="media" tabindex="-1" aria-hidden="true">
|
||||
<Avatar person={row.person} />
|
||||
</a>
|
||||
<a href="#" class="list-group-item-title">
|
||||
{row.person.full_name}
|
||||
</a>
|
||||
<div class="list-group-item-description">{row.description}</div>
|
||||
</ListGroupItem>
|
||||
</>
|
||||
))
|
||||
|
||||
@@ -5,18 +5,24 @@ import type { HTMLTag } from 'astro/types'
|
||||
|
||||
type PolymorphicProps = { as?: HTMLTag }
|
||||
|
||||
/** core/scss/ui/_lists.scss `.list-group-{size}` density modifiers */
|
||||
type ListGroupSize = 'sm' | 'lg'
|
||||
|
||||
interface Props extends PolymorphicProps {
|
||||
size?: ListGroupSize | undefined
|
||||
flush?: boolean
|
||||
hoverable?: boolean
|
||||
/** list-group-selectable: an item with a checked .list-group-selectable-check input gets the active look */
|
||||
selectable?: boolean
|
||||
transparent?: boolean
|
||||
class?: string
|
||||
/** remaining attributes (data-sortable, style, …) are forwarded to the element */
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const { as: Element = 'div', flush, hoverable, transparent, class: className, ...rest }: Props = Astro.props
|
||||
const { as: Element = 'div', size, flush, hoverable, selectable, transparent, class: className, ...rest }: Props = Astro.props
|
||||
---
|
||||
|
||||
<Element class:list={['list-group', flush && 'list-group-flush', hoverable && 'list-group-hoverable', transparent && 'list-group-transparent', className]} {...rest}>
|
||||
<Element class:list={['list-group', size && `list-group-${size}`, flush && 'list-group-flush', hoverable && 'list-group-hoverable', selectable && 'list-group-selectable', transparent && 'list-group-transparent', className]} {...rest}>
|
||||
<slot />
|
||||
</Element>
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
import type { HTMLTag } from 'astro/types'
|
||||
|
||||
// List group item (.list-group-item).
|
||||
// List group item (.list-group-item). With a title, a description or a named
|
||||
// slot it renders the slot layout: media, content, meta and actions in a row.
|
||||
|
||||
type PolymorphicProps = { as?: HTMLTag }
|
||||
|
||||
@@ -10,14 +11,52 @@ interface Props extends PolymorphicProps {
|
||||
action?: boolean
|
||||
active?: boolean
|
||||
disabled?: boolean
|
||||
/** first line of the content slot (.list-group-item-title) */
|
||||
title?: string | undefined
|
||||
/** second line of the content slot (.list-group-item-description) */
|
||||
description?: string | undefined
|
||||
/** keeps the actions slot visible in a hoverable list (.show) */
|
||||
showActions?: boolean
|
||||
class?: string
|
||||
/** remaining attributes (href, data-*, …) are forwarded to the element */
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const { as: Element = 'div', action, active, disabled, class: className, ...rest }: Props = Astro.props
|
||||
const { as: Element = 'div', action, active, disabled, title, description, showActions, class: className, ...rest }: Props = Astro.props
|
||||
|
||||
const hasMedia = Astro.slots.has('media')
|
||||
const hasMeta = Astro.slots.has('meta')
|
||||
const hasActions = Astro.slots.has('actions')
|
||||
const hasSlots = Boolean(title || description || hasMedia || hasMeta || hasActions)
|
||||
---
|
||||
|
||||
<Element class:list={['list-group-item', action && 'list-group-item-action', active && 'active', disabled && 'disabled', className]} aria-disabled={disabled ? 'true' : undefined} tabindex={Element === 'a' && disabled ? -1 : undefined} {...rest}>
|
||||
<slot />
|
||||
{
|
||||
hasSlots ? (
|
||||
<>
|
||||
{hasMedia && (
|
||||
<div class="list-group-item-media">
|
||||
<slot name="media" />
|
||||
</div>
|
||||
)}
|
||||
<div class="list-group-item-content">
|
||||
{title && <div class="list-group-item-title">{title}</div>}
|
||||
{description && <div class="list-group-item-description">{description}</div>}
|
||||
<slot />
|
||||
</div>
|
||||
{hasMeta && (
|
||||
<div class="list-group-item-meta">
|
||||
<slot name="meta" />
|
||||
</div>
|
||||
)}
|
||||
{hasActions && (
|
||||
<div class:list={['list-group-item-actions', showActions && 'show']}>
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<slot />
|
||||
)
|
||||
}
|
||||
</Element>
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
interface Props {
|
||||
color?: string
|
||||
color?: string | undefined
|
||||
animated?: boolean
|
||||
/** accessible name (visually-hidden text inside the dot) */
|
||||
ariaLabel?: string
|
||||
|
||||
Reference in new issue
Block a user