Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a Color Selector Control #30 #574

Merged
merged 18 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions examples/svelte3/src/ColorButton.story.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script lang="ts">
import { logEvent } from 'histoire/client'
import type { Hst } from '@histoire/plugin-svelte'
import ColorButton from './ColorButton.svelte'

export let Hst: Hst

let disabled = false
let size = 'medium'
let colorselect = "#000000"

let source;

$: {
source = `<ColorButton`;
if (disabled) {
source += ` disabled`;
}
source += `>Click me !</ColorButton>`;
}
</script>

<Hst.Story title="ColorButton" {source}>
<ColorButton {disabled} {colorselect} on:click={event => logEvent('click', event)}>
Click me!
</ColorButton>
<div style="margin-top: 6px;">
<label>
<input type="checkbox" bind:checked={disabled} >
Disabled
</label>
</div>

<svelte:fragment slot="controls">
<Hst.Checkbox
bind:value={disabled}
title="Disabled"
/>
<Hst.Select
bind:value={size}
options={['small', 'medium', 'large']}
title="Size"
/>
<Hst.ColorSelect
bind:value={colorselect}
title="Background Color"
/>
<pre>{JSON.stringify({ disabled, size }, null, 2)}</pre>
</svelte:fragment>
</Hst.Story>

<style>
pre {
padding: 8px;
background: rgba(0, 0, 0, .1);
border-radius: 4px;
margin: 8px;
font-size: 0.8rem;
}
</style>
24 changes: 24 additions & 0 deletions examples/svelte3/src/ColorButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
export let disabled: boolean = false
export let colorselect = "#d5bebe"
</script>

<button class:disabled class={"button"} style="background: {colorselect}" on:click>
<slot />
</button>

<style>
button {
color: white;
border-radius: 6px;
cursor: pointer;
transition: opacity .15s;
padding: 7px 16px;
font-size: 24px;
}

button.disabled {
opacity: 0.5;
}
</style>

