DEV Community

Cover image for Reusable Tagged Templates
Isa Ozler
Isa Ozler

Posted on • Updated on

Reusable Tagged Templates

TLTR; See it in action [https://github.com/isaozler/tagged-templates-io]

Once again, I was working on a dragon component. Based on the transition and loading state the class names should change for custom transition and loading states. There is a really nice package classnames [https://github.com/JedWatson/classnames], but most of the time I find myself stating the class name between two values. If it's true ? '--visible' : '--hidden'.

const transitionClass = `app__overlay--${isTransitioning ? 'trans-start' : 'trans-end'}`
const loadingClass = `app__overlay--${isLoading ? 'visble' : 'hidden'}`

const stateClasses = [transitionClass, loadingClass].join(' ');

# React Sample
<div className={`app__overlay ${stateClass}`} />

Problem

This does the job actually, but is quite messy, not an elegant solution and not reusable. As I mentioned earlier in the classname package you can do this;

className({ foo: true }) // => 'foo'

But, then you have to do another object to get the opposite state.

const stateClass = className({
 'app__overlay--visible': isLoading,
 'app__overlay--hidden': !isLoading,
 'app__overlay--trans-start': isTransitioning,
 'app__overlay--trans-end': !isTransitioning,
});

<div className={stateClass} />

Solution

Of course, there is always room for improvement. But for now, I ended up with a very lightweight package making at least my life easier.

const stateClass = taggedTemplatesIo(
  `{0} {0}--{1} {0}--{2}`,
  [
    ['app__overlay'],
    ['trans-start','trans-end'],
    ['visble','hidden'],
  ],
  [true, isTransitioning, isLoading]
);

# React Sample
<div className={stateClass} />

GraphQL / SQL interpolations

You can always use this for other implementations of course. It was very useful for me with GraphQL / SQL interpolations. To give you an example;

SQL

const isClient = true;
const as = 'age';
const from = ['clientTable', 'relationTable'];
const fromCondition = isClient;
const where = `${as} = ${42}`;
const start = 0, end = 10;

taggedTemplates(`
  SELECT {select} AS {as}
  FROM {from}
  WHERE {where}
  LIMIT {start}, {end}
`,
  { select: 'age_col', as, from, where, start, end },
  { from: fromCondition },
)


// Outputs

SELECT age_col AS age
  FROM clientTable
  WHERE age = 42
  LIMIT 0, 10

Conclusion

With this lightweight simple helper, I can write cleaner, easier to maintain code blocks. Hope it helps others too!

Top comments (0)