Vue(Nuxt)でborder-radiusのプレイグラウンドを作ってみた


Vue.js(Nuxt)でcssのborder-radiusプロパティのプレイグラウンドを作ってみた。

# 動作ページ
https://playcss.dev/border-radius

# スクリーンショット
こんな感じでぐりぐり動かせるので、直観的に理解できると思う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163837/35bd62d1-f00d-bca0-9bdf-7ecd2cee3457.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163837/f694775c-f8d3-f23b-588b-de3d6faf2795.png)

# カラースキーム
solarizedをほぼそのまま適用してる。
https://ethanschoonover.com/solarized/
## ダークモード
カラースキームの色を適用すれば、ダークモードにできるので割とお手軽にできる。そうsolarizedならね。
![darkmode.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163837/f9a7b856-2161-0476-24b9-4d327457f0fb.gif)
<details><summary>code</summary><div>

```scss
/* scssの変数(solarized) */
$base03:#002b36;
$base02:#073642;
$base01:#586e75;
$base00:#657b83;
$base02-d10: darken($color: $base02, $amount: 10);
$base03-l3: lighten($color: $base03, $amount: 3);
$base03-d10: darken($color: $base03, $amount: 10);
$base0:#839496;
$base1:#93a1a1;
$base2:#eee8d5;
$base3:#fdf6e3;
$base2-d10: darken($color: $base2, $amount: 10);
$base3-l3: lighten($color: $base3, $amount: 3);
$base3-d10: darken($color: $base3, $amount: 10);

/* cssの変数に入れる */
:root {
  --base3-l3: #{$base3-l3};
  --base3-d10: #{$base3-d10};
  --base3: #{$base3};
  --base2-d10: #{$base2-d10};
  --base2: #{$base2};
  --base1: #{$base1};
  --base0: #{$base0};
  --base00: #{$base00};
}
@media (prefers-color-scheme: dark) {
  :root {
    --base3-l3: #{$base03-l3};
    --base3-d10: #{$base03-d10};
    --base3: #{$base03};
    --base2-d10: #{$base02-d10};
    --base2: #{$base02};
    --base1: #{$base01};
    --base0: #{$base00};
    --base00: #{$base0};
  }
}
```
</div></details>
# transition
## タイトル(h1)部分の表示時アニメーション
![h1anime.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163837/59ceed61-729e-9aa5-13ae-8a7cb0269768.gif)


こんな感じのコンポーネントを作っておいて、呼び出せば表示の際にアニメーションされるようになる。

```vuejs
<template>
  <transition name="h1" appear>
    <h1>
      <slot></slot>
    </h1>
  </transition>
</template>

<style lang="scss" scoped>
.h1-enter-active {
  transition: all 0.5s ease-out;
}
.h1-enter {
  opacity: 0;
  transform: translateX(-4px);
}
.h1-enter-to {
  opacity: 1;
  transform: translateX(0);
}
</style>

```

## remove addの部分のアニメーション
ユニークIDを付与して指定する形にすると追加した要素もうまくアニメーションしてくれる。
![remove.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163837/52c2fbbd-f8aa-43be-fba8-64f9870527bd.gif)

```vuejs
<transition-group name="border">
  <template v-for="(item, index) in borderRadiuses">
    <div :key="item.id">
      code
    </div>
  </template>
</transition>

<script>
export default {
  data() {
    return {
      borderRadiuses: [
        { id: 1, size: 15, unit: "px" },
        { id: 2, size: 15, unit: "px" },
        { id: 3, size: 15, unit: "px" },
        { id: 4, size: 15, unit: "px" }
      ],
    }
  },
</script>
```
追加したときには、idが被らないように割り振る。

# select box
コンポーネント化して、デフォルトの見た目を消してCSSのみでそれらしい形にしている。
横幅がoptionの最大文字数の大きさに合わせてしまうので、表示している文字数の大きさに合わせるようにしたい。
<details><summary>code</summary><div>

```vuejs
<template>
  <label>
    <select
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
      @change="$emit('allUnitChange')"
    >
      <option value="px">px</option>
      <option value="%">%</option>
      <option value="cm">cm</option>
      <option value="mm">mm</option>
      <option value="in">in</option>
      <option value="pc">pc</option>
      <option value="pt">pt</option>
      <option value="vh">vh</option>
      <option value="vw">vw</option>
      <option value="vmin">vmin</option>
      <option value="vmax">vmax</option>
      <option value="em">em</option>
      <option value="ex">ex</option>
      <option value="ch">ch</option>
      <option value="rem">rem</option>
      <option value="ex">ex</option>
    </select>
  </label>
</template>

<script>
export default {
  props: ["value"]
};
</script>

<style lang="scss" scoped>
label {
  border-bottom: 1px #ccc solid;
  &:after {
    content: "";
    display: inline-block;
    vertical-align: sub;
    height: 10px;
    border-top: 6px solid #ccc;
    border-right: 3px solid transparent;
    border-left: 3px solid transparent;
  }
  &:focus,
  &:hover {
    outline: darken($color: $base2, $amount: 30) auto 1px;
  }
}
select {
  -webkit-appearance: none;
  padding: 0 4px 0 2px;
  line-height: 1em;
  background: var(--base3-l3);
  &:focus {
    outline: none;
  }
  &:hover {
    cursor: pointer;
  }
}
</style>

```
</div></details>
# color picker
[vue-color](https://github.com/xiaokaike/vue-color)
chromeのdevtoolのcolor pickerと同じ見た目のコンポーネントがあるので、適用している。

# editor部分
[Vue Prism Editor](https://github.com/koca/vue-prism-editor)
編集しながら、ハイライトをかけてくれるライブラリを探したらちょうどいいのがあったので、solarizedを自分で適用して使っている。

# スクロール部分
atomエディターのコードを参考にした。というか全体的にatomエディターにsolarizedを適用した感じの見た目

```scss
.scrollbars-visible-always {
  ::-webkit-scrollbar-thumb {
    border-radius: 5px;
    border: 3px solid var(--base2);
    background: var(--base2-d10);
    background-clip: content-box;
  }
  ::-webkit-scrollbar-corner {
    background: var(--base2);
  }
  ::-webkit-scrollbar-track {
    background: var(--base2);
  }
  ::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  main {
    &::-webkit-scrollbar-thumb {
      border: 3px solid var(--base3);
      background: var(--base3-d10);
    }
    &::-webkit-scrollbar-corner {
      background: var(--base2);
    }
    &::-webkit-scrollbar-track {
      background: var(--base3);
    }
  }
}
```

# サイドバーのリサイズ
これは完全に蛇足:sweat_smile:
![resize.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163837/cd366df2-06c5-ffbb-0fab-e4471c49b757.gif)
addEventListenerでイベントを追加して動かしてる。
<details><summary>code</summary><div>

```vuejs
<script>
  ...
  mounted() {
    const resizer = document.querySelector("#resizer");
    resizer.addEventListener("mousedown", this.mouseDown, false);
  },
  methods: {
    mouseDown: function(e) {
      this.firstClientX = e.clientX;
      document.addEventListener("mousemove", this.mouseMoveEvent);
      document.addEventListener("mouseup", this.removeMouseMove);
    },
    removeMouseMove: function() {
      this.asideWidth = this.width;
      document.removeEventListener("mousemove", this.mouseMoveEvent, false);
    },
    mouseMoveEvent: function(e) {
      this.movingClientX = e.clientX;
      this.calcAsideWidth;
    }
  },
  ...
</script>
```
</div></details>


# まとめ
スラッシュ区切りで指定するborder-radiusはほとんど使ってこなかったので、動きが理解できててよかった。
VuetifyなどのCSSのフレームワークを使わなかったのと、作っているといろいろと凝ってしまって少しずつ作っているうちに時間をかけてしまったけど、形はできたのでほかのプロパティにも展開していきたい()。