8 changes: 7 additions & 1 deletion examples/vue3/cypress/integration/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('Controls', () => {

it('HstText', () => {
getIframeBody().find('.state-output').contains('"text": "Hello"')
cy.get('[data-test-id="story-controls"] input[type="text"]').clear().type('Foo')
cy.get('[data-test-id="story-controls"]').contains('HstText').clear().type('Foo')
getIframeBody().find('.state-output').contains('"text": "Foo"')
})

Expand All @@ -33,4 +33,10 @@ describe('Controls', () => {
cy.get('[data-test-id="story-controls"] textarea').clear().type('Meow meow meow')
getIframeBody().find('.state-output').contains('"longText": "Meow meow meow"')
})

it('HstColorSelect', () => {
getIframeBody().find('.state-output').contains('"colorselect": "#000000"')
cy.get('[data-test-id="story-controls"]').contains('HstColorSelect').clear().type('#ffffff')
getIframeBody().find('.state-output').contains('"colorselect": "#ffffff"')
})
})
2 changes: 1 addition & 1 deletion examples/vue3/cypress/integration/stories-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe('Stories list', () => {
it('should display the stories', () => {
cy.clearLocalStorage()
cy.visit('/')
cy.get('[data-test-id="story-list-item"]').should('have.length', 29)
cy.get('[data-test-id="story-list-item"]').should('have.length', 30)
cy.get('[data-test-id="story-list-item"]').contains('🐱 Meow')
cy.get('[data-test-id="story-list-item"]').contains('BaseButton')
.contains('3') // Variants count
Expand Down
45 changes: 45 additions & 0 deletions examples/vue3/src/components/ColorButton.story.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script lang="ts" setup>
import ColorButton from './ColorButton.vue'

function initState () {
return {
bgcolorselect: '#000000',
txtcolorselect: '#ffffff',
}
}
</script>

<template>
<Story
title="Color Button"
:layout="{
type: 'grid',
width: 200,
}"
>
<Variant
title="playground"
:init-state="initState"
>
<template #default="{ state }">
<ColorButton
:bgcolorselect="state.bgcolorselect"
:txtcolorselect="state.txtcolorselect"
>
Click me
</ColorButton>
</template>

<template #controls="{ state }">
<HstColorSelect
v-model="state.bgcolorselect"
title="Background Color Select"
/>
<HstColorSelect
v-model="state.txtcolorselect"
title="Text Color Select"
/>
</template>
</Variant>
</Story>
</template>
27 changes: 27 additions & 0 deletions examples/vue3/src/components/ColorButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts" setup>
defineProps({
bgcolorselect: {
type: String,
default: null,
},
txtcolorselect: {
type: String,
default: null,
},
})
</script>

<template>
<button
:style="{ background: bgcolorselect, color: txtcolorselect }"
class="htw-px-2 htw-py-1 htw-rounded-sm btn"
>
<slot />
</button>
</template>

<style scoped>
.btn {
cursor: pointer;
}
</style>
5 changes: 5 additions & 0 deletions examples/vue3/src/components/Controls.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function initState () {
number: 20,
longText: 'Longer text...',
select: 'crash-bandicoot',
colorselect: '#000000',
radio: 'metal-gear',
object: { foo: 'bar' },
}
Expand Down Expand Up @@ -63,6 +64,10 @@ function initState () {
title="HstSelect"
:options="options"
/>
<HstColorSelect
v-model="state.colorselect"
title="HstColorSelect"
/>
<HstRadio
v-model="state.radio"
title="HstRadio"
Expand Down
5 changes: 5 additions & 0 deletions examples/vue3/src/components/SharedControls.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const state = reactive({
number: 20,
longText: 'Longer text...',
select: 'crash-bandicoot',
colorselect: '#000000',
fn: () => { /* noop */ },
})

Expand Down Expand Up @@ -45,6 +46,10 @@ defineExpose({
title="HstSelect"
:options="options"
/>
<HstColorSelect
v-model="state.colorselect"
title="HstColorSelect"
/>
</template>

<Variant
Expand Down
3 changes: 3 additions & 0 deletions examples/vue3/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export default defineConfig({
hmr: {
clientPort: process.env.CODESPACES ? 443 : undefined,
MichaelThomas0721 marked this conversation as resolved.
Show resolved Hide resolved
},
port: 5173,
host: true,

},

plugins: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts" setup>
import { reactive } from 'vue'
import HstColorSelect from './HstColorSelect.vue'

const state = reactive({
value: '#000000',
})
</script>

<template>
<Story
title="HstColorSelect"
group="controls"
:layout="{ type: 'single', iframe: false }"
>
<HstColorSelect
v-model="state.value"
title="Color Select"
/>
<pre>{{ state }}</pre>
<template #controls>
<HstColorSelect
v-model="state.value"
title="Value"
/>
</template>
</Story>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<script lang="ts">
export default {
name: 'HstColorSelector',
inheritAttrs: false,
}
</script>

<script lang="ts" setup>
import { computed, ref } from 'vue'
import HstWrapper from '../HstWrapper.vue'

const props = defineProps<{
title?: string
modelValue?: string
}>()

const emit = defineEmits({
'update:modelValue': (newValue: string) => true,
})

const input = ref<HTMLInputElement>(null)

const stringModel = computed({
get: () => props.modelValue,
set: value => {
emit('update:modelValue', value)
},
})

function throttle(cb, delay = 15) {
let shouldWait = false
let waitingArgs
const timeoutFunc = () => {
if (waitingArgs == null) {
shouldWait = false
} else {
cb(...waitingArgs)
waitingArgs = null
setTimeout(timeoutFunc, delay)
}
}

return (...args) => {
if (shouldWait) {
waitingArgs = args
return
}

cb(...args)
shouldWait = true
setTimeout(timeoutFunc, delay)
}
}
const updateValue = throttle((value: string) => {
emit('update:modelValue', value)
})
function processChange(inp) {
updateValue(inp)
}
</script>

<script>

</script>

<template>
<HstWrapper
:title="title"
class="histoire-select htw-cursor-text htw-items-center"
:class="$attrs.class"
:style="$attrs.style"
>
<div class="htw-flex htw-flex-row htw-gap-1">
<input
ref="input"
v-bind="{ ...$attrs, class: null, style: null }"
v-model="stringModel"
type="text"
class="htw-text-inherit htw-bg-transparent htw-w-full htw-outline-none htw-px-2 htw-py-1 -htw-my-1 htw-border htw-border-solid htw-border-black/25 dark:htw-border-white/25 focus:htw-border-primary-500 dark:focus:htw-border-primary-500 htw-rounded-sm"
>
<input
type="color"
:value="modelValue"
@input="((e) => processChange((e.target as HTMLInputElement).value as string))"
>
</div>

<template #actions>
<slot name="actions" />
</template>
</HstWrapper>
</template>
6 changes: 3 additions & 3 deletions packages/histoire-controls/src/components/radio/HstRadio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,17 @@ const animationEnabled = ref(false)
:key="value"
>
<input
:id="`${value}-radio`"
:id="`${value}-radio_${title}`"
type="radio"
:name="`${value}-radio`"
:name="`${value}-radio_${title}`"
:value="value"
:checked="value === modelValue"
class="htw-hidden"
@change="selectOption(value)"
>
<label
tabindex="0"
:for="`${value}-radio`"
:for="`${value}-radio_${title}`"
class="htw-cursor-pointer htw-flex htw-items-center htw-relative htw-py-1 htw-group"
@keydown.enter.prevent="selectOption(value)"
@keydown.space.prevent="selectOption(value)"
Expand Down
Loading