Skip to content

Instantly share code, notes, and snippets.

@kjoshi1988
Last active July 28, 2020 17:43
Show Gist options
  • Save kjoshi1988/7c4f4cdb707fe00f4807e7e10d14b937 to your computer and use it in GitHub Desktop.
Save kjoshi1988/7c4f4cdb707fe00f4807e7e10d14b937 to your computer and use it in GitHub Desktop.
Member-List Example
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class extends Component {
@tracked showMenu;
@action
blur() {
this.args.onVisibilityChange && this.args.onVisibilityChange(false);
}
@action
focus() {
this.args.onVisibilityChange && this.args.onVisibilityChange(true);
}
}
import Component from '@glimmer/component';
import { computed, action } from '@ember/object';
import { readOnly } from '@ember/object/computed';
import { tracked } from '@glimmer/tracking';
export default class extends Component {
@readOnly('args.member.overflowActions')
overflowActions;
@readOnly('args.member.primaryAction')
primaryAction;
@readOnly('args.member.secondaryAction')
secondaryAction;
@readOnly('args.member.miniProfile')
miniProfile;
@tracked isOverflowOpen;
@action
toogleOverflowVisibility(visibility) {
this.isOverflowOpen = visibility;
}
}
import Component from '@glimmer/component';
import { computed } from '@ember/object';
import { readOnly } from '@ember/object/computed';
export default class extends Component {
}
import Controller from '@ember/controller';
export default class ApplicationController extends Controller {
appName = 'MemberList Design Example';
}
import Controller from '@ember/controller';
const imgSrc = 'https://freeiconshop.com/wp-content/uploads/edd/person-outline-filled.png';
const distance = {
'1': '1st',
'2': '2nd',
'3': '3rd'
};
function generateMemberList({
count = 1,
overflowActions,
primaryAction,
secondaryAction
} = {}) {
const memberList = [];
let index = 0;
while (index < count) {
index++;
memberList.push({
miniProfile: {
name: `Lorum Ipsum - ${index}`,
imgSrc,
designation: `SDE ${index}`,
distance: distance[Math.ceil((Math.random() * 10) % 3)]
},
overflowActions,
primaryAction,
secondaryAction
});
}
return memberList;
}
export default class ApplicationController extends Controller {
memberListWithPrimaryActionOnly = generateMemberList({
primaryAction: 'MESSAGE'
});
memberListWithPrimaryActionAndOverflow = generateMemberList({
primaryAction: 'MESSAGE',
overflowActions: ['CONNECT', 'BLOCK', 'DENY']
});
memberListWithPrimaryActionAndSecondaryAction = generateMemberList({
primaryAction: 'ACCEPT',
secondaryAction: 'DENY'
});
memberListWithAllOptions = generateMemberList({
primaryAction: 'MESSAGE',
secondaryAction: 'DENY',
overflowActions: ['CONNECT', 'BLOCK', 'DENY']
});
}
import EmberRouter from '@ember/routing/router';
import config from './config/environment';
const Router = EmberRouter.extend({
location: 'none',
rootURL: config.rootURL
});
Router.map(function() {
this.route('member-list-examples', {path: '/'});
});
export default Router;
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.member-list-item {
border: 1px solid #cccccc;
box-shadow: 1px 1px 1px #cccccc;
padding: 5px;
font-size: 14px;
}
.display-flex {
display: flex;
}
.member-img {
max-width: 48px;
}
.m-5 {
margin: 5px;
}
.m-2 {
margin: 2px;
}
.p-2 {
padding: 2px;
}
.p-5 {
padding: 5px
}
.justify-space-between {
justify-content: space-between!important;
}
.align-items-center {
align-items: center!important;
}
.bold {
font-weight: bold;
}
.btn {
transition-timing-function: cubic-bezier(.4,0,.2,1);
transition-duration: 167ms;
align-items: center;
border: none;
border-radius: 2px;
box-sizing: border-box;
cursor: pointer;
font-family: inherit;
font-weight: 600;
display: inline-flex;
justify-content: center;
min-width: 6.4rem;
max-width: 480px;
overflow: hidden;
text-align: center;
transition-property: background-color,box-shadow,color;
vertical-align: middle;
padding: 10px;
}
.btn-primary {
background-color: #0073b1;
color: #fff;
}
.btn-secondary {
background-color: transparent;
color: rgba(0,0,0,.6);
box-shadow: inset 0 0 0 1px rgba(0,0,0,.6);
}
.action-overflow {
position: relative;
}
.overflow-items-wrapper {
position: absolute;
left: auto;
right: 0;
z-index: 999;
}
.overflow-ctr {
font-weight: bold;
font-size: 20px;
padding: 0 10px;
background: transparent;
border: none;
cursor: pointer;
}
.overflow-items {
margin-top: 5px;
min-width: 120px;
border: 1px solid #0073b1;
box-shadow: 1px 1px 3px #0073b1;
background: white;
}
.overflow-item {
padding: 8px;
font-size: 12px;
}
.overflow-item:hover {
background-color: #0073b1;
color: #fff;
}
<h2>Welcome to {{this.appName}}</h2>
{{outlet}}
<br>
<br>
{{#if hasBlock}}
{{yield}}
{{else}}
{{#if @actionKey}}
<button class='btn {{@btnClass}} p-2 m-2'>
{{@displayText}}
</button>
{{/if}}
{{/if}}
{{#if hasBlock}}
{{yield}}
{{else}}
{{#if @overflowActionItems}}
<div class='action-overflow p-2'>
<button
class='overflow-ctr'
{{on "focus" this.focus}}
{{on "blur" this.blur}}
>...</button>
{{#if @isOpen}}
{{#if @overflowActionItems.length}}
<div class='overflow-items-wrapper'>
<div class='overflow-items'>
{{#each @overflowActionItems as |overflowActionItem|}}
<div class='overflow-item'>{{overflowActionItem}}</div>
{{/each}}
</div>
</div>
{{/if}}
{{/if}}
</div>
{{/if}}
{{/if}}
<div class='member-list-item display-flex justify-space-between align-items-center m-2'>
<div class='display-flex'>
<div class='member-img-wrapper p-2'>
<img class='member-img' src={{miniProfile.imgSrc}}/>
</div>
<div class='member-info p-5'>
<div>
<span class='bold'>{{miniProfile.name}}</span>
<span class='distance'>
·
{{miniProfile.distance}}
</span>
</div>
<div class='designation'>{{miniProfile.designation}}</div>
</div>
</div>
<div class='member-actions display-flex p-5'>
{{yield (hash
overflowActions=(component 'action-overflow'
overflowActionItems=overflowActions
isOpen=isOverflowOpen
onVisibilityChange=(action toogleOverflowVisibility)
)
primaryAction=(component 'action-button'
btnClass='btn-primary'
actionKey=primaryAction
displayText=primaryAction
)
secondaryAction=(component 'action-button'
btnClass='btn-secondary'
actionKey=secondaryAction
displayText=secondaryAction
)
)}}
</div>
</div>
<div class='member-list'>
{{#each @memberList as |member|}}
<MemberListItem
@member={{member}}
as |memberListItem|
>
{{#unless @overflowAtEnd}}
<memberListItem.overflowActions/>
{{/unless}}
<memberListItem.secondaryAction/>
<memberListItem.primaryAction/>
{{#if @overflowAtEnd}}
<memberListItem.overflowActions/>
{{/if}}
</MemberListItem>
{{/each}}
</div>
<div>
<div>
<h3>List with primay action only</h3>
<MemberList @memberList={{memberListWithPrimaryActionOnly}}/>
</div>
<div>
<h3>List with primay action and overflow action</h3>
<MemberList @memberList={{memberListWithPrimaryActionAndOverflow}}/>
</div>
<div>
<h3>List with all options</h3>
<MemberList @memberList={{memberListWithAllOptions}}/>
</div>
<div>
<h3>List with all options and overflow at last</h3>
<MemberList
@memberList={{memberListWithAllOptions}}
@overflowAtEnd={{true}}
/>
</div>
</div>
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment