squircle

Make all the squircles you need, in the browser. https://github.com/georgedoescode/squircle https://squircley.app/
git clone http://git.hanabi.in/repos/squircle.git
Log | Files | Refs | LICENSE

GeneratorControls.vue (7305B)


      1 <script>
      2 import VSwatches from 'vue-swatches';
      3 import 'vue-swatches/dist/vue-swatches.css';
      4 import GeneratorExportOptions from './GeneratorExportOptions.vue';
      5 
      6 export default {
      7     name: 'GeneratorControls',
      8     components: {
      9         VSwatches,
     10         GeneratorExportOptions,
     11     },
     12     props: {
     13         initialFill: {
     14             type: String,
     15             required: true,
     16         },
     17         rotation: {
     18             type: Number,
     19             required: true,
     20         },
     21         scale: {
     22             type: Number,
     23             required: true,
     24         },
     25         curvature: {
     26             type: Number,
     27             required: true,
     28         },
     29     },
     30     data() {
     31         return {
     32             fill: this.initialFill,
     33         };
     34     },
     35     watch: {
     36         fill(newVal) {
     37             this.$emit('controls-changed', {
     38                 id: 'fill',
     39                 value: newVal,
     40             });
     41         },
     42     },
     43     methods: {
     44         handleControlChange(e) {
     45             this.$emit('controls-changed', {
     46                 id: e.target.id,
     47                 value: e.target.value,
     48             });
     49         },
     50         handleDetailChange(e) {
     51             const { id } = e.target;
     52 
     53             for (const propertyIndex in this.detailToggleState) {
     54                 const state = this.detailToggleState[~~propertyIndex];
     55 
     56                 if (state.id === id) {
     57                     state.checked = true;
     58 
     59                     this.$emit('controls-changed', {
     60                         id: 'detail',
     61                         value: state.value,
     62                     });
     63                 } else {
     64                     state.checked = false;
     65                 }
     66             }
     67         },
     68     },
     69 };
     70 </script>
     71 
     72 <template>
     73     <div class="generator-controls">
     74         <div class="generator-controls__inputs">
     75             <label for="rotation" class="generator-controls__label">
     76                 Rotation
     77             </label>
     78             <BaseRangeInput
     79                 name="rotation"
     80                 class="generator-controls__slider"
     81                 :min="-45"
     82                 :max="45"
     83                 :value="rotation"
     84                 :step="1"
     85                 @change="handleControlChange"
     86             />
     87             <label for="scale" class="generator-controls__label">
     88                 Scale
     89             </label>
     90             <BaseRangeInput
     91                 name="scale"
     92                 class="generator-controls__slider"
     93                 :min="0"
     94                 :max="200"
     95                 :value="scale"
     96                 :step="1"
     97                 @change="handleControlChange"
     98             />
     99             <label for="curvature" class="generator-controls__label">
    100                 Curvature
    101             </label>
    102             <BaseRangeInput
    103                 name="curvature"
    104                 class="generator-controls__slider"
    105                 :min="0"
    106                 :max="1"
    107                 :value="curvature"
    108                 :step="0.01"
    109                 @change="handleControlChange"
    110             />
    111             <label for="colorHex" class="generator-controls__label">
    112                 Fill
    113             </label>
    114             <div class="generator-controls__swatch">
    115                 <input
    116                     id="colorHex"
    117                     v-model="fill"
    118                     class="generator-conrols__swatch-text"
    119                     type="text"
    120                     name="colorHex"
    121                 />
    122                 <VSwatches
    123                     v-model="fill"
    124                     :swatches="[
    125                         '#EF4E4E',
    126                         '#F9703E',
    127                         '#FADB5F',
    128                         '#6CD410',
    129                         '#31B237',
    130                         '#2DCCA7',
    131                         '#1CD4D4',
    132                         '#40C3F7',
    133                         '#2186EB',
    134                         '#3A66DB',
    135                         '#9446ED',
    136                         '#ED47ED',
    137                         '#E8368F',
    138                         '#829AB1',
    139                         '#7B8794',
    140                         '#F5F7FA',
    141                     ]"
    142                     :trigger-style="{
    143                         width: '64px',
    144                         height: '48px',
    145                         borderRadius: '0 12px 12px 0',
    146                     }"
    147                 />
    148             </div>
    149             <hr />
    150             <p
    151                 class="generator-controls__label generator-controls__label--export"
    152             >
    153                 Export
    154             </p>
    155             <GeneratorExportOptions />
    156         </div>
    157     </div>
    158 </template>
    159 
    160 <style scoped>
    161 .generator-controls {
    162     justify-self: center;
    163     display: flex;
    164     justify-content: center;
    165     align-items: center;
    166     flex-direction: column;
    167     max-width: var(--spacing-13);
    168     width: 100%;
    169     padding-right: var(--spacing-1);
    170 }
    171 
    172 .generator-controls__inputs {
    173     display: grid;
    174     grid-template-columns: max-content 1fr;
    175     grid-template-rows: var(--spacing-6) var(--spacing-6) var(--spacing-6) max-content max-content;
    176     grid-row-gap: var(--spacing-5);
    177     justify-content: center;
    178     width: 100%;
    179 }
    180 
    181 .generator-controls__label {
    182     grid-column: 1;
    183     align-self: center;
    184     margin-right: var(--spacing-6);
    185     font-size: var(--font-size-4);
    186     font-weight: 700;
    187 }
    188 
    189 .generator-controls__slider {
    190     grid-column: 2;
    191 }
    192 
    193 .generator-controls__color-picker {
    194     grid-column: -1 / 1;
    195 }
    196 
    197 .generator-controls__swatch {
    198     grid-column: 2;
    199     display: flex;
    200     align-items: center;
    201     justify-content: space-between;
    202     height: var(--spacing-6);
    203     background: var(--grey-000);
    204     border-radius: 12px;
    205 }
    206 
    207 .generator-conrols__swatch-text {
    208     -webkit-appearance: none;
    209     position: relative;
    210     width: 100%;
    211     min-width: 0;
    212     text-transform: uppercase;
    213     height: 100%;
    214     padding-left: var(--spacing-3);
    215     background: transparent;
    216     border: 2px solid var(--grey-000);
    217     border-radius: 12px 0 0 12px;
    218     box-shadow: none;
    219     transition: border 125ms ease-in-out;
    220 }
    221 
    222 .generator-controls__swatch:hover .generator-conrols__swatch-text {
    223     border: 2px solid var(--grey-100);
    224     border-right: 0;
    225 }
    226 
    227 .generator-controls__detail {
    228     align-self: center;
    229 }
    230 
    231 .generator-export-controls {
    232     grid-column: 2;
    233 }
    234 
    235 hr {
    236     grid-column: -1 / 1;
    237     border: 0;
    238     height: 2px;
    239     background: var(--grey-000);
    240     margin: var(--spacing-1) 0;
    241 }
    242 
    243 @media only screen and (max-width: 62rem) {
    244     .generator-controls {
    245         padding: 0 var(--spacing-4);
    246         padding-bottom: var(--spacing-3);
    247     }
    248 
    249     .generator-controls__inputs {
    250         grid-row-gap: var(--spacing-5);
    251         grid-auto-rows: minmax(var(--spacing-5), max-content);
    252     }
    253 
    254     .generator-controls__label {
    255         font-size: var(--font-size-3);
    256         margin-right: var(--spacing-5);
    257     }
    258 
    259     .generator-export-controls {
    260         grid-column: -1 / 1;
    261     }
    262 
    263     .generator-controls__label--export {
    264         display: none;
    265     }
    266 }
    267 </style>
    268 
    269 <style>
    270 .vue-swatches__trigger__wrapper {
    271     display: block;
    272     transform-origin: 100% 100%;
    273     transition: transform 125ms ease-in-out;
    274 }
    275 
    276 .generator-controls__swatch:hover .vue-swatches__trigger__wrapper {
    277     transform: scaleX(1.125);
    278 }
    279 
    280 .vue-swatches__container {
    281     box-shadow: 0 24px 32px rgba(16, 42, 67, 0.075) !important;
    282     border: 2px solid var(--grey-100);
    283     border-radius: 24px !important;
    284 }
    285 </style>