added locations and about me text

This commit is contained in:
Grzegorz Leoniec 2018-11-12 14:27:12 +01:00
parent fb3d88f3d7
commit f57c45bb3b
61 changed files with 1960 additions and 155 deletions

View File

@ -119,3 +119,11 @@ blockquote {
margin-top: 0;
}
}
hr {
border: 0;
width: 100%;
color: $color-neutral-80;
background-color: $color-neutral-80;
height: 1px !important;
}

View File

@ -24,13 +24,22 @@
</no-ssr>
</ds-space>
<template slot="footer">
<span :style="{ opacity: post.shoutedCount ? 1 : .5 }">
<ds-icon name="heart-o" /> <small>{{ post.shoutedCount }}</small>
</span>
&nbsp;
<span :style="{ opacity: post.commentsCount ? 1 : .5 }">
<ds-icon name="comments" /> <small>{{ post.commentsCount }}</small>
</span>
<div style="display: inline-block; opacity: .5;">
<ds-icon
v-tooltip="{content: category.name, placement: 'bottom-start', delay: { show: 500 }}"
v-for="category in post.categories"
:key="category.id"
:name="category.icon" />&nbsp;
</div>
<div style="display: inline-block; float: right">
<span :style="{ opacity: post.shoutedCount ? 1 : .5 }">
<ds-icon name="bullhorn" /> <small>{{ post.shoutedCount }}</small>
</span>
&nbsp;
<span :style="{ opacity: post.commentsCount ? 1 : .5 }">
<ds-icon name="comments" /> <small>{{ post.commentsCount }}</small>
</span>
</div>
</template>
</ds-card>
</a>

View File

@ -6,7 +6,7 @@
:disabled="disabled || loading"
danger
size="x-large"
icon="heart"
icon="bullhorn"
@click="shout" />
<ds-space margin-bottom="xx-small" />
<ds-text color="soft">

View File

