Skip to content

Instantly share code, notes, and snippets.

@gossi
Created April 11, 2021 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gossi/6b15f5749c8fecd54d1b6d57168108b7 to your computer and use it in GitHub Desktop.
Save gossi/6b15f5749c8fecd54d1b6d57168108b7 to your computer and use it in GitHub Desktop.
SFC Glimmer Components

SFC Glimmer Components

High Level

Follow the concepts introduced with ember octane:

  1. html-first: create a .html .hbs file and start writing your html, that's all to get the rudimentary things going
  2. native classes: drop off all ember object shenanigan syntax and write native js

Apply these concepts:

  1. Create a file and start writing html
  2. Add a <script> to add behavior when needed. In there might be functional code or a default exported class which becomes the class backup.
  3. Add a <style> to add styling when needed.

PS. Make that file a .gc for .glimmer component (no pun intended) PPS. Looks like svelte and vue - but they are doing good then 👍

Low Level

The <script> can contain private internal components. They also need a way to write them in javascript only. That is, this needs a more exhaustive syntax to which a .gc translates to (internally).

The really low level is already possible as of today:

class Option extends Component {
  id = guidFor(this);
}

export default setComponentTemplate(
  hbs`<span local-class="pretty">{{yield}}</span>`,
  Option
);

However, this is not really something we want to write.

PS. This needs an equivalent setComponentStyles() function, too - that's missing as of today.

Mid Level

For writing components in plain javascript, they need to be a little less exhaustive than the low level above. For template-only, no style components, this seems suitable enough:

const Option = hbs`<span data-pretty>{{yield}}</span>`;

Add more substance to it, this can look like so:

const plusOne = helper(([num]) => num + 1);

class MyComponent extends Component {
  static style = style`...`;
  static template = hbs`...look my id: {{this.id}}, this is two: {{plusOne 1}}....`;
  
  id = guidFor(this);
}

That would keep it in natural javascript syntax without the need for adding magic on top.

<script>
import { helper } from '@ember/component/helper';
import { modifier } from 'ember-modifier';
import List from '../list';
// private internal component (not final syntax)
const Option = hbs`<span local-class="pretty">{{yield}}</span>`;
// private internal helper and modifer
const plusOne = helper(([num]) => num + 1);
const handleKeyNavigation((element) => {
const handler = (event) => {};
element.addEventListener('keydown', handler);
return () => {
element.removeEventListener('keydown', handler);
}
});
export interface SelectSignature {
Args: {
options: unknown[]
};
}
export default class SelectComponent extends Component<SelectSignature> {
// exporting makes it public... that's ok, sometimes its nice to `{{yield this}}` and then refer to the exported type
}
</script>
<style>
.pretty {
color: pink;
}
</style>
<div>
<button>
</button>
<List
@items={{@options}}
{{handleKeyNavigation}}
as |item index|>
<Option>
#{{plusOne index}}: {{item}}
</Option>
</List>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment