feat: GitHub完全活用ガイド - 包括的な解説書とWebサイトを追加

🎯 主要機能:
- GitHub機能の網羅的解説書 (10章構成)
- 外部ツール代替戦略とコスト分析
- 実践的な設定例とベストプラクティス
- 実務ケーススタディと段階的移行計画

🌐 GitHub Pages Webサイト:
- Jekyll設定とレスポンシブデザイン
- 自動デプロイワークフロー
- 美しいランディングページ
- SEO最適化とモバイル対応

📊 期待効果:
- 年間37%のコスト削減
- 開発効率2倍向上
- セキュリティ強化

🚀 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
marketing-shibata50 2025-07-20 11:21:37 +09:00
commit 1e2b71e1b3
17 changed files with 4250 additions and 0 deletions

162
practice-project/README.md Normal file
View file

@ -0,0 +1,162 @@
# 🎯 Personal Task Manager - GitHub機能実践プロジェクト
> GitHub機能を体系的に学習するための実践プロジェクト
## 🎯 プロジェクト概要
シンプルなタスク管理アプリケーションを通じて、GitHub のすべての主要機能を実際に体験・習得します。
## 🏗️ プロジェクト構成
```
personal-task-manager/
├── index.html # メインページ
├── style.css # スタイルシート
├── script.js # JavaScript ロジック
├── package.json # Node.js設定Actions用
├── .github/
│ ├── workflows/ # GitHub Actions
│ ├── ISSUE_TEMPLATE/ # Issueテンプレート
│ └── pull_request_template.md
├── docs/ # GitHub Pages用
└── tests/ # テストファイル
```
## 🎓 学習目標と体験する機能
### Phase 1: 基本機能の体験
- [x] **リポジトリ作成** - 設定とクローン
- [ ] **Issues管理** - バグ報告、機能要望、タスク作成
- [ ] **Projects** - かんばんボードでタスク進行管理
- [ ] **ブランチ管理** - feature ブランチでの開発
### Phase 2: コラボレーション機能
- [ ] **Pull Request** - コードレビューフロー体験
- [ ] **テンプレート** - Issue/PR テンプレートの活用
- [ ] **ラベル・マイルストーン** - プロジェクト管理の体系化
- [ ] **レビュー機能** - サジェスト機能の活用
### Phase 3: 自動化・デプロイ
- [ ] **GitHub Actions** - CI/CDパイプライン構築
- [ ] **自動テスト** - コード品質の自動チェック
- [ ] **GitHub Pages** - 自動デプロイメント
- [ ] **セキュリティ** - Dependabot、Code scanning
## 🚀 実装予定機能
### 基本機能
- ✅ タスクの追加・編集・削除
- ✅ タスクの完了状態管理
- ✅ カテゴリ別フィルタリング
- ✅ ローカルストレージでの永続化
### 発展機能GitHub機能習得用
- ⏳ タスクの優先度設定
- ⏳ 期限管理機能
- ⏳ 進捗レポート表示
- ⏳ データエクスポート機能
## 📋 開発フローGitHub機能実践
### 1. Issue駆動開発
```mermaid
graph LR
A[Issue作成] --> B[ラベル付与]
B --> C[Projects追加]
C --> D[ブランチ作成]
D --> E[実装]
E --> F[PR作成]
F --> G[レビュー]
G --> H[マージ]
H --> I[Issue クローズ]
```
### 2. ブランチ戦略
```
main : プロダクションコード
develop : 開発版(統合テスト)
feature/* : 機能開発用
hotfix/* : 緊急修正用
```
### 3. 自動化フロー
```yaml
# CI/CD パイプライン
1. コミット → 自動テスト実行
2. PR作成 → コードスキャン + レビュー
3. mainマージ → 自動デプロイGitHub Pages
4. リリース → 自動タグ作成 + チェンジログ生成
```
## 🎯 GitHub機能習得チェックリスト
### 基本操作
- [ ] リポジトリ作成・クローン
- [ ] ブランチ作成・切り替え
- [ ] コミット・プッシュ
- [ ] Issue作成・管理
### プロジェクト管理
- [ ] GitHub Projects セットアップ
- [ ] Issue テンプレート作成
- [ ] ラベル体系の構築
- [ ] マイルストーン設定
### コラボレーション
- [ ] Pull Request作成
- [ ] コードレビュー
- [ ] サジェスト機能使用
- [ ] コンフリクト解決
### 自動化
- [ ] GitHub Actions セットアップ
- [ ] CI/CD パイプライン構築
- [ ] 自動テスト実装
- [ ] 自動デプロイ設定
### セキュリティ・品質
- [ ] Dependabot 有効化
- [ ] Code scanning 設定
- [ ] Branch protection 設定
- [ ] Secret管理
### 公開・ドキュメント
- [ ] GitHub Pages デプロイ
- [ ] README 充実
- [ ] Wiki 作成
- [ ] Release 作成
## 🎮 次のアクション
1. **今すぐ試せること**:
```bash
# このプロジェクトをクローン
git clone https://github.com/your-username/personal-task-manager
cd personal-task-manager
# 最初のIssueを作成
gh issue create --title "タスク追加機能の実装" --body "ユーザーが新しいタスクを追加できる機能を実装する"
```
2. **最初の1週間で体験する機能**:
- Issues でタスク管理
- Projects でかんばん作成
- 基本的なHTML/CSS/JS開発
- Pull Request フロー
3. **2週間目で学ぶ高度な機能**:
- GitHub Actions 設定
- 自動テスト・デプロイ
- セキュリティ機能
- パフォーマンス最適化
## 💡 学習のコツ
1. **小さく始める** - 最初は基本機能のみ実装
2. **実際に使う** - 本物のタスク管理に活用
3. **記録する** - 体験したことを都度ドキュメント化
4. **実験する** - 新しい機能を積極的に試す
---
このプロジェクトを通じて、理論だけでなく実践的なGitHub活用スキルを身につけましょう