@ -6,14 +6,11 @@ export default gql(`
id
name
avatar
createdAt
friendsCount
friends {
id
about
location {
name
slug
avatar
}
createdAt
badges {
id
key
@ -63,6 +60,11 @@ export default gql(`
deleted
image
createdAt
categories {
id
name
icon
}
author {
User {
id

View File

@ -1,10 +1,5 @@
const pkg = require('./package')
const envWhitelist = [
'NODE_ENV',
'BACKEND_URL',
'MAINTENANCE'
]
const envWhitelist = ['NODE_ENV', 'BACKEND_URL', 'MAINTENANCE']
module.exports = {
mode: 'universal',
@ -102,6 +97,7 @@ module.exports = {
*/
modules: [
'@nuxtjs/apollo',
'@nuxtjs/axios',
['@nuxtjs/dotenv', { only: envWhitelist }],
['nuxt-env', { keys: envWhitelist }]
],
@ -129,7 +125,7 @@ module.exports = {
// },
// required
clientConfigs: {
default: '~/plugins/apollo-config.js',
default: '~/plugins/apollo-config.js'
}
},

View File

@ -17,6 +17,7 @@
},
"dependencies": {
"@nuxtjs/apollo": "^4.0.0-rc3",
"@nuxtjs/axios": "^5.3.4",
"@nuxtjs/dotenv": "^1.3.0",
"accounting": "^0.4.1",
"cross-env": "^5.2.0",

View File

@ -47,6 +47,10 @@ export default {
name: 'Categories',
path: `/admin/categories`
},
{
name: 'Tags',
path: `/admin/tags`
},
{
name: 'Settings',
path: `/admin/settings`

View File

@ -1,7 +1,42 @@
<template>
<ds-card>
<ds-space margin="small">
Categories...
</ds-space>
<ds-card space="small">
<ds-heading tag="h3">Themen / Kategorien</ds-heading>
<ds-table
:data="Category"
:fields="['icon', 'name', 'postCount']"
condensed>
<template
slot="icon"
slot-scope="scope">
<ds-icon :name="scope.row.icon" />
</template>
</ds-table>
</ds-card>
</template>
<script>
import gql from 'graphql-tag'
export default {
data() {
return {
Category: []
}
},
apollo: {
Category: {
query: gql(`
query {
Category(orderBy: postCount_desc) {
id
name
slug
icon
postCount
}
}
`)
}
}
}
</script>

47
pages/admin/tags.vue Normal file
View File

@ -0,0 +1,47 @@
<template>
<ds-card space="small">
<ds-heading tag="h3">Tags</ds-heading>
<ds-table
:data="Tag"
:fields="fields"
condensed>
<template
slot="id"
slot-scope="scope">
{{ scope.index + 1 }}
</template>
</ds-table>
</ds-card>
</template>
<script>
import gql from 'graphql-tag'
export default {
data() {
return {
Tag: [],
fields: {
id: { label: '#' },
name: { label: 'Name' },
taggedCountUnique: { label: 'Nutzer' },
taggedCount: { label: 'Beiträge' }
}
}
},
apollo: {
Tag: {
query: gql(`
query {
Tag(first: 20, orderBy: taggedCountUnique_desc) {
id
name
taggedCount
taggedCountUnique
}
}
`)
}
}
}
</script>

View File

@ -106,6 +106,7 @@ export default {
categories {
id
name
icon
}
shoutedCount
}

View File

@ -17,11 +17,18 @@
:count="post.shoutedCount"
:post-id="post.id" />
<!-- Categories -->
<div class="tags">
<ds-icon
v-tooltip="{content: category.name, placement: 'top-start', delay: { show: 300 }}"
v-for="category in post.categories"
:key="category.id"
:name="category.icon"
size="large" />&nbsp;
<ds-space margin-bottom="small" />
<!--<div class="tags">
<ds-icon name="compass" /> <ds-tag
v-for="category in post.categories"
:key="category.id">{{ category.name }}</ds-tag>
</div>
:key="category.id"><ds-icon :name="category.icon" /> {{ category.name }}</ds-tag>
</div>-->
<!-- Tags -->
<template v-if="post.tags && post.tags.length">
<ds-space margin="xx-small"/>
@ -140,7 +147,7 @@ export default {
name
}
commentsCount
comments(orderBy: _id_desc) {
comments(orderBy: createdAt_desc) {
id
contentExcerpt
createdAt
@ -166,6 +173,7 @@ export default {
categories {
id
name
icon
}
shoutedCount
}

View File

@ -5,9 +5,15 @@
<ds-space/>
<h3><ds-icon name="compass" /> Themenkategorien</h3>
<div class="tags">
<ds-tag
<ds-icon
v-tooltip="{content: category.name, placement: 'top-start', delay: { show: 300 }}"
v-for="category in post.categories"
:key="category.id">{{ category.name }}</ds-tag>
:key="category.id"
:name="category.icon"
size="large" />&nbsp;
<!--<ds-tag
v-for="category in post.categories"
:key="category.id"><ds-icon :name="category.icon" /> {{ category.name }}</ds-tag>-->
</div>
<template v-if="post.tags && post.tags.length">
<h3><ds-icon name="tags" /> Schlagwörter</h3>
@ -70,6 +76,7 @@ export default {
categories {
id
name
icon
}
relatedContributions(first: 2) {
id
@ -78,6 +85,11 @@ export default {
contentExcerpt
shoutedCount
commentsCount
categories {
id
name
icon
}
author {
User {
id

View File

@ -21,10 +21,17 @@
align="center"
no-margin>{{ user.name }}</ds-heading>
<ds-text
v-if="user.location && user.location.length"
align="center"
color="soft"
size="small">
Mitglied seid {{ user.createdAt | date('MMMM yyyy') }}
<ds-icon name="map-marker" /> {{ user.location[0].name }}
</ds-text>
<ds-text
align="center"
color="soft"
size="small">
Mitglied seit {{ user.createdAt | date('MMMM yyyy') }}
</ds-text>
</ds-space>
<ds-space
@ -60,6 +67,18 @@
:follow-id="user.id"
@update="voted = true && fetchUser()" />
</ds-space>
<template v-if="user.about">
<hr>
<ds-space
margin-top="small"
margin-bottom="small">
<ds-text
color="soft"
size="small">
{{ user.about }}
</ds-text>
</ds-space>
</template>
</ds-card>
<ds-space/>
<ds-heading

View File

@ -1,5 +1,203 @@
<template>
<ds-card>
<p>My Data...</p>
<ds-card space="small">
<ds-input
id="name"
v-model="form.name"
icon="user"
label="Dein Name"
placeholder="Dein Name"/>
<ds-select
id="city"
:options="cities"
v-model="city"
icon="map-marker"
label="Deine Stadt"
placeholder="Deine Stadt"
@input="handleCitySelection"
@input.native="handleCityInput" />
<ds-input
id="bio"
v-model="form.about"
type="textarea"
rows="3"
label="Erzähl doch ein wenig (in zwei Sätzen) über dich"
placeholder="Über mich"/>
<template slot="footer">
<ds-button
style="float: right;"
icon="check"
primary
@click.prevent="submit">Speichern</ds-button>
</template>
</ds-card>
</template>
<script>
import gql from 'graphql-tag'
import { mapGetters } from 'vuex'
import { CancelToken } from 'axios'
import find from 'lodash/find'
let timeout
const mapboxToken =
'pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.KZ8KK9l70omjXbEkkbHGsQ'
export default {
data() {
return {
axiosSource: null,
cities: [],
city: null,
form: {
name: null,
locationId: null,
about: null
}
}
},
computed: {
...mapGetters({
user: 'auth/user'
})
},
watch: {
user: {
immediate: true,
handler: function(user) {
this.form = {
name: user.name,
locationId: user.locationId,
about: user.about
}
}
}
},
methods: {
submit() {
console.log('SUBMIT', { ...this.form })
this.$apollo
.mutate({
mutation: gql`
mutation(
$id: ID!
$name: String
$locationId: String
$about: String
) {
UpdateUser(
id: $id
name: $name
locationId: $locationId
about: $about
) {
id
name
locationId
about
}
}
`,
// Parameters
variables: {
id: this.user.id,
name: this.form.name,
locationId: this.form.locationId,
about: this.form.about
},
// Update the cache with the result
// The query will be updated with the optimistic response
// and then with the real result of the mutation
update: (store, { data: { UpdateUser } }) => {
this.$store.dispatch('auth/refresh', UpdateUser)
// Read the data from our cache for this query.
// const data = store.readQuery({ query: TAGS_QUERY })
// Add our tag from the mutation to the end
// data.tags.push(addTag)
// Write our data back to the cache.
// store.writeQuery({ query: TAGS_QUERY, data })
}
// Optimistic UI
// Will be treated as a 'fake' result as soon as the request is made
// so that the UI can react quickly and the user be happy
/* optimisticResponse: {
__typename: 'Mutation',
addTag: {
__typename: 'Tag',
id: -1,
label: newTag
}
} */
})
.then(data => {
console.log(data)
this.$toast.success('Updated user')
})
.catch(err => {
console.error(err)
this.$toast.error(err.message)
})
},
handleCityInput(value) {
clearTimeout(timeout)
timeout = setTimeout(() => this.requestGeoData(value), 500)
},
handleCitySelection(value) {
console.log('SET CURRENT VALUE', value)
const item = find(this.cities, { value: value })
console.log('ID:', item.id)
this.form.locationId = item.id
},
handleCityEnter() {
console.log('SET CURRENT VALUE')
},
processCityResults(res) {
if (
!res ||
!res.data ||
!res.data.features ||
!res.data.features.length
) {
return []
}
let output = []
res.data.features.forEach(item => {
output.push({
label: item.place_name,
value: item.place_name,
id: item.id
})
})
return output
},
requestGeoData(e) {
if (this.axiosSource) {
// cancel last request
this.axiosSource.cancel()
}
const value = e.target ? e.target.value.trim() : ''
if (value === '' || value.length < 3) {
this.cities = []
return
}
this.axiosSource = CancelToken.source()
this.$axios
.get(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${value}.json?access_token=${mapboxToken}&types=region,postcode,district,place,country&language=de`,
{
cancelToken: this.axiosSource.token
}
)
.then(res => {
this.cities = this.processCityResults(res)
})
console.log('TRY TO GET DATA FOR ', value)
}
}
}
</script>

View File

@ -85,7 +85,9 @@ export const actions = {
slug: user.slug,
email: user.email,
avatar: user.avatar,
role: user.role
role: user.role,
locationId: user.locationId,
about: user.about
})
commit('SET_TOKEN', token)
}
@ -96,6 +98,21 @@ export const actions = {
}
return getters.isLoggedIn
},
refresh({ state, commit }, { id, name, locationId, about, avatar }) {
if (!state.user.id || id !== state.user.id) {
return
}
commit('SET_USER', {
id: state.user.id, // do not change
name: name || state.user.name,
slug: state.user.slug, // do not change
email: state.user.email, // do not change
avatar: avatar || state.user.avatar,
role: state.user.role,
locationId: locationId || state.user.locationId,
about: about || state.user.about
})
},
async login({ commit }, { email, password }) {
try {
commit('SET_PENDING', true)
@ -112,6 +129,8 @@ export const actions = {
email
avatar
role
locationId
about
token
}
}

View File

@ -19,7 +19,7 @@
height: 100%;
top: 0px;
left: 0px;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 0 0 1px rgba($color-neutral-0, .1);
border-radius: 50%;
}

View File

@ -5,7 +5,11 @@
<table
cellpadding="0"
cellspacing="0"
class="ds-table">
class="ds-table"
:class="[
condensed && 'ds-table-condensed',
bordered && 'ds-table-bordered'
]">
<colgroup>
<col
v-for="header in headers"
@ -24,7 +28,7 @@
<tbody>
<tr
v-for="(row, index) in rows"
:key="index">
:key="row.key || index">
<ds-table-col
v-for="col in row"
:key="col.key">
@ -75,6 +79,20 @@ export default {
default() {
return null
}
},
/**
* Should the table be more condense?
*/
condensed: {
type: Boolean,
default: false
},
/**
* Should the table have borders?
*/
bordered: {
type: Boolean,
default: true
}
},
computed: {

View File

@ -11,19 +11,34 @@
.ds-table-col {
@include reset;
border-bottom: $border-color-softer solid $border-size-base;
vertical-align: top;
padding: $space-small $space-xx-small;
&:last-child {
padding-right: 0;
}
}
.ds-table-head-col {
@include reset;
border-bottom: $border-color-softer solid $border-size-base;
padding: $space-small $space-xx-small;
text-align: left;
font-weight: $font-weight-bold;
}
}
// bordered
.ds-table-bordered {
.ds-table-col,
.ds-table-head-col {
border-bottom: $border-color-softer dotted $border-size-base;
}
tr:last-child .ds-table-col {
border-bottom: none;
}
}
// condensed
.ds-table-condensed {
.ds-table-col,
.ds-table-head-col {
padding-top: $space-x-small;
padding-bottom: $space-x-small;
}
}

View File

@ -1,10 +1,9 @@
<template>
<div
<div
class="ds-form-item"
:class="$parentInput ? $parentInput.stateClasses : ''">
<ds-input-label
v-if="$parentInput"
:label="$parentInput.label"
:class="$parentInput.stateClasses">
<ds-input-label
:label="$parentInput.label"
:for="$parentInput.id" />
<slot/>
<ds-input-error :error="$parentInput.error" />

View File

View File

View File

View File

@ -17,11 +17,12 @@
:type="type"
:autofocus="autofocus"
:placeholder="placeholder"
:tabindex="tabindex"
:disabled="disabled"
:readonly="readonly"
:is="tag"
:value.prop="innerValue"
@input="input"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur"
:rows="type === 'textarea' ? rows : null"

View File

View File

View File

@ -1,33 +1,119 @@
<template>
<ds-form-item>
<div class="ds-select-wrap">
<div
class="ds-select-wrap"
v-click-outside="handleBlur"
:tabindex="searchable ? -1 : tabindex"
@keydown.self.down.prevent="pointerNext"
@keydown.self.up.prevent="pointerPrev"
@keypress.enter.prevent.stop.self="selectPointerOption"
@keyup.esc="close">
<div
v-if="icon"
class="ds-select-icon">
<ds-icon :name="icon"/>
</div>
<select
<div
class="ds-select"
@click="handleClick"
:class="[
icon && `ds-select-has-icon`,
iconRight && `ds-select-has-icon-right`
]"
:id="id"
:name="model"
:autofocus="autofocus"
:placeholder="placeholder"
:disabled="disabled"
:readonly="readonly"
:value.prop="innerValue"
@input="input"
@focus="handleFocus"
@blur="handleBlur">
<option
v-for="option in options"
:key="option.label || option">
{{ option.label || option }}
</option>
</select>
iconRight && `ds-select-has-icon-right`,
multiple && `ds-select-multiple`
]">
<div
v-if="multiple"
class="ds-selected-options">
<div
class="ds-selected-option"
v-for="(value, index) in innerValue"
:key="value">
<!-- @slot Slot to provide a custom selected option display -->
<slot
name="optionitem"
:value="value">
<ds-chip
removable
@remove="deselectOption(index)"
color="primary">
{{ value }}
</ds-chip>
</slot>
</div>
<input
ref="search"
class="ds-select-search"
:id="id"
:name="model"
:autofocus="autofocus"
:placeholder="placeholder"
:tabindex="tabindex"
:disabled="disabled"
:readonly="readonly"
v-model="searchString"
@focus="handleFocus"
@keydown.delete.stop="deselectLastOption"
@keydown.down.prevent="pointerNext"
@keydown.up.prevent="pointerPrev"
@keypress.enter.prevent.stop="selectPointerOption"
@keyup.esc="close">
</div>
<div
v-else
class="ds-select-value">
<div
v-if="placeholder && !innerValue"
class="ds-select-placeholder">
{{ placeholder }}
</div>
<!-- @slot Slot to provide a custom value display -->
<slot
v-else
name="value"
:value="innerValue">
{{ innerValue }}
</slot>
</div>
<input
v-if="!multiple"
ref="search"
class="ds-select-search"
:id="id"
:name="model"
:autofocus="autofocus"
:placeholder="placeholder"
:tabindex="tabindex"
:disabled="disabled"
:readonly="readonly"
v-model="searchString"
@focus="handleFocus"
@keydown.delete.stop="deselectLastOption"
@keydown.down.prevent="pointerNext"
@keydown.up.prevent="pointerPrev"
@keypress.enter.prevent.stop="selectPointerOption"
@keyup.esc="close">
</div>
<div class="ds-select-dropdown">
<ul class="ds-select-options">
<li
class="ds-select-option"
:class="[
isSelected(option) && `ds-select-option-is-selected`,
pointer === index && `ds-select-option-hover`
]"
v-for="(option, index) in filteredOptions"
@click="handleSelect(option)"
@mouseover="setPointer(index)"
:key="option.label || option">
<!-- @slot Slot to provide custom option items -->
<slot
name="option"
:option="option">
{{ option.label || option }}
</slot>
</li>
</ul>
</div>
<div
v-if="iconRight"
class="ds-select-icon-right">
@ -39,6 +125,11 @@
<script>
import inputMixin from '../shared/input'
import multiinputMixin from '../shared/multiinput'
import ClickOutside from 'vue-click-outside'
import DsFormItem from '@@/components/data-input/FormItem/FormItem'
import DsChip from '@@/components/typography/Chip/Chip'
import DsIcon from '@@/components/typography/Icon/Icon'
/**
* Used for handling basic user input.
@ -46,7 +137,21 @@ import inputMixin from '../shared/input'
*/
export default {
name: 'DsSelect',
mixins: [inputMixin],
mixins: [inputMixin, multiinputMixin],
components: {
DsFormItem,
DsChip,
DsIcon
},
directives: {
ClickOutside
},
data() {
return {
searchString: '',
pointer: 0
}
},
props: {
/**
* The placeholder shown when value is empty.
@ -69,13 +174,6 @@ export default {
type: Boolean,
default: false
},
/**
* Whether the user can select multiple items
*/
multiple: {
type: Boolean,
default: false
},
/**
* The name of the input's icon.
*/
@ -88,7 +186,7 @@ export default {
*/
iconRight: {
type: String,
default: null
default: 'angle-down'
},
/**
* The select options.
@ -98,6 +196,98 @@ export default {
default() {
return []
}
},
/**
* Whether the options are searchable
*/
searchable: {
type: Boolean,
default: true
}
},
computed: {
filteredOptions() {
if (!this.searchString) {
return this.options
}
const searchParts = this.searchString.split(' ')
return this.options.filter(option => {
const value = option.value || option
return searchParts.every(part => {
if (!part) {
return true
}
return value.toLowerCase().includes(part.toLowerCase())
})
})
},
pointerMax() {
return this.filteredOptions.length - 1
}
},
watch: {
pointerMax(max) {
if (max < this.pointer) {
this.$nextTick(() => {
this.pointer = max
})
}
}
},
methods: {
handleSelect(options) {
this.selectOption(options)
this.resetSearch()
if (this.multiple) {
this.$refs.search.focus()
this.handleFocus()
} else {
this.close()
}
},
resetSearch() {
this.searchString = ''
},
handleClick() {
if (!this.focus || this.multiple) {
this.$refs.search.focus()
this.handleFocus()
}
},
close() {
this.$refs.search.blur()
this.handleBlur()
},
deselectLastOption() {
if (
this.multiple &&
this.innerValue &&
this.innerValue.length &&
!this.searchString.length
) {
this.deselectOption(this.innerValue.length - 1)
}
},
setPointer(index) {
this.pointer = index
},
pointerPrev() {
if (this.pointer === 0) {
this.pointer = this.pointerMax
} else {
this.pointer--
}
},
pointerNext() {
if (this.pointer === this.pointerMax) {
this.pointer = 0
} else {
this.pointer++
}
},
selectPointerOption() {
this.handleSelect(this.filteredOptions[this.pointer])
}
}
}

View File

@ -0,0 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Select.vue matches snapshot 1`] = `
<dsformitem-stub>
<div
class="ds-select-wrap"
tabindex="-1"
>
<!---->
<div
class="ds-select ds-select-has-icon-right"
>
<div
class="ds-select-value"
>
1
</div>
<input
class="ds-select-search"
tabindex="0"
/>
</div>
<div
class="ds-select-dropdown"
>
<ul
class="ds-select-options"
>
<li
class="ds-select-option ds-select-option-is-selected ds-select-option-hover"
>
1
</li>
<li
class="ds-select-option"
>
2
</li>
<li
class="ds-select-option"
>
3
</li>
</ul>
</div>
<div
class="ds-select-icon-right"
>
<dsicon-stub
arialabel="icon"
name="angle-down"
tag="span"
/>
</div>
</div>
</dsformitem-stub>
`;

View File

@ -2,4 +2,158 @@
```
<ds-select :options="['blue', 'red', 'green']" />
```
## Usage with label
```
<ds-select
label="Color"
:options="['blue', 'red', 'green']" />
```
## Bind to a value
Use v-model to bind a value to the select input.
```
<template>
<div>
<ds-select
v-model="color"
:options="['blue', 'red', 'green']"
placeholder="Color ..."></ds-select>
<ds-text>Your color: {{ color }}</ds-text>
</div>
</template>
<script>
export default {
data() {
return {
color: 'blue'
}
}
}
</script>
```
## Multiselect
Use the multiple prop to allow the user selecting multiple values.
```
<template>
<div>
<ds-select
v-model="color"
:options="['blue', 'red', 'green']"
placeholder="Color ..."
multiple></ds-select>
<ds-text>Your colors: {{ color }}</ds-text>
</div>
</template>
<script>
export default {
data() {
return {
color: ['blue', 'red']
}
}
}
</script>
```
## Options as objects
Options can be objects with a label and a value property.
```
<template>
<div>
<ds-select
v-model="color"
:options="colorOptions"
placeholder="Color ..."></ds-select>
<ds-text>Your color: {{ color }}</ds-text>
</div>
</template>
<script>
export default {
data() {
return {
color: '',
colorOptions: [
{
label: 'blue',
value: '#0e17d8'
},
{
label: 'red',
value: '#d80e3f'
},
{
label: 'green',
value: '#0ed853'
}
]
}
}
}
</script>
```
## Validation
We use <a href="https://github.com/yiminghe/async-validator" targe="_blank">async-validator schemas</a> for validation.
If you need to validate more than one field it is better to use the form component.
```
<template>
<div>
<ds-select
v-model="color"
:options="['blue', 'red', 'green']"
:schema="{type: 'enum', enum: ['green'], message: 'Please choose green :)' }"
placeholder="Color ..." />
</div>
</template>
<script>
export default {
data() {
return {
color: ''
}
}
}
</script>
```
## Select sizes
```
<ds-select placeholder="Small ..." size="small"></ds-select>
<ds-select placeholder="Base ..."></ds-select>
<ds-select placeholder="Large ..." size="large"></ds-select>
```
## Select icons
Add an icon to help the user identify the select fields usage.
```
<ds-select
placeholder="User ..."
icon="user"></ds-select>
<ds-select
placeholder="Day ..."
icon="clock"></ds-select>
<ds-select
placeholder="User ..."
size="small"
icon="user"></ds-select>
<ds-select
placeholder="User ..."
size="large"
icon="user"></ds-select>
```

View File

@ -0,0 +1,309 @@
import { shallowMount } from '@vue/test-utils'
import Comp from './Select.vue'
describe('Select.vue', () => {
describe('Events emitting', () => {
describe('@input', () => {
test('should be called when the value is changed passing the new value', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: '3',
options: ['1', '2', '3']
}
})
wrapper.vm.selectOption(wrapper.vm.options[0])
expect(wrapper.emitted().input[0]).toEqual(['1'])
})
test('should be called when an option is clicked passing the options value', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: '3',
options: ['1', '2', '3']
}
})
wrapper.find('.ds-select-option').trigger('click')
expect(wrapper.emitted().input[0]).toEqual(['1'])
})
})
})
describe('innerValue', () => {
test('should contain a single selected value by default', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: '1',
options: ['1', '2', '3']
}
})
expect(wrapper.vm.innerValue).toEqual('1')
})
test('should contain an array of values when multiple: true', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: ['1'],
options: ['1', '2', '3'],
multiple: true
}
})
expect(wrapper.vm.innerValue).toEqual(['1'])
})
})
describe('options', () => {
test('should highlight the selected value', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: '1',
options: ['1', '2', '3']
}
})
const option = wrapper.find('.ds-select-option')
expect(option.classes()).toContain('ds-select-option-is-selected')
})
test('should highlight all selected values when multiple: true', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: ['1', '2'],
options: ['1', '2', '3'],
multiple: true
}
})
const option = wrapper.findAll('.ds-select-option')
expect(option.at(0).classes()).toContain('ds-select-option-is-selected')
expect(option.at(1).classes()).toContain('ds-select-option-is-selected')
})
})
describe('selectOption', () => {
test('should set innerValue to selected value', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: '3',
options: ['1', '2', '3']
}
})
wrapper.vm.selectOption(wrapper.vm.options[0])
expect(wrapper.vm.innerValue).toEqual('1')
})
test('should add selected value to innerValue when multiple: true', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: ['3'],
options: ['1', '2', '3'],
multiple: true
}
})
wrapper.vm.selectOption(wrapper.vm.options[0])
expect(wrapper.vm.innerValue).toEqual(['3', '1'])
})
test('should toggle selected value in innerValue when multiple: true', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: ['3', '1'],
options: ['1', '2', '3'],
multiple: true
}
})
wrapper.vm.selectOption(wrapper.vm.options[0])
expect(wrapper.vm.innerValue).toEqual(['3'])
})
})
describe('search', () => {
test('should filter options by search string', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['cat', 'duck', 'dog']
}
})
wrapper.vm.searchString = 'do'
expect(wrapper.vm.filteredOptions).toEqual(['dog'])
})
test('should be case insensitive', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['cat', 'duck', 'dog']
}
})
wrapper.vm.searchString = 'DO'
expect(wrapper.vm.filteredOptions).toEqual(['dog'])
})
test('should ignore spaces', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['cat', 'duck', 'dog']
}
})
wrapper.vm.searchString = 'd o'
expect(wrapper.vm.filteredOptions).toEqual(['dog'])
})
test('should display filtered options', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['cat', 'duck', 'dog']
}
})
wrapper.vm.searchString = 'do'
const filteredOptions = wrapper.findAll('.ds-select-option')
expect(filteredOptions.length).toEqual(1)
})
test('should work when using search input', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['cat', 'duck', 'dog']
}
})
const searchInput = wrapper.find('.ds-select-search')
searchInput.setValue('do')
expect(wrapper.vm.filteredOptions).toEqual(['dog'])
})
})
describe('pointer', () => {
test('should be set by mouse over option', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
const options = wrapper.findAll('.ds-select-option')
options.at(2).trigger('mouseover')
expect(wrapper.vm.pointer).toEqual(2)
})
test('should be set by pointerNext', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointerNext()
expect(wrapper.vm.pointer).toEqual(1)
})
test('should be set to 0 by pointerNext when on last entry', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointer = 2
wrapper.vm.pointerNext()
expect(wrapper.vm.pointer).toEqual(0)
})
test('should be set by pointerPrev', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointer = 1
wrapper.vm.pointerPrev()
expect(wrapper.vm.pointer).toEqual(0)
})
test('should be set to last entry by pointerPrev when 0', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointerPrev()
expect(wrapper.vm.pointer).toEqual(2)
})
test('should be set by key down on wrap', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
const wrap = wrapper.find('.ds-select-wrap')
wrap.trigger('keydown.down')
expect(wrapper.vm.pointer).toEqual(1)
})
test('should be set by key up on wrap', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
const wrap = wrapper.find('.ds-select-wrap')
wrap.trigger('keydown.up')
expect(wrapper.vm.pointer).toEqual(2)
})
test('should be set by key down on search input', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
const searchInput = wrapper.find('.ds-select-search')
searchInput.trigger('keydown.down')
expect(wrapper.vm.pointer).toEqual(1)
})
test('should be set by key up on search input', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
const searchInput = wrapper.find('.ds-select-search')
searchInput.trigger('keydown.up')
expect(wrapper.vm.pointer).toEqual(2)
})
test('should select option by pointer value', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointer = 1
wrapper.vm.selectPointerOption()
expect(wrapper.vm.innerValue).toEqual('2')
})
test('should select option by enter key on wrap', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointer = 1
const wrap = wrapper.find('.ds-select-wrap')
wrap.trigger('keypress.enter')
expect(wrapper.vm.innerValue).toEqual('2')
})
test('should select option by enter key on search input', () => {
const wrapper = shallowMount(Comp, {
propsData: {
options: ['1', '2', '3']
}
})
wrapper.vm.pointer = 1
const searchInput = wrapper.find('.ds-select-search')
searchInput.trigger('keypress.enter')
expect(wrapper.vm.innerValue).toEqual('2')
})
})
it('matches snapshot', () => {
const wrapper = shallowMount(Comp, {
propsData: {
value: '1',
options: ['1', '2', '3']
}
})
expect(wrapper.element).toMatchSnapshot()
})
})

