Skip to content

Commit

Permalink
Merge pull request #206 from US-CBP/Card-Interactive
Browse files Browse the repository at this point in the history
Interactive cards
  • Loading branch information
bagrub authored Sep 24, 2024
2 parents 9a1699d + 53e7bc4 commit 0e9e742
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 31 deletions.
136 changes: 132 additions & 4 deletions packages/web-components/src/components/cbp-card/cbp-card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@
* @prop --cbp-flag-card-color-dark: var(--cbp-color-text-darker);
* @prop --cbp-flag-card-color-background: var(--cbp-color-gray-cool-60);
* @prop --cbp-flag-card-color-background-dark: var(--cbp-color-gray-cool-30);
* @prop --cbp-interactive-card-outline-focus: var(--cbp-color-white);
* @prop --cbp-interactive-card-outline-focus-dark: var(--cbp-color-black);
* @prop --cbp-interactive-card-danger-outline-focus: var(--cbp-color-white);
* @prop --cbp-interactive-card-danger-outline-focus-dark: var(--cbp-color-black);
*/

:root {
--cbp-card-color-background: var(--cbp-color-white);
--cbp-card-color-background-dark: var(--cbp-color-gray-cool-60);
--cbp-card-color-background-dark: var(--cbp-color-gray-cool-70);
--cbp-card-color-border: var(--cbp-color-gray-cool-10);
--cbp-card-color-border-dark: var(--cbp-color-gray-cool-50);
--cbp-card-color-title: var(--cbp-color-text-darker);
--cbp-card-color-title-dark: var(--cbp-color-text-lighter);
--cbp-card-color-text: var(--cbp-color-text-darkest);
--cbp-card-color-text-dark: var(--cbp-color-text-lightest);

//banner
--cbp-banner-card-color: var(--cbp-color-gray-cool-60);
--cbp-banner-card-color-dark: var(--cbp-color-gray-cool-20);
--cbp-banner-card-color-title: var(--cbp-color-text-lighter);
Expand All @@ -40,16 +46,23 @@
--cbp-banner-card-color-border: var(--cbp-color-base-neutral-lighter);
--cbp-banner-card-color-border-dark: var(--cbp-color-gray-cool-50);

//flag
--cbp-flag-card-min-width: 7rem;
--cbp-flag-card-color: var(--cbp-color-text-lighter);
--cbp-flag-card-color-dark: var(--cbp-color-text-darker);
--cbp-flag-card-color-background: var(--cbp-color-gray-cool-60);
--cbp-flag-card-color-background-dark: var(--cbp-color-gray-cool-30);

//interactive
--cbp-interactive-card-outline-color-focus: var(--cbp-color-white);
--cbp-interactive-card-outline-color-focus-dark: var(--cbp-color-black);
--cbp-interactive-card-danger-outline-color-focus: var(--cbp-color-white);
--cbp-interactive-card-danger-outline-color-focus-dark: var(--cbp-color-black);
}


