-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(kviewswitcher): update k-view-switcher for vue 3 (#557)
- Loading branch information
1 parent
f0c15a7
commit 5c5909c
Showing
6 changed files
with
373 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
--- | ||
pageClass: table-docs | ||
turtleOptions: | ||
headers: | ||
- key: profile | ||
hideLabel: true | ||
- label: Name | ||
key: name | ||
- label: Age | ||
key: age | ||
- label: Color | ||
key: color | ||
--- | ||
|
||
# View Switcher | ||
|
||
**KViewSwitcher** Is used to toggle list views to grid views. | ||
|
||
<KComponent :data="{ currentView: 'table' }" v-slot="{ data }"> | ||
<KViewSwitcher :view="data.currentView" @view-changed="(view) => data.currentView = view"/> | ||
</KComponent> | ||
|
||
## Props | ||
|
||
### view | ||
|
||
The current view of your UI, one of `table` or `grid`. The button will show icons for the opposite. For example, if your data is currently in a list/table, passing `list` will render the grid icon. | ||
|
||
<KComponent :data="{ currentView: 'grid' }" v-slot="{ data }"> | ||
<div> | ||
<KCard class="mb-4"> | ||
<template v-slot:body>{{ data }}</template> | ||
</KCard> | ||
<KViewSwitcher :view="data.currentView" @view-changed="(view) => data.currentView = view"/> | ||
</div> | ||
</KComponent> | ||
|
||
> The `KComponent` component is used in this example to create state. | ||
```vue | ||
<KComponent :data="{ currentView: 'grid' }" v-slot="{ data }"> | ||
<div> | ||
<KCard class="mb-4"> | ||
<template v-slot:body>{{ data }}</template> | ||
</KCard> | ||
<KViewSwitcher | ||
:view="data.currentView" | ||
@view-changed="(view) => data.currentView = view"/> | ||
</div> | ||
</KComponent> | ||
``` | ||
|
||
## Usage | ||
|
||
`KViewSwitcher` will emit the new view on click. This then allows you to change the UI to the new view. The button will also toggle to the opposite view for users to switch back. | ||
|
||
<KComponent :data="{ currentView: 'table', turtles: [{ name: 'Leonardo', age: 34, color: 'blue' }, { name: 'Michelangelo', age: 32, color: 'orange' }, { name: 'Raphael', age: 32, color: 'red' }, { name: 'Donatello', age: 29, color: 'purple' }] }" v-slot="{ data }"> | ||
<div> | ||
<div class="d-flex align-items-center justify-content-between mb-4"> | ||
<h3>Teenage Mutant Ninja Turtles</h3> | ||
<KViewSwitcher | ||
:view="data.currentView" | ||
@view-changed="(view) => data.currentView = view"/> | ||
</div> | ||
<div v-if="data.currentView === 'table'"> | ||
<KTable | ||
:hasHover="false" | ||
:hasSideBorder="false" | ||
:options="{ headers: $frontmatter.turtleOptions.headers, data: data.turtles }"> | ||
<template v-slot:profile="{row}"> | ||
<img class="profile-pic" :src="getTurtlePic(row.name)" width="75" /> | ||
</template> | ||
</KTable> | ||
</div> | ||
<div | ||
v-if="data.currentView === 'grid'" | ||
class="card-view"> | ||
<KCard | ||
v-for="turtle in data.turtles" | ||
:key="turtle.name"> | ||
<template v-slot:body> | ||
<div class="mb-2"><strong>{{ turtle.name }}</strong></div> | ||
<div class="mb-2"> | ||
<img class="profile-pic" :src="getTurtlePic(turtle.name)" width="100" /> | ||
</div> | ||
<div class="mb-2"> | ||
<KBadge :background-color="turtle.color" color="var(--white)">{{ turtle.color }}</KBadge> | ||
</div> | ||
<div><strong>Age: </strong>{{ turtle.age }}</div> | ||
</template> | ||
</KCard> | ||
</div> | ||
</div> | ||
</KComponent> | ||
|
||
<script lang="ts"> | ||
import { defineComponent } from 'vue' | ||
|
||
export default defineComponent({ | ||
methods: { | ||
getTurtlePic (name) { | ||
return `https://nick-intl.mtvnimages.com/uri/mgid:file:gsp:kids-assets:/nick/polls/images/tmnt-poll-crown-the-pizza-king-${name.toLowerCase()}.jpg?quality=0.75&height=150&width=150&crop=true` | ||
} | ||
} | ||
}) | ||
</script> | ||
|
||
<style lang="scss"> | ||
.table-docs .k-table { | ||
display: table; | ||
th, tr, td { | ||
border: unset; | ||
} | ||
} | ||
|
||
.profile-pic { | ||
border-radius: 50%; | ||
object-fit: center; | ||
overflow: hidden; | ||
} | ||
|
||
.card-view { | ||
display: grid; | ||
grid-template-columns: repeat(4, 1fr); | ||
grid-gap: 1rem; | ||
text-align: center; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Import types for custom commands | ||
/// <reference types="../../cypress/support" /> | ||
|
||
import { mount } from '@cypress/vue' | ||
import KViewSwitcher from '@/components/KViewSwitcher/KViewSwitcher.vue' | ||
|
||
describe('KViewSwitcher', () => { | ||
it('toggles view when clicked', async () => { | ||
mount(KViewSwitcher, { | ||
props: { | ||
view: 'table', | ||
}, | ||
}) | ||
|
||
cy.get('.view-switch-button').should('have.class', 'table') | ||
cy.get('.view-switch-button').click().then(() => { | ||
cy.wrap(Cypress.vueWrapper.emitted()).should('have.property', 'view-changed') | ||
// cy.get('.view-switch-button').should('have.class', 'grid') | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
|
||
<template> | ||
<KButton | ||
:is-rounded="false" | ||
:class="[view, { paused: isPaused }]" | ||
:title="`Toggle to ${view === 'table' ? 'grid' : 'table'} view`" | ||
size="small" | ||
appearance="outline" | ||
class="k-view-switcher view-switch-button non-visual-button" | ||
@click="toggleView" | ||
> | ||
<div class="icon"> | ||
<div class="dots"> | ||
<i | ||
v-for="i in 4" | ||
:key="i" | ||
/> | ||
</div> | ||
<div class="lines"> | ||
<i | ||
v-for="i in 4" | ||
:key="i" | ||
/> | ||
</div> | ||
</div> | ||
</KButton> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, ref } from 'vue' | ||
import KButton from '@/components/KButton/KButton.vue' | ||
export default defineComponent({ | ||
name: 'KViewSwitcher', | ||
components: { KButton }, | ||
props: { | ||
view: { | ||
type: String, | ||
default: 'table', | ||
required: true, | ||
validator: (val: string): boolean => ['table', 'grid'].includes(val), | ||
}, | ||
}, | ||
emits: ['view-changed'], | ||
setup(props, { emit }) { | ||
const isPaused = ref(true) | ||
const toggleView = (): void => { | ||
// Removed paused animations | ||
isPaused.value = false | ||
// Emit new view | ||
emit('view-changed', props.view === 'table' ? 'grid' : 'table') | ||
} | ||
return { | ||
isPaused, | ||
toggleView, | ||
} | ||
}, | ||
}) | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
@import '@/styles/variables'; | ||
// Originally forked and modified from https://codepen.io/aaroniker/pen/dyoKeMP | ||
.view-switch-button { | ||
--KButtonPaddingY: 6px; | ||
--KButtonPaddingX: 6px; | ||
--KButtonSecondaryHover: var(--white); | ||
--KButtonSecondaryHoverBorder: var(--blue-300); | ||
--KButtonSecondaryFocus: none; | ||
transform: scale(var(--scale, 1)) translateZ(0); | ||
&.paused .icon i { | ||
animation-duration: 0s; | ||
} | ||
.icon { | ||
width: 1.5rem; | ||
height: 1.5rem; | ||
position: relative; | ||
i { | ||
position: absolute; | ||
left: var(--left, 4px); | ||
top: var(--top, 4px); | ||
display: block; | ||
border-radius: 2px; | ||
width: var(--width, 7px); | ||
height: var(--height, 7px); | ||
background-color: var(--grey-500); | ||
animation: var(--name, var(--dots-name, none)) var(--duration, var(--dots-duration, .5s)) var(--easing, var(--dots-easing, linear)) forwards var(--delay, var(--dots-delay, 0s)); | ||
transition: background-color 200ms ease; | ||
} | ||
.dots i { | ||
&:nth-child(1) { | ||
--x-middle: -8px; | ||
--y-middle: 10px; | ||
--x-end: -2px; | ||
--y-end: 12px; | ||
--x-back: 10px; | ||
--y-back: 7px; | ||
--x-back-end: 9px; | ||
--y-back-end: 0; | ||
} | ||
&:nth-child(2) { | ||
--left: 13px; | ||
--x-middle: -12px; | ||
--y-middle: 5px; | ||
--x-end: -11px; | ||
--y-end: 7px; | ||
--x-back: -3px; | ||
--y-back: 1px; | ||
--x-back-end: -9px; | ||
--y-back-end: 0; | ||
} | ||
&:nth-child(3) { | ||
--top: 13px; | ||
--x-middle: 4px; | ||
--y-middle: -5px; | ||
--x-end: -2px; | ||
--y-end: -7px; | ||
--x-back: -5px; | ||
--y-back: 0px; | ||
--x-back-end: 9px; | ||
--y-back-end: 0; | ||
} | ||
&:nth-child(4) { | ||
--left: 13px; | ||
--top: 13px; | ||
--x-middle: 0; | ||
--y-middle: -10px; | ||
--x-end: -11px; | ||
--y-end: -12px; | ||
--x-back: -14px; | ||
--y-back: -8px; | ||
--x-back-end: -9px; | ||
--y-back-end: 0; | ||
} | ||
} | ||
.lines { | ||
--name: var(--lines-name, none); | ||
--duration: var(--lines-duration, 0.15s); | ||
--easing: var(--lines-easing, linear); | ||
--delay: var(--lines-delay, 0s); | ||
i { | ||
--left: 9px; | ||
--top: 3px; | ||
--height: 2px; | ||
--width: 11px; | ||
transform-origin: 0 50%; | ||
transform: translateY(20%) translateZ(0) scaleX(0); | ||
&:nth-child(2) { --top: 8px; } | ||
&:nth-child(3) { --top: 13px; } | ||
&:nth-child(4) { --top: 18px; } | ||
&:nth-child(3), | ||
&:nth-child(4) { transform-origin: 100% 50%; } | ||
} | ||
} | ||
} | ||
&.table { | ||
--dots-name: back; | ||
--lines-name: scale-down; | ||
.lines i { | ||
transform-origin: 0 50%; | ||
&:nth-child(3), | ||
&:nth-child(4) { transform-origin: 100% 50%; } | ||
} | ||
} | ||
&.grid { | ||
--dots-name: move; | ||
--lines-name: scale; | ||
--lines-duration: 0.15s; | ||
--lines-delay: 0.3s; | ||
.lines i { | ||
transform-origin: 100% 50%; | ||
&:nth-child(3), | ||
&:nth-child(4) { transform-origin: 0 50%; } | ||
} | ||
} | ||
} | ||
</style> | ||
|
||
<style lang="scss"> | ||
// @keyframes animations need to be un-scoped | ||
.k-view-switcher { | ||
@keyframes move { | ||
50% { transform: translate(var(--x-middle, 0), var(--y-middle, 0)) scale(.4); } | ||
100% { transform: translate(var(--x-end, 0), var(--y-end, 0)) scale(.4); } | ||
} | ||
@keyframes back { | ||
0%, | ||
15% { transform: translate(var(--x-end, 0), var(--y-end, 0)) scale(.4); } | ||
50% { transform: translate(var(--x-back, 0), var(--y-back, 0)) scale(.5); } | ||
100% { transform: translate(var(--x-back-end, 0), var(--y-back-end, 0)) scale(1); } | ||
} | ||
@keyframes scale { | ||
100% { transform: translateY(20%) translateZ(0) scaleX(1); } | ||
} | ||
@keyframes scale-down { | ||
0% { transform: translateY(20%) translateZ(0) scaleX(1); } | ||
100% { transform: translateY(20%) translateZ(0) scaleX(0); } | ||
} | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters