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: Open in new tab (fix #52) #59

Merged
merged 3 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions packages/histoire/src/client/app/components/sandbox/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Story, Variant } from '../../types'

export function getSandboxUrl (story: Story, variant: Variant) {
const url = new URLSearchParams()
url.append('storyId', story.id)
url.append('variantId', variant.id)
return '/__sandbox?' + url.toString()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import HatchedPattern from '../misc/HatchedPattern.vue'
import CheckerboardPattern from '../misc/CheckerboardPattern.vue'
import { toRawDeep } from '../../util/reactivity'
import { Settings } from 'http2'
import { getSandboxUrl } from '../sandbox/lib'

const props = defineProps<{
story: Story
Expand Down Expand Up @@ -61,10 +62,7 @@ useEventListener(window, 'message', (event) => {
})

const sandboxUrl = computed(() => {
const url = new URLSearchParams()
url.append('storyId', props.story.id)
url.append('variantId', props.variant.id)
return '/__sandbox?' + url.toString()
return getSandboxUrl(props.story, props.variant)
})

const isIframeLoaded = ref(false)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
<script lang="ts" setup>
import { PropType, ref } from 'vue'
import { Icon } from '@iconify/vue'
import { PropType } from 'vue'
import type { Story, Variant } from '../../types'
import { histoireConfig } from '../../util/config'
import { usePreviewSettings } from '../../util/preview-settings'
import StoryResponsivePreview from './StoryResponsivePreview.vue'
import BaseCheckbox from '../base/BaseCheckbox.vue'
import { isMobile } from '../../util/responsive'
import StoryVariantTitle from './variant/StoryVariantTitle.vue'
import StoryVariantResponsiveSize from './variant/StoryVariantResponsiveSize.vue'
import StoryVariantBackground from './variant/StoryVariantBackground.vue'
import StoryVariantNewTab from './variant/StoryVariantNewTab.vue'

defineProps({
variant: {
type: Object as PropType<Variant>,
required: true,
},

story: {
type: Object as PropType<Story>,
required: true,
},
})
defineProps<{
variant: Variant
story: Story
}>()

const settings = usePreviewSettings()
</script>
Expand All @@ -33,141 +27,13 @@ const settings = usePreviewSettings()
v-if="!isMobile"
class="htw-flex-none htw-flex htw-items-center htw-h-8 -htw-mt-1"
>
<!-- Variant title -->
<div class="htw-flex htw-items-center htw-gap-1 htw-text-gray-500 htw-flex-1 htw-truncate htw-min-w-0">
<Icon
:icon="variant.icon ?? 'carbon:cube'"
class="base-list-item-link-icon htw-w-4 htw-h-4 htw-opacity-50"
:class="[
variant.iconColor ? 'bind-icon-color' : 'htw-text-gray-500',
]"
/>
<span>{{ variant.title }}</span>
</div>

<!-- Responsive size -->
<VDropdown
placement="bottom-end"
:skidding="6"
:disabled="!histoireConfig.responsivePresets?.length"
class="htw-h-full htw-flex-none"
>
<div
v-tooltip="'Responsive sizes'"
class="htw-flex htw-items-center htw-gap-1 htw-h-full htw-px-2"
:class="{
'htw-cursor-pointer hover:htw-text-primary-500': histoireConfig.responsivePresets?.length,
}"
>
<Icon
icon="ic:baseline-phone-android"
class="htw-w-4 htw-h-4 htw-opacity-50"
/>
<Icon
icon="carbon:caret-down"
class="htw-w-4 htw-h-4 htw-opacity-50"
/>
</div>

<template #popper="{ hide }">
<div class="htw-flex htw-flex-col htw-items-stretch">
<BaseCheckbox v-model="settings.rotate">
Rotate
</BaseCheckbox>

<div class="htw-flex htw-gap-2 htw-px-4 htw-py-3">
<input
v-model.number="settings.responsiveWidth"
v-tooltip="'Responsive width (px)'"
type="number"
class="htw-bg-transparent htw-border htw-border-gray-200 dark:htw-border-gray-850 htw-rounded htw-w-20 htw-opacity-50 focus:htw-opacity-100 htw-flex-1 htw-min-w-0"
step="16"
placeholder="Auto"
>
<span class="htw-opacity-50">x</span>
<input
v-model.number="settings.responsiveHeight"
v-tooltip="'Responsive height (px)'"
type="number"
class="htw-bg-transparent htw-border htw-border-gray-200 dark:htw-border-gray-850 htw-rounded htw-w-20 htw-opacity-50 focus:htw-opacity-100 htw-flex-1 htw-min-w-0"
step="16"
placeholder="Auto"
>
</div>

<button
v-for="(preset, index) in histoireConfig.responsivePresets"
:key="index"
class="htw-px-4 htw-py-3 htw-cursor-pointer htw-text-left htw-flex htw-gap-4"
:class="[
settings.responsiveWidth === preset.width && settings.responsiveHeight === preset.height
? 'htw-bg-primary-500 hover:htw-bg-primary-600 htw-text-white dark:htw-text-black'
: 'htw-bg-transparent hover:htw-bg-primary-100 dark:hover:htw-bg-primary-700',
]"
@click="settings.responsiveWidth = preset.width;settings.responsiveHeight = preset.height;hide()"
>
{{ preset.label }}
<span class="htw-ml-auto htw-opacity-70 htw-flex htw-gap-1">
<span v-if="preset.width">{{ preset.width }}<span v-if="!preset.height">px</span></span>
<span v-if="preset.width && preset.height">x</span>
<span v-if="preset.height">{{ preset.height }}<span v-if="!preset.width">px</span></span>
</span>
</button>
</div>
</template>
</VDropdown>

<!-- Background -->
<VDropdown
v-if="histoireConfig.backgroundPresets.length"
placement="bottom-end"
:skidding="6"
class="htw-h-full htw-flex-none"
>
<div
v-tooltip="'Background color'"
class="htw-cursor-pointer hover:htw-text-primary-500 htw-flex htw-items-center htw-gap-1 htw-h-full htw-px-2"
>
<div
class="bind-preview-bg htw-w-4 htw-h-4 htw-rounded-full htw-border htw-border-black/20 dark:htw-border-white/20"
/>
<Icon
icon="carbon:caret-down"
class="htw-w-4 htw-h-4 htw-opacity-50"
/>
</div>

<template #popper="{ hide }">
<div class="htw-flex htw-flex-col htw-items-stretch">
<BaseCheckbox v-model="settings.checkerboard">
Checkerboard
</BaseCheckbox>

<button
v-for="(option, index) in histoireConfig.backgroundPresets"
:key="index"
class="htw-px-4 htw-py-3 htw-cursor-pointer htw-text-left htw-flex htw-gap-4"
:class="[
settings.backgroundColor === option.color
? 'htw-bg-primary-500 hover:htw-bg-primary-600 htw-text-white dark:htw-text-black'
: 'htw-bg-transparent hover:htw-bg-primary-100 dark:hover:htw-bg-primary-700',
]"
@click="settings.backgroundColor = option.color;hide()"
>
<span class="htw-mr-auto">{{ option.label }}</span>
<template v-if="option.color !== '$checkerboard'">
<span class="htw-ml-auto htw-opacity-70">{{ option.color }}</span>
<div
class="htw-w-4 htw-h-4 htw-rounded-full htw-border htw-border-black/20 dark:htw-border-white/20"
:style="{
backgroundColor: option.color,
}"
/>
</template>
</button>
</div>
</template>
</VDropdown>
<StoryVariantTitle :variant="variant" />
<StoryVariantResponsiveSize />
<StoryVariantBackground />
<StoryVariantNewTab
:variant="variant"
:story="story"
/>
</div>

<!-- Preview -->
Expand All @@ -178,9 +44,3 @@ const settings = usePreviewSettings()
/>
</div>
</template>

<style scoped>
.bind-preview-bg {
background-color: v-bind('settings.backgroundColor');
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script lang="ts" setup>
import { Icon } from '@iconify/vue'
import { histoireConfig } from '../../../util/config'
import { usePreviewSettings } from '../../../util/preview-settings'
import BaseCheckbox from '../../base/BaseCheckbox.vue'

const settings = usePreviewSettings()
</script>

<template>
<VDropdown
v-if="histoireConfig.backgroundPresets.length"
placement="bottom-end"
:skidding="6"
class="htw-h-full htw-flex-none"
>
<div
v-tooltip="'Background color'"
class="htw-cursor-pointer hover:htw-text-primary-500 htw-flex htw-items-center htw-gap-1 htw-h-full htw-px-2"
>
<div
class="bind-preview-bg htw-w-4 htw-h-4 htw-rounded-full htw-border htw-border-black/50 dark:htw-border-white/50"
/>
<Icon
icon="carbon:caret-down"
class="htw-w-4 htw-h-4 htw-opacity-50"
/>
</div>

<template #popper="{ hide }">
<div class="htw-flex htw-flex-col htw-items-stretch">
<BaseCheckbox v-model="settings.checkerboard">
Checkerboard
</BaseCheckbox>

<button
v-for="(option, index) in histoireConfig.backgroundPresets"
:key="index"
class="htw-px-4 htw-py-3 htw-cursor-pointer htw-text-left htw-flex htw-gap-4"
:class="[
settings.backgroundColor === option.color
? 'htw-bg-primary-500 hover:htw-bg-primary-600 htw-text-white dark:htw-text-black'
: 'htw-bg-transparent hover:htw-bg-primary-100 dark:hover:htw-bg-primary-700',
]"
@click="settings.backgroundColor = option.color;hide()"
>
<span class="htw-mr-auto">{{ option.label }}</span>
<template v-if="option.color !== '$checkerboard'">
<span class="htw-ml-auto htw-opacity-70">{{ option.color }}</span>
<div
class="htw-w-4 htw-h-4 htw-rounded-full htw-border htw-border-black/20 dark:htw-border-white/20"
:style="{
backgroundColor: option.color,
}"
/>
</template>
</button>
</div>
</template>
</VDropdown>
</template>

<style scoped>
.bind-preview-bg {
background-color: v-bind('settings.backgroundColor');
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts" setup>
import { Icon } from '@iconify/vue'
import type { Story, Variant } from '../../../types'
import { computed } from 'vue'
import { getSandboxUrl } from '../../sandbox/lib'

const props = defineProps<{
variant: Variant
story: Story
}>()

const sandboxUrl = computed(() => {
return getSandboxUrl(props.story, props.variant)
})
</script>

<template>
<a
v-tooltip="'Open variant in new tab'"
:href="sandboxUrl"
target="_blank"
class="htw-flex htw-items-center htw-gap-1 htw-h-full htw-px-2 hover:htw-text-primary-500"
>
<Icon
icon="carbon:launch"
class="base-list-item-link-icon htw-w-4 htw-h-4 htw-opacity-50"
/>
</a>
</template>
Loading