Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs): Interactive playground component #140

Merged
merged 15 commits into from
Mar 9, 2020
21 changes: 21 additions & 0 deletions packages/@nucleus/app/styles/doc/_icon.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// icon tiles
.icon-container {
display: flex;
flex-wrap: wrap;

.icon {
text-align: center;
padding: 10px 5px 5px;
margin: 5px;
width: 150px;
cursor: pointer;

&:hover {
background: #dae1e7;
}

&--text {
padding: 5px 0;
}
}
}
52 changes: 52 additions & 0 deletions packages/@nucleus/app/styles/doc/_playground.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
$playground-border-color: #dae1e7;
$padding: 8px;

.playground-container {
display: flex;
border-bottom: 1px dotted $playground-border-color;
justify-content: space-around;

&--preview {
display: flex;
align-self: center;
width: 75%;
justify-content: center;
padding: $padding;
}

&--props {
padding: $padding;
border-left: 1px dotted $playground-border-color;
max-height: 25vh;
width: 50%;
overflow-y: auto;

.item {
margin: 10px;

&--label {
display: block;
padding-bottom: $padding;
font-weight: 700;
}

.ember-text-field {
border: 1px solid $playground-border-color;
padding: $padding;
}
}
}

&--code {
position: relative;
margin: 8px;
padding: $padding 0;
overflow-x: hidden;
}

&--code-copy {
position: absolute;
right: 0;
bottom: 0;
}
}
2 changes: 2 additions & 0 deletions packages/@nucleus/app/styles/nucleus-docs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
@import "./doc/custom-addon-theme";
@import "./doc/custom-syntax-highlight";
@import "./doc/nucleus-mod";
@import "./doc/icon";
@import "./doc/playground";
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Component from '@ember/component';

export default Component.extend({
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Component from '@ember/component';
import { action, computed, get } from '@ember/object';
import { highlightCode } from 'ember-cli-addon-docs/utils/compile-markdown';
import copyToClipboard from '../../utils/copy-to-clipboard';


class Code extends Component {
@computed('code')
get computedCode() {
return highlightCode(get(this, 'code'), 'hbs');
}


@action
copyCode() {
copyToClipboard(get(this, 'code'))
.then(this.flashMessages.success(`Code copied.`));
}
}

export default Code;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Component from '@ember/component';

export default Component.extend({
tagName: ''
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Component from '@ember/component';
import { action } from '@ember/object';

class Props extends Component {
@action
handleChange(property, e) {
let value = (property.toggle) ? e.target.checked : e.target.value;
this.onchange(property.name, value, e);
}

}

export default Props;
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import Component from '@ember/component';
import { get, set, action } from "@ember/object";
import {
registerComputedProperties,
handlePropertyChange,
generateCode
} from '../../utils/playground';

import icons from '../../constants/icons';

const PROPERTIES = [
{
name: 'label',
input: true,
value: 'Click here',
},
{
name: 'variant',
select: true,
value: 'primary',
types: [
'primary',
'secondary',
'danger',
'link',
'text'
]
},
{
name: 'size',
select: true,
value: 'none',
types: [
'none',
'small',
'mini'
]
},
{
name: 'block',
toggle: true,
value: false,
},
{
name: 'disabled',
toggle: true,
value: false,
},
{
name: 'icon',
select: true,
value: 'none',
types: [
'none',
...icons
]
},
{
name: 'iconSize',
select: true,
value: 'none',
types: [
'none',
'medium',
'small',
'mini'
]
},
{
name: 'iconOnly',
toggle: true,
value: false,
}
]
class Playground extends Component {
properties = PROPERTIES;

code = null;

init() {
super.init(...arguments);
registerComputedProperties(this, get(this, 'properties'));
this._generateCode();
}

@action
onchange(name, value) {
let properties = get(this, 'properties');

if (name === 'iconOnly' && !name.value) {
this._handleIconOnly(properties);
}

handlePropertyChange(properties, name, value);
this._generateCode();
}


_generateCode() {
set(this, 'code', generateCode({
component:'nucleus-button',
properties: get(this, 'properties'),
multiline: true
}));
}

_handleIconOnly(properties) {
let changables = ['label', 'variant', 'icon'];
let [
label,
type,
icon
] = properties.filter(prop => changables.includes(prop.name));

set(label, 'value', '');
set(type, 'value', 'text');
set(icon, 'value', (icon.value === 'none') ? icon.types[1] : icon.value);
}
}

export default Playground;
25 changes: 13 additions & 12 deletions packages/@nucleus/tests/dummy/app/components/nucleus-icon/demo-1.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
// BEGIN-SNIPPET nucleus-icon.js
import Component from '@ember/component';

const ICON_LIST = [
"nucleus-circle-check",
"nucleus-circle-cross",
"nucleus-circle-help",
"nucleus-circle-info",
"nucleus-circle-minus",
"nucleus-circle-plus",
"nucleus-cross-thin",
"nucleus-cross"
];
import { inject } from '@ember/service';
import copyToClipboard from '../../utils/copy-to-clipboard';
import icons from '../../constants/icons';

export default Component.extend({
flashMessages: inject(),

icons: null,

init() {
this._super(...arguments);
this.set('icons', ICON_LIST)
this.set('icons', icons)
},

actions: {
copyIcon(icon) {
copyToClipboard(icon)
.then(this.flashMessages.success(`Copied '${icon}' to clipboard`));
}
}
});
// END-SNIPPET
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Component from '@ember/component';
import { get, set, action } from "@ember/object";
import {
registerComputedProperties,
handlePropertyChange,
generateCode
} from '../../utils/playground';
import icons from '../../constants/icons';


const PROPERTIES = [
{
name: 'name',
select: true,
value: 'nucleus-circle-check',
types: icons
},
{
name: 'size',
select: true,
value: 'large',
types: [
'small',
'medium',
'large'
]
},
{
name: 'variant',
select: true,
value: 'none',
types: [
'none',
'danger',
'success'
]
}
]

class Playground extends Component {
properties = PROPERTIES;

code = null;

init() {
super.init(...arguments);
registerComputedProperties(this, get(this, 'properties'));
this._generateCode();
}

@action
onchange(name, value) {
handlePropertyChange(get(this, 'properties'), name, value);
this._generateCode();
}


_generateCode() {
set(this, 'code', generateCode({
component: 'nucleus-icon',
properties: get(this, 'properties')
}));
}
}

export default Playground;

Loading