kopia lustrzana https://github.com/shoelace-style/shoelace
Add card component
rodzic
905152a412
commit
66c3de9c3b
|
@ -12,6 +12,7 @@
|
|||
- [Avatar](/components/avatar.md)
|
||||
- [Badge](/components/badge.md)
|
||||
- [Button](/components/button.md)
|
||||
- [Card](/components/card.md)
|
||||
- [Checkbox](/components/checkbox.md)
|
||||
- [Color Picker](/components/color-picker.md)
|
||||
- [Details](/components/details.md)
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
# Card
|
||||
|
||||
[component-header:sl-card]
|
||||
|
||||
Cards can be used to group related subjects in a container.
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
alt="A kitten sits patiently between a terracotta pot and decorative grasses."
|
||||
>
|
||||
|
||||
<strong>Mittens</strong><br>
|
||||
This kitten is as cute as he is playful. Bring him home today!<br>
|
||||
<small>6 weeks old</small>
|
||||
|
||||
<div slot="footer">
|
||||
<sl-button type="primary" pill>More Info</sl-button>
|
||||
<sl-rating></sl-rating>
|
||||
</div>
|
||||
</sl-card>
|
||||
|
||||
<style>
|
||||
.card-overview {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-overview small {
|
||||
color: var(--sl-color-gray-60);
|
||||
}
|
||||
|
||||
.card-overview [slot="footer"] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
## Basic Card
|
||||
|
||||
Basic cards aren't very exciting, but they can display any content you want them to.
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-basic">
|
||||
This is just a basic card. No image, no header, and no footer. Just your content.
|
||||
</sl-card>
|
||||
|
||||
<style>
|
||||
.card-basic {
|
||||
max-width: 300px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Card with Header
|
||||
|
||||
Headers can be used to display titles and other card options.
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-header">
|
||||
<div slot="header">
|
||||
Header Title
|
||||
|
||||
<sl-dropdown placement="bottom-end">
|
||||
<sl-button slot="trigger" type="text">
|
||||
<sl-icon slot="suffix" name="pencil"></sl-icon>
|
||||
Edit
|
||||
</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item>Rename</sl-menu-item>
|
||||
<sl-menu-item>Duplicate</sl-menu-item>
|
||||
<sl-menu-divider></sl-menu-divider>
|
||||
<sl-menu-item>Delete</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</div>
|
||||
|
||||
This card has a header. You can put all sorts of things in it!
|
||||
</sl-card>
|
||||
|
||||
<style>
|
||||
.card-header {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-header [slot="header"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-header h3 {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Card with Footer
|
||||
|
||||
Footers can be used to display actions, summaries, or other relevant content.
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-footer">
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
|
||||
<div slot="footer">
|
||||
<sl-rating></sl-rating>
|
||||
<sl-button slot="footer" type="primary">Preview</sl-button>
|
||||
</div>
|
||||
</sl-card>
|
||||
|
||||
<style>
|
||||
.card-footer {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.card-footer [slot="footer"] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Images
|
||||
|
||||
Cards accept an `image` slot. The image is displayed atop the card and stretches to fit.
|
||||
|
||||
```html preview
|
||||
<sl-card class="card-image">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
alt="A kitten walks towards camera on top of pallet."
|
||||
>
|
||||
This is a kitten, but not just any kitten. This kitten likes walking along pallets.
|
||||
</sl-card>
|
||||
|
||||
<style>
|
||||
.card-image {
|
||||
max-width: 300px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
[component-metadata:sl-card]
|
|
@ -106,6 +106,8 @@ export namespace Components {
|
|||
*/
|
||||
"value": string;
|
||||
}
|
||||
interface SlCard {
|
||||
}
|
||||
interface SlCheckbox {
|
||||
/**
|
||||
* Set to true to draw the checkbox in a checked state.
|
||||
|
@ -904,6 +906,12 @@ declare global {
|
|||
prototype: HTMLSlButtonElement;
|
||||
new (): HTMLSlButtonElement;
|
||||
};
|
||||
interface HTMLSlCardElement extends Components.SlCard, HTMLStencilElement {
|
||||
}
|
||||
var HTMLSlCardElement: {
|
||||
prototype: HTMLSlCardElement;
|
||||
new (): HTMLSlCardElement;
|
||||
};
|
||||
interface HTMLSlCheckboxElement extends Components.SlCheckbox, HTMLStencilElement {
|
||||
}
|
||||
var HTMLSlCheckboxElement: {
|
||||
|
@ -1071,6 +1079,7 @@ declare global {
|
|||
"sl-avatar": HTMLSlAvatarElement;
|
||||
"sl-badge": HTMLSlBadgeElement;
|
||||
"sl-button": HTMLSlButtonElement;
|
||||
"sl-card": HTMLSlCardElement;
|
||||
"sl-checkbox": HTMLSlCheckboxElement;
|
||||
"sl-color-picker": HTMLSlColorPickerElement;
|
||||
"sl-details": HTMLSlDetailsElement;
|
||||
|
@ -1209,6 +1218,8 @@ declare namespace LocalJSX {
|
|||
*/
|
||||
"value"?: string;
|
||||
}
|
||||
interface SlCard {
|
||||
}
|
||||
interface SlCheckbox {
|
||||
/**
|
||||
* Set to true to draw the checkbox in a checked state.
|
||||
|
@ -2074,6 +2085,7 @@ declare namespace LocalJSX {
|
|||
"sl-avatar": SlAvatar;
|
||||
"sl-badge": SlBadge;
|
||||
"sl-button": SlButton;
|
||||
"sl-card": SlCard;
|
||||
"sl-checkbox": SlCheckbox;
|
||||
"sl-color-picker": SlColorPicker;
|
||||
"sl-details": SlDetails;
|
||||
|
@ -2111,6 +2123,7 @@ declare module "@stencil/core" {
|
|||
"sl-avatar": LocalJSX.SlAvatar & JSXBase.HTMLAttributes<HTMLSlAvatarElement>;
|
||||
"sl-badge": LocalJSX.SlBadge & JSXBase.HTMLAttributes<HTMLSlBadgeElement>;
|
||||
"sl-button": LocalJSX.SlButton & JSXBase.HTMLAttributes<HTMLSlButtonElement>;
|
||||
"sl-card": LocalJSX.SlCard & JSXBase.HTMLAttributes<HTMLSlCardElement>;
|
||||
"sl-checkbox": LocalJSX.SlCheckbox & JSXBase.HTMLAttributes<HTMLSlCheckboxElement>;
|
||||
"sl-color-picker": LocalJSX.SlColorPicker & JSXBase.HTMLAttributes<HTMLSlColorPickerElement>;
|
||||
"sl-details": LocalJSX.SlDetails & JSXBase.HTMLAttributes<HTMLSlDetailsElement>;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
@import 'component';
|
||||
|
||||
/**
|
||||
* @prop --border-color: The card's border color, including borders that occur inside the card.
|
||||
* @prop --border-radius: The border radius for card edges.
|
||||
* @prop --border-width: The width of card borders.
|
||||
* @prop --padding: The padding to use for card sections.
|
||||
*/
|
||||
:host {
|
||||
--border-color: var(--sl-color-gray-90);
|
||||
--border-radius: var(--sl-border-radius-medium);
|
||||
--border-width: 1px;
|
||||
--padding: var(--sl-spacing-large);
|
||||
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--sl-color-white);
|
||||
box-shadow: var(--sl-shadow-x-small);
|
||||
border: solid var(--border-width) var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.card__image {
|
||||
border-top-left-radius: calc(var(--border-radius) - var(--border-width));
|
||||
border-top-right-radius: calc(var(--border-radius) - var(--border-width));
|
||||
border-top-left-radius: var(--border-radius);
|
||||
border-top-right-radius: var(--border-radius);
|
||||
margin: calc(-1 * var(--border-width));
|
||||
overflow: hidden;
|
||||
|
||||
::slotted(img) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.card:not(.card--has-image) .card__image {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card__header {
|
||||
border-bottom: solid var(--border-width) var(--border-color);
|
||||
padding: calc(var(--padding) / 2) var(--padding);
|
||||
}
|
||||
|
||||
.card:not(.card--has-header) .card__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card__body {
|
||||
padding: var(--padding);
|
||||
}
|
||||
|
||||
.card--has-footer .card__footer {
|
||||
border-top: solid var(--border-width) var(--border-color);
|
||||
padding: var(--padding);
|
||||
}
|
||||
|
||||
.card:not(.card--has-footer) .card__footer {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import { Component, Element, State, h } from '@stencil/core';
|
||||
import { hasSlot } from '../../utilities/slot';
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
* @status stable
|
||||
*
|
||||
* @slot - The card's body.
|
||||
* @slot header - The card's header.
|
||||
* @slot footer - The card's footer.
|
||||
* @slot image - The card's image.
|
||||
*
|
||||
* @part base - The component's base wrapper.
|
||||
* @part image - The card's image, if present.
|
||||
* @part header - The card's header, if present.
|
||||
* @part body - The card's body.
|
||||
* @part footer - The card's footer, if present.
|
||||
*/
|
||||
|
||||
@Component({
|
||||
tag: 'sl-card',
|
||||
styleUrl: 'card.scss',
|
||||
shadow: true
|
||||
})
|
||||
export class Card {
|
||||
@Element() host: HTMLSlCardElement;
|
||||
|
||||
@State() hasFooter = false;
|
||||
@State() hasImage = false;
|
||||
@State() hasHeader = false;
|
||||
|
||||
componentWillLoad() {
|
||||
this.updateSlots();
|
||||
this.host.shadowRoot.addEventListener('slotchange', this.updateSlots);
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
this.host.shadowRoot.removeEventListener('slotchange', this.updateSlots);
|
||||
}
|
||||
|
||||
updateSlots() {
|
||||
this.hasFooter = hasSlot(this.host, 'footer');
|
||||
this.hasImage = hasSlot(this.host, 'image');
|
||||
this.hasHeader = hasSlot(this.host, 'header');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
part="base"
|
||||
class={{
|
||||
card: true,
|
||||
'card--has-footer': this.hasFooter,
|
||||
'card--has-image': this.hasImage,
|
||||
'card--has-header': this.hasHeader
|
||||
}}
|
||||
>
|
||||
<div part="image" class="card__image">
|
||||
<slot name="image" />
|
||||
</div>
|
||||
|
||||
<div part="header" class="card__header">
|
||||
<slot name="header" />
|
||||
</div>
|
||||
|
||||
<div part="body" class="card__body">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div part="footer" class="card__footer">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue