Merge branch 'card' into next

pull/136/head
Cory LaViska 2020-07-22 17:13:53 -04:00
commit 69d3daff4a
8 zmienionych plików z 314 dodań i 5 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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]

13
src/components.d.ts vendored
Wyświetl plik

@ -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>;

Wyświetl plik

@ -2,7 +2,7 @@ import { Component, Prop, h } from '@stencil/core';
/**
* @since 2.0
* @status experimental
* @status stable
*
* @slot - The badge's content.
*

Wyświetl plik

@ -332,10 +332,6 @@
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Block modifier
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Caret modifier
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -35,3 +35,10 @@ export function getTextContent(slot: HTMLSlotElement): string {
return text;
}
//
// Determines whether a slot with the given name exists in an element.
//
export function hasSlot(el: HTMLElement, name: string) {
return [...el.querySelectorAll('[slot]')].filter((slottedEl: HTMLSlotElement) => slottedEl.slot === name).length > 0;
}