View File

@ -1,3 +1,149 @@
@import '../shared/input.scss';
@include input(ds-select);
@include input(ds-select);
.ds-select {
user-select: none;
.ds-input-has-focus & {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
.ds-select-search, .ds-select-value {
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: $input-border-size solid transparent;
padding: $input-padding-vertical $space-x-small;
line-height: $line-height-base;
.ds-input-size-small & {
padding: $input-padding-vertical-small $space-x-small;
}
.ds-input-size-large & {
padding: $input-padding-vertical-large $space-x-small;
}
.ds-select-has-icon & {
padding-left: $input-height;
.ds-input-size-small & {
padding-left: $input-height-small;
}
.ds-input-size-large & {
padding-left: $input-height-large;
}
}
.ds-select-has-icon-right & {
padding-right: $input-height;
.ds-input-size-small & {
padding-right: $input-height-small;
}
.ds-input-size-large & {
padding-right: $input-height-large;
}
}
}
.ds-select-search {
appearance: none;
font-size: inherit;
font-family: $font-family-text;
width: 100%;
background: transparent;
color: $text-color-base;
outline: none;
user-select: text;
opacity: 0;
&::placeholder {
color: $text-color-disabled;
}
.ds-input-has-focus & {
opacity: 1;
}
.ds-select-multiple & {
position: relative;
display: inline-flex;
width: auto;
height: auto;
padding: 0;
opacity: 1;
}
}
.ds-select-placeholder, .ds-select-value {
pointer-events: none;
.ds-input-has-focus & {
opacity: 0;
}
}
.ds-select-placeholder {
color: $text-color-disabled;
}
.ds-selected-options {
display: flex;
}
.ds-selected-option {
display: inline-flex;
margin-right: $space-xx-small;
}
.ds-select-dropdown {
position: absolute;
z-index: $z-index-dropdown;
top: 100%;
left: 0;
width: 100%;
background-color: $background-color-base;
border: $input-border-size solid $border-color-active;
border-top: 0;
border-bottom-left-radius: $border-radius-base;
border-bottom-right-radius: $border-radius-base;
visibility: hidden;
opacity: 0;
transition: all $duration-short $ease-out;
max-height: 240px;
overflow: auto;
.ds-input-has-focus & {
visibility: visible;
opacity: 1;
}
}
.ds-select-options {
@include reset-list;
}
.ds-select-option {
padding: $input-padding-vertical $space-x-small;
cursor: pointer;
transition: all $duration-short $ease-out;
&.ds-select-option-hover {
background-color: $background-color-primary;
color: $text-color-primary-inverse;
}
}
.ds-select-option-is-selected {
background-color: $background-color-soft;
color: $text-color-primary;
}

View File

@ -20,7 +20,7 @@ export default {
* The value of the input. Can be passed via v-model.
*/
value: {
type: [String, Object, Number],
type: [String, Object, Number, Array],
default: null
},
/**
@ -56,7 +56,7 @@ export default {
*/
schema: {
type: Object,
default: () => ({})
default: () => null
},
/**
* The input's size.
@ -68,6 +68,10 @@ export default {
validator: value => {
return value.match(/(small|base|large)/)
}
},
tabindex: {
type: Number,
default: 0
}
},
data() {
@ -107,9 +111,13 @@ export default {
}
},
methods: {
input(event) {
handleInput(event) {
this.input(event.target.value)
},
input(value) {
this.innerValue = value
if (this.$parentForm) {
this.$parentForm.update(this.model, event.target.value)
this.$parentForm.update(this.model, value)
} else {
/**
* Fires after user input.
@ -117,8 +125,8 @@ export default {
*
* @event input
*/
this.$emit('input', event.target.value)
this.validate(event.target.value)
this.$emit('input', value)
this.validate(value)
}
},
handleFormUpdate(data, errors) {
@ -126,6 +134,9 @@ export default {
this.error = errors ? errors[this.model] : null
},
validate(value) {
if (!this.schema) {
return
}
const validator = new Schema({ input: this.schema })
// Prevent validator from printing to console
// eslint-disable-next-line

View File

@ -2,63 +2,67 @@
.#{$class}-wrap {
position: relative;
}
.#{$class} {
appearance: none;
box-sizing: border-box;
font-size: $font-size-base;
font-size: $input-font-size-base;
line-height: $line-height-base;
font-family: $font-family-text;
width: 100%;
padding: $input-padding-vertical $space-x-small;
height: $input-height;
color: $text-color-base;
background: $background-color-base;
border: $input-border-size solid $border-color-soft;
border: $input-border-size solid $border-color-base;
border-radius: $border-radius-base;
outline: none;
transition: all $duration-short $ease-out;
&::placeholder {
color: $text-color-disabled;
}
.ds-input-has-focus &,
&:focus {
border-color: $border-color-active;
background: $background-color-base;
}
.#{$class}-is-disabled &,
.ds-input-is-disabled &,
&:disabled {
color: $text-color-disabled;
opacity: $opacity-disabled;
cursor: not-allowed;
}
.#{$class}-has-error & {
.ds-input-has-error & {
border-color: $border-color-danger;
}
}
.#{$class}-size-small {
.ds-input-size-small {
font-size: $font-size-small;
.#{$class} {
font-size: $input-font-size-small;
height: $input-height-small;
padding: $input-padding-vertical-small $space-x-small;
}
}
.#{$class}-size-large {
.ds-input-size-large {
font-size: $font-size-large;
.#{$class} {
font-size: $input-font-size-large;
height: $input-height-large;
padding: $input-padding-vertical-large $space-x-small;
}
}
.#{$class}-icon,
.#{$class}-icon-right {
position: absolute;
@ -71,32 +75,47 @@
width: $input-height;
color: $text-color-softer;
transition: color $duration-short $ease-out;
.#{$class}-has-focus & {
pointer-events: none;
.ds-input-has-focus & {
color: $text-color-base;
}
}
.ds-input-size-small & {
width: $input-height-small;
}
.ds-input-size-large & {
width: $input-height-large;
}
}
.#{$class}-icon-right {
right: 0;
left: auto;
}
.#{$class}-has-icon {
padding-left: $input-height;
.ds-input-size-small & {
padding-left: $input-height-small;
}
.#{$class}-size-small &,
.#{$class}-size-large & {
padding-left: $input-height;
.ds-input-size-large & {
padding-left: $input-height-large;
}
}
.#{$class}-has-icon-right {
padding-right: $input-height;
.#{$class}-size-small &,
.#{$class}-size-large & {
padding-right: $input-height;
.ds-input-size-small & {
padding-right: $input-height-small;
}
}
.ds-input-size-large & {
padding-right: $input-height-large;
}
}
}

