Skip to content
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
1 change: 1 addition & 0 deletions .gitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
git config --global alias.mmerge '!f() { git merge master -m "Merge master into $(git rev-parse --abbrev-ref HEAD)"; }; f'
18 changes: 15 additions & 3 deletions frontend/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts">
import Button from "./lib/Button.svelte";
import Input from "./lib/Input.svelte";
import Message from "./lib/Message.svelte";
import Label from "./lib/Label.svelte";

let under_diff = $state<string>("0");
let over_diff = $state<string>("0");
Expand Down Expand Up @@ -47,6 +49,8 @@

<div class="w-full h-full">
<div class="container flex flex-col max-w-xl w-full gap-2">
<h1 class="text-3xl mb-8">AtCoder Random Picker</h1>

{#if errors.rangeError}
<p class="text-destructive mb-2 text-sm">最低Diffが最高Diffを超えています。</p>
{:else if errors.isMinusOverDiff}
Expand All @@ -59,13 +63,21 @@
<p class="text-destructive mb-2 text-sm">{errorMessage}</p>
{/if}

{#if result !== null}
<p class="text-green-600 mb-2 text-sm">サーバーからの結果: {result}</p>
{/if}
<div class="flex items-center gap-2">
<Input type="number" placeholder="最低Diffを入力してください。" isErrors={errors} bind:value={under_diff} />
<Input type="number" placeholder="最高Diffを入力してください。" isErrors={errors} bind:value={over_diff} />
<Button onclick={sendQuery} class="shrink-0">ボタン</Button>
</div>

{#if result !== null}
<div class="mt-4">
<Message variant="success">
<div class="flex flex-col">
<Label class="!text-base leading-tight font-medium text-3xl mb-1.5">Success</Label>
<p class="text-base-foreground-default mb-2 text-sm">サーバーからの結果: {result}</p>
</div>
</Message>
</div>
{/if}
</div>
</div>
11 changes: 10 additions & 1 deletion frontend/src/input.css
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,18 @@

* {
box-sizing: border-box;
font-family: "Ubuntu Sans Mono", "Noto Sans JP";
font-family: "Ubuntu Sans Mono", "Noto Sans JP", "serif";
text-decoration: none;
list-style: none;
font-size: 103.5%;
}

h1 {
font-size: 3rem;
}

label {
font-size: 1.5rem;
}

.container {
Expand Down
62 changes: 62 additions & 0 deletions frontend/src/lib/Label.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<!--
@component
## 概要
- テキスト入力欄や選択肢などのフォーム要素に対して、その内容を明示するために使用されるコンポーネントです

## 機能
- フォーム要素と関連付けることでアクティブ化することができます
- 任意の属性を渡せます

## Props
- disabled: 指定するとグレーアウトされ、クリック不可になります

## Usage
```svelte
<Label for="forName">ラベル</Label>
```
-->
<script module lang="ts">
import { cva, type VariantProps } from 'class-variance-authority';
import type { Snippet } from 'svelte';
import type { HTMLLabelAttributes } from 'svelte/elements';

export const labelVariants = cva('inline-block w-fit leading-tight text-sm text-base-foreground-default', {
variants: {
/** 操作できるかどうか */
disabled: {
true: ['opacity-50'],
false: [],
},
},
defaultVariants: {
disabled: false,
},
});

export type LabelVariants = VariantProps<typeof labelVariants>;

export interface LabelProps extends LabelVariants, HTMLLabelAttributes {
/** 必須かどうか */
required?: boolean;
/** クラス */
class?: string;
children?: Snippet<[]>;
}
</script>

<script lang="ts">
let { disabled = false, class: className = '', children, required = false, ...labelAttributes }: LabelProps = $props();

let labelVariantClass = $derived(labelVariants({
disabled,
class: className,
}));
</script>

<label class={labelVariantClass} {...labelAttributes}>
{@render children?.()}

{#if required}
<span class="inline-block bg-destructive text-white text-3xl leading-none px-1.5 py-0.5 ml-2">必須</span>
{/if}
</label>
96 changes: 96 additions & 0 deletions frontend/src/lib/Message.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!--
@component
## 概要
- ユーザーに重要な情報や通知を伝えるためのコンポーネントです

## 機能
- 見た目を変更するためのいくつかのスタイル用Propsが追加されています(詳細はPropsセクションを参照)

## Props
- variant: 通知の意味を指定すると、それに合わせたスタイルになります

## Usage
```svelte
<Message variant="default">
<div class="flex flex-col">
<Label class="!text-base leading-tight font-medium mb-1.5">ラベル</Label>
<p class="text-base-foreground-default text-sm">ここに補足文が入ります。</p>
</div>
</Message>
```
-->

<script module lang="ts">
import { cva, type VariantProps } from 'class-variance-authority';
import type { Snippet } from 'svelte';

export const messageVariants = cva(
'flex items-start gap-3 w-full p-4 border rounded-lg text-xl',
{
variants: {
/** 通知の使用用途 */
variant: {
error: ['bg-destructive/10 border-destructive'],
warning: ['bg-warning/10 border-warning'],
success: ['bg-success/10 border-success'],
default: ['bg-primary/10 border-primary'],
},
},
defaultVariants: {
variant: "default",
}
},
);

export const messageIconVariants = cva('', {
variants: {
variant: {
error: ['text-destructive'],
warning: ['text-warning'],
success: ['text-success'],
default: ['text-primary'],
},
defaultVariants: {
variant: "default",
}
},
});

export type MessageVariants = VariantProps<typeof messageVariants>;

export interface MessageProps extends MessageVariants {
/** クラス */
class?: string;
children?: Snippet<[]>;
}
</script>

<script lang="ts">
import { Info, CircleAlert, TriangleAlert, Check } from '@lucide/svelte';

let { variant, class: className = '', children }: MessageProps = $props();

let messageVariantClass = $derived(messageVariants({
variant,
class: className,
}));

let messageIconVariantClass = $derived(messageIconVariants({
variant,
}));
</script>

<div class={messageVariantClass}>
<div class={messageIconVariantClass}>
{#if variant === "error"}
<CircleAlert size="1.5rem" />
{:else if variant === "warning"}
<TriangleAlert size="1.5rem" />
{:else if variant === "success"}
<Check size="1.5rem" />
{:else}
<Info size="1.5rem" />
{/if}
</div>
{@render children?.()}
</div>
Loading