brutalism design

This commit is contained in:
2026-05-23 22:49:52 +06:00
parent d06892e990
commit 12ae0ae839
17 changed files with 497 additions and 158 deletions

View File

@@ -1,37 +1,53 @@
<template>
<button
class="chad-button"
:data-loading="loading || undefined"
:data-disabled="disabled || undefined"
:class="[
bem.b(),
bem.exp(!!type, bem.m(type!)),
bem.is('loading', loading),
bem.is('disabled', disabled),
bem.is('full', full),
]"
:disabled="disabled"
:type="type"
:data-full="full || undefined"
:type="nativeType"
>
<ChadSpinner v-if="loading" class="chad-button__spinner" />
<slot v-else />
<template v-else>
<Component :is="icon" v-if="icon" class="chad-button__icon" />
<span v-if="$slots.default">
<slot />
</span>
</template>
</button>
</template>
<script setup lang="ts">
import type { Component } from 'vue'
import ChadSpinner from '@shared/components/ui/Spinner.vue'
import useBem from '@shared/composables/use-bem.ts'
defineOptions({
name: 'ChadButton',
})
withDefaults(
defineProps<Props>(),
defineProps<ChadButtonProps>(),
{
type: 'button',
nativeType: 'button',
},
)
interface Props {
export interface ChadButtonProps {
loading?: boolean
disabled?: boolean
type?: 'button' | 'submit'
type?: 'secondary'
nativeType?: 'button' | 'submit'
icon?: Component
full?: boolean
}
const bem = useBem('chad-button')
</script>
<style lang="scss">
@@ -41,7 +57,7 @@ interface Props {
flex-shrink: 0;
border: none;
color: var(--ink);
padding-inline: var(--space-3);
padding: 0 var(--space-3);
height: 44px;
background-color: var(--yellow);
font-weight: 700;
@@ -50,7 +66,7 @@ interface Props {
outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1);
&[data-full] {
&.is-full {
width: 100%;
}
@@ -64,16 +80,35 @@ interface Props {
color: var(--yellow);
}
&[data-disabled],
&--secondary {
background-color: var(--grey-1);
&:hover,
&:focus {
background-color: var(--grey-2);
}
&:active {
background-color: var(--grey-3);
color: var(--ink);
}
}
&:disabled {
cursor: not-allowed;
background-color: var(--grey-1);
color: var(--grey-3);
}
&[data-loading] {
&.is-loading {
background-color: var(--grey-1);
cursor: wait;
}
&__icon {
&:not(:last-child) {
margin-right: var(--space-1);
}
}
}
</style>

View File

@@ -9,7 +9,7 @@
{{ label }}
</label>
<input :id="inputId" v-model="modelValue" class="chad-input__input" :placeholder="placeholder" type="text">
<input :id="inputId" v-model="modelValue" class="chad-input__input" :placeholder="placeholder" type="text" autocomplete="off">
<p v-if="helper" class="chad-input__helper">
{{ helper }}

View File

@@ -0,0 +1,25 @@
<template>
<div class="chad-notification-badge">
<slot />
</div>
</template>
<script setup lang="ts">
</script>
<style lang="scss">
.chad-notification-badge {
position: relative;
&::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 12px;
aspect-ratio: 1;
background-color: var(--yellow);
}
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<button class="chad-to-bottom">
<ArrowDown />
</button>
</template>
<script setup lang="ts">
import { ArrowDown } from '@lucide/vue'
defineOptions({
name: 'ChadToBottom',
})
</script>
<style lang="scss">
.chad-to-bottom {
cursor: pointer;
width: 40px;
aspect-ratio: 1;
text-align: center;
line-height: 40px;
outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1);
border: none;
background-color: var(--grey-1);
padding: 0;
box-shadow: var(--shadow-sm);
&:hover,
&:focus {
background-color: var(--grey-2);
}
&:active {
background-color: var(--grey-3);
}
}
</style>