# Comments on the Proposal: ["Death to the `<tag>` tag"](https://hackmd.io/@markojs/r1HjDmcUp)
> by [name=Saulo Vallory]
I took some time to think about the proposed syntax because something looked odd to me but I couldn’t put my finger on it.
After reading what @angusmorton said on the discord thread, I got it. The name “attribute tag” suggests it's defining an attribute, which demands something that has that attribute.
That something in this case would be the exports object, but that isn’t made clear by the syntax. How about we do…
https://markojs.com/docs/custom-tags/#from-variables
## Reasoning
I think before we focus on a specific syntax, we should agree on what this change means. For me, the impact of this is greater than the syntax. Correct me if I'm wrong, but I think we are about to:
1. **Named exports**, while up until now we could only export an `Input` type/interface, and a Marko Template as the `default` export.
2. **Variable referencing renderBody functions**, indirectly via `Primary.args.renderBody`
Right now the proposed syntax does not support directly setting the value of a variable to be a template, but if we can do...
```
export { Primary }
<@Primary>
Hello
</>
```
then there's a `Primary` variable, which has a renderBody (which is almost as good as a Template). It is likely that users will attempt to do things such as...
```
<@DefaultBody>
Click Me
</>
export const Primary: Story = {
args: {
renderBody: DefaultBody.renderBody,
},
};
```
I believe we should focus on finding the best syntax for those 2 features and only then decide what to do with `<macro>`, `<tag>`, and `<@attr>`.
## Guidelines I followed
- Remain as close to JS/TS as possible as `exports` are their native concepts
- The standard syntax should be obvious as everything in Marko has been, think of syntax sugars later
- The `!` before the `exports` was intentional. I've been wanting to propose we add that to the tags that do not affect the template output for a while, like (`let`, `const`, etc...), but this discussion should happen in another tread.
My reason for suggesting it is that in HTML tags that add metadata or control behavior without changing the visible DOM structure always start with `!`: `<!doctype>`, `<!-- -->`, and `<![CDATA[ ]]>`.
## Proposed Syntax
### Summary
- `<@attr>` remains as a setter of its parent's attribute
- we can export any value as a named export
- we can define renderBody functions using the Fragment syntax `<></>`
- If we do want to allow `<@>` at the top-level, we prohibit naming it
### Quick Overview
#### Single named export
```marko
// exporting a body
export const DefaultBody = <>
Primary Button
</>;
// exporting an object
export const Primary = <@>
<@args variant="secondary">
Primary Button
</>
</>;
// shorthand, same as:
// export const Secondary = <@>
export <@/Secondary>
<@args variant="secondary">
Secondary Button
</>
</>;
```
#### Multiple Exports
```marko
export default {
title: "My Component",
component,
} as Meta<Input>;
const baseStory = { args: { /* ... */ } }
<!exports>
<@Secondary:Story<Input>>
<@args variant="secondary">
Secondary Button
</>
</>
<@(Danger: Story<Input>) ...baseStory>
<@args ...baseStory.args variant="danger">
Secondary Button
</>
</>
</>
```
or more like `$ {}` and `static {}`
```marko
exports {
<@Secondary ...baseStory>
<@args ...baseStory.args variant="secondary">
<span class=icon></span> ${story} Button
</>
</>;
}
```
#### About Typing
`<@Primary<Story<Input>>` gives the impression that `Story<Input>` is a type parameter So my first thought is: "where is the Primary type defined?"
Instead, I suggest we follow TS standard and go for `<@Primary:Story<Input>>` (no space allowed after `:`, or `<@(Primary: Story<Input>)>` (space allowed).
> *Maybe we can allow space in the first option, but I'm not familiar enough with the parser to know for sure*
### Details
No matter what syntax is chosen, I think the key here is to allow the `renderBody` (maybe a Template too) to be assigned to variable right after it is created.
That variable should be made available to the static context so it can be exported, and the same should happen to `tagVariables`.
This allows for some interesting reusability patterns:
```marko
type Icon = 'confirm' | 'cancel' | 'none';
type StoryName = 'Primary' | 'Secondary';
type ButtonBody = {
icon: IconName,
label: StoryName
};
<tag<ButtonBody>|{ icon, name }|/buttonBody>
<span class=icon></span> ${name} Button
</tag>
export const buttonBody;
export const Primary: Story = {
...baseStory
args: {
...baseStory.args,
renderBody: <buttonBody icon="confirm" label="Primary" />,
},
};
```
Fragments would also enable us to return render functions seamlessly from inside functions...
```marko
function bodyFor(story: StoryName, icon: IconName = 'none') {
return <>
<span class=icon></span> ${story} Button
</>
}
export const Default: Story = {
...baseStory
args: {
...baseStory.args,
renderBody: bodyFor("Default"),
},
};
```
If we really want to use the `<@attr>` at the top level, I think a nameless attr tag should be allowed (or even required) when it has no parent...
```marko
export const Secondary: Story<Input> =
<@ ...baseStory>
<@args ...baseStory.args variant="secondary">
<span class=icon></span> ${story} Button
</>
</>;
```
the shorthand could make use of the tag variable syntax to define the exported variable name:
```marko
// implicitly exports as `const`
// Should we allow `export let`?
export <@/Secondary ...baseStory>
<@args ...baseStory.args variant="secondary">
<span class=icon></span> ${story} Button
</>
</>;
```
If we allow `<!exports>` or `exports {` to be used multiple times (like `static`) the two blocks below should be merged
```marko
<!exports>
<@Primary>
<@args size="medium">
Primary Button
</>
</>
</>
exports {
<@Secondary>
<@args ...Primary.args variant="secondary">
Secondary Button
</>
</>;
}
```