Skip to content

Commit 6397491

Browse files
authored
Button links tab options and CLI module (#190)
* Button links tab options and CLI module * Button defaults to self * Fix for CLI Module not showing * Remove block for cli module and add to header * Remove leftover cli block types * Remove extra type
1 parent d5649df commit 6397491

File tree

6 files changed

+119
-1
lines changed

6 files changed

+119
-1
lines changed

components/Base/Button.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface BaseButtonProps {
1717
const props = withDefaults(defineProps<BaseButtonProps>(), {
1818
size: 'medium',
1919
type: 'button',
20+
target: '_self',
2021
});
2122
2223
const as = computed(() => {

components/Base/CliSnippet.vue

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<script setup lang="ts">
2+
const props = defineProps<{
3+
command: string;
4+
}>();
5+
6+
const isCopied = ref(false);
7+
8+
const commandParts = computed(() => {
9+
const firstSpaceIndex = props.command.indexOf(' ');
10+
if (firstSpaceIndex === -1) return { prefix: props.command, command: '' };
11+
return {
12+
prefix: props.command.slice(0, firstSpaceIndex + 1),
13+
command: props.command.slice(firstSpaceIndex + 1),
14+
};
15+
});
16+
17+
const copyToClipboard = async () => {
18+
try {
19+
await navigator.clipboard.writeText(props.command);
20+
isCopied.value = true;
21+
22+
setTimeout(() => {
23+
isCopied.value = false;
24+
}, 2000);
25+
} catch {
26+
// Silently fail if copy doesn't work
27+
}
28+
};
29+
</script>
30+
31+
<template>
32+
<div class="cli-snippet" @click="copyToClipboard">
33+
<div class="command">
34+
<code class="prefix">{{ commandParts.prefix }}</code>
35+
<code class="command-text">{{ commandParts.command }}</code>
36+
</div>
37+
<div class="copy-status">
38+
<template v-if="isCopied">
39+
<span>Copied!</span>
40+
</template>
41+
<BaseIcon v-else name="content_copy" size="small" />
42+
</div>
43+
</div>
44+
</template>
45+
46+
<style lang="scss" scoped>
47+
.cli-snippet {
48+
display: flex;
49+
align-items: center;
50+
justify-content: space-between;
51+
width: 470px;
52+
height: 44px;
53+
border-radius: 8px;
54+
padding: 9px 24px;
55+
background: var(--colors-background--inverted, #172940);
56+
border: 1px solid transparent;
57+
box-shadow: 0px 0px 10px 2px #6644ff33;
58+
transition: all 300ms ease-out;
59+
cursor: pointer;
60+
&:hover {
61+
box-shadow:
62+
0px 0px 10px 2px #6644ff33,
63+
0px 0px 10px 1px #ffade44d;
64+
border-color: #745eff;
65+
}
66+
&:active {
67+
border-color: var(--colors-primary, #6644ff);
68+
}
69+
}
70+
.command {
71+
display: flex;
72+
gap: 4px;
73+
font-family: var(--family-monospace);
74+
font-weight: 500;
75+
font-size: var(--font-size-md);
76+
line-height: var(--line-height-sm);
77+
}
78+
.prefix {
79+
color: #ff69b4;
80+
}
81+
.command-text {
82+
color: var(--white);
83+
}
84+
.copy-status {
85+
color: var(--white);
86+
font-family: var(--family-body);
87+
font-size: var(--font-size-sm);
88+
font-weight: 500;
89+
min-width: 50px;
90+
text-align: right;
91+
.base-icon {
92+
--base-icon-color: var(--white);
93+
font-size: 20px;
94+
line-height: 20px;
95+
}
96+
}
97+
</style>

components/Block/Button.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const { data: block } = await useAsyncData(props.uuid, () =>
1616
'outline',
1717
'icon',
1818
'size',
19+
'target',
1920
{ page: ['permalink'], resource: ['slug', { type: ['slug'] }] },
2021
'ph_event',
2122
],
@@ -52,5 +53,6 @@ const href = computed(() => {
5253
:size="block.size"
5354
:label="block.label ?? undefined"
5455
:outline="block.outline"
56+
:target="block.target || '_self'"
5557
/>
5658
</template>

components/Block/Header.vue

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const { data: block } = useAsyncData(props.uuid, () =>
1818
'button_group',
1919
'subheading_color',
2020
'subheading_type',
21+
'command',
2122
],
2223
}),
2324
),
@@ -44,6 +45,10 @@ const { data: block } = useAsyncData(props.uuid, () =>
4445
:type="block.subheading_type"
4546
size="large"
4647
/>
48+
<template v-if="block.command">
49+
<BaseCliSnippet class="cli-snippet" :command="block.command" />
50+
<BaseDivider class="separator" />
51+
</template>
4752
<BlockButtonGroup
4853
v-if="block.button_group"
4954
class="buttons"
@@ -74,10 +79,21 @@ const { data: block } = useAsyncData(props.uuid, () =>
7479
max-inline-size: 45rem;
7580
}
7681
82+
.cli-snippet {
83+
margin-block-start: var(--space-6);
84+
}
85+
86+
.separator {
87+
width: 470px;
88+
margin-inline: auto;
89+
}
90+
7791
.align-center {
7892
.heading,
7993
.text,
80-
.badge {
94+
.badge,
95+
.cli-snippet,
96+
.separator {
8197
margin-inline: auto;
8298
}
8399
}

types/schema/blocks/block-button.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export interface BlockButton {
1414
icon: string | null;
1515
size: 'small' | 'medium' | 'large' | 'x-large';
1616
ph_event: any;
17+
target: '_blank' | '_self' | null;
1718
}

types/schema/blocks/block-header.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export interface BlockHeader {
1414
heading_size: 'title' | 'x-large' | 'large' | 'medium' | 'small';
1515
subheading_color: 'foreground' | 'subdued';
1616
subheading_type: 'default' | 'subtext';
17+
command: string | null;
1718
}

0 commit comments

Comments
 (0)