View File

@ -0,0 +1,49 @@
/**
* @mixin
*/
export default {
props: {
/**
* Whether the user can select multiple items
*/
multiple: {
type: Boolean,
default: false
}
},
methods: {
selectOption(option) {
const newValue = option.value || option
if (this.multiple) {
this.selectMultiOption(newValue)
} else {
this.input(newValue)
}
},
selectMultiOption(value) {
if (!this.innerValue) {
return this.input([value])
}
const index = this.innerValue.indexOf(value)
if (index < 0) {
return this.input([...this.innerValue, value])
}
this.deselectOption(index)
},
deselectOption(index) {
const newArray = [...this.innerValue]
newArray.splice(index, 1)
this.input(newArray)
},
isSelected(option) {
if (!this.innerValue) {
return false
}
const value = option.value || option
if (this.multiple) {
return this.innerValue.includes(value)
}
return this.innerValue === value
}
}
}

View File

@ -14,9 +14,9 @@
v-if="image || $slots.image">
<!-- @slot Content of the card's image -->
<slot name="image">
<img
:src="image"
v-if="!error"
<img
:src="image"
v-if="!error"
@error="onError" >
</slot>
</div>
@ -36,7 +36,14 @@
</slot>
</header>
<div class="ds-card-content">
<slot />
<template v-if="space">
<ds-space :margin="space">
<slot />
</ds-space>
</template>
<template v-else>
<slot />
</template>
</div>
<footer
class="ds-card-footer"
@ -125,6 +132,14 @@ export default {
hover: {
type: Boolean,
default: false
},
/**
* If you need some spacing you can provide it here like for ds-space
* `xxx-small, xx-small, x-small, small, large, x-large, xx-large, xxx-large`
*/
space: {
type: String,
default: null
}
},
data() {

View File

@ -21,6 +21,23 @@ Set a header and image for the card and provide some content.
</ds-flex>
```
## Space
Need more or less space top and bottom of the card?
Specify with with the `space` prop
```html
<ds-card space="xx-small">
xx-small
</ds-card>
```
```html
<ds-card space="xx-large">
xx-large
</ds-card>
```
## Cards with footer
Most commonly the footer will contain some actions connected to the content.

View File

@ -0,0 +1,93 @@
<template>
<component
:is="tag"
class="ds-chip"
:class="[
`ds-chip-size-${size}`,
`ds-chip-${color}`,
removable && 'ds-chip-removable',
round && 'ds-chip-round'
]"
>
<slot />
<button
v-if="removable"
@click="remove"
class="ds-chip-close">
<ds-icon name="close" />
</button>
</component>
</template>
<script>
/**
* Chips are used to represent small blocks of information.
* Their most common usage is for displaying contacts or tags.
* @version 1.0.0
*/
export default {
name: 'DsChip',
props: {
/**
* The background color used for the chip.
* `medium, inverse, primary, success, warning, danger`
*/
color: {
type: String,
default: 'medium',
validator: value => {
return value.match(/(medium|inverse|primary|success|warning|danger)/)
}
},
/**
* The size used for the text.
* `base, large, small`
*/
size: {
type: String,
default: 'base',
validator: value => {
return value.match(/(base|large|small)/)
}
},
/**
* Whether the chip should be removeable
* `true, false`
*/
removable: {
type: Boolean,
default: false
},
/**
* Whether the chip should be rounded
* `true, false`
*/
round: {
type: Boolean,
default: true
},
/**
* The html element name used for the text.
*/
tag: {
type: String,
default: 'span'
}
},
methods: {
remove() {
/**
* Fires after user clicked the remove button.
*
* @event remove
*/
this.$emit('remove')
}
}
}
</script>
<style lang="scss" src="./style.scss">
</style>
<docs src="./demo.md"></docs>

View File

@ -0,0 +1,62 @@
## Chip colors
Use different colors to emphasize or provide meaning.
```
<ds-chip>Medium</ds-chip>
<ds-chip color="inverse">Inverse</ds-chip>
<ds-chip color="primary">Primary</ds-chip>
<ds-chip color="success">Success</ds-chip>
<ds-chip color="warning">Warning</ds-chip>
<ds-chip color="danger">Danger</ds-chip>
```
## Chip sizes
Use different sizes to create hierarchy (defaults to `base`).
```
<ds-chip size="small">Small</ds-chip>
<ds-chip size="base">Base</ds-chip>
<ds-chip size="large">Large</ds-chip>
```
## Deletable
A chip can be deletable.
```
<template>
<div>
<ds-chip
v-for="(tag, index) in tags"
@remove="removeTag(index)"
removable
:key="tag">
{{ tag }}
</ds-chip>
<ds-chip
v-for="(tag, index) in tags"
@remove="removeTag(index)"
removable
color="primary"
:key="tag">
{{ tag }}
</ds-chip>
</div>
</template>
<script>
export default {
data() {
return {
tags: ['Dog', 'Cat', 'Duck']
}
},
methods: {
removeTag (index) {
this.tags.splice(index, 1)
}
}
}
</script>
```

View File

@ -0,0 +1,81 @@
.ds-chip {
@include reset;
@include stack-space($space-xx-small);
position: relative;
display: inline-block;
font-family: $font-family-text;
line-height: $line-height-base;
padding: $space-xx-small $space-x-small;
border-radius: $border-radius-base;
font-weight: $font-weight-bold;
color: $text-color-base;
background-color: $background-color-softest;
&.ds-chip-removable {
padding-right: $space-x-small + $space-small;
}
}
.ds-chip-inverse {
color: $text-color-inverse;
background-color: $background-color-inverse-softer;
}
.ds-chip-primary {
color: $text-color-primary-inverse;
background-color: $background-color-primary;
}
.ds-chip-success {
color: $text-color-success-inverse;
background-color: $background-color-success;
}
.ds-chip-warning {
color: $text-color-warning-inverse;
background-color: $background-color-warning;
}
.ds-chip-danger {
color: $text-color-danger-inverse;
background-color: $background-color-danger;
}
.ds-chip-round {
border-radius: $border-radius-rounded;
}
.ds-chip-size-base {
font-size: $font-size-small;
}
.ds-chip-size-small {
font-size: $font-size-x-small;
}
.ds-chip-size-large {
font-size: $font-size-base;
}
.ds-chip-close {
@include reset-button;
position: absolute;
right: $space-xx-small;
top: 50%;
transform: translateY(-50%);
display: inline-flex;
align-items: center;
justify-content: center;
font-size: $font-size-x-small;
width: $space-small;
height: $space-small;
border-radius: $border-radius-circle;
//background-color: $background-color-base;
opacity: $opacity-soft;
cursor: pointer;
transition: all $duration-short $ease-out-sharp;
&:hover {
opacity: 1;
}
}

View File

@ -3,6 +3,7 @@
:is="tag"
:aria-label="ariaLabel"
class="ds-icon"
:class="[size && `ds-icon-size-${size}`]"
>
<component
v-if="svgComponent"
@ -40,6 +41,19 @@ export default {
tag: {
type: String,
default: 'span'
},
/**
* Which size should the icon have?
* `xx-small, x-small, small, base, large, x-large, xx-large, xxx-large`
*/
size: {
type: String,
default: null,
validator: value => {
return value.match(
/(xx-small|x-small|small|base|large|x-large|xx-large|xxx-large)/
)
}
}
},
computed: {

View File

@ -17,4 +17,29 @@
// overflow: visible;
// Use this if the icons are build with solids
fill: currentColor
}
}
.ds-icon-size-xx-small {
font-size: $font-size-xx-small
}
.ds-icon-size-x-small {
font-size: $font-size-x-small
}
.ds-icon-size-small {
font-size: $font-size-small
}
.ds-icon-size-base {
font-size: $font-size-base
}
.ds-icon-size-large {
font-size: $font-size-large
}
.ds-icon-size-x-large {
font-size: $font-size-x-large
}
.ds-icon-size-xx-large {
font-size: $font-size-xx-large
}
.ds-icon-size-xxx-large {
font-size: $font-size-xxx-large
}

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>angellist</title>
<path d="M12.813 4c0.312 0.021 0.615 0.118 0.875 0.25 0.521 0.265 0.919 0.67 1.281 1.125 0.725 0.91 1.311 2.103 1.813 3.313 0.207 0.498 0.39 0.985 0.563 1.469 0.109-0.401 0.21-0.808 0.344-1.219 0.391-1.201 0.902-2.395 1.594-3.344 0.346-0.474 0.731-0.895 1.25-1.188s1.174-0.421 1.813-0.281c0.628 0.138 1.091 0.677 1.281 1.156s0.24 0.97 0.25 1.5c0.020 1.060-0.168 2.29-0.406 3.5-0.385 1.96-0.863 3.535-1.063 4.188 0.328 0.248 0.624 0.516 0.844 0.813 1.025 1.382 0.75 3.010 0.75 3.375 0 4.219-1.55 6.731-3.406 8s-3.874 1.344-4.75 1.344c-0.805 0-2.922 0.024-4.938-0.906s-3.906-3.011-3.906-6.563c0-1.078 0.261-1.996 0.906-2.625 0.403-0.392 0.929-0.57 1.469-0.625-0.205-0.548-0.361-1.162-0.281-1.844 0.089-0.757 0.563-1.558 1.344-2.063 0.319-0.206 0.672-0.326 1.031-0.344 0.169-0.008 0.336 0.001 0.5 0.031-0.273-0.768-0.577-1.665-0.844-2.625-0.325-1.173-0.597-2.383-0.625-3.469-0.014-0.543 0.037-1.059 0.219-1.563s0.577-1.017 1.156-1.25c0.303-0.122 0.625-0.177 0.938-0.156zM12.656 5.969c-0.013-0.002-0.018 0.026-0.031 0.031 0.004 0.007-0.006 0.024-0.031 0.094-0.051 0.14-0.104 0.453-0.094 0.844 0.020 0.781 0.229 1.879 0.531 2.969 0.497 1.791 1.081 3.25 1.313 3.813 0.442-0.431 1.082-0.719 1.781-0.719h0.063c-0.255-0.9-0.658-2.135-1.25-3.563-0.465-1.121-1.026-2.178-1.531-2.813-0.253-0.317-0.492-0.526-0.625-0.594-0.066-0.034-0.103-0.060-0.125-0.063zM21.656 6.125c-0.047-0-0.102 0.001-0.156 0.031-0.168 0.095-0.391 0.304-0.625 0.625-0.468 0.641-0.925 1.687-1.281 2.781-0.488 1.498-0.754 2.761-0.906 3.594 0.721 0.094 1.355 0.232 1.906 0.406 0.238-0.82 0.595-2.103 0.906-3.688 0.224-1.139 0.39-2.277 0.375-3.063-0.006-0.332-0.054-0.548-0.094-0.688-0.040 0.001-0.078 0-0.125 0zM16.125 15c-0.248 0-0.319 0.061-0.406 0.156s-0.169 0.254-0.188 0.469c-0.015 0.179 0.007 0.355 0.063 0.5 0.046 0.070 0.080 0.147 0.125 0.219 0.020 0.024 0.040 0.042 0.063 0.063 0.062 0.056 0.14 0.102 0.219 0.125 1.258 0.369 2.844 0.844 2.844 0.844 0.399 0.115 0.723 0.546 0.723 0.961 0 0.444-0.352 0.881-0.785 0.977 0 0-0.565 0.117-1.125 0.469-0.348 0.218-0.665 0.461-0.844 0.813-0.109 0.214-0.156 0.468-0.156 0.781 0 0.866 0.241 1.414 0.469 1.75s0.375 0.406 0.375 0.406l-1.094 1.656s-0.515-0.316-0.938-0.938c-0.189-0.278-0.354-0.651-0.5-1.063-0.079 0.184-0.099 0.39-0.219 0.531-0.466 0.55-1.139 0.906-1.906 0.906-0.74 0-1.409-0.369-1.906-0.813s-0.89-0.987-1.281-1.594l1.688-1.094c0.346 0.537 0.672 0.982 0.938 1.219s0.412 0.281 0.563 0.281c0.124 0 0.312-0.113 0.375-0.188-0.216-0.366-0.428-0.696-0.656-1-0.988-1.312-2.049-2.044-2.656-2.188-0.376-0.089-0.483-0.046-0.594 0.063s-0.313 0.471-0.313 1.219c0 2.907 1.245 4.056 2.75 4.75s3.296 0.719 4.094 0.719c0.727 0 2.304-0.097 3.625-1s2.531-2.589 2.531-6.344c0-0.822 0.143-1.5-0.344-2.156s-1.846-1.5-5.531-1.5zM11.5 15.031c-0.34 0.22-0.376 0.367-0.406 0.625s0.025 0.662 0.188 1.063c0.324 0.802 0.938 1.531 0.938 1.531 0.663 0.506 1.276 1.177 1.875 2l0.063-0.031c-0.196-0.257-0.218-0.129-0.063-0.125s0.414-0.041 0.594-0.125 0.279-0.181 0.313-0.25 0.064-0.147-0.063-0.469c-0.536-1.37-1.376-2.666-2.156-3.438-0.39-0.386-0.765-0.63-1-0.719s-0.239-0.090-0.281-0.063z"></path>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>balance-scale</title>
<path d="M16 5c1.292 0 2.394 0.844 2.813 2h7.188v2h-1.406l0.281 0.5 4 7 0.125 0.25v0.25c0 2.75-2.25 5-5 5s-5-2.25-5-5v-0.25l0.125-0.25 4-7 0.281-0.5h-4.594c-0.304 0.84-0.973 1.509-1.813 1.813v13.188h4v2h-10v-2h4v-13.188c-0.842-0.304-1.507-0.969-1.813-1.813h-4.594l0.281 0.5 4 7 0.125 0.25v0.25c0 2.75-2.251 5-5 5s-5-2.25-5-5v-0.25l0.125-0.25 4-7 0.281-0.5h-1.406v-2h7.188c0.418-1.156 1.521-2 2.813-2zM16 7c-0.564 0-1 0.436-1 1s0.436 1 1 1 1-0.436 1-1-0.436-1-1-1zM8 12.031l-2.281 3.969h4.563zM24 12.031l-2.281 3.969h4.563zM5.25 18c0.402 1.161 1.444 2 2.75 2s2.348-0.839 2.75-2h-5.5zM21.25 18c0.402 1.161 1.444 2 2.75 2s2.348-0.839 2.75-2h-5.5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 820 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>bell</title>
<path d="M15 3c1.105 0 2 0.895 2 2 0 0.085-0.021 0.168-0.031 0.25 3.521 0.924 6.031 4.273 6.031 8.031v8.719c0 0.565 0.435 1 1 1h1v2h-7.188c0.114 0.316 0.188 0.647 0.188 1 0 1.645-1.355 3-3 3s-3-1.355-3-3c0-0.353 0.073-0.684 0.188-1h-7.188v-2h1c0.565 0 1-0.435 1-1v-9c0-3.726 2.574-6.866 6.031-7.75-0.010-0.082-0.031-0.165-0.031-0.25 0-1.105 0.895-2 2-2zM14.563 7c-3.118 0.226-5.563 2.824-5.563 6v9c0 0.353-0.073 0.684-0.188 1h12.375c-0.114-0.316-0.188-0.647-0.188-1v-8.719c0-3.319-2.546-6.183-5.813-6.281-0.064-0.002-0.124-0-0.188 0-0.148 0-0.292-0.011-0.438 0zM15 25c-0.564 0-1 0.436-1 1s0.436 1 1 1 1-0.436 1-1-0.436-1-1-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 793 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>bullhorn</title>
<path d="M28 3.031v9.156c1.156 0.418 2 1.521 2 2.813s-0.844 2.394-2 2.813v9.156l-1.594-1.156s-2.007-1.443-4.875-2.906-6.587-2.906-9.813-2.906h-3.375l1.625 5.719 0.344 1.281h-6.063l-0.219-0.719-2-7-0.031-0.156v-9.125h9.719c3.27 0 6.987-1.412 9.844-2.875s4.844-2.938 4.844-2.938zM26 6.75c-0.82 0.558-1.459 1.064-3.531 2.125-2.929 1.5-6.726 3.050-10.469 3.125v6c3.708 0.073 7.499 1.595 10.438 3.094 2.078 1.060 2.735 1.567 3.563 2.125v-16.469zM4 12v6h6v-6h-6zM4.344 20l1.406 5h1.906l-1.406-5h-1.906z"></path>
</svg>

After

Width:  |  Height:  |  Size: 668 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>gamepad</title>
<path d="M16 7c6.383 0 11.969 2.063 11.969 2.063l0.594 0.219 0.063 0.594 1.344 10.25c0.365 2.835-1.665 5.479-4.5 5.844-2.639 0.34-5.005-1.44-5.625-3.969h-7.688c-0.619 2.529-2.985 4.309-5.625 3.969-2.835-0.365-4.865-3.009-4.5-5.844l1.344-10.25 0.063-0.594 0.594-0.219s5.586-2.063 11.969-2.063zM16 9c-5.486 0-10.007 1.524-10.75 1.781l-1.219 9.625c-0.227 1.763 0.987 3.335 2.75 3.563s3.368-0.987 3.594-2.75l0.031-0.344 0.125-0.875h10.938l0.125 0.875 0.031 0.344c0.227 1.763 1.832 2.977 3.594 2.75 1.763-0.227 2.977-1.8 2.75-3.563l-1.219-9.625c-0.743-0.258-5.264-1.781-10.75-1.781zM9 12h2v2h2v2h-2v2h-2v-2h-2v-2h2v-2zM22 12c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM20 14c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM24 14c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM22 16c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>graduation-cap</title>
<path d="M16 6.781l0.313 0.094 15.344 5.125-2.844 0.938-2.813 0.938v5.125c0 0.82-0.499 1.5-1.094 1.969s-1.332 0.798-2.219 1.094c-1.773 0.591-4.112 0.938-6.688 0.938s-4.914-0.346-6.688-0.938c-0.887-0.296-1.624-0.625-2.219-1.094s-1.094-1.149-1.094-1.969v-5.125l-2-0.656v8.063c0.597 0.346 1 0.979 1 1.719 0 1.105-0.895 2-2 2s-2-0.895-2-2c0-0.74 0.403-1.373 1-1.719v-8.75l-1.656-0.531 2.844-0.938 12.5-4.188zM16 8.875l-9.375 3.125 9.375 3.125 9.375-3.125zM8 14.563v4.438c0 0.009-0.004 0.126 0.313 0.375s0.883 0.565 1.625 0.813c1.484 0.495 3.667 0.813 6.063 0.813s4.579-0.318 6.063-0.813c0.742-0.247 1.309-0.563 1.625-0.813s0.313-0.366 0.313-0.375v-4.438l-7.688 2.563-0.313 0.094-0.313-0.094z"></path>
</svg>

After

Width:  |  Height:  |  Size: 865 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>leaf</title>
<path d="M25.031 4l0.313 1.094s1.656 5.616 1.656 13.438c0 3.995-0.921 6.637-2.344 8.281s-3.306 2.188-4.844 2.188c-1.728 0-3.206-0.784-4.375-1.594s-2.165-1.731-2.344-1.844l1.063-1.688c0.704 0.445 1.398 1.177 2.406 1.875s2.173 1.25 3.25 1.25c1.083 0 2.301-0.33 3.313-1.5s1.875-3.282 1.875-6.969c0-6.501-1.022-10.659-1.344-11.875-3.442 1.276-7.451 1.856-10.688 3-1.789 0.632-3.284 1.437-4.313 2.563s-1.656 2.577-1.656 4.781c0 1.938 1.058 3.143 2.219 3.969 0.603 0.429 1.187 0.698 1.625 0.875 1.72-2.744 4.356-6.157 8.438-10.531l1.438 1.375c-6.808 7.295-9.428 11.855-10.375 14.625-0.473 1.385-0.53 2.32-0.5 3s0.217 1.058 0.156 1.781l-2-0.188c-0.002 0.020-0.116-0.597-0.156-1.5s0.047-2.151 0.594-3.75c0.303-0.885 0.756-1.918 1.375-3.063-0.512-0.228-1.12-0.551-1.75-1-1.477-1.051-3.063-2.897-3.063-5.594 0-2.605 0.833-4.643 2.188-6.125s3.168-2.402 5.125-3.094c3.913-1.384 8.509-1.908 11.688-3.313z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>mouse-pointer</title>
<path d="M9 2.594l1.719 1.688 16.125 16.156-7.094 0.875 1.844 3.625 0.438 0.906-0.875 0.438-4 2.063-0.438-0.906-2.031-4.031-4.031 3.375-1.656 1.375v-25.563zM11 7.438v16.406l4.313-3.625 0.594 1.125 2.156 4.313 1.313-0.688-2.063-4-0.656-1.281 1.406-0.188 4.5-0.531z"></path>
</svg>

After

Width:  |  Height:  |  Size: 440 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>paint-brush</title>
<path d="M24.813 4.031c0.837 0 1.648 0.335 2.281 0.969 1.267 1.267 1.267 3.327 0 4.594v0.031l-12.688 12.5-0.5 0.469c-0.124 0.793-0.46 1.572-1.063 2.188l-0.031 0.031c-1.318 1.318-3.898 3.188-7.813 3.188h-1.844l1-1.563c0.967-1.474 1.37-2.804 1.688-4s0.479-2.31 1.313-3.219c0.565-0.616 1.282-0.985 2.031-1.125l0.625-0.594 12.688-12.5c0.633-0.633 1.476-0.969 2.313-0.969zM24.813 6c-0.313 0-0.64 0.14-0.906 0.406l-9.063 8.906 1.813 1.813 9.031-8.938c0.533-0.533 0.533-1.248 0-1.781-0.267-0.267-0.562-0.406-0.875-0.406zM13.406 16.719l-1.5 1.469 1.813 1.813 1.5-1.469zM9.969 20.031c-0.506-0.014-0.997 0.153-1.344 0.531-0.267 0.291-0.511 1.152-0.844 2.406-0.216 0.814-0.55 1.794-1.031 2.844 2.249-0.421 3.787-1.537 4.656-2.406 0.827-0.827 0.808-2.069 0.031-2.781-0.417-0.383-0.963-0.579-1.469-0.594z"></path>
</svg>

After

Width:  |  Height:  |  Size: 966 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>paw</title>
<path d="M12.5 5c1.069 0 2.002 0.608 2.594 1.438s0.906 1.903 0.906 3.063-0.314 2.233-0.906 3.063-1.525 1.438-2.594 1.438-2.002-0.608-2.594-1.438-0.906-1.903-0.906-3.063 0.314-2.233 0.906-3.063 1.525-1.438 2.594-1.438zM16 9.5c0-1.159 0.314-2.233 0.906-3.063s1.525-1.438 2.594-1.438 2.002 0.608 2.594 1.438 0.906 1.903 0.906 3.063-0.314 2.233-0.906 3.063-1.525 1.438-2.594 1.438-2.002-0.608-2.594-1.438-0.906-1.903-0.906-3.063zM12.5 7c-0.312 0-0.656 0.156-0.969 0.594s-0.531 1.133-0.531 1.906 0.219 1.469 0.531 1.906 0.657 0.594 0.969 0.594 0.656-0.156 0.969-0.594 0.531-1.133 0.531-1.906-0.219-1.469-0.531-1.906-0.657-0.594-0.969-0.594zM19.5 7c-0.312 0-0.656 0.156-0.969 0.594s-0.531 1.133-0.531 1.906 0.219 1.469 0.531 1.906 0.657 0.594 0.969 0.594 0.656-0.156 0.969-0.594 0.531-1.133 0.531-1.906-0.219-1.469-0.531-1.906-0.657-0.594-0.969-0.594zM7.5 12c1.069 0 2.002 0.608 2.594 1.438s0.906 1.903 0.906 3.063-0.314 2.233-0.906 3.063-1.525 1.438-2.594 1.438-2.002-0.608-2.594-1.438-0.906-1.903-0.906-3.063 0.314-2.233 0.906-3.063 1.525-1.438 2.594-1.438zM24.5 12c1.069 0 2.002 0.608 2.594 1.438s0.906 1.903 0.906 3.063-0.314 2.233-0.906 3.063-1.525 1.438-2.594 1.438-2.002-0.608-2.594-1.438-0.906-1.903-0.906-3.063 0.314-2.233 0.906-3.063 1.525-1.438 2.594-1.438zM7.5 14c-0.312 0-0.656 0.156-0.969 0.594s-0.531 1.133-0.531 1.906 0.219 1.469 0.531 1.906 0.657 0.594 0.969 0.594 0.656-0.156 0.969-0.594 0.531-1.133 0.531-1.906-0.219-1.469-0.531-1.906-0.657-0.594-0.969-0.594zM24.5 14c-0.312 0-0.656 0.156-0.969 0.594s-0.531 1.133-0.531 1.906 0.219 1.469 0.531 1.906 0.657 0.594 0.969 0.594 0.656-0.156 0.969-0.594 0.531-1.133 0.531-1.906-0.219-1.469-0.531-1.906-0.657-0.594-0.969-0.594zM16 16c1.339 0 2.29 0.861 2.75 1.625s0.73 1.417 0.969 1.656c0.142 0.142 1.126 0.562 2.125 1.094 0.5 0.266 1.012 0.582 1.438 1.094s0.719 1.238 0.719 2.031c0 1.921-1.579 3.5-3.5 3.5-0.867 0-1.77-0.279-2.656-0.531s-1.844-0.469-1.844-0.469-0.957 0.216-1.844 0.469-1.79 0.531-2.656 0.531c-1.921 0-3.5-1.579-3.5-3.5 0-0.813 0.291-1.538 0.719-2.063s0.935-0.869 1.438-1.125c1.006-0.513 1.97-0.877 2.125-1.031 0.264-0.264 0.544-0.897 1-1.656s1.385-1.625 2.719-1.625zM16 18c-0.667 0-0.737 0.135-1.031 0.625s-0.514 1.358-1.25 2.094c-0.845 0.845-1.881 0.995-2.625 1.375-0.372 0.19-0.677 0.39-0.844 0.594s-0.25 0.41-0.25 0.813c0 0.841 0.659 1.5 1.5 1.5 0.29 0 1.224-0.221 2.094-0.469s1.59-0.531 2.406-0.531c0.817 0 1.536 0.284 2.406 0.531s1.803 0.469 2.094 0.469c0.841 0 1.5-0.659 1.5-1.5 0-0.353-0.077-0.542-0.25-0.75s-0.464-0.423-0.844-0.625c-0.759-0.404-1.801-0.583-2.625-1.406-0.727-0.727-0.952-1.568-1.25-2.063s-0.37-0.656-1.031-0.656z"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>recycle</title>
<path d="M16 3.969c1.055 0 2.118 0.517 2.75 1.5l3.125 5.063 1.438-0.844v5.313l-4.625-2.594 1.5-0.875-3.125-5c-0.53-0.824-1.553-0.806-2.094 0l-2.813 4.594-1.719-1.031 2.813-4.625c0.632-0.983 1.695-1.5 2.75-1.5zM10.406 12.094v5.313l-1.531-0.938-2.625 4.25v0.031l-0.031 0.031c-0.665 0.968 0.015 2.219 1.281 2.219h5.5v2h-5.5c-2.712 0-4.409-3.084-2.938-5.313 0.012-0.018-0.012-0.045 0-0.063l0.031 0.031 2.563-4.219-1.25-0.75zM25.063 15.656l2.5 4v0.031c1.36 2.312-0.332 5.313-2.969 5.313h-5.594v2l-4.906-3 4.906-3v2h5.594c1.163 0 1.89-1.193 1.25-2.281l-2.5-4z"></path>
</svg>

After

Width:  |  Height:  |  Size: 724 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>toggle-off</title>
<path d="M9 7h14c4.959 0 9 4.041 9 9s-4.041 9-9 9h-14c-0.94 0-1.835-0.137-2.688-0.406-0.282-0.088-0.543-0.198-0.813-0.313-2.413-1.023-4.298-3.072-5.094-5.594-0.003-0.009 0.003-0.022 0-0.031-0.264-0.845-0.406-1.727-0.406-2.656 0-0.94 0.137-1.835 0.406-2.688 0.088-0.282 0.198-0.543 0.313-0.813 1.023-2.413 3.072-4.298 5.594-5.094 0.282-0.088 0.582-0.159 0.875-0.219 0.585-0.12 1.193-0.188 1.813-0.188zM9 9c-3.635 0-6.612 2.743-6.969 6.281-0.024 0.236-0.031 0.476-0.031 0.719 0 3.878 3.123 7 7 7s7-3.122 7-7-3.122-7-7-7zM14.625 9c2.051 1.652 3.375 4.171 3.375 7s-1.324 5.348-3.375 7h8.375c3.878 0 7-3.122 7-7s-3.122-7-7-7h-8.375z"></path>
</svg>

After

Width:  |  Height:  |  Size: 801 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>toggle-on</title>
<path d="M9 7h14c4.959 0 9 4.041 9 9s-4.041 9-9 9h-14c-4.962 0-9-4.037-9-9s4.038-9 9-9zM23 9c-3.878 0-7 3.122-7 7s3.122 7 7 7 7-3.122 7-7-3.122-7-7-7z"></path>
</svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>tree</title>
<path d="M16 3.594l0.719 0.688 5.938 5.969 1 0.969-1.281 0.625s-1.015 0.366-2.438 0.688l4.406 4.406 1 0.969-1.25 0.625s-1.079 0.304-1.625 0.5l3.594 3.594 0.969 1-1.219 0.625s-2.462 1.176-6.813 1.594v3.156h-2v-3.031c-0.335 0.011-0.648 0.031-1 0.031s-0.666-0.021-1-0.031v3.031h-2v-3.156c-4.343-0.417-6.781-1.594-6.781-1.594l-1.25-0.625 0.969-1 3.594-3.594c-0.546-0.196-1.625-0.5-1.625-0.5l-1.25-0.625 1-0.969 4.406-4.406c-1.422-0.322-2.438-0.688-2.438-0.688l-1.281-0.625 1-0.969 5.938-5.969zM16 6.438l-4 3.969c0.593 0.199 0.714 0.356 2.188 0.5l1.813 0.188 1.813-0.188c1.474-0.144 1.594-0.301 2.188-0.5zM16 11.438l-1.188 1.156-4.594 4.594c0.465 0.163 0.453 0.219 1.406 0.406l1.844 0.375-1.344 1.313-3.625 3.656c1.287 0.457 3.459 1.063 7.5 1.063 4.077 0 6.258-0.607 7.531-1.063l-3.656-3.656-1.344-1.313 1.844-0.375c0.953-0.188 0.941-0.243 1.406-0.406l-4.594-4.594z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>university</title>
<path d="M16 3.906l12.375 5.156 0.625 0.281v2.656h-2v11h2v5h-26v-5h2v-11h-2v-2.656l0.625-0.281 12-5zM16 6.094l-9.375 3.906h18.75zM7 12v11h2v-11h-2zM11 12v11h2v-11h-2zM15 12v11h2v-11h-2zM19 12v11h2v-11h-2zM23 12v11h2v-11h-2zM5 25v1h22v-1h-22z"></path>
</svg>

After

Width:  |  Height:  |  Size: 415 B

View File

@ -1,23 +1,27 @@
/* FORM VARIABLES / MIXINS
--------------------------------------------- */
$input-font-size-base: $font-size-base;
$input-border-size: $border-size-base;
$input-padding-vertical: $space-x-small;
$input-height: calc(
#{$font-size-base * $line-height-base} + #{($input-padding-vertical + $input-border-size) * 2}
);
$input-padding-vertical-small: $space-xx-small;
$input-font-size-small: $font-size-base;
$input-padding-vertical-small: $space-xxx-small;
$input-height-small: calc(
#{$font-size-small * $line-height-base} + #{($input-padding-vertical-small + $input-border-size) * 2}
#{$font-size-base * $line-height-base} + #{($input-padding-vertical-small + $input-border-size) * 2}
);
$input-font-size-large: $font-size-large;
$input-padding-vertical-large: $space-x-small;
$input-height-large: calc(
#{$font-size-large * $line-height-base} + #{($input-padding-vertical-large + $input-border-size) * 2}
#{$input-font-size-large * $line-height-base} + #{($input-padding-vertical-large + $input-border-size) * 2}
);
// $input-font-size-large: $font-size-x-large;
$input-padding-vertical-x-large: $space-small;
$input-height-x-large: calc(
#{$font-size-x-large * $line-height-base} + #{($input-padding-vertical-x-large + $input-border-size) * 2}
#{$input-font-size-large * $line-height-base} + #{($input-padding-vertical-x-large + $input-border-size) * 2}
);

View File

@ -2,15 +2,11 @@
--------------------------------------------- */
/* AUTO SCALING FOR TYPE WITH MIN/MAX SIZES
@param {Number} $responsive - Viewport-based size
@param {Number} $min - Minimum font size (px)
@param {Number} $max - Maximum font size (px) (optional)
@param {Number} $fallback - Fallback for viewport-based units (optional)
@example SCSS - 5vw size, 35px min & 150px max size + 50px fallback:
@include responsive-font(5vw, 35px, 150px, 50px);
*/
@mixin responsive-font($responsive, $min, $max: false, $fallback: false) {
@ -44,6 +40,32 @@
margin: 0;
}
@mixin reset-list {
@include reset;
list-style: none;
}
@mixin reset-button {
@include reset;
border: 0;
width: auto;
overflow: visible;
background: transparent;
color: inherit;
font: inherit;
line-height: normal;
outline: none;
font-smoothing: inherit;
-webkit-font-smoothing: inherit;
-moz-osx-font-smoothing: inherit;
-webkit-appearance: none;
&::-moz-focus-inner {
border: 0;
padding: 0;
}
}
@mixin clearfix {
&:before, &:after {
display: table;
@ -104,4 +126,4 @@
border-bottom-left-radius: $size;
border-bottom-right-radius: $size;
}
}
}

View File

@ -291,6 +291,10 @@ props:
value: *color-neutral-80
category: border-color
- name: border-color-light
value: *color-neutral-90
category: border-color
- name: border-color-active
value: *color-primary
category: border-color

View File

@ -17,7 +17,7 @@ props:
- name: font-size-base
value: "1rem"
- name: font-size-body
value: "16px"
value: "15px"
- name: font-size-small
value: "0.8rem"
- name: font-size-x-small

View File

@ -6,6 +6,8 @@
props:
- name: z-index-modal
value: "9999"
- name: z-index-dropdown
value: "8888"
- name: z-index-page-submenu
value: "2500"
- name: z-index-page-header

View File

@ -693,6 +693,15 @@
vue-apollo "^3.0.0-beta.25"
vue-cli-plugin-apollo "^0.17.0"
"@nuxtjs/axios@^5.3.4":
version "5.3.4"
resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.3.4.tgz#f04c16188ec967606e265ae8e4c6ee0fcc22d0af"
dependencies:
"@nuxtjs/proxy" "^1.3.0"
axios "^0.18.0"
axios-retry "^3.1.1"
consola "^1.4.4"
"@nuxtjs/babel-preset-app@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@nuxtjs/babel-preset-app/-/babel-preset-app-0.7.0.tgz#b208a95e0a053259c29b99a9e4ca9ea2604dbdd2"
@ -732,6 +741,13 @@
esm "^3.0.79"
node-fetch "^2.2.0"
"@nuxtjs/proxy@^1.3.0":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@nuxtjs/proxy/-/proxy-1.3.1.tgz#7d76179aff321491f126d6560434579a4dc7a89a"
dependencies:
consola "^1.4.4"
http-proxy-middleware "^0.19.0"
"@nuxtjs/youch@^4.2.3":
version "4.2.3"
resolved "https://registry.yarnpkg.com/@nuxtjs/youch/-/youch-4.2.3.tgz#36f8b22df5a0efaa81373109851e1d857aca6bed"
@ -1459,6 +1475,19 @@ aws4@^1.6.0, aws4@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
axios-retry@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.1.1.tgz#88d2971f671a9023b21d887c5dcac6c54f332cde"
dependencies:
is-retry-allowed "^1.1.0"
axios@^0.18.0:
version "0.18.0"
resolved "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
dependencies:
follow-redirects "^1.3.0"
is-buffer "^1.1.5"
babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@ -1508,21 +1537,6 @@ babel-plugin-transform-vue-jsx@^4.0.1:
dependencies:
esutils "^2.0.2"
babel-polyfill@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
dependencies:
babel-runtime "^6.26.0"
core-js "^2.5.0"
regenerator-runtime "^0.10.5"
babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
babylon@7.0.0-beta.44:
version "7.0.0-beta.44"
resolved "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d"
@ -2138,6 +2152,15 @@ consola@^1.4.3:
lodash "^4.17.5"
std-env "^1.1.0"
consola@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/consola/-/consola-1.4.4.tgz#cf5eda375c0e99df8970cc8f5e98be023da24ce0"
dependencies:
chalk "^2.3.2"
figures "^2.0.0"
lodash "^4.17.5"
std-env "^1.1.0"
console-browserify@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
@ -2195,7 +2218,7 @@ copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7:
core-js@^2.5.7:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
@ -2515,6 +2538,12 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
ms "2.0.0"
debug@^3.1.0:
version "3.2.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.5.tgz#c2418fbfd7a29f4d4f70ff4cea604d4b64c46407"
@ -3007,7 +3036,7 @@ event-stream@~3.3.0:
stream-combiner "^0.2.2"
through "^2.3.8"
eventemitter3@^3.1.0:
eventemitter3@^3.0.0, eventemitter3@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
@ -3289,6 +3318,12 @@ flush-write-stream@^1.0.0:
inherits "^2.0.1"
readable-stream "^2.0.4"
follow-redirects@^1.0.0, follow-redirects@^1.3.0:
version "1.5.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.9.tgz#c9ed9d748b814a39535716e531b9196a845d89c6"
dependencies:
debug "=3.1.0"
for-in@^0.1.3:
version "0.1.8"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
@ -3736,6 +3771,23 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
http-proxy-middleware@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.0.tgz#40992b5901dc44bc7bc3795da81b0b248eca02d8"
dependencies:
http-proxy "^1.17.0"
is-glob "^4.0.0"
lodash "^4.17.10"
micromatch "^3.1.10"
http-proxy@^1.17.0:
version "1.17.0"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a"
dependencies:
eventemitter3 "^3.0.0"
follow-redirects "^1.0.0"
requires-port "^1.0.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@ -4089,7 +4141,7 @@ is-resolvable@^1.0.0, is-resolvable@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
is-retry-allowed@^1.0.0:
is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
@ -6278,11 +6330,7 @@ regenerate@^1.2.1, regenerate@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
regenerator-runtime@^0.10.5:
version "0.10.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1:
regenerator-runtime@^0.11.1:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
@ -6460,6 +6508,10 @@ require-uncached@^1.0.3:
caller-path "^0.1.0"
resolve-from "^1.0.0"
requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"