[data-cbp-theme=light] cbp-card[context*=dark]:not([context=light-always]),
[data-cbp-theme=dark] cbp-card:not([context=dark-inverts]):not([context=light-always]) {
[data-cbp-theme=dark][theme="dark"] cbp-card:not([context=dark-inverts]):not([context=light-always]) {
--cbp-card-color-background: var(--cbp-card-color-background-dark);
--cbp-card-color-border: var(--cbp-card-color-border-dark);
--cbp-card-color-title: var(--cbp-card-color-title-dark);
Expand All @@ -62,6 +75,9 @@

--cbp-flag-card-color: var(--cbp-flag-card-color-dark);
--cbp-flag-card-color-background: var(--cbp-flag-card-color-background-dark);

--cbp-interactive-card-outline-color-focus: var(--cbp-interactive-card-outline-color-focus-dark);
--cbp-interactive-card-danger-outline-color-focus: var(--cbp-interactive-card-danger-outline-color-focus-dark);
}

cbp-card {
Expand Down Expand Up @@ -106,7 +122,7 @@ cbp-card {
&[variant=decision] [slot=cbp-card-title] {
margin-bottom: var(--cbp-space-2x);
}

&[color=info] {
--cbp-card-color-background: var(--cbp-color-info-lighter);
--cbp-card-color-border: var(--cbp-color-info-light);
Expand Down Expand Up @@ -258,6 +274,9 @@ cbp-card {
background-color: var(--cbp-flag-card-color-background);
}

.cbp-card-clickable{
display: flex;
}

&[color=info] {
--cbp-flag-card-color-dark: (--cbp-color-text-lighter);
Expand All @@ -279,6 +298,115 @@ cbp-card {
&[color=danger] {
--cbp-flag-card-color-background: var(--cbp-color-danger-base);
--cbp-flag-card-color-background-dark: var(--cbp-color-danger-light);
}
}

.cbp-card-clickable{
text-decoration-line: none;
}

//interactive cards
&[interactive="clickable"],
// &[select],
&[interactive="multi"]{
--cbp-checkbox-min-height: var(--cbp-space-6x); //adjust spacing for checkbox in title for multi variant

a{
color: var(--cbp-card-color-text);
flex-grow: 1;
}
}

&:hover{
--cbp-card-color-background: var(--cbp-color-gray-cool-10);
--cbp-card-color-border: var(--cbp-color-interactive-secondary-darker);
--cbp-card-color-title: var(--cbp-color-text-darker);
--cbp-card-color-text: var(--cbp-color-text-darker);

--cbp-card-color-background-dark: var(--cbp-color-gray-cool-60);
--cbp-card-color-border-dark: var(--cbp-color-interactive-secondary-lighter);
--cbp-card-color-title-dark: var(--cbp-color-text-lighter);
--cbp-card-color-text-dark: var(--cbp-color-text-lighter);
}

&:focus,
&:focus-within{
--cbp-card-color-background: var(--cbp-color-interactive-focus-dark);
--cbp-card-color-border: var(--cbp-color-interactive-secondary-lighter);
--cbp-card-color-title: var(--cbp-color-text-lighter);
--cbp-card-color-text: var(--cbp-color-text-lighter);

--cbp-card-color-background-dark: var(--cbp-color-interactive-focus-light);
--cbp-card-color-border-dark: var(--cbp-color-interactive-secondary-darker);
--cbp-card-color-title-dark: var(--cbp-color-text-darker);
--cbp-card-color-text-dark: var(--cbp-color-text-darker);

&:not(disabled) .cbp-card-body{
outline: 2px solid var(--cbp-interactive-card-outline-color-focus);
outline-offset: -4px;
}
}

&:active{ //pressed/clicked
--cbp-card-color-background: var(--cbp-color-interactive-active-dark);
--cbp-card-color-border: var(--cbp-color-interactive-secondary-light);
--cbp-card-color-title: var(--cbp-color-text-lighter);
--cbp-card-color-text: var(--cbp-color-text-lighter);

--cbp-card-color-background-dark: var(--cbp-color-interactive-active-light);
--cbp-card-color-border-dark: var(--cbp-color-interactive-secondary-base);
--cbp-card-color-title-dark: var(--cbp-color-text-darker);
--cbp-card-color-text-dark: var(--cbp-color-text-darker);
}

&[color="danger"]{

&:hover{
--cbp-card-color-background: var(--cbp-color-danger-light);
--cbp-card-color-border: var(--cbp-color-danger-base);
--cbp-card-color-title: var(--cbp-color-text-darkest);
--cbp-card-color-text: var(--cbp-color-text-darkest);

--cbp-card-color-background-dark: var(--cbp-color-danger-base);
--cbp-card-color-border-dark: var(--cbp-color-danger-light);
--cbp-card-color-title-dark: var(--cbp-color-text-lighter);
--cbp-card-color-text-dark: var(--cbp-color-text-lighter);
}

&:focus,
&:focus-within{
--cbp-card-color-background: var(--cbp-color-interactive-focus-dark);
--cbp-card-color-border: var(--cbp-color-danger-light);
--cbp-card-color-title: var(--cbp-color-text-lightest);
--cbp-card-color-text: var(--cbp-color-text-lightest);

--cbp-card-color-background-dark: var(--cbp-color-interactive-focus-light);
--cbp-card-color-border-dark: var(--cbp-color-danger-base);
--cbp-card-color-title-dark: var(--cbp-color-text-darker);
--cbp-card-color-text-dark: var(--cbp-color-text-darker);

&:not(disabled) .cbp-card-body{
outline: 2px solid var(--cbp-interactive-card-danger-outline-color-focus);
outline-offset: -4px;
}
}
}

&[disabled]{

// a{
// pointer-events: none;
// cursor: not-allowed;
// }

--cbp-card-color-background: var(--cbp-color-interactive-disabled-light);
--cbp-card-color-border: var(--cbp-color-interactive-disabled-dark);
--cbp-card-color-title: var(--cbp-color-interactive-disabled-dark);
--cbp-card-color-text: var(--cbp-color-interactive-disabled-dark);

--cbp-card-color-background-dark: var(--cbp-color-interactive-disabled-dark);
--cbp-card-color-border-dark: var(--cbp-color-interactive-disabled-light);
--cbp-card-color-title-dark: var(--cbp-color-interactive-disabled-light);
--cbp-card-color-text-dark: var(--cbp-color-interactive-disabled-light);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ The Card component is a visual treatment for a container meant for similarly-siz
* The Card is a generic wrapper that supports several variants.
* The Card defines several color variants as well, based on design tokens (info, success, warning, danger).
* The Card may optionally contain a title and/or actions in the form of buttons (or links).
* The Card has an optional property called 'interactive' which enables states (hover, focus, active) for the colors (default & danger)
* Using the 'clickable' option will wrap the card in an anchor tag and use the 'href' property to define what happens on click of the card
* Using the 'multi' option will add a checkbox for the card with the cbp-card-title slot as the label of the checkbox
* the 'select' option is currently in progress due to the radio button work being in process

## Technical Specifications

### User Interactions

* Cards are essentially containers and any user interactions will be handled by slotted content and components.
* Cards are essentially containers and any user interactions will be handled by slotted content and components. with the exception of the use of the interactive property which will enables states (hover, focus, active) for the colors (default & danger)

### Responsiveness

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export default {
description: 'Set the body text of the card',
control: 'text',
},
color: {
control: 'select',
options: ['default', 'info', 'success', 'warning', 'danger'],
},
// color: {
// control: 'select',
// options: ['default', 'info', 'success', 'warning', 'danger'],
// },
stretch: {
control: 'boolean',
},
Expand Down Expand Up @@ -133,7 +133,8 @@ const BannerTemplate = ({ title, color, bodyText, withIcon, context, sx }) => {
`;
};

const FlagTemplate = ({ title, color, flag, bodyText, withIcon, context, sx }) => {
//documentation for dicebear(image generator in below) https://www.dicebear.com/how-to-use/http-api/
const FlagTemplate = ({ title, color, bodyText, withIcon, context, sx }) => {
return `
<cbp-card
variant='flag'
Expand All @@ -142,7 +143,7 @@ const FlagTemplate = ({ title, color, flag, bodyText, withIcon, context, sx }) =
${sx ? 'sx=' + JSON.stringify(sx) : ''}
>
<div slot='cbp-card-flag'>
${flag}
<img src="https://api.dicebear.com/9.x/personas/svg" />
</div>
<cbp-typography tag='h4' slot="cbp-card-title">
${withIcon ? `<cbp-icon name='triangle-exclamation' size='1.25rem'></cbp-icon>` : ''}
Expand All @@ -153,6 +154,42 @@ const FlagTemplate = ({ title, color, flag, bodyText, withIcon, context, sx }) =
`;
};

const InteractiveTemplate = ({ title, color, disabled, bodyText, withIcon, interactive, href, variant, context, sx }) => {
return `
<cbp-card
${variant !=='general' ? `variant=` + variant : ''}
${interactive ? `interactive=${interactive}` : ''}
${href ? `href=${href}` : ''}
${disabled ? `disabled=${disabled}` : ''}
${color ? `color=${color}` : ''}
${context && context != 'light-inverts' ? `context=${context}` : ''}
${sx ? 'sx=' + JSON.stringify(sx) : ''}
>
${variant=== 'flag' ? `<div slot='cbp-card-flag'><img src="https://api.dicebear.com/9.x/personas/svg" /></div>` : ''}
${interactive === 'multi' ? `
<cbp-checkbox value="1" slot="cbp-card-title">
<cbp-typography tag='h4' sx='{"color":"var(--cbp-card-color-title)"}'>
${withIcon ? `<cbp-icon name='triangle-exclamation' size='1.25rem'></cbp-icon>` : ''}
${title}
</cbp-typography>
<input
type="checkbox"
name="multiCard"
value="1"
style="margin-left: auto"
/>
</cbp-checkbox>
`
: `<cbp-typography tag='h4' slot="cbp-card-title">
${withIcon ? `<cbp-icon name='triangle-exclamation' size='1.25rem'></cbp-icon>` : ''}
${title}
</cbp-typography>`}
<p>${bodyText}</p>
</cbp-card>
`;
};

// For testing only:
/*
const CardsGridTemplate = ({ title, color, stretch, bodyText, actionsLayout, actionsConfig, sx }) => {
Expand Down Expand Up @@ -303,8 +340,6 @@ BannerCard.args = {

export const FlagCard = FlagTemplate.bind({});
FlagCard.args = {
// flag: '<cbp-icon name="globe" size="3rem"> </cbp-icon>',
flag: '<img src="https://api.dicebear.com/9.x/personas/svg" />', //documentation for dicebear https://www.dicebear.com/how-to-use/http-api/
title: 'Card Title',
bodyText: 'Here is an example of some body text for this purely informational card',
};
Expand All @@ -315,4 +350,38 @@ FlagCard.argTypes = {
control: 'select',
options: ['default', 'info', 'success', 'warning', 'danger'],
},
};

export const InteractiveCard = InteractiveTemplate.bind({});
InteractiveCard.args = {
title: 'Banner Card Title',
bodyText: 'Here is an example of some supplementary text for this purely informational card',
interactive: 'clickable',
variant: 'general',
href: 'https://us-cbp.github.io/design-system/?path=/story/introduction--introduction'
};

InteractiveCard.argTypes = {
interactive: {
name: 'Interactive',
description: 'Set the interactivity of the card',
control: 'select',
options: ['clickable', 'select', 'multi'],
},
href:{
control: 'text'
},
disabled: {
control: 'boolean',
},
color: {
control: 'select',
options: ['default', 'danger'],
},
variant: {
name: 'Variant',
description: 'set Variant of the card',
control: 'select',
options: ['general', 'decision', 'flag']
},
};
Loading

0 comments on commit 0e9e742

Please sign in to comment.