FlexboxとAuto marginを組み合わせる

f:id:ryotah:20170721204657p:plain

こんな感じでコンテンツを左右(上下)に配置する時に便利。


以下のような問題(仕様)があるので、Flexboxを入れ子にした場合かつ、上下揃えをした場合は注意が必要。
css - Chrome / Safari not filling 100% height of flex parent - Stack Overflow

f:id:ryotah:20170721210737p:plain

  • キャプチャの左がChrome、右はSafari
  • 一番左のパターンは「Flexboxで伸びている高さ = height: 100%」という前提のもの
    • Chromeでは動く。ただしflex-basisを0にしないとこのような結果にはならない
  • 二番目はposition: absoluteを利用
  • 三番目はheight: 100%を利用せずにflex-growを活用するパターン
    • これがよさそう

ブロック要素にリンク(a tag)をつける

  1. ブロック要素内のaタグを、要素いっぱいに広げる
    • text-indent: -999px; などでテキストを非表示にする必要がある
  2. シンプルにaタグでブロック要素を包む
    • ブロック要素内のテキストがリンクテキストと同じスタイルにならないように調整する(必要ならば)
    • a { color: inherit; text-decoration: none; } など

複数行をTruncate

f:id:ryotah:20170718210942p:plain

  • ブラウザが限られている(Safari, Chrome)
  • そのうち使えなくなるかもしれない
  • heightで制限しているので、対象ブラウザ以外でもレイアウトが崩れることはない、はず
.note {
  font-size: 16px;
  line-height: 1.25;
  width: 100px;
  border: 1px solid #000;
  overflow: hidden;
  word-wrap: break-word;
  
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  display: -webkit-box;

  height: calc(16px * 1.25 * 3);
}

ユーザーからのフィードバックをSlackで受け取る

f:id:ryotah:20170713131031p:plain

f:id:ryotah:20170713131027p:plain

こういうやつを作りました。


Node.js用のSlack SDKを利用したら簡単にできました。

GitHub - slackapi/node-slack-sdk: Slack Developer Kit for Node.js

以下、Webhook URL発行前提の話です。

const IncomingWebhook = require('@slack/client').IncomingWebhook;
const webhook = new IncomingWebhook(SLACK_WEBHOOK_URL);

router.get('/send', (req, res) => {

  // ...

  new Promise((resolve, reject) => {
    webhook.send({
      attachments: createAttachments({
        id: '00001',
        name: '名前',
        text: '本文が入ります。本文が入ります。本文が入ります。本文が入ります。本文が入ります。',
        title: 'タイトル',
      })
    }, (err, header, statusCode, body) => {
      if (err) {
        reject(err);
      } else {
        resolve('ok');
      }
    })
  })
  .then((result) => {
    res.json(result);
  })
  .catch((err) => {
    // エラー処理
  });
});

function createAttachments(params) {
  return [{
      color: '#03A9F4',
      pretext: 'ユーザーからのフィードバックです',
      author_name: params.name,
      title: params.title,
      text: params.text,
      fields: [{
        title: 'User ID',
        value: params.id
      }],
      ts: Math.floor(Date.now() / 1000)
    }
  ];
}

参考URL

カラーコードの変換 (Hex -> RGB)

例えば#ff0000rgb(255,0,0)に変換したい場合。

  1. カラーコード(文字列)を2文字ずつに分ける
  2. 16進法を10進法に変換する
import compose from 'lodash/fp/compose';
import map from 'lodash/fp/map';

function hexToRgb(hex: string): string {
  return compose(
    (decimals) => `rgb(${decimals.join(',')})`,

    // hex to decimal
    map((hex) => parseInt(hex, 16)),

    // split string every 2 characters
    //   e.g. 'ff0000' -> ['ff', '00', '00']
    (hex) => hex.match(/.{1,2}/g),

    // remove `#`
    (hex) => hex.substr(1),

  )(hex);
}

console.error(hexToRgb('#ff0000'));
// -> 'rgb(255,0,0)'

split正規表現が使えた。文字を分割する処理に関してはsplitでもできそう。

String.prototype.split() - JavaScript | MDN

null vs undefined

undefinedを使うべきかnullを使うべきか。コンテキストで使い分けるべきか。


Coding guidelines · Microsoft/TypeScript Wiki · GitHub

contributors向けのガイド。undefinedを使えとのこと。

Rule: no-null-keyword

TSLintにルールもある。

MouseEvent, KeyboardEventを利用してHTMLElementを操作

/**
 * ボタンのdisabled属性を変更
 */
public onMouseEvent($event: MouseEvent) {
  const el = <HTMLButtonElement>$event.target;

  /* disabled */
  el.disabled = true;
  
  /* enabled */
  // el.disabled = false;

  /**
   * 以下でも可
   */
  /* disabled */
  // el.setAttribute('disabled', '');
  /* enabled */
  // el.removeAttribute('disabled');
}

/**
 * フォーカスを外す
 */
public onKeyEvent($event: KeyboardEvent) {
  const el = <HTMLElement>$event.target;
  el.blur();
}