From d823bf29bbdb6ec70fa0ea16ea9d6ff60156c22d Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Thu, 28 Jan 2016 11:39:16 -0800 Subject: [PATCH] feat(card): Add card component --- src/components/card/card-header.html | 5 + src/components/card/card-title-group.html | 5 + src/components/card/card.html | 3 + src/components/card/card.scss | 221 ++++++++++++++++++++++ src/components/card/card.ts | 71 +++++++ src/core/style/_variables.scss | 4 + src/demo-app/demo-app.html | 52 ++++- src/demo-app/demo-app.scss | 22 +++ src/demo-app/demo-app.ts | 5 +- 9 files changed, 385 insertions(+), 3 deletions(-) create mode 100644 src/components/card/card-header.html create mode 100644 src/components/card/card-title-group.html create mode 100644 src/components/card/card.html create mode 100644 src/components/card/card.scss create mode 100644 src/components/card/card.ts diff --git a/src/components/card/card-header.html b/src/components/card/card-header.html new file mode 100644 index 00000000000..efaa67b2ac8 --- /dev/null +++ b/src/components/card/card-header.html @@ -0,0 +1,5 @@ + +
+ +
+ diff --git a/src/components/card/card-title-group.html b/src/components/card/card-title-group.html new file mode 100644 index 00000000000..150dd99ce08 --- /dev/null +++ b/src/components/card/card-title-group.html @@ -0,0 +1,5 @@ +
+ +
+ + diff --git a/src/components/card/card.html b/src/components/card/card.html new file mode 100644 index 00000000000..d8084700e76 --- /dev/null +++ b/src/components/card/card.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/components/card/card.scss b/src/components/card/card.scss new file mode 100644 index 00000000000..74703cd0fba --- /dev/null +++ b/src/components/card/card.scss @@ -0,0 +1,221 @@ + +@import "variables"; +@import "shadows"; +@import "default-theme"; // TODO: Remove this + +$md-card-default-padding: 24px !default; +$md-card-mobile-padding: 24px 16px !default; +$md-card-border-radius: 2px !default; +$md-card-header-size: 40px !default; + +md-card { + display: block; + position: relative; + padding: $md-card-default-padding; + border-radius: $md-card-border-radius; + box-shadow: $md-shadow-bottom-z-1; + font-family: $font-family; + background: md-color($md-background, 50); // TODO(kara): use updated background palette +} + +md-card:hover { + box-shadow: $md-shadow-bottom-z-2; + transition: $swift-ease-in; +} + +.md-card-flat { + box-shadow: none; +} + +// base styles for each card section preset (md-card-content, etc) +%md-card-section-base { + display: block; + margin-bottom: 16px; +} + +md-card-title { + @extend %md-card-section-base; + font-size: 24px; + font-weight: 400; +} + +md-card-subtitle { + @extend %md-card-section-base; + font-size: $md-body-font-size-base; + color: md-color($md-foreground, secondary-text); +} + +md-card-content { + @extend %md-card-section-base; + font-size: $md-body-font-size-base; +} + +md-card-actions { + @extend %md-card-section-base; + margin-left: -16px; + margin-right: -16px; + padding: 8px 0; +} + +[md-card-image] { + width: calc(100% + 48px); + margin: 0 -24px 16px -24px; +} + +[md-card-xl-image] { + width: 240px; + height: 240px; + margin: -8px; +} + +md-card-footer { + position: absolute; + bottom: 0; +} + +md-card-actions { + [md-button], [md-raised-button] { + margin: 0 4px; + } +} + +/* HEADER STYLES */ + +md-card-header { + display: flex; + flex-direction: row; + height: $md-card-header-size; + margin: -8px 0 16px 0; +} + +.md-card-header-text { + height: $md-card-header-size; + margin: 0 8px; +} + +[md-card-avatar] { + height: $md-card-header-size; + width: $md-card-header-size; + border-radius: 50%; +} + +md-card-header md-card-title { + font-size: $md-body-font-size-base; +} + +/* TITLE-GROUP STYLES */ + +// images grouped with title in title-group layout +%md-card-title-img { + margin: -8px 0; +} + +md-card-title-group { + display: flex; + justify-content: space-between; + margin: 0 -8px; +} + +[md-card-sm-image] { + @extend %md-card-title-img; + width: 80px; + height: 80px; +} + +[md-card-md-image] { + @extend %md-card-title-img; + width: 112px; + height: 112px; +} + +[md-card-lg-image] { + @extend %md-card-title-img; + width: 152px; + height: 152px; +} + +/* MEDIA QUERIES */ + +@media ($md-xsmall) { + md-card { + padding: $md-card-mobile-padding; + } + + [md-card-image] { + width: calc(100% + 32px); + margin: 16px -16px; + } + + md-card-title-group { + margin: 0; + } + + [md-card-xl-image] { + margin-left: 0; + margin-right: 0; + } + + md-card-header { + margin: -8px 0 0 0; + } + +} + +/* FIRST/LAST CHILD ADJUSTMENTS */ + +// top els in md-card-content and md-card can't have their default margin-tops (e.g.

tags) +// or they'll incorrectly add to card's top padding +.md-card > :first-child, md-card-content > :first-child { + margin-top: 0; +} + +// last els in md-card-content and md-card can't have their default margin-bottoms (e.g.

tags) +// or they'll incorrectly add to card's bottom padding +.md-card > :last-child, md-card-content > :last-child { + margin-bottom: 0; +} + +// if main image is on top, need to place it flush against top +// (by stripping card's default 24px padding) +[md-card-image]:first-child { + margin-top: -24px; +} + +// actions panel on bottom should be 8px from bottom of card +// so must strip 16px from default card padding of 24px +.md-card > md-card-actions:last-child { + margin-bottom: -16px; + padding-bottom: 0; +} + +// actions panel should always be 8px from sides, +// so the first button in the actions panel can't add its own margins +md-card-actions [md-button]:first-child, +md-card-actions [md-raised-button]:first-child { + margin-left: 0; + margin-right: 0; +} + +// should be 12px space between titles and subtitles generally +// default margin-bottom is 16px, so need to move lower title up 4px +md-card-title:not(:first-child), md-card-subtitle:not(:first-child) { + margin-top: -4px; +} + +// should be 8px space between titles and subtitles in header +// default margin-bottom is 16px, so need to move subtitle in header up 4px +md-card-header md-card-subtitle:not(:first-child) { + margin-top: -8px; +} + +// xl image should always have 16px on top. +// when it's the first el, it'll need to remove 8px from default card padding of 24px +.md-card > [md-card-xl-image]:first-child{ + margin-top: -8px; +} + +// xl image should always have 16px on bottom +// when it's the last el, it'll need to remove 8px from default card padding of 24px +.md-card > [md-card-xl-image]:last-child { + margin-bottom: -8px; +} diff --git a/src/components/card/card.ts b/src/components/card/card.ts new file mode 100644 index 00000000000..f8ea4b014f6 --- /dev/null +++ b/src/components/card/card.ts @@ -0,0 +1,71 @@ +import {Component, View, ViewEncapsulation} from 'angular2/core'; +import {CONST_EXPR, Type} from 'angular2/src/facade/lang'; + +/* + + is a basic content container component that adds the styles of a material design card. + +While you can use this component alone, it also provides a number of preset styles for common card sections, including: + - md-card-title + - md-card-subtitle + - md-card-content + - md-card-actions + - md-card-footer + + You can see some examples of cards here: + http://embed.plnkr.co/s5O4YcyvbLhIApSrIhtj/ + + TODO(kara): update link to demo site when it exists + +*/ + +@Component({ + selector: 'md-card', + templateUrl: './components/card/card.html', + styleUrls: ['./components/card/card.css'], + encapsulation: ViewEncapsulation.None +}) +export class MdCard {} + + +/* The following components don't have any behavior. They simply use content projection to wrap user content + for flex layout purposes in (and thus allow a cleaner, boilerplate-free API). + + + is a component intended to be used within the component. +It adds styles for a preset header section (i.e. a title, subtitle, and avatar layout). + +You can see an example of a card with a header here: +http://embed.plnkr.co/tvJl19z3gZTQd6WmwkIa/ + +TODO(kara): update link to demo site when it exists +*/ + +@Component({ + selector: 'md-card-header', + templateUrl: '/components/card/card-header.html', + encapsulation: ViewEncapsulation.None +}) +export class MdCardHeader {} + +/* + + is a component intended to be used within the component. +It adds styles for a preset layout that groups an image with a title section. + +You can see an example of a card with a title-group section here: +http://embed.plnkr.co/EDfgCF9eKcXjini1WODm/ + +TODO(kara): update link to demo site when it exists +*/ + +@Component({ + selector: 'md-card-title-group', + templateUrl: './components/card/card-title-group.html', + encapsulation: ViewEncapsulation.None +}) +export class MdCardTitleGroup {} + +export const MD_CARD_DIRECTIVES: Type[] = + CONST_EXPR([MdCard, MdCardHeader, MdCardTitleGroup]); + diff --git a/src/core/style/_variables.scss b/src/core/style/_variables.scss index 880a0091336..e54e70361ec 100644 --- a/src/core/style/_variables.scss +++ b/src/core/style/_variables.scss @@ -3,6 +3,10 @@ // Typography $md-body-font-size-base: rem(1.400) !default; +$font-family: Roboto, 'Helvetica Neue', sans-serif !default; + +// Media queries +$md-xsmall: "max-width: 600px"; // z-index master list $z-index-fab: 20 !default; diff --git a/src/demo-app/demo-app.html b/src/demo-app/demo-app.html index 8cfb86efe37..af29b899c40 100644 --- a/src/demo-app/demo-app.html +++ b/src/demo-app/demo-app.html @@ -1,7 +1,57 @@

material2 Works! -

+
+ + + + Card with title + Subtitle + + + + + + Subtitle + Card with title + +

This is supporting text.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+ + + + +
+ + + + Content Title + +

Here is some content

+
+
+ + + + + Header title + Header subtitle + + + +

Here is some content

+
+
+ + + Easily customizable + + + + + +
\ No newline at end of file diff --git a/src/demo-app/demo-app.scss b/src/demo-app/demo-app.scss index e69de29bb2d..c3fe5a4f3ad 100644 --- a/src/demo-app/demo-app.scss +++ b/src/demo-app/demo-app.scss @@ -0,0 +1,22 @@ +md-card { + margin: 0 16px 16px 0; + width: 350px; +} + +.card-container { + display: flex; + flex-flow: column nowrap; +} + +.blue { + background-color: #B0BECC; +} + +.blue md-card-actions { + display: flex; + flex-direction: column; +} + +img { + background-color: gray; +} diff --git a/src/demo-app/demo-app.ts b/src/demo-app/demo-app.ts index 9589221d781..0a08ca97571 100644 --- a/src/demo-app/demo-app.ts +++ b/src/demo-app/demo-app.ts @@ -1,12 +1,13 @@ import {Component} from 'angular2/core'; import {MdButton} from '../components/button/button'; - +import {MD_CARD_DIRECTIVES} from '../components/card/card'; @Component({ selector: 'demo-app', providers: [], templateUrl: 'demo-app/demo-app.html', - directives: [MdButton], + styleUrls: ['demo-app/demo-app.css'], + directives: [MdButton, MD_CARD_DIRECTIVES], pipes: [] }) export class DemoApp { }