143
practice-project/index.html Normal file
View file

@ -0,0 +1,143 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Personal Task Manager</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<header>
<h1>🎯 Personal Task Manager</h1>
<p>GitHub機能学習用タスク管理アプリ</p>
</header>
<main>
<!-- タスク追加フォーム -->
<section class="add-task-section">
<h2>新しいタスクを追加</h2>
<form id="addTaskForm">
<div class="form-group">
<input type="text" id="taskTitle" placeholder="タスクタイトル" required>
</div>
<div class="form-group">
<textarea id="taskDescription" placeholder="詳細説明(任意)"></textarea>
</div>
<div class="form-group">
<select id="taskCategory">
<option value="feature">新機能</option>
<option value="bug">バグ修正</option>
<option value="improvement">改善</option>
<option value="documentation">ドキュメント</option>
</select>
</div>
<div class="form-group">
<select id="taskPriority">
<option value="low">低優先度</option>
<option value="medium" selected>中優先度</option>
<option value="high">高優先度</option>
</select>
</div>
<button type="submit">タスクを追加</button>
</form>
</section>
<!-- フィルタリング -->
<section class="filter-section">
<h2>フィルタ</h2>
<div class="filters">
<select id="categoryFilter">
<option value="all">すべてのカテゴリ</option>
<option value="feature">新機能</option>
<option value="bug">バグ修正</option>
<option value="improvement">改善</option>
<option value="documentation">ドキュメント</option>
</select>
<select id="statusFilter">
<option value="all">すべての状態</option>
<option value="todo">TODO</option>
<option value="in-progress">進行中</option>
<option value="done">完了</option>
</select>
<select id="priorityFilter">
<option value="all">すべての優先度</option>
<option value="high">高優先度</option>
<option value="medium">中優先度</option>
<option value="low">低優先度</option>
</select>
</div>
</section>
<!-- タスクリスト -->
<section class="tasks-section">
<h2>タスク一覧</h2>
<div class="task-board">
<div class="task-column" data-status="todo">
<h3>📋 TODO</h3>
<div class="task-list" id="todoTasks"></div>
</div>
<div class="task-column" data-status="in-progress">
<h3>🔄 進行中</h3>
<div class="task-list" id="inProgressTasks"></div>
</div>
<div class="task-column" data-status="done">
<h3>✅ 完了</h3>
<div class="task-list" id="doneTasks"></div>
</div>
</div>
</section>
<!-- 統計情報 -->
<section class="stats-section">
<h2>統計</h2>
<div class="stats-grid">
<div class="stat-card">
<h3>総タスク数</h3>
<span id="totalTasks">0</span>
</div>
<div class="stat-card">
<h3>完了タスク</h3>
<span id="completedTasks">0</span>
</div>
<div class="stat-card">
<h3>進行中</h3>
<span id="inProgressCount">0</span>
</div>
<div class="stat-card">
<h3>完了率</h3>
<span id="completionRate">0%</span>
</div>
</div>
</section>
</main>
<footer>
<p>GitHub機能学習プロジェクト - Personal Task Manager</p>
<p>Issues、Projects、Actions、Pages の実践的な学習を目的としています</p>
</footer>
</div>
<!-- タスクテンプレート -->
<template id="taskTemplate">
<div class="task-card" draggable="true">
<div class="task-header">
<span class="task-id"></span>
<span class="task-priority"></span>
<span class="task-category"></span>
</div>
<h4 class="task-title"></h4>
<p class="task-description"></p>
<div class="task-meta">
<span class="task-created"></span>
<div class="task-actions">
<button class="edit-btn" title="編集">✏️</button>
<button class="delete-btn" title="削除">🗑️</button>
</div>
</div>
</div>
</template>
<script src="script.js"></script>
</body>
</html>

412
practice-project/script.js Normal file
View file

@ -0,0 +1,412 @@
// Personal Task Manager - GitHub学習用JavaScript
class TaskManager {
constructor() {
this.tasks = this.loadTasks();
this.taskIdCounter = this.getNextTaskId();
this.initializeApp();
}
// アプリケーション初期化
initializeApp() {
this.setupEventListeners();
this.renderTasks();
this.updateStats();
this.setupDragAndDrop();
}
// イベントリスナー設定
setupEventListeners() {
// タスク追加フォーム
document.getElementById('addTaskForm').addEventListener('submit', (e) => {
e.preventDefault();
this.addTask();
});
// フィルタ変更
document.getElementById('categoryFilter').addEventListener('change', () => this.applyFilters());
document.getElementById('statusFilter').addEventListener('change', () => this.applyFilters());
document.getElementById('priorityFilter').addEventListener('change', () => this.applyFilters());
// タスク操作(イベント委譲)
document.addEventListener('click', (e) => {
if (e.target.classList.contains('edit-btn')) {
this.editTask(e.target.closest('.task-card').dataset.taskId);
}
if (e.target.classList.contains('delete-btn')) {
this.deleteTask(e.target.closest('.task-card').dataset.taskId);
}
});
}
// タスク追加
addTask() {
const title = document.getElementById('taskTitle').value.trim();
const description = document.getElementById('taskDescription').value.trim();
const category = document.getElementById('taskCategory').value;
const priority = document.getElementById('taskPriority').value;
if (!title) {
alert('タスクタイトルを入力してください');
return;
}
const task = {
id: this.taskIdCounter++,
title,
description,
category,
priority,
status: 'todo',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
this.tasks.push(task);
this.saveTasks();
this.renderTasks();
this.updateStats();
this.clearForm();
// GitHub風の成功メッセージ実際のGitHubではIssue作成時に表示される
this.showNotification(`タスク #${task.id} を作成しました`, 'success');
}
// タスク編集
editTask(taskId) {
const task = this.tasks.find(t => t.id === parseInt(taskId));
if (!task) return;
const newTitle = prompt('タスクタイトル:', task.title);
if (newTitle === null) return;
const newDescription = prompt('タスク説明:', task.description);
if (newDescription === null) return;
task.title = newTitle.trim();
task.description = newDescription.trim();
task.updatedAt = new Date().toISOString();
this.saveTasks();
this.renderTasks();
this.showNotification(`タスク #${task.id} を更新しました`, 'info');
}
// タスク削除
deleteTask(taskId) {
const task = this.tasks.find(t => t.id === parseInt(taskId));
if (!task) return;
if (confirm(`タスク「${task.title}」を削除しますか?`)) {
this.tasks = this.tasks.filter(t => t.id !== parseInt(taskId));
this.saveTasks();
this.renderTasks();
this.updateStats();
this.showNotification(`タスク #${task.id} を削除しました`, 'warning');
}
}
// タスクレンダリング
renderTasks() {
const todoContainer = document.getElementById('todoTasks');
const inProgressContainer = document.getElementById('inProgressTasks');
const doneContainer = document.getElementById('doneTasks');
// コンテナをクリア
todoContainer.innerHTML = '';
inProgressContainer.innerHTML = '';
doneContainer.innerHTML = '';
// フィルタリングされたタスクを取得
const filteredTasks = this.getFilteredTasks();
// 各タスクをレンダリング
filteredTasks.forEach(task => {
const taskElement = this.createTaskElement(task);
switch (task.status) {
case 'todo':
todoContainer.appendChild(taskElement);
break;
case 'in-progress':
inProgressContainer.appendChild(taskElement);
break;
case 'done':
doneContainer.appendChild(taskElement);
break;
}
});
}
// タスク要素作成
createTaskElement(task) {
const template = document.getElementById('taskTemplate');
const taskElement = template.content.cloneNode(true);
const taskCard = taskElement.querySelector('.task-card');
taskCard.dataset.taskId = task.id;
taskCard.dataset.status = task.status;
// タスク情報を設定
taskElement.querySelector('.task-id').textContent = `#${task.id}`;
taskElement.querySelector('.task-title').textContent = task.title;
taskElement.querySelector('.task-description').textContent = task.description || '説明なし';
// 優先度設定
const priorityElement = taskElement.querySelector('.task-priority');
priorityElement.textContent = this.getPriorityLabel(task.priority);
priorityElement.className = `task-priority ${task.priority}`;
// カテゴリ設定
const categoryElement = taskElement.querySelector('.task-category');
categoryElement.textContent = this.getCategoryLabel(task.category);
categoryElement.className = `task-category ${task.category}`;
// 作成日時
taskElement.querySelector('.task-created').textContent =
new Date(task.createdAt).toLocaleDateString('ja-JP');
return taskElement;
}
// フィルタリング適用
applyFilters() {
this.renderTasks();
}
// フィルタリングされたタスク取得
getFilteredTasks() {
const categoryFilter = document.getElementById('categoryFilter').value;
const statusFilter = document.getElementById('statusFilter').value;
const priorityFilter = document.getElementById('priorityFilter').value;
return this.tasks.filter(task => {
const matchesCategory = categoryFilter === 'all' || task.category === categoryFilter;
const matchesStatus = statusFilter === 'all' || task.status === statusFilter;
const matchesPriority = priorityFilter === 'all' || task.priority === priorityFilter;
return matchesCategory && matchesStatus && matchesPriority;
});
}
// 統計更新
updateStats() {
const totalTasks = this.tasks.length;
const completedTasks = this.tasks.filter(t => t.status === 'done').length;
const inProgressTasks = this.tasks.filter(t => t.status === 'in-progress').length;
const completionRate = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
document.getElementById('totalTasks').textContent = totalTasks;
document.getElementById('completedTasks').textContent = completedTasks;
document.getElementById('inProgressCount').textContent = inProgressTasks;
document.getElementById('completionRate').textContent = `${completionRate}%`;
}
// ドラッグ&ドロップ設定
setupDragAndDrop() {
// タスクカードのドラッグ開始
document.addEventListener('dragstart', (e) => {
if (e.target.classList.contains('task-card')) {
e.target.classList.add('dragging');
e.dataTransfer.setData('text/plain', e.target.dataset.taskId);
}
});
// ドラッグ終了
document.addEventListener('dragend', (e) => {
if (e.target.classList.contains('task-card')) {
e.target.classList.remove('dragging');
}
});
// ドロップゾーンの設定
document.querySelectorAll('.task-column').forEach(column => {
column.addEventListener('dragover', (e) => {
e.preventDefault();
column.classList.add('drag-over');
});
column.addEventListener('dragleave', (e) => {
if (!column.contains(e.relatedTarget)) {
column.classList.remove('drag-over');
}
});
column.addEventListener('drop', (e) => {
e.preventDefault();
column.classList.remove('drag-over');
const taskId = e.dataTransfer.getData('text/plain');
const newStatus = column.dataset.status;
this.updateTaskStatus(parseInt(taskId), newStatus);
});
});
}
// タスクステータス更新
updateTaskStatus(taskId, newStatus) {
const task = this.tasks.find(t => t.id === taskId);
if (!task || task.status === newStatus) return;
const oldStatus = task.status;
task.status = newStatus;
task.updatedAt = new Date().toISOString();
this.saveTasks();
this.renderTasks();
this.updateStats();
// GitHub風のステータス更新メッセージ
this.showNotification(
`タスク #${taskId}${this.getStatusLabel(oldStatus)} から ${this.getStatusLabel(newStatus)} に移動しました`,
'info'
);
}
// ユーティリティ関数
getPriorityLabel(priority) {
const labels = {
'high': '高',
'medium': '中',
'low': '低'
};
return labels[priority] || priority;
}
getCategoryLabel(category) {
const labels = {
'feature': '新機能',
'bug': 'バグ',
'improvement': '改善',
'documentation': 'ドキュメント'
};
return labels[category] || category;
}
getStatusLabel(status) {
const labels = {
'todo': 'TODO',
'in-progress': '進行中',
'done': '完了'
};
return labels[status] || status;
}
// 通知表示GitHub風
showNotification(message, type = 'info') {
// 簡易的な通知実装
const notification = document.createElement('div');
notification.className = `notification notification-${type}`;
notification.textContent = message;
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
padding: 12px 16px;
background: #0366d6;
color: white;
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000;
max-width: 300px;
animation: slideIn 0.3s ease-out;
`;
// タイプ別スタイル
const colors = {
'success': '#28a745',
'warning': '#ffd33d',
'error': '#d73a49',
'info': '#0366d6'
};
if (colors[type]) {
notification.style.background = colors[type];
}
document.body.appendChild(notification);
// 3秒後に削除
setTimeout(() => {
notification.remove();
}, 3000);
}
// フォームクリア
clearForm() {
document.getElementById('addTaskForm').reset();
}
// データ永続化
saveTasks() {
localStorage.setItem('github-learning-tasks', JSON.stringify(this.tasks));
localStorage.setItem('github-learning-task-counter', this.taskIdCounter.toString());
}
loadTasks() {
const saved = localStorage.getItem('github-learning-tasks');
return saved ? JSON.parse(saved) : [];
}
getNextTaskId() {
const saved = localStorage.getItem('github-learning-task-counter');
return saved ? parseInt(saved) : 1;
}
// デモデータ生成(学習用)
generateSampleTasks() {
const sampleTasks = [
{
id: this.taskIdCounter++,
title: 'GitHub Issues の基本操作を学習',
description: 'Issue の作成、編集、クローズの方法を実践で学ぶ',
category: 'documentation',
priority: 'high',
status: 'todo',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
},
{
id: this.taskIdCounter++,
title: 'Pull Request のワークフローを実践',
description: 'ブランチ作成からマージまでの一連の流れを体験',
category: 'feature',
priority: 'high',
status: 'in-progress',
createdAt: new Date(Date.now() - 86400000).toISOString(),
updatedAt: new Date().toISOString()
},
{
id: this.taskIdCounter++,
title: 'GitHub Actions でCI/CDを設定',
description: '自動テストとデプロイの仕組みを構築',
category: 'improvement',
priority: 'medium',
status: 'todo',
createdAt: new Date(Date.now() - 172800000).toISOString(),
updatedAt: new Date(Date.now() - 172800000).toISOString()
}
];
if (this.tasks.length === 0) {
this.tasks = sampleTasks;
this.saveTasks();
}
}
}
// アプリケーション開始
document.addEventListener('DOMContentLoaded', () => {
const taskManager = new TaskManager();
// デモデータ生成(初回のみ)
taskManager.generateSampleTasks();
taskManager.renderTasks();
taskManager.updateStats();
// グローバルに公開(デバッグ用)
window.taskManager = taskManager;
console.log('🎯 Personal Task Manager が起動しました!');
console.log('GitHub機能学習用のタスク管理アプリです。');
console.log('タスクを追加して、GitHub の各機能を実践的に学習しましょう!');
});

377
practice-project/style.css Normal file
View file

@ -0,0 +1,377 @@
/* Personal Task Manager - GitHub学習用スタイル */
:root {
--primary-color: #0366d6;
--secondary-color: #586069;
--success-color: #28a745;
--warning-color: #ffd33d;
--danger-color: #d73a49;
--background-color: #f6f8fa;
--card-background: #ffffff;
--border-color: #e1e4e8;
--text-primary: #24292e;
--text-secondary: #586069;
--shadow: 0 1px 3px rgba(27, 31, 35, 0.12);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
background-color: var(--background-color);
color: var(--text-primary);
line-height: 1.5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* ヘッダー */
header {
text-align: center;
margin-bottom: 40px;
padding: 20px;
background: var(--card-background);
border-radius: 8px;
box-shadow: var(--shadow);
}
header h1 {
color: var(--primary-color);
margin-bottom: 10px;
}
header p {
color: var(--text-secondary);
}
/* セクション共通スタイル */
section {
background: var(--card-background);
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: var(--shadow);
}
section h2 {
margin-bottom: 15px;
color: var(--text-primary);
border-bottom: 2px solid var(--primary-color);
padding-bottom: 5px;
}
/* フォーム */
.form-group {
margin-bottom: 15px;
}
.form-group input,
.form-group textarea,
.form-group select {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 14px;
transition: border-color 0.2s;
}
.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(3, 102, 214, 0.1);
}
.form-group textarea {
resize: vertical;
min-height: 80px;
}
button {
background: var(--primary-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s;
}
button:hover {
background: #0256cc;
}
/* フィルタ */
.filters {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
/* タスクボード */
.task-board {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.task-column {
background: var(--background-color);
border-radius: 8px;
padding: 15px;
min-height: 400px;
}
.task-column h3 {
margin-bottom: 15px;
padding: 10px;
background: var(--card-background);
border-radius: 6px;
text-align: center;
border: 2px solid var(--border-color);
}
.task-list {
min-height: 300px;
}
/* タスクカード */
.task-card {
background: var(--card-background);
border: 1px solid var(--border-color);
border-radius: 6px;
padding: 15px;
margin-bottom: 10px;
cursor: grab;
transition: all 0.2s;
box-shadow: var(--shadow);
}
.task-card:hover {
border-color: var(--primary-color);
box-shadow: 0 2px 8px rgba(27, 31, 35, 0.15);
}
.task-card:active {
cursor: grabbing;
}
.task-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.task-id {
font-family: 'Monaco', 'Menlo', monospace;
background: var(--background-color);
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
color: var(--text-secondary);
}
.task-priority {
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.task-priority.high {
background: var(--danger-color);
color: white;
}
.task-priority.medium {
background: var(--warning-color);
color: var(--text-primary);
}
.task-priority.low {
background: var(--success-color);
color: white;
}
.task-category {
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
background: var(--primary-color);
color: white;
}
.task-category.feature {
background: #28a745;
}
.task-category.bug {
background: #d73a49;
}
.task-category.improvement {
background: #0366d6;
}
.task-category.documentation {
background: #6f42c1;
}
.task-title {
margin-bottom: 8px;
color: var(--text-primary);
}
.task-description {
color: var(--text-secondary);
font-size: 14px;
margin-bottom: 10px;
line-height: 1.4;
}
.task-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
color: var(--text-secondary);
}
.task-actions {
display: flex;
gap: 5px;
}
.task-actions button {
background: none;
border: none;
padding: 4px;
cursor: pointer;
border-radius: 3px;
font-size: 14px;
}
.task-actions button:hover {
background: var(--border-color);
}
/* 統計 */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
.stat-card {
text-align: center;
padding: 20px;
background: var(--background-color);
border-radius: 8px;
border: 1px solid var(--border-color);
}
.stat-card h3 {
margin-bottom: 10px;
color: var(--text-secondary);
font-size: 14px;
}
.stat-card span {
font-size: 32px;
font-weight: bold;
color: var(--primary-color);
}
/* フッター */
footer {
text-align: center;
margin-top: 40px;
padding: 20px;
color: var(--text-secondary);
border-top: 1px solid var(--border-color);
}
/* ドラッグ&ドロップ */
.task-column.drag-over {
background: rgba(3, 102, 214, 0.1);
border: 2px dashed var(--primary-color);
}
.task-card.dragging {
opacity: 0.5;
transform: rotate(5deg);
}
/* レスポンシブ */
@media (max-width: 768px) {
.container {
padding: 10px;
}
.task-board {
grid-template-columns: 1fr;
}
.filters {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* アニメーション */
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.task-card {
animation: slideIn 0.3s ease-out;
}
/* GitHub風のボタン */
.github-btn {
background: #f6f8fa;
color: var(--text-primary);
border: 1px solid var(--border-color);
}
.github-btn:hover {
background: #e1e4e8;
}
.github-btn.primary {
background: var(--primary-color);
color: white;
}
.github-btn.success {
background: var(--success-color);
color: white;
}
.github-btn.danger {
background: var(--danger-color);
color